Skip to content

Commit 07a5bf9

Browse files
Merged PR 8176148: Linux RNG perf testing and improvements
+ Enable measurements of Linux RNG system + Make various performance improvements to defer costly calls into JitterEntropy until they are strictly required, and reduce cost of calls when they are made. Related work items: #42441472, #42441492
1 parent 2ef5a91 commit 07a5bf9

File tree

15 files changed

+335
-127
lines changed

15 files changed

+335
-127
lines changed

inc/symcrypt.h

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ SymCryptHashResult(
816816
SIZE_T cbResult );
817817
//
818818
// SymCryptHashResult
819-
//
819+
//
820820
// Finalizes the hash computation by calling the resultFunc member
821821
// of pHash.
822822
// The hash result is produced to an internal buffer and
@@ -4130,21 +4130,21 @@ SymCryptSshKdfExpandKey(
41304130
// Process the key using the specified hash function and store the result in
41314131
// SYMCRYPT_SSHKDF_EXPANDED_KEY structure. Once the key is expanded,
41324132
// SymCryptSshKdfDerive can be called multiple times to generate keys for
4133-
// different uses/labels.
4134-
//
4133+
// different uses/labels.
4134+
//
41354135
// After all the keys are derived from a particular "shared secret" key,
41364136
// SYMCRYPT_SSHKDF_EXPANDED_KEY structure must be wiped.
4137-
//
4137+
//
41384138
// Parameters:
41394139
// - pExpandedKey : Pointer to a SYMCRYPT_SSHKDF_EXPANDED_KEY structure that
41404140
// will contain the expanded key after the function returns.
41414141
// - pHashFunc : Hash function that will be used in the key derivation.
41424142
// This function is saved in SYMCRYPT_SSHKDF_EXPANDED_KEY
41434143
// so that it is also used by the SymCryptSshKdfDerive function.
41444144
// - pbKey, cbKey : Buffer contatining the secret key for the KDF.
4145-
//
4145+
//
41464146
// Returns SYMCRYPT_NO_ERROR
4147-
//
4147+
//
41484148

41494149

41504150
SYMCRYPT_ERROR
@@ -4162,7 +4162,7 @@ SymCryptSshKdfDerive(
41624162
// Derive keys using the expanded key that was initialized with SymCryptSshKdfExpandKey
41634163
// along with other inputs. This function can be called consecutively with varying label
41644164
// values to generate keys for different purposes as defined in the RFC.
4165-
//
4165+
//
41664166
// Parameters:
41674167
// - pExpandedKey : Pointer to a SYMCRYPT_SSHKDF_EXPANDED_KEY structure that is
41684168
// initialized by a prior call to SymCryptSshKdfExpandKey.
@@ -4174,7 +4174,7 @@ SymCryptSshKdfDerive(
41744174
// - pbSessionId, cbSessionId : Buffer pointing to the session identifier. cbSessionId must be equal
41754175
// to the output size of the hash function passed to SymCryptSshKdfExpandKey.
41764176
// - pbOutput, cbOutput : Buffer to store the derived key. Exactly cbOutput bytes of output will be generated.
4177-
//
4177+
//
41784178
// Returns SYMCRYPT_NO_ERROR
41794179
//
41804180

@@ -4192,7 +4192,7 @@ SymCryptSshKdf(
41924192
SIZE_T cbSessionId,
41934193
_Out_writes_(cbOutput) PBYTE pbOutput,
41944194
SIZE_T cbOutput);
4195-
//
4195+
//
41964196
// This function is a wrapper for using SymCryptSshKdfExpandKey followed by SymCryptSshKdfDerive
41974197
// in order to produce SSH-KDF output.
41984198
//
@@ -4231,23 +4231,23 @@ SymCryptSrtpKdfExpandKey(
42314231
_In_reads_(cbKey) PCBYTE pbKey,
42324232
SIZE_T cbKey);
42334233
//
4234-
// Process the key and store the result in SYMCRYPT_SRTPKDF_EXPANDED_KEY structure.
4235-
// Once the key is expanded, SymCryptSrtpKdfDerive can be called multiple times to
4236-
// generate keys for different uses/labels.
4237-
//
4234+
// Process the key and store the result in SYMCRYPT_SRTPKDF_EXPANDED_KEY structure.
4235+
// Once the key is expanded, SymCryptSrtpKdfDerive can be called multiple times to
4236+
// generate keys for different uses/labels.
4237+
//
42384238
// After all the keys are derived from a particular "shared secret" key,
42394239
// SYMCRYPT_SRTPKDF_EXPANDED_KEY structure must be wiped.
4240-
//
4240+
//
42414241
// Parameters:
42424242
// - pExpandedKey : Pointer to a SYMCRYPT_SRTPKDF_EXPANDED_KEY structure that
42434243
// will contain the expanded key after the function returns.
42444244
// - pbKey, cbKey : Buffer contatining the secret key for the KDF. cbKey must be
42454245
// a valid AES key size (16-, 24-, or 32-bytes).
4246-
//
4246+
//
42474247
// Returns:
42484248
// SYMCRYPT_WRONG_KEY_SIZE : If cbKey is not a valid AES key size
42494249
// SYMCRYPT_NO_ERROR : On success
4250-
//
4250+
//
42514251

42524252
SYMCRYPT_ERROR
42534253
SYMCRYPT_CALL
@@ -4265,7 +4265,7 @@ SymCryptSrtpKdfDerive(
42654265
// Derive keys using the expanded key that was initialized with SymCryptSrtpKdfExpandKey
42664266
// along with other inputs. This function can be called consecutively with varying label
42674267
// values to generate keys for different purposes as defined in the RFC.
4268-
//
4268+
//
42694269
// Parameters:
42704270
// - pExpandedKey : Pointer to a SYMCRYPT_SRTPKDF_EXPANDED_KEY structure that is
42714271
// initialized by a prior call to SymCryptSrtpKdfExpandKey.
@@ -4281,9 +4281,9 @@ SymCryptSrtpKdfDerive(
42814281
// to be 48-bits by Errata ID 3712. SRTP index values are defined to be 48-bits.
42824282
// - label : Label value used to indicate the type of the derived key.
42834283
// - pbOutput, cbOutput : Buffer to store the derived key. Exactly cbOutput bytes of output will be generated.
4284-
//
4284+
//
42854285
// Returns:
4286-
// SYMCRYPT_INVALID_ARGUMENT : If cbSalt is not 14-bytes, or uKeyDerivationRate in invalid.
4286+
// SYMCRYPT_INVALID_ARGUMENT : If cbSalt is not 14-bytes, or uKeyDerivationRate in invalid.
42874287
// SYMCRYPT_NO_ERROR : On success.
42884288
//
42894289

@@ -4301,7 +4301,7 @@ SymCryptSrtpKdf(
43014301
BYTE label,
43024302
_Out_writes_(cbOutput) PBYTE pbOutput,
43034303
SIZE_T cbOutput);
4304-
//
4304+
//
43054305
// This function is a wrapper for using SymCryptSrtpKdfExpandKey followed by SymCryptSrtpKdfDerive
43064306
// in order to produce SRTP-KDF output.
43074307
//
@@ -4428,7 +4428,7 @@ SymCryptRngAesInstantiate(
44284428
// Initialize a new SYMCRYPT_RNG_AES_STATE, and seed it with the seed material.
44294429
//
44304430
// 'Instantiate' is the SP800-90 terminology.
4431-
// The seed material must be at least SYMCRYPT_RNG_AES_MIN_SEED_SIZE bytes,
4431+
// The seed material must be at least SYMCRYPT_RNG_AES_MIN_INSTANTIATE_SIZE bytes,
44324432
// and at most SYMCRYPT_RNG_AES_MAX_SEED_SIZE bytes.
44334433
//
44344434
// This implementation always uses 256-bit security strength, and
@@ -4446,7 +4446,7 @@ SymCryptRngAesInstantiate(
44464446
// Nonce: must either be a random value with 128-bits of entropy, or a value that does not
44474447
// repeat with a probability of more than 2^{-128}.
44484448
// Together these requirements imply that cbSeedMaterial should be at least
4449-
// SYMCRYPT_RNG_AES_MIN_SEED_SIZE
4449+
// SYMCRYPT_RNG_AES_MIN_INSTANTIATE_SIZE
44504450
//
44514451
// This function only returns an error if the cbSeedMaterial value is out of range.
44524452
//

inc/symcrypt_low_level.h

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,6 +2654,35 @@ SymCryptEcpointMultiScalarMul(
26542654
// - cbScratch >= SYMCRYPT_SCRATCH_BYTES_FOR_MULTI_SCALAR_ECURVE_OPERATIONS( pCurve, nPoints ).
26552655
//
26562656

2657+
2658+
////////////////////////////////////////////////////////////////////////////
2659+
// AES-CTR-DRBG
2660+
//
2661+
2662+
#define SYMCRYPT_RNG_AES_INTERNAL_SEED_SIZE (32 + 16)
2663+
2664+
SYMCRYPT_ERROR
2665+
SYMCRYPT_CALL
2666+
SymCryptRngAesGenerateSmall(
2667+
_Inout_ PSYMCRYPT_RNG_AES_STATE pRngState,
2668+
_Out_writes_( cbRandom ) PBYTE pbRandom,
2669+
SIZE_T cbRandom,
2670+
_In_reads_opt_( cbAdditionalInput ) PCBYTE pbAdditionalInput,
2671+
SIZE_T cbAdditionalInput );
2672+
//
2673+
// Generate random output from the state per SP 800-90.
2674+
// Callers should almost always use SymCryptRngAesGenerate from symcrypt.h instead.
2675+
//
2676+
// This is the core generation function that produces up to 64 kB at a time
2677+
// This function returns an error code so that we can test the
2678+
// error handling of having done more than 2^48 requests between reseeds,
2679+
// as required by SP 800-90.
2680+
// This is also the Generate function of our SP800-90 compliant implementation.
2681+
// If pRngState->fips140-2Check is true, this function runs the continuous self test
2682+
// required by FIPS 140-2 (but not by FIPS 140-3 as far as we know).
2683+
// pbAdditionalInput is optional.
2684+
//
2685+
26572686
//=====================================================
26582687
// ECDSA-EX
26592688
//
@@ -2806,7 +2835,7 @@ SymCrypt802_11SaeCustomCreatePTGeneric(
28062835
_Out_writes_( cbPT ) PBYTE pbPT,
28072836
SIZE_T cbPT );
28082837
//
2809-
// Generic version of the SymCrypt802_11SaeCustomCreatePT() function that allows elliptic curve
2838+
// Generic version of the SymCrypt802_11SaeCustomCreatePT() function that allows elliptic curve
28102839
// group selection.
28112840
// Generate the PT secret element for use with the SAE Hash-to-Element algorithm, as described in
28122841
// section 12.4.4.2.3 of the 802.11 spec ("Hash-to-curve generation of the password element with
@@ -2856,7 +2885,7 @@ SymCrypt802_11SaeCustomInitH2EGeneric(
28562885
_Inout_updates_opt_( cbMask ) PBYTE pbMask,
28572886
SIZE_T cbMask );
28582887
//
2859-
// Generic version of the SymCrypt802_11SaeCustomInitH2E() function that allows elliptic curve
2888+
// Generic version of the SymCrypt802_11SaeCustomInitH2E() function that allows elliptic curve
28602889
// group selection.
28612890
// Initialize the state object using the Hash-to-Element algorithm, using the PT value calculated
28622891
// by SymCrypt802_11SaeCustomCreatePT.

lib/aesCtrDrbg.c

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include "precomp.h"
1212

1313
#define SYMCRYPT_RNG_AES_KEY_SIZE (32)
14-
#define SYMCRYPT_RNG_AES_INTERNAL_SEED_SIZE (32 + 16)
1514
#define SYMCRYPT_RNG_AES_KEY_AND_V_SIZE (32 + 16)
1615
#define SYMCRYPT_RNG_AES_MAX_REQUEST_SIZE (1<<16)
1716
#define SYMCRYPT_RNG_AES_MAX_REQUESTS_PER_RESEED ((UINT64)1<<48)
@@ -380,7 +379,7 @@ VOID
380379
SYMCRYPT_CALL
381380
SymCryptRngAesUpdate(
382381
_Inout_ PSYMCRYPT_RNG_AES_STATE pState,
383-
_In_reads_opt_( SYMCRYPT_RNG_AES_INTERNAL_SEED_SIZE ) PBYTE pbProvidedData,
382+
_In_reads_opt_( SYMCRYPT_RNG_AES_INTERNAL_SEED_SIZE ) PCBYTE pbProvidedData,
384383
_In_opt_ PSYMCRYPT_AES_EXPANDED_KEY pAesKey)
385384
//
386385
// Implement the CTR_DRBG Update function.
@@ -435,26 +434,19 @@ SymCryptRngAesUpdate(
435434
SYMCRYPT_ERROR
436435
SYMCRYPT_CALL
437436
SymCryptRngAesGenerateSmall(
438-
_Inout_ PSYMCRYPT_RNG_AES_STATE pRngState,
439-
_Out_writes_(cbRandom) PBYTE pbRandom,
440-
SIZE_T cbRandom )
437+
_Inout_ PSYMCRYPT_RNG_AES_STATE pRngState,
438+
_Out_writes_( cbRandom ) PBYTE pbRandom,
439+
SIZE_T cbRandom,
440+
_In_reads_opt_( cbAdditionalInput ) PCBYTE pbAdditionalInput,
441+
SIZE_T cbAdditionalInput )
441442
//
442-
// The core generation function that produces upto 64 kB at a time
443-
// This function returns an error code so that we can test the
444-
// error handling of having done more than 2^48 requests between reseeds,
445-
// as required by SP 800-90.
446-
// This is also the Generate function of our SP800-90 compliant implementation.
447-
// If fips140-2Check is true, this function runs the continuous self test required
448-
// by FIPS 140-2 (but not by FIPS 140-3 as far as we know).
443+
// This is the Generate function of our SP800-90 compliant implementation.
444+
// It follows the method specified in SP800-90A 10.2.1.5.2
449445
//
450446
{
451447
SYMCRYPT_AES_EXPANDED_KEY aesKey;
452448
SYMCRYPT_ALIGN BYTE buf[SYMCRYPT_AES_BLOCK_SIZE];
453-
454-
if( cbRandom == 0 )
455-
{
456-
return SYMCRYPT_NO_ERROR;
457-
}
449+
SYMCRYPT_ALIGN BYTE abSeed[SYMCRYPT_RNG_AES_INTERNAL_SEED_SIZE];
458450

459451
//
460452
// SP 800-90 9.3.1 requires a check on the length of the request.
@@ -466,14 +458,24 @@ SymCryptRngAesGenerateSmall(
466458
//
467459
// The requestCounter test is useless as it can never happen. (It would require
468460
// 2^48 calls to this function to trigger this error.)
469-
// Unfortunatly, SP800-90 section 11 requires a test of this error, so we have
470-
// to impelement the error.
461+
// Unfortunately, SP800-90 section 11 requires a test of this error, so we have
462+
// to implement the error.
471463
//
472464
if( pRngState->requestCounter > SYMCRYPT_RNG_AES_MAX_REQUESTS_PER_RESEED )
473465
{
474466
return SYMCRYPT_FIPS_FAILURE;
475467
}
476468

469+
if( pbAdditionalInput != NULL )
470+
{
471+
// Update additional input using Derivation function
472+
SymCryptRngAesDf( pbAdditionalInput, cbAdditionalInput, abSeed );
473+
pbAdditionalInput = &abSeed[0];
474+
475+
// Update state with modified additional input
476+
SymCryptRngAesUpdate( pRngState, pbAdditionalInput, NULL );
477+
}
478+
477479
SymCryptAesExpandKeyEncryptOnly( &aesKey, pRngState->keyAndV, SYMCRYPT_RNG_AES_KEY_SIZE );
478480

479481
if( cbRandom >= SYMCRYPT_AES_BLOCK_SIZE )
@@ -507,11 +509,12 @@ SymCryptRngAesGenerateSmall(
507509
SymCryptWipeKnownSize( buf, sizeof( buf ) );
508510
}
509511

510-
SymCryptRngAesUpdate( pRngState, NULL, &aesKey );
512+
SymCryptRngAesUpdate( pRngState, pbAdditionalInput, &aesKey );
511513

512514
++pRngState->requestCounter;
513515

514516
SymCryptWipeKnownSize( &aesKey, sizeof( aesKey ) );
517+
SymCryptWipeKnownSize( abSeed, sizeof( abSeed ) );
515518

516519
return SYMCRYPT_NO_ERROR;
517520
}
@@ -574,7 +577,7 @@ SymCryptRngAesGenerate( PSYMCRYPT_RNG_AES_STATE pRngState,
574577
while( cbRandom > SYMCRYPT_RNG_AES_MAX_REQUEST_SIZE )
575578
{
576579

577-
scError = SymCryptRngAesGenerateSmall( pRngState, pbRandom, SYMCRYPT_RNG_AES_MAX_REQUEST_SIZE );
580+
scError = SymCryptRngAesGenerateSmall( pRngState, pbRandom, SYMCRYPT_RNG_AES_MAX_REQUEST_SIZE, NULL, 0 );
578581
if( scError != SYMCRYPT_NO_ERROR )
579582
{
580583
SymCryptFatal( 'acdx' );
@@ -583,10 +586,13 @@ SymCryptRngAesGenerate( PSYMCRYPT_RNG_AES_STATE pRngState,
583586
cbRandom -= SYMCRYPT_RNG_AES_MAX_REQUEST_SIZE;
584587
}
585588

586-
scError = SymCryptRngAesGenerateSmall( pRngState, pbRandom, cbRandom );
587-
if( scError != SYMCRYPT_NO_ERROR )
589+
if( cbRandom > 0 )
588590
{
589-
SymCryptFatal( 'acdx' );
591+
scError = SymCryptRngAesGenerateSmall( pRngState, pbRandom, cbRandom, NULL, 0 );
592+
if( scError != SYMCRYPT_NO_ERROR )
593+
{
594+
SymCryptFatal( 'acdx' );
595+
}
590596
}
591597
}
592598

@@ -811,7 +817,7 @@ SymCryptRngAesTestGenerate( PSYMCRYPT_RNG_AES_STATE pRngState )
811817
//
812818

813819
pRngState->requestCounter = SYMCRYPT_RNG_AES_MAX_REQUESTS_PER_RESEED + 1;
814-
scError = SymCryptRngAesGenerateSmall( pRngState, abOutput, sizeof( g_abOutput1 ) );
820+
scError = SymCryptRngAesGenerateSmall( pRngState, abOutput, sizeof( g_abOutput1 ), NULL, 0 );
815821

816822
if( scError == SYMCRYPT_NO_ERROR )
817823
{
@@ -820,7 +826,7 @@ SymCryptRngAesTestGenerate( PSYMCRYPT_RNG_AES_STATE pRngState )
820826
pRngState->requestCounter = 7;
821827

822828
#pragma prefast( suppress: 6202 26000, "buffer size of cbOutput is purposely incorrect");
823-
scError = SymCryptRngAesGenerateSmall( pRngState, abOutput, SYMCRYPT_RNG_AES_MAX_REQUEST_SIZE + 1);
829+
scError = SymCryptRngAesGenerateSmall( pRngState, abOutput, SYMCRYPT_RNG_AES_MAX_REQUEST_SIZE + 1, NULL, 0 );
824830

825831
if( scError == SYMCRYPT_NO_ERROR )
826832
{
@@ -830,7 +836,7 @@ SymCryptRngAesTestGenerate( PSYMCRYPT_RNG_AES_STATE pRngState )
830836
//
831837
// Now test for correct output data.
832838
//
833-
scError = SymCryptRngAesGenerateSmall( pRngState, abOutput, sizeof( g_abOutput1 ) );
839+
scError = SymCryptRngAesGenerateSmall( pRngState, abOutput, sizeof( g_abOutput1 ), NULL, 0 );
834840

835841
SymCryptInjectError( abOutput, sizeof( abOutput ) );
836842

modules_linux/common/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ include_directories(${CMAKE_SOURCE_DIR}/inc)
66

77
add_library(symcrypt_module_linux_common STATIC ${SOURCES})
88

9-
set(jitter_cflags "${CMAKE_C_FLAGS} -fwrapv -fvisibility=hidden")
9+
set(jitter_cflags "${CMAKE_C_FLAGS} -fwrapv -fvisibility=hidden -DCONFIG_CRYPTO_CPU_JITTERENTROPY_SECURE_MEMORY")
1010
set(jitter_ldflags "")
1111

1212
if(SYMCRYPT_TARGET_ARCH MATCHES "X86")
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// rngforkdetection.c
3+
// Defines fork detection functions using getpid system call and a global variable.
4+
//
5+
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
6+
//
7+
8+
#include "precomp.h"
9+
#include <unistd.h>
10+
11+
pid_t g_pid = 0;
12+
13+
// Sets the initial pid
14+
VOID
15+
SYMCRYPT_CALL
16+
SymCryptRngForkDetectionInit()
17+
{
18+
g_pid = getpid();
19+
}
20+
21+
// Returns true if pid has changed since init or last call
22+
BOOLEAN
23+
SYMCRYPT_CALL
24+
SymCryptRngForkDetect()
25+
{
26+
BOOLEAN forkDetected = FALSE;
27+
pid_t currPid = getpid();
28+
29+
if( currPid != g_pid )
30+
{
31+
forkDetected = TRUE;
32+
g_pid = currPid;
33+
}
34+
35+
return forkDetected;
36+
}

0 commit comments

Comments
 (0)