/src/SymCrypt/lib/pbkdf2.c
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // pbkdf2.c |
3 | | // |
4 | | // Copyright (c) Microsoft Corporation. Licensed under the MIT license. |
5 | | // |
6 | | |
7 | | // |
8 | | // This module contains the routines to implement the pbkdf2 function |
9 | | // |
10 | | // |
11 | | |
12 | | #include "precomp.h" |
13 | | |
14 | | SYMCRYPT_ERROR |
15 | | SYMCRYPT_CALL |
16 | | SymCryptPbkdf2Derive( |
17 | | _In_ PCSYMCRYPT_PBKDF2_EXPANDED_KEY pExpandedKey, |
18 | | _In_reads_opt_(cbSalt) PCBYTE pbSalt, |
19 | | SIZE_T cbSalt, |
20 | | UINT64 iterationCnt, |
21 | | _Out_writes_(cbResult) PBYTE pbResult, |
22 | | SIZE_T cbResult) |
23 | 337 | { |
24 | 337 | SYMCRYPT_MAC_STATE macState; |
25 | 337 | UINT32 iBlock; |
26 | 337 | SIZE_T bytes; |
27 | 337 | SIZE_T blockSize = pExpandedKey->macAlg->resultSize; |
28 | 337 | UINT64 iterations; |
29 | 337 | SYMCRYPT_ALIGN BYTE rbBlockResult[SYMCRYPT_MAC_MAX_RESULT_SIZE]; |
30 | 337 | SYMCRYPT_ALIGN BYTE rbWorkBuffer[SYMCRYPT_MAC_MAX_RESULT_SIZE]; |
31 | | |
32 | 337 | SYMCRYPT_ASSERT( |
33 | 337 | blockSize <= SYMCRYPT_MAC_MAX_RESULT_SIZE && |
34 | 337 | cbResult > 0 ); |
35 | | |
36 | 337 | if (iterationCnt == 0) |
37 | 43 | { |
38 | 43 | return SYMCRYPT_WRONG_ITERATION_COUNT; |
39 | 43 | } |
40 | | |
41 | 294 | iBlock = 0; |
42 | 5.14k | while( cbResult > 0 ) |
43 | 4.85k | { |
44 | 4.85k | iBlock += 1; |
45 | 4.85k | SYMCRYPT_STORE_MSBFIRST32( &rbBlockResult[0], iBlock ); // use result buf as temp |
46 | | |
47 | 4.85k | pExpandedKey->macAlg->initFunc ( &macState, &pExpandedKey->macKey); |
48 | 4.85k | pExpandedKey->macAlg->appendFunc( &macState, pbSalt, cbSalt); |
49 | 4.85k | pExpandedKey->macAlg->appendFunc( &macState, &rbBlockResult[0], 4 ); // block count encoded in 4 bytes |
50 | 4.85k | pExpandedKey->macAlg->resultFunc( &macState, rbWorkBuffer); |
51 | | |
52 | 4.85k | #pragma warning(suppress: 22105) |
53 | 4.85k | memcpy( rbBlockResult, rbWorkBuffer, blockSize ); |
54 | 12.5k | for( iterations = 1; iterations < iterationCnt; iterations++ ) |
55 | 7.65k | { |
56 | 7.65k | pExpandedKey->macAlg->initFunc ( &macState, &pExpandedKey->macKey ); |
57 | 7.65k | pExpandedKey->macAlg->appendFunc( &macState, rbWorkBuffer, blockSize ); |
58 | 7.65k | pExpandedKey->macAlg->resultFunc( &macState, rbWorkBuffer ); |
59 | 7.65k | SymCryptXorBytes( &rbWorkBuffer[0], &rbBlockResult[0], &rbBlockResult[0], blockSize ); |
60 | 7.65k | } |
61 | | |
62 | 4.85k | bytes = SYMCRYPT_MIN( cbResult, blockSize ); |
63 | 4.85k | memcpy( pbResult, rbBlockResult, bytes ); |
64 | 4.85k | pbResult += bytes; |
65 | 4.85k | cbResult -= bytes; |
66 | 4.85k | } |
67 | | |
68 | 294 | SymCryptWipeKnownSize( &rbWorkBuffer[0], sizeof( rbWorkBuffer ) ); |
69 | 294 | SymCryptWipeKnownSize( &rbBlockResult[0], sizeof( rbBlockResult ) ); |
70 | 294 | return SYMCRYPT_NO_ERROR; |
71 | 337 | } |
72 | | |
73 | | SYMCRYPT_ERROR |
74 | | SYMCRYPT_CALL |
75 | | SymCryptPbkdf2ExpandKey( |
76 | | _Out_ PSYMCRYPT_PBKDF2_EXPANDED_KEY pExpandedKey, |
77 | | _In_ PCSYMCRYPT_MAC macAlgorithm, |
78 | | _In_reads_(cbKey) PCBYTE pbKey, |
79 | | SIZE_T cbKey ) |
80 | 337 | { |
81 | 337 | SYMCRYPT_ASSERT( macAlgorithm->expandedKeySize <= sizeof( pExpandedKey->macKey ) ); |
82 | | |
83 | 337 | pExpandedKey->macAlg = macAlgorithm; |
84 | 337 | return macAlgorithm->expandKeyFunc(&pExpandedKey->macKey, pbKey, cbKey ); |
85 | 337 | } |
86 | | |
87 | | SYMCRYPT_ERROR |
88 | | SYMCRYPT_CALL |
89 | | SymCryptPbkdf2( |
90 | | PCSYMCRYPT_MAC macAlgorithm, |
91 | | _In_reads_(cbKey) PCBYTE pbKey, |
92 | | SIZE_T cbKey, |
93 | | _In_reads_opt_(cbSalt) PCBYTE pbSalt, |
94 | | SIZE_T cbSalt, |
95 | | UINT64 iterationCnt, |
96 | | _Out_writes_(cbResult) PBYTE pbResult, |
97 | | SIZE_T cbResult) |
98 | 337 | { |
99 | 337 | SYMCRYPT_PBKDF2_EXPANDED_KEY key; |
100 | 337 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
101 | | |
102 | 337 | scError = SymCryptPbkdf2ExpandKey( &key, macAlgorithm, pbKey, cbKey ); |
103 | 337 | if( scError != SYMCRYPT_NO_ERROR ) |
104 | 0 | { |
105 | 0 | goto cleanup; |
106 | 0 | } |
107 | | |
108 | 337 | scError = SymCryptPbkdf2Derive( &key, pbSalt, cbSalt, iterationCnt, pbResult, cbResult ); |
109 | 337 | if( scError != SYMCRYPT_NO_ERROR ) |
110 | 43 | { |
111 | 43 | goto cleanup; |
112 | 43 | } |
113 | | |
114 | 337 | cleanup: |
115 | | |
116 | 337 | SymCryptWipeKnownSize( &key, sizeof( key ) ); |
117 | | |
118 | 337 | return scError; |
119 | | |
120 | 337 | } |
121 | | |
122 | | // |
123 | | // Self tests are in pbkdf_*.c files |
124 | | // to avoid pulling in SHA-1 when only PBKDF-SHA256 is used and |
125 | | // similar scenarios. |
126 | | // |
127 | | |