in unittest/lib/testDh.cpp [165:316]
VOID generateDlGroups()
{
// Fill up our array of key blobs with generated keys
UINT32 desiredFixedGroupSizes[] = {
(4096 << 16) + 1, // 1 keys of 4096 bits
(3072 << 16) + 2, // 2 keys of 3072 bits
(2048 << 16) + 5,
(1536 << 16) + 2,
(1024 << 16) + 5,
(768 << 16) + 2,
(512 << 16) + 2,
0,
};
UINT32 bitSize;
UINT32 primResult;
char * sep = " [group safeprime:";
UINT32 previousSize = 0;
if( g_nDlgroups >= MAX_TEST_DLGROUPS )
{
goto cleanup;
}
for( int i = 0; i<ARRAY_SIZE(g_safePrimeTypes); i++)
{
SYMCRYPT_ERROR scError;
SYMCRYPT_DLGROUP_DH_SAFEPRIMETYPE eDhSafePrimeType = g_safePrimeTypes[i];
iprint( sep );
switch(eDhSafePrimeType)
{
case SYMCRYPT_DLGROUP_DH_SAFEPRIMETYPE_IKE_3526:
sep = " IKE";
break;
case SYMCRYPT_DLGROUP_DH_SAFEPRIMETYPE_TLS_7919:
sep = " TLS";
break;
default:
sep = " ???";
break;
}
UINT32 maxBitSize = g_maxSafePrimeGroupBitSize;
while( TRUE )
{
PSYMCRYPT_DLGROUP pGroup = SymCryptDlgroupAllocate( maxBitSize, maxBitSize );
CHECK( pGroup != NULL, "?" );
scError = SymCryptDlgroupSetValueSafePrime( eDhSafePrimeType, pGroup );
// Assume we've reached the minimum supported size
if( scError == SYMCRYPT_INVALID_ARGUMENT )
{
SymCryptDlgroupFree( pGroup );
break;
}
CHECK( scError == SYMCRYPT_NO_ERROR, "Error setting DL safe-prime group" );
CHECK(pGroup->isSafePrimeGroup, "DL safe-prime group initialized incorrectly")
CHECK(pGroup->nBitsOfP <= maxBitSize, "DL safe-prime group P is wrong size");
CHECK(pGroup->nBitsOfQ <= maxBitSize-1, "DL safe-prime group Q is wrong size");
iprint( "%s%d", sep, pGroup->nBitsOfP );
sep = ",";
maxBitSize = pGroup->nBitsOfP-1;
// Check that the constants selected by SetValueSafePrime are indeed prime
primResult = SymCryptIntMillerRabinPrimalityTest(
SymCryptIntFromModulus( pGroup->pmP ),
pGroup->nBitsOfP,
8, // nIterations - reduce runtime overhead as this should always pass
SYMCRYPT_FLAG_DATA_PUBLIC, //flags
g_dlGroupScratch,
SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( pGroup->pmP->nDigits ) );
CHECK(primResult != 0, "Primality test failed for DL safe-prime group P");
primResult = SymCryptIntMillerRabinPrimalityTest(
SymCryptIntFromModulus( pGroup->pmQ ),
pGroup->nBitsOfQ,
8, // nIterations - reduce runtime overhead as this should always pass
SYMCRYPT_FLAG_DATA_PUBLIC, //flags
g_dlGroupScratch,
SYMCRYPT_SCRATCH_BYTES_FOR_INT_IS_PRIME( pGroup->pmQ->nDigits ) );
CHECK(primResult != 0, "Primality test failed for DL safe-prime group Q");
// Need to enable DH keypairs larger than 4096b in CNG before testing with these groups
if (pGroup->nBitsOfP <= 4096)
{
g_nDhNamedGroups++;
addDlgroupToGlobalTestBlobArray( pGroup->nBitsOfP, pGroup );
}
else
{
SymCryptDlgroupFree( pGroup );
}
}
}
sep = "]\n [group gen: ";
for( int i = 0; desiredFixedGroupSizes[i] != 0; i++ )
{
bitSize = desiredFixedGroupSizes[i] >> 16;
int n = desiredFixedGroupSizes[i] & 0xff;
while( n-- && g_nDlgroups < MAX_TEST_DLGROUPS )
{
if( bitSize == previousSize )
{
iprint( "." );
} else {
iprint( "%s%d", sep, bitSize );
sep = ",";
previousSize = bitSize;
}
addOneDlgroup( bitSize, FALSE );
}
}
// And we fill the rest with randomly-sized keys
// For performance we favor the smaller key sizes.
while( g_nDlgroups < MAX_TEST_DLGROUPS )
{
UINT32 r = g_rng.uint32();
// We use prime moduli as they are almost independent
if( (r % 51) == 0 )
{
bitSize = (UINT32) g_rng.sizet( 2048, 4096 );
} else if ( (r % 5) == 0 ) {
bitSize = (UINT32) g_rng.sizet( 1024, 2049 );
} else {
bitSize = (UINT32) g_rng.sizet( 512, 1025 );
}
if( bitSize == previousSize )
{
iprint( "." );
} else {
iprint( "%s%d", sep, bitSize );
sep = ",";
previousSize = bitSize;
}
addOneDlgroup( bitSize, TRUE );
}
iprint( "]" );
cleanup:
return;
}