Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/symcrypt/lib/aescmac.c
15010 views
1
//
2
// aescmac.c Implementation of the AES-CMAC block cipher mode
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
7
#include "precomp.h"
8
9
const SYMCRYPT_MAC SymCryptAesCmacAlgorithm_fast = {
10
SymCryptAesCmacExpandKey,
11
SymCryptAesCmacInit,
12
SymCryptAesCmacAppend,
13
SymCryptAesCmacResult,
14
sizeof(SYMCRYPT_AES_CMAC_EXPANDED_KEY),
15
sizeof(SYMCRYPT_AES_CMAC_STATE),
16
SYMCRYPT_AES_CMAC_RESULT_SIZE,
17
NULL,
18
0,
19
};
20
21
const PCSYMCRYPT_MAC SymCryptAesCmacAlgorithm = &SymCryptAesCmacAlgorithm_fast;
22
23
VOID
24
SYMCRYPT_CALL
25
SymCryptCmacMunge(
26
_Inout_updates_bytes_(SYMCRYPT_AES_BLOCK_SIZE) BYTE buf[SYMCRYPT_AES_BLOCK_SIZE] )
27
{
28
SIZE_T carry = 0;
29
SIZE_T tmp;
30
int i;
31
32
for( i=15; i>=0; i-- )
33
{
34
tmp = buf[i];
35
buf[i] = ((tmp << 1) | carry) & 0xff;
36
carry = tmp >> 7;
37
}
38
39
buf[15] ^= (0 - carry) & 0x87; // This is the R_128 value from SP 800-38B 5.3
40
}
41
42
SYMCRYPT_ERROR
43
SYMCRYPT_CALL
44
SymCryptAesCmacExpandKey(
45
_Out_ PSYMCRYPT_AES_CMAC_EXPANDED_KEY pExpandedKey,
46
_In_reads_(cbKey) PCBYTE pbKey,
47
SIZE_T cbKey )
48
{
49
SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
50
SYMCRYPT_ALIGN BYTE buf[SYMCRYPT_AES_BLOCK_SIZE];
51
52
scError = SymCryptAesExpandKey( &pExpandedKey->aesKey, pbKey, cbKey );
53
if( scError != SYMCRYPT_NO_ERROR )
54
{
55
goto cleanup;
56
}
57
58
SymCryptWipeKnownSize( buf, sizeof( buf ) );
59
60
SymCryptAesEncrypt( &pExpandedKey->aesKey, buf, buf );
61
62
SymCryptCmacMunge( buf );
63
memcpy( &pExpandedKey->K1, buf, sizeof( buf ) );
64
SymCryptCmacMunge( buf );
65
memcpy( &pExpandedKey->K2, buf, sizeof( buf ) );
66
67
SymCryptWipeKnownSize( buf, sizeof( buf ) );
68
69
SYMCRYPT_SET_MAGIC( pExpandedKey );
70
71
cleanup:
72
73
return scError;
74
}
75
76
77
VOID
78
SYMCRYPT_CALL
79
SymCryptAesCmacKeyCopy(
80
_In_ PCSYMCRYPT_AES_CMAC_EXPANDED_KEY pSrc,
81
_Out_ PSYMCRYPT_AES_CMAC_EXPANDED_KEY pDst )
82
{
83
SYMCRYPT_CHECK_MAGIC( pSrc );
84
SymCryptAesKeyCopy( &pSrc->aesKey, &pDst->aesKey );
85
memcpy( pDst->K1, pSrc->K1, sizeof( pDst->K1 ) );
86
memcpy( pDst->K2, pSrc->K2, sizeof( pDst->K2 ) );
87
SYMCRYPT_SET_MAGIC( pDst );
88
}
89
90
91
VOID
92
SYMCRYPT_CALL
93
SymCryptAesCmac(
94
_In_ PSYMCRYPT_AES_CMAC_EXPANDED_KEY pExpandedKey,
95
_In_reads_( cbData ) PCBYTE pbData,
96
SIZE_T cbData,
97
_Out_writes_( SYMCRYPT_AES_CMAC_RESULT_SIZE ) PBYTE pbResult )
98
{
99
SYMCRYPT_AES_CMAC_STATE state;
100
101
SymCryptAesCmacInit( &state, pExpandedKey );
102
SymCryptAesCmacAppend( &state, pbData, cbData );
103
SymCryptAesCmacResult( &state, pbResult );
104
105
SymCryptWipeKnownSize( &state, sizeof( state ) );
106
}
107
108
109
VOID
110
SYMCRYPT_CALL
111
SymCryptAesCmacStateCopy(
112
_In_ PCSYMCRYPT_AES_CMAC_STATE pSrc,
113
_In_opt_ PCSYMCRYPT_AES_CMAC_EXPANDED_KEY pExpandedKey,
114
_Out_ PSYMCRYPT_AES_CMAC_STATE pDst )
115
{
116
SYMCRYPT_CHECK_MAGIC( pSrc );
117
*pDst = *pSrc;
118
119
if( pExpandedKey == NULL )
120
{
121
SYMCRYPT_CHECK_MAGIC( pSrc->pKey );
122
pDst->pKey = pSrc->pKey;
123
}
124
else
125
{
126
SYMCRYPT_CHECK_MAGIC( pExpandedKey );
127
pDst->pKey = pExpandedKey;
128
}
129
130
SYMCRYPT_SET_MAGIC( pDst );
131
}
132
133
VOID
134
SYMCRYPT_CALL
135
SymCryptAesCmacInit(
136
_Out_ PSYMCRYPT_AES_CMAC_STATE pState,
137
_In_ PCSYMCRYPT_AES_CMAC_EXPANDED_KEY pExpandedKey)
138
{
139
SYMCRYPT_CHECK_MAGIC( pExpandedKey );
140
141
pState->bytesInBuf = 0;
142
SymCryptWipeKnownSize( pState->chain, sizeof( pState->chain ) );
143
pState->pKey = pExpandedKey;
144
145
SYMCRYPT_SET_MAGIC( pState );
146
}
147
148
VOID
149
SYMCRYPT_CALL
150
SymCryptAesCmacAppend(
151
_Inout_ PSYMCRYPT_AES_CMAC_STATE pState,
152
_In_reads_( cbData ) PCBYTE pbData,
153
SIZE_T cbData )
154
{
155
156
SYMCRYPT_CHECK_MAGIC( pState );
157
158
if( pState->bytesInBuf != 0 )
159
{
160
SIZE_T freeInBuf = SYMCRYPT_AES_BLOCK_SIZE - pState->bytesInBuf;
161
SYMCRYPT_ASSERT( freeInBuf < SYMCRYPT_AES_BLOCK_SIZE );
162
163
if( cbData <= freeInBuf )
164
{
165
// Do nothing.
166
// the data will be copied into the buf at the end of this function
167
//
168
}
169
else
170
{
171
memcpy( &pState->buf[pState->bytesInBuf], pbData, freeInBuf );
172
pbData += freeInBuf;
173
cbData -= freeInBuf;
174
SymCryptAesCbcMac( &pState->pKey->aesKey, &pState->chain[0], &pState->buf[0], SYMCRYPT_AES_BLOCK_SIZE );
175
pState->bytesInBuf = 0;
176
}
177
}
178
179
//
180
// At this point, either pState->bytesInBuf == 0, or it is !=0 but cbData is small enough that all the
181
// data will still fit in the buffer without further processing.
182
//
183
184
if( cbData > SYMCRYPT_AES_BLOCK_SIZE )
185
{
186
SIZE_T bytesToDo = (cbData-1) & ~(SIZE_T)(SYMCRYPT_AES_BLOCK_SIZE - 1);
187
SymCryptAesCbcMac( &pState->pKey->aesKey, &pState->chain[0], pbData, bytesToDo );
188
pbData += bytesToDo;
189
cbData -= bytesToDo;
190
}
191
192
if( cbData > 0 )
193
{
194
memcpy( &pState->buf[pState->bytesInBuf], pbData, cbData );
195
pState->bytesInBuf += cbData;
196
}
197
}
198
199
200
VOID
201
SYMCRYPT_CALL
202
SymCryptAesCmacResult(
203
_Inout_ PSYMCRYPT_AES_CMAC_STATE pState,
204
_Out_writes_( SYMCRYPT_AES_CMAC_RESULT_SIZE ) PBYTE pbResult )
205
{
206
SYMCRYPT_CHECK_MAGIC( pState );
207
208
if( pState->bytesInBuf < SYMCRYPT_AES_BLOCK_SIZE )
209
{
210
SymCryptWipe( &pState->buf[pState->bytesInBuf + 1], SYMCRYPT_AES_BLOCK_SIZE - pState->bytesInBuf - 1 );
211
pState->buf[pState->bytesInBuf] = 0x80;
212
SymCryptXorBytes( &pState->buf[0], &pState->pKey->K2[0], &pState->buf[0], SYMCRYPT_AES_BLOCK_SIZE );
213
}
214
else
215
{
216
SymCryptXorBytes( &pState->buf[0], &pState->pKey->K1[0], &pState->buf[0], SYMCRYPT_AES_BLOCK_SIZE );
217
}
218
219
SymCryptAesCbcMac( &pState->pKey->aesKey, &pState->chain[0], &pState->buf[0], SYMCRYPT_AES_BLOCK_SIZE );
220
memcpy( pbResult, &pState->chain[0], SYMCRYPT_AES_BLOCK_SIZE );
221
222
//
223
// Put the state back in the original starting state,
224
// and wipe any traces of the data.
225
//
226
pState->bytesInBuf = 0;
227
SymCryptWipeKnownSize( pState->chain, sizeof( pState->chain ) );
228
SymCryptWipeKnownSize( pState->buf, sizeof( pState->buf ) );
229
}
230
231
232
233
static const BYTE aesCmacKat[SYMCRYPT_AES_CMAC_RESULT_SIZE] = {
234
0x0a, 0x54, 0xa6, 0xa4, 0x25, 0xd4, 0x84, 0x38, 0xc3, 0xf8, 0xbb, 0xe0, 0x9b, 0xf9, 0x44, 0xcc,
235
};
236
237
238
VOID
239
SYMCRYPT_CALL
240
SymCryptAesCmacSelftest(void)
241
{
242
SYMCRYPT_AES_CMAC_EXPANDED_KEY xKey;
243
BYTE res[SYMCRYPT_AES_CMAC_RESULT_SIZE];
244
245
SymCryptAesCmacExpandKey( &xKey, SymCryptTestKey32, 16 );
246
SymCryptAesCmac( &xKey, SymCryptTestMsg3, sizeof( SymCryptTestMsg3 ), res );
247
248
SymCryptInjectError( res, sizeof( res ) );
249
if( memcmp( res, aesCmacKat, sizeof( res ) ) != 0 )
250
{
251
SymCryptFatal( 'hsh5' );
252
}
253
254
//
255
// Normally we would wipe the expanded key structure here,
256
// but as this is a selftest with known data this is not needed.
257
//
258
}
259
260