643 lines
18 KiB
C++
643 lines
18 KiB
C++
|
|
||
|
//+-----------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation 2000
|
||
|
//
|
||
|
// File: nonce.cxx
|
||
|
//
|
||
|
// Contents: Context APIs for the Digest security package
|
||
|
// Main entry points into this dll:
|
||
|
// NonceCreate
|
||
|
// NonceValidate
|
||
|
// NonceInitialize
|
||
|
//
|
||
|
// History: ChandanS 26-Jul-1996 Stolen from kerberos\client2\ctxtapi.cxx
|
||
|
// KDamour 16Mar00 Stolen from NTLM ctxtapi.cxx
|
||
|
//
|
||
|
//------------------------------------------------------------------------
|
||
|
#include <global.h>
|
||
|
#include <time.h>
|
||
|
|
||
|
// Hold the Hex representation plus the NULL
|
||
|
char g_cNoncePrivateKey[(2*NONCE_PRIVATE_KEY_BYTESIZE) + 1];
|
||
|
|
||
|
|
||
|
//
|
||
|
// Globals
|
||
|
//
|
||
|
|
||
|
HCRYPTPROV g_hCryptProv = 0; // Handle for CryptoAPI
|
||
|
WORD g_SupportedCrypto = 0; // Supported Crypt Functions bitmask (i.e. SUPPORT_DES)
|
||
|
|
||
|
|
||
|
// Needed for Digest Calculation and Nonce Hash
|
||
|
char *pbSeparator = COLONSTR;
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: NonceInitialize
|
||
|
//
|
||
|
// Synopsis: This function is to be called
|
||
|
//
|
||
|
// Arguments: None
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Notes:
|
||
|
// CryptReleaseContext( g_hCryptProv, 0 ) to release the cypt context
|
||
|
//
|
||
|
//---------------------------------------------------------------------
|
||
|
|
||
|
NTSTATUS NTAPI
|
||
|
NonceInitialize(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
BYTE abTemp[NONCE_PRIVATE_KEY_BYTESIZE];
|
||
|
HCRYPTKEY hKey = 0;
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceInitialize: Entering\n"));
|
||
|
|
||
|
if (g_hCryptProv)
|
||
|
{ // Catch cases where LSA and Usermode running in same addr space
|
||
|
DebugLog((DEB_TRACE, "NonceInitialize: Already Inited Leaving\n"));
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get a handle to the CSP we'll use for all our hash functions etc
|
||
|
//
|
||
|
if ( !CryptAcquireContext( &g_hCryptProv,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
PROV_RSA_FULL,
|
||
|
CRYPT_VERIFYCONTEXT ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceInitialize:CryptCreateHash() failed : 0x%lx\n", GetLastError()));
|
||
|
Status = STATUS_INTERNAL_ERROR;
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Generate and copy over the random bytes
|
||
|
//
|
||
|
if ( !CryptGenRandom( g_hCryptProv,
|
||
|
NONCE_PRIVATE_KEY_BYTESIZE,
|
||
|
abTemp ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceInitialize:NonceInitialize CryptGenRandom() failed : 0x%lx\n", GetLastError()));
|
||
|
Status = STATUS_INTERNAL_ERROR;
|
||
|
return (Status);
|
||
|
}
|
||
|
|
||
|
BinToHex((LPBYTE) abTemp, NONCE_PRIVATE_KEY_BYTESIZE, (LPSTR) g_cNoncePrivateKey);
|
||
|
|
||
|
SetSupportedCrypto();
|
||
|
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceInitialize:Leaving NonceInitialize\n"));
|
||
|
|
||
|
return (Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: SetSupportedCrypto
|
||
|
//
|
||
|
// Synopsis: Set the bitmask for the supported crypto CSP installed
|
||
|
//
|
||
|
// Arguments: none
|
||
|
//
|
||
|
// Returns: STATUS_DATA_ERROR - error in reading CSP capabilities
|
||
|
// STATUS_SUCCESS - operation completed normally
|
||
|
//
|
||
|
//
|
||
|
//---------------------------------------------------------------------
|
||
|
|
||
|
NTSTATUS NTAPI
|
||
|
SetSupportedCrypto(VOID)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
|
||
|
g_SupportedCrypto = SUPPORT_3DES | SUPPORT_DES | SUPPORT_RC4_40 | SUPPORT_RC4 | SUPPORT_RC4_56;
|
||
|
|
||
|
// FIXFIX use CryptGetProvParam to set to actual installed CSP
|
||
|
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: NonceCreate
|
||
|
//
|
||
|
// Synopsis: This function is to be called once during User Mode initialization
|
||
|
//
|
||
|
// Arguments: pczNonce - pointer to a STRING to fillin
|
||
|
// with a new nonce
|
||
|
//
|
||
|
// Returns: STATUS_DATA_ERROR - input NONCE not enough space
|
||
|
// STATUS_SUCCESS - operation completed normally
|
||
|
//
|
||
|
// Notes: Function will return error if Nonce UNICODE_STRING is not empty
|
||
|
// NONCE FORMAT
|
||
|
// rand-data = rand[16]
|
||
|
// nonce_binary = time-stamp rand-data H(time-stamp ":" rand-data ":" nonce_private_key)
|
||
|
// nonce = hex(nonce_binary)
|
||
|
//
|
||
|
//---------------------------------------------------------------------
|
||
|
|
||
|
NTSTATUS NTAPI
|
||
|
NonceCreate(
|
||
|
IN OUT PSTRING pstrNonce
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
BYTE abRandomData[RANDDATA_BYTESIZE];
|
||
|
char acRandomHex[(2*RANDDATA_BYTESIZE) + 1];
|
||
|
int cbNonce = 0;
|
||
|
|
||
|
time_t tcurrent = time(NULL);
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceCreate: Entering\n"));
|
||
|
|
||
|
// Check to make sure that there is enough space on ouput string
|
||
|
// Need room for the Nonce and the NULL terminator
|
||
|
if (!pstrNonce->Buffer)
|
||
|
{
|
||
|
Status = StringAllocate(pstrNonce, NONCE_SIZE);
|
||
|
if (!NT_SUCCESS (Status))
|
||
|
{
|
||
|
Status = SEC_E_INSUFFICIENT_MEMORY;
|
||
|
DebugLog((DEB_ERROR, "NonceCreate: StringAllocate error 0x%x\n", Status));
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
if (pstrNonce->MaximumLength < (NONCE_SIZE + 1))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceCreate: Input STRING too small\n"));
|
||
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Copy over the current time
|
||
|
BinToHex((LPBYTE)&tcurrent, sizeof(time_t), (LPSTR) pstrNonce->Buffer);
|
||
|
cbNonce += (sizeof(time_t) * 2);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Generate and copy over the random bytes
|
||
|
//
|
||
|
if ( !CryptGenRandom( g_hCryptProv,
|
||
|
RANDDATA_BYTESIZE,
|
||
|
abRandomData ) )
|
||
|
{
|
||
|
DebugLog((DEB_TRACE, "NonceCreate: CryptGenRandom() failed : 0x%x\n", GetLastError()));
|
||
|
Status = STATUS_INTERNAL_ERROR;
|
||
|
return (Status);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert to ASCII, doubling the length, and add to nonce
|
||
|
//
|
||
|
BinToHex( abRandomData, RANDDATA_BYTESIZE, acRandomHex);
|
||
|
memcpy(pstrNonce->Buffer + NONCE_RANDDATA_LOC, acRandomHex, (2 * NONCE_PRIVATE_KEY_BYTESIZE));
|
||
|
|
||
|
//
|
||
|
// Now calculate the Hash. It will be NULL terminated but STRING length does not include NULL
|
||
|
//
|
||
|
|
||
|
Status = NonceHash((LPBYTE) pstrNonce->Buffer, (2 * sizeof(time_t)),
|
||
|
(LPBYTE) acRandomHex, (2 * RANDDATA_BYTESIZE),
|
||
|
(LPBYTE) g_cNoncePrivateKey, (2 * NONCE_PRIVATE_KEY_BYTESIZE),
|
||
|
(LPBYTE) (pstrNonce->Buffer + NONCE_HASH_LOC));
|
||
|
if (!NT_SUCCESS (Status))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceCreate: failed %d\n", Status));
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
pstrNonce->Length = NONCE_SIZE;
|
||
|
|
||
|
CleanUp:
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
pstrNonce->Length = 0;
|
||
|
}
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceCreate: Leaving\n"));
|
||
|
|
||
|
return (Status);
|
||
|
}
|
||
|
|
||
|
//+--------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: NonceIsValid
|
||
|
//
|
||
|
// Synopsis: Called with a pointer to a Nonce and returns NTSTATUS This is the
|
||
|
// main function that checks for a valid nonce.
|
||
|
//
|
||
|
// Arguments: None
|
||
|
//
|
||
|
// Returns: NTSTATUS STATUS_SUCCESS if NONCE generated locally and is valid
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//---------------------------------------------------------------------
|
||
|
|
||
|
NTSTATUS
|
||
|
NonceIsValid(
|
||
|
PSTRING pstrNonce
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceIsValid: Entering\n"));
|
||
|
|
||
|
// Check the size first
|
||
|
if (pstrNonce->Length != NONCE_SIZE)
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceIsValid: Incorrect size for the Nonce\n"));
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
|
||
|
if (!pstrNonce->Buffer)
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceIsValid: NULL pointer for the Nonce\n"));
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
|
||
|
if (NonceIsTampered(pstrNonce))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceIsValid: Nonce hash does not match\n"));
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceIsValid: Leaving\n"));
|
||
|
|
||
|
return (Status);
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Creates MD5 hash of input buffer
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pbData - data to hash
|
||
|
cbData - size of data pointed to by pbData
|
||
|
pbHash - buffer that receives hash; is assumed to be big enough to contain MD5 hash
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful, FALSE if not
|
||
|
|
||
|
--*/
|
||
|
BOOL HashData( BYTE *pbData,
|
||
|
DWORD cbData,
|
||
|
BYTE *pbHash )
|
||
|
{
|
||
|
HCRYPTHASH hHash = NULL;
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "HashData: Entering\n"));
|
||
|
|
||
|
if ( !CryptCreateHash( g_hCryptProv,
|
||
|
CALG_MD5,
|
||
|
0,
|
||
|
0,
|
||
|
&hHash ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "HashData: CryptCreateHash failed : 0x%lx\n", GetLastError()));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( !CryptHashData( hHash,
|
||
|
pbData,
|
||
|
cbData,
|
||
|
0 ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "HashData: CryptCreateHash failed : 0x%lx\n", GetLastError()));
|
||
|
|
||
|
CryptDestroyHash( hHash );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
DWORD cbHash = MD5_HASH_BYTESIZE;
|
||
|
if ( !CryptGetHashParam( hHash,
|
||
|
HP_HASHVAL,
|
||
|
pbHash,
|
||
|
&cbHash,
|
||
|
0 ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "HashData: CryptCreateHash failed : 0x%lx\n", GetLastError()));
|
||
|
|
||
|
CryptDestroyHash( hHash );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
CryptDestroyHash( hHash );
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "HashData: Leaving\n"));
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Creates MD5 hash of the Nonce values
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pbTime - pointer to char buffer encoded Time()
|
||
|
cbTime - number of bytes in encoded Time() buffer to process
|
||
|
pbRandom - pointer to char buffer encoded random sequence
|
||
|
cbRandom - number of bytes in encoded random buffer to process
|
||
|
pbTKey - pointer to char buffer encoded private key
|
||
|
cbKey - number of bytes in encoded private key buffer to process
|
||
|
pbHash - pointer to char buffer encoded Nonce Hash
|
||
|
cbHash - number of bytes in encoded Time() buffer to process
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_SUCCESS - normal completion
|
||
|
|
||
|
--*/
|
||
|
NTSTATUS NTAPI
|
||
|
NonceHash( IN LPBYTE pbTime,
|
||
|
IN DWORD cbTime,
|
||
|
IN LPBYTE pbRandom,
|
||
|
IN DWORD cbRandom,
|
||
|
IN LPBYTE pbKey,
|
||
|
IN DWORD cbKey,
|
||
|
OUT LPBYTE pbHash)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
HCRYPTHASH hHash = NULL;
|
||
|
DWORD cbHash = MD5_HASH_BYTESIZE; // Number of bytes for MD5 hash
|
||
|
unsigned char abHashBin[MD5_HASH_BYTESIZE];
|
||
|
|
||
|
DebugLog((DEB_TRACE, "NonceHash: Entering\n"));
|
||
|
|
||
|
if ( !CryptCreateHash( g_hCryptProv,
|
||
|
CALG_MD5,
|
||
|
0,
|
||
|
0,
|
||
|
&hHash ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceHash: CryptCreateHash failed : 0x%lx\n", GetLastError()));
|
||
|
Status = STATUS_INTERNAL_ERROR;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
if ( !CryptHashData( hHash,
|
||
|
pbTime,
|
||
|
cbTime,
|
||
|
0 ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceHash: CryptCreateHash failed : 0x%lx\n", GetLastError()));
|
||
|
Status = STATUS_INTERNAL_ERROR;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
if ( !CryptHashData( hHash,
|
||
|
(const unsigned char *)pbSeparator,
|
||
|
COLONSTR_LEN,
|
||
|
0 ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceHash: CryptCreateHash failed : 0x%lx\n", GetLastError()));
|
||
|
Status = STATUS_INTERNAL_ERROR;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
if ( !CryptHashData( hHash,
|
||
|
pbRandom,
|
||
|
cbRandom,
|
||
|
0 ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceHash: CryptCreateHash failed : 0x%lx\n", GetLastError()));
|
||
|
Status = STATUS_INTERNAL_ERROR;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
if ( !CryptHashData( hHash,
|
||
|
(const unsigned char *)pbSeparator,
|
||
|
COLONSTR_LEN,
|
||
|
0 ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceHash: CryptCreateHash failed : 0x%lx\n", GetLastError()));
|
||
|
Status = STATUS_INTERNAL_ERROR;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
if ( !CryptHashData( hHash,
|
||
|
pbKey,
|
||
|
cbKey,
|
||
|
0 ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceHash: CryptCreateHash failed : 0x%lx\n", GetLastError()));
|
||
|
Status = STATUS_INTERNAL_ERROR;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
if ( !CryptGetHashParam( hHash,
|
||
|
HP_HASHVAL,
|
||
|
abHashBin,
|
||
|
&cbHash,
|
||
|
0 ) )
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceHash: CryptCreateHash failed : 0x%lx\n", GetLastError()));
|
||
|
Status = STATUS_INTERNAL_ERROR;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
// Now convert the Hash to hex
|
||
|
BinToHex(abHashBin, MD5_HASH_BYTESIZE, (char *)pbHash);
|
||
|
|
||
|
CleanUp:
|
||
|
if (hHash)
|
||
|
{
|
||
|
CryptDestroyHash( hHash );
|
||
|
hHash = NULL;
|
||
|
}
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceHash: Leaving\n"));
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
//+--------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: NonceIsExpired
|
||
|
//
|
||
|
// Synopsis: Check the timestamp to make sure that Nonce is still valid
|
||
|
//
|
||
|
// Arguments: None
|
||
|
//
|
||
|
// Returns: TRUE/FALSE if Nonce is expired
|
||
|
//
|
||
|
// Notes: Called from NonceIsValid
|
||
|
//
|
||
|
//---------------------------------------------------------------------
|
||
|
BOOL NonceIsExpired(PSTRING pstrNonce)
|
||
|
{
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceIsExpired: Entering\n"));
|
||
|
time_t tcurrent = time(NULL);
|
||
|
time_t tnonce = 0;
|
||
|
|
||
|
// time-stamp is the first bytes in the nonce
|
||
|
|
||
|
HexToBin(pstrNonce->Buffer, (2*TIMESTAMP_BYTESIZE), (unsigned char *)&tnonce);
|
||
|
|
||
|
// If LifeTime set to zero - nonces never expire
|
||
|
if (((unsigned long)tnonce > (unsigned long)tcurrent) ||
|
||
|
(g_dwParameter_Lifetime && (((unsigned long)tcurrent - (unsigned long)tnonce) > g_dwParameter_Lifetime)))
|
||
|
{
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceIsExpired: NonceHash has expired. Expired = TRUE\n"));
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceIsExpired: Leaving Expired = FALSE\n"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: NonceIsTampered
|
||
|
//
|
||
|
// Synopsis: Check the hash matches for the Nonce
|
||
|
//
|
||
|
// Arguments: None
|
||
|
//
|
||
|
// Returns: TRUE/FALSE if Nonce hash fails check
|
||
|
//
|
||
|
// Notes: Called from NonceIsValid
|
||
|
//
|
||
|
//---------------------------------------------------------------------
|
||
|
BOOL NonceIsTampered(PSTRING pstrNonce)
|
||
|
{
|
||
|
BOOL bStatus = FALSE;
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
unsigned char abHashHex[(2*MD5_HASH_BYTESIZE) + 1];
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceIsTampered:Entering \n"));
|
||
|
|
||
|
Status = NonceHash((LPBYTE) (pstrNonce->Buffer + NONCE_TIME_LOC), (2 * sizeof(time_t)),
|
||
|
(LPBYTE) (pstrNonce->Buffer + NONCE_RANDDATA_LOC), (2 * RANDDATA_BYTESIZE),
|
||
|
(LPBYTE) g_cNoncePrivateKey, (2 * NONCE_PRIVATE_KEY_BYTESIZE),
|
||
|
(LPBYTE) abHashHex);
|
||
|
if (!NT_SUCCESS (Status))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceIsTampered: NonceHash has failed %d\n", Status));
|
||
|
bStatus = TRUE;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
if (memcmp(abHashHex, (pstrNonce->Buffer + NONCE_HASH_LOC), (2 * MD5_HASH_BYTESIZE)))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "NonceIsTampered: memcmp failed\n"));
|
||
|
bStatus = TRUE;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
CleanUp:
|
||
|
DebugLog((DEB_TRACE_FUNC, "NonceIsTampered: Leaving\n"));
|
||
|
return bStatus;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: OpaqueCreate
|
||
|
//
|
||
|
// Synopsis: Creates an Opaque string composed of OPAQUE_SIZE of random data
|
||
|
//
|
||
|
// Arguments: pstrOpque - pointer to a STRING to fillin
|
||
|
// with a new opaque
|
||
|
//
|
||
|
// Returns: STATUS_DATA_ERROR - input NONCE not enough space
|
||
|
// STATUS_SUCCESS - operation completed normally
|
||
|
//
|
||
|
// Notes: Function will return error if Nonce STRING is not empty
|
||
|
// OPAQUE FORMAT
|
||
|
// opaque_binary = rand[OPAQUE_SIZE]
|
||
|
// nonce = Hex(opaque_binary)
|
||
|
//
|
||
|
//---------------------------------------------------------------------
|
||
|
|
||
|
NTSTATUS NTAPI
|
||
|
OpaqueCreate(
|
||
|
IN OUT PSTRING pstrOpaque
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
BYTE abRandomData[OPAQUE_RANDATA_SIZE];
|
||
|
char acRandomHex[(2*OPAQUE_RANDATA_SIZE) + 1];
|
||
|
int cbNonce = 0;
|
||
|
DebugLog((DEB_TRACE_FUNC, "OpaqueCreate: Entering\n"));
|
||
|
|
||
|
// Check to make sure that there is enough space on ouput string
|
||
|
// Need room for the Nonce and the NULL terminator
|
||
|
if (!pstrOpaque->Buffer)
|
||
|
{
|
||
|
Status = StringAllocate(pstrOpaque, OPAQUE_SIZE);
|
||
|
if (!NT_SUCCESS (Status))
|
||
|
{
|
||
|
Status = SEC_E_INSUFFICIENT_MEMORY;
|
||
|
DebugLog((DEB_ERROR, "OpaqueCreate: StringAllocate error 0x%x\n", Status));
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
}
|
||
|
else if (pstrOpaque->MaximumLength < ((2 * OPAQUE_RANDATA_SIZE) + 1))
|
||
|
{
|
||
|
DebugLog((DEB_ERROR, "OpaqueCreate: Input STRING too small\n"));
|
||
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Generate and copy over the random bytes
|
||
|
//
|
||
|
if ( !CryptGenRandom( g_hCryptProv,
|
||
|
OPAQUE_RANDATA_SIZE,
|
||
|
abRandomData ) )
|
||
|
{
|
||
|
DebugLog((DEB_TRACE, "OpaqueCreate: CryptGenRandom() failed : 0x%lx\n", GetLastError()));
|
||
|
Status = STATUS_INTERNAL_ERROR;
|
||
|
return (Status);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert to ASCII, doubling the length, and add to nonce
|
||
|
//
|
||
|
BinToHex( abRandomData, OPAQUE_RANDATA_SIZE, pstrOpaque->Buffer);
|
||
|
|
||
|
pstrOpaque->Length = (2 * OPAQUE_RANDATA_SIZE);
|
||
|
|
||
|
CleanUp:
|
||
|
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
pstrOpaque->Length = 0;
|
||
|
}
|
||
|
|
||
|
DebugLog((DEB_TRACE_FUNC, "OpaqueCreate: Leaving\n"));
|
||
|
|
||
|
return (Status);
|
||
|
}
|
||
|
|