Skip to content

Commit 674f8cd

Browse files
committed
Fix various issues in the MAC code.
- Fix a bunch of compilation issues uncovered when specifying either --disable-hmac or --disable-cmac. - Circle back on the HMAC edge cases: in the case that the key length is less than the block size of the underlying hash algorithm, we need to pad the key with zeroes. Previously, I had solved this by always allocating a buffer of zeroes for the key that was as large as the largest hash block size. Then, we'd copy the key bytes to that buffer. Then, before we called wc_HmacSetKey, I'd check the key size and set it to the block size if it was less than the block size. This would effectively 0-pad the key to the block size. However, this doesn't account for the fact that the key can be larger than the largest hash block size. In that case, we could overrun the buffer. So, the buffer has to be dynamically allocated. wc_HmacSetKey will handle hashing the key down to the block size if needed. - Add HMAC test cases that use 1) a key of length 0 and 2) a key of length greater than the block size of the hash algo.
1 parent 6bfb522 commit 674f8cd

File tree

3 files changed

+105
-141
lines changed

3 files changed

+105
-141
lines changed

include/wolfengine/we_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ int we_init_hmac_pkey_asn1_meth(void);
227227
* CMAC methods.
228228
*/
229229

230-
#ifdef WE_HAVE_HMAC
230+
#ifdef WE_HAVE_CMAC
231231

232232
#define NID_wolfengine_cmac 101
233233
extern EVP_PKEY_METHOD *we_cmac_pkey_method;

src/we_mac.c

Lines changed: 81 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,57 @@ typedef struct we_Mac
6565
int type;
6666
} we_Mac;
6767

68-
static int we_hmac_reset_key(we_Mac *mac);
69-
static int we_cmac_reset_key(we_Mac *mac, size_t newSize);
68+
/**
69+
* Clear out the existing MAC key in mac and allocate a new key buffer of
70+
* newKeySz bytes. Copy newKey into that buffer.
71+
*
72+
* @param mac [in] Internal MAC object.
73+
* @param newKey [in] New key buffer.
74+
* @param newKeySz [in] New key buffer size.
75+
* @returns 1 on success and 0 on failure.
76+
*/
77+
static int we_mac_set_key(we_Mac* mac, const unsigned char* newKey,
78+
int newKeySz)
79+
{
80+
int ret = 1;
81+
82+
WOLFENGINE_ENTER(WE_LOG_MAC, "we_mac_set_key");
83+
84+
if (mac == NULL) {
85+
WOLFENGINE_ERROR_MSG(WE_LOG_MAC, "we_mac_set_key called with NULL "
86+
"mac");
87+
ret = 0;
88+
}
89+
if (newKeySz < 0) {
90+
WOLFENGINE_ERROR_MSG(WE_LOG_MAC, "we_mac_set_key called with newKeySz "
91+
"< 0");
92+
ret = 0;
93+
}
94+
95+
if (ret == 1) {
96+
/* Dispose of old key. */
97+
if (mac->key != NULL) {
98+
OPENSSL_clear_free(mac->key, mac->keySz);
99+
}
100+
/* We allow the key size to be 0, which OpenSSL also allows. In that
101+
* case, we need to allocate at least one byte, which we'll set to a
102+
* null terminator. */
103+
mac->key = (unsigned char *)OPENSSL_malloc(newKeySz + 1);
104+
if (mac->key == NULL) {
105+
WOLFENGINE_ERROR_FUNC_NULL(WE_LOG_MAC, "OPENSSL_malloc", mac->key);
106+
ret = 0;
107+
}
108+
else {
109+
XMEMCPY(mac->key, newKey, newKeySz);
110+
mac->key[newKeySz] = '\0';
111+
mac->keySz = newKeySz;
112+
}
113+
}
114+
115+
WOLFENGINE_LEAVE(WE_LOG_MAC, "we_mac_set_key", ret);
116+
117+
return ret;
118+
}
70119

71120
/**
72121
* Create ASN.1 octet string from key in context.
@@ -166,6 +215,7 @@ static int we_mac_cache_key(EVP_PKEY_CTX *ctx, we_Mac *mac)
166215
int ret = 1;
167216
ASN1_OCTET_STRING *key;
168217
EVP_PKEY *pkey;
218+
int dataLen;
169219
const unsigned char *data;
170220

171221
WOLFENGINE_ENTER(WE_LOG_MAC, "we_mac_cache_key");
@@ -193,26 +243,14 @@ static int we_mac_cache_key(EVP_PKEY_CTX *ctx, we_Mac *mac)
193243

194244
if (ret == 1) {
195245
/* Get key length and data. */
196-
mac->keySz = ASN1_STRING_length(key);
197-
data = ASN1_STRING_get0_data(key);
198-
if (data == NULL || mac->keySz < 0) {
246+
dataLen = ASN1_STRING_length(key);
247+
data = ASN1_STRING_get0_data(key);
248+
if (data == NULL || dataLen < 0) {
199249
ret = 0;
200250
}
201251
}
202252
if (ret == 1) {
203-
if (mac->algo == WE_HMAC_ALGO) {
204-
ret = we_hmac_reset_key(mac);
205-
}
206-
else if (mac->algo == WE_CMAC_ALGO) {
207-
ret = we_cmac_reset_key(mac, mac->keySz);
208-
}
209-
else {
210-
ret = 0;
211-
}
212-
}
213-
if (ret == 1) {
214-
/* Copy key data into cache. */
215-
XMEMCPY(mac->key, data, mac->keySz);
253+
ret = we_mac_set_key(mac, data, dataLen);
216254
}
217255

218256
WOLFENGINE_LEAVE(WE_LOG_MAC, "we_mac_cache_key", ret);
@@ -221,41 +259,6 @@ static int we_mac_cache_key(EVP_PKEY_CTX *ctx, we_Mac *mac)
221259
}
222260

223261
#ifdef WE_HAVE_HMAC
224-
/**
225-
* Clear out the existing HMAC key in mac and allocate a new key buffer large
226-
* enough to hold any hash block size (i.e. the largest supported block size,
227-
* WC_SHA3_224_BLOCK_SIZE). This is required because this function may be called
228-
* before the hash type is known. Set buffer to zeros.
229-
*
230-
* @param mac [in] Internal MAC object.
231-
* @returns 1 on success and 0 on failure.
232-
*/
233-
static int we_hmac_reset_key(we_Mac *mac)
234-
{
235-
int ret = 1;
236-
237-
WOLFENGINE_ENTER(WE_LOG_MAC, "we_hmac_reset_key");
238-
239-
if (mac == NULL) {
240-
WOLFENGINE_ERROR_FUNC_NULL(WE_LOG_MAC, "we_hmac_reset_key", mac);
241-
ret = 0;
242-
}
243-
244-
if (ret == 1) {
245-
/* Dispose of old key. */
246-
if (mac->key != NULL) {
247-
OPENSSL_clear_free(mac->key, mac->keySz);
248-
}
249-
mac->key = (unsigned char *)OPENSSL_zalloc(WC_SHA3_224_BLOCK_SIZE);
250-
if (mac->key == NULL) {
251-
ret = 0;
252-
}
253-
}
254-
255-
WOLFENGINE_LEAVE(WE_LOG_MAC, "we_hmac_reset_key", ret);
256-
257-
return ret;
258-
}
259262

260263
/**
261264
* Initialize the MAC for HMAC operations.
@@ -282,63 +285,38 @@ static int we_mac_hmac_init(EVP_PKEY_CTX *ctx, we_Mac *mac)
282285
WOLFENGINE_ERROR_FUNC(WE_LOG_MAC, "wc_HashGetBlockSize", blockSize);
283286
ret = 0;
284287
}
285-
if (ret == 1) {
288+
}
289+
if (ret == 1 && mac->keySz < blockSize) {
290+
/* If the key is smaller than the block size of the underlying hash
291+
* algorithm, we need to pad the key with zeroes to the block
292+
* size. */
293+
mac->key = OPENSSL_realloc(mac->key, blockSize);
294+
if (mac->key == NULL) {
295+
WOLFENGINE_ERROR_FUNC_NULL(WE_LOG_MAC, "OPENSSL_realloc",
296+
mac->key);
297+
ret = 0;
298+
}
299+
else {
300+
XMEMSET(mac->key + mac->keySz, 0, blockSize - mac->keySz);
286301
mac->keySz = blockSize;
287-
rc = wc_HmacSetKey(&mac->state.hmac, mac->type,
288-
(const byte*)mac->key, (word32)mac->keySz);
289-
if (rc != 0) {
290-
WOLFENGINE_ERROR_FUNC(WE_LOG_MAC, "wc_HmacSetKey", rc);
291-
ret = 0;
292-
}
293302
}
294303
}
295-
296-
WOLFENGINE_LEAVE(WE_LOG_MAC, "we_mac_hmac_init", ret);
297-
298-
return ret;
299-
}
300-
#endif
301-
302-
#ifdef WE_HAVE_CMAC
303-
/**
304-
* Clear out the existing CMAC key in mac and allocate a new key buffer of
305-
* newSize bytes. Set buffer to zeros.
306-
*
307-
* @param mac [in] Internal MAC object.
308-
* @returns 1 on success and 0 on failure.
309-
*/
310-
static int we_cmac_reset_key(we_Mac *mac, size_t newSize)
311-
{
312-
int ret = 1;
313-
314-
WOLFENGINE_ENTER(WE_LOG_MAC, "we_cmac_reset_key");
315-
316-
if (mac == NULL) {
317-
WOLFENGINE_ERROR_MSG(WE_LOG_MAC, "we_cmac_reset_key called with NULL "
318-
"mac");
319-
ret = 0;
320-
}
321-
if (ret == 1 && newSize <= 0) {
322-
WOLFENGINE_ERROR_MSG(WE_LOG_MAC, "we_cmac_reset_key called with "
323-
"newSize <= 0");
324-
ret = 0;
325-
}
326-
327304
if (ret == 1) {
328-
/* Dispose of old key. */
329-
if (mac->key != NULL) {
330-
OPENSSL_clear_free(mac->key, mac->keySz);
331-
}
332-
mac->key = (unsigned char *)OPENSSL_zalloc(newSize);
333-
if (mac->key == NULL) {
305+
rc = wc_HmacSetKey(&mac->state.hmac, mac->type,
306+
(const byte*)mac->key, (word32)mac->keySz);
307+
if (rc != 0) {
308+
WOLFENGINE_ERROR_FUNC(WE_LOG_MAC, "wc_HmacSetKey", rc);
334309
ret = 0;
335310
}
336311
}
337312

338-
WOLFENGINE_LEAVE(WE_LOG_MAC, "we_cmac_reset_key", ret);
313+
WOLFENGINE_LEAVE(WE_LOG_MAC, "we_mac_hmac_init", ret);
339314

340315
return ret;
341316
}
317+
#endif
318+
319+
#ifdef WE_HAVE_CMAC
342320

343321
/**
344322
* Initialize the MAC for CMAC operations.
@@ -375,6 +353,7 @@ static int we_mac_cmac_init(EVP_PKEY_CTX *ctx, we_Mac *mac)
375353
}
376354
#endif
377355

356+
#ifdef WE_HAVE_HMAC
378357
/**
379358
* Convert an EVP_MD to a hash type that wolfSSL understands.
380359
*
@@ -395,7 +374,7 @@ static int we_mac_md_to_hash_type(EVP_MD *md)
395374

396375
return ret;
397376
}
398-
377+
#endif
399378

400379
/**
401380
* Function that is called for setting key, EVP_MD, and digest init.
@@ -486,20 +465,7 @@ static int we_mac_pkey_ctrl(EVP_PKEY_CTX *ctx, int type, int num, void *ptr)
486465
*/
487466
WOLFENGINE_MSG(WE_LOG_MAC, "type: EVP_PKEY_CTRL_SET_MAC_KEY");
488467
if (ptr != NULL && num >= 0) {
489-
if (mac->algo == WE_HMAC_ALGO) {
490-
ret = we_hmac_reset_key(mac);
491-
}
492-
else if (mac->algo == WE_CMAC_ALGO) {
493-
ret = we_cmac_reset_key(mac, num);
494-
}
495-
else {
496-
ret = 0;
497-
}
498-
if (ret == 1) {
499-
/* Copy in key data and store size. */
500-
XMEMCPY(mac->key, ptr, num);
501-
mac->keySz = num;
502-
}
468+
ret = we_mac_set_key(mac, ptr, num);
503469
}
504470
else {
505471
ret = 0;
@@ -612,19 +578,7 @@ static int we_mac_dup(we_Mac *src, we_Mac **dst)
612578
mac->keySz = src->keySz;
613579
/* Duplicate the key if set. */
614580
if (src->keySz >= 0) {
615-
if (mac->algo == WE_HMAC_ALGO) {
616-
ret = we_hmac_reset_key(mac);
617-
}
618-
else if (mac->algo == WE_CMAC_ALGO) {
619-
ret = we_cmac_reset_key(mac, mac->keySz);
620-
}
621-
else {
622-
ret = 0;
623-
}
624-
if (ret == 1) {
625-
/* Copy over key bytes. */
626-
XMEMCPY(mac->key, src->key, src->keySz);
627-
}
581+
ret = we_mac_set_key(mac, src->key, src->keySz);
628582
}
629583
else {
630584
mac->key = NULL;

test/test_hmac.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,10 @@ static int test_mac_generation(ENGINE *e, const EVP_MD *md, int pkeyType,
6262
}
6363

6464

65-
static int test_hmac_create_helper(ENGINE *e, void *data, const EVP_MD *md)
65+
static int test_hmac_create_helper(ENGINE *e, void *data, const EVP_MD *md,
66+
unsigned char* pswd, int pswdSz)
6667
{
6768
int ret;
68-
unsigned char pswd[] = "My empire of dirt";
69-
int pswdSz;
7069

7170
unsigned char exp[128];
7271
int expLen;
@@ -81,7 +80,6 @@ static int test_hmac_create_helper(ENGINE *e, void *data, const EVP_MD *md)
8180
len = sizeof(msg);
8281
macLen = sizeof(mac);
8382
expLen = sizeof(exp);
84-
pswdSz = (int)strlen((const char*)pswd);
8583

8684
/* generate mac using OpenSSL */
8785
ret = test_mac_generation(NULL, md, EVP_PKEY_HMAC, pswd, pswdSz, msg,
@@ -118,52 +116,64 @@ static int test_hmac_create_helper(ENGINE *e, void *data, const EVP_MD *md)
118116
int test_hmac_create(ENGINE *e, void *data)
119117
{
120118
int ret = 0;
119+
unsigned char pswd[] = "My empire of dirt";
120+
unsigned char bigPswd[100];
121121

122122
PRINT_MSG("Testing with SHA1");
123-
ret = test_hmac_create_helper(e, data, EVP_sha1());
123+
ret = test_hmac_create_helper(e, data, EVP_sha1(), pswd, sizeof(pswd));
124+
if (ret == 0) {
125+
PRINT_MSG("Testing with SHA1, 0 length key");
126+
ret = test_hmac_create_helper(e, data, EVP_sha1(), pswd, 0);
127+
}
128+
if (ret == 0) {
129+
PRINT_MSG("Testing with SHA1, key length larger than block size");
130+
RAND_bytes(bigPswd, sizeof(bigPswd));
131+
ret = test_hmac_create_helper(e, data, EVP_sha1(), bigPswd,
132+
sizeof(bigPswd));
133+
}
124134

125135
if (ret == 0) {
126136
PRINT_MSG("Testing with SHA224");
127-
ret = test_hmac_create_helper(e, data, EVP_sha224());
137+
ret = test_hmac_create_helper(e, data, EVP_sha224(), pswd, sizeof(pswd));
128138
}
129139

130140
if (ret == 0) {
131141
PRINT_MSG("Testing with SHA256");
132-
ret = test_hmac_create_helper(e, data, EVP_sha256());
142+
ret = test_hmac_create_helper(e, data, EVP_sha256(), pswd, sizeof(pswd));
133143
}
134144

135145
if (ret == 0) {
136146
PRINT_MSG("Testing with SHA384");
137-
ret = test_hmac_create_helper(e, data, EVP_sha384());
147+
ret = test_hmac_create_helper(e, data, EVP_sha384(), pswd, sizeof(pswd));
138148
}
139149

140150
if (ret == 0) {
141151
PRINT_MSG("Testing with SHA512");
142-
ret = test_hmac_create_helper(e, data, EVP_sha512());
152+
ret = test_hmac_create_helper(e, data, EVP_sha512(), pswd, sizeof(pswd));
143153
}
144154

145155
#ifdef WE_HAVE_SHA3_224
146156
if (ret == 0) {
147157
PRINT_MSG("Testing with SHA3-224");
148-
ret = test_hmac_create_helper(e, data, EVP_sha3_224());
158+
ret = test_hmac_create_helper(e, data, EVP_sha3_224(), pswd, sizeof(pswd));
149159
}
150160
#endif
151161
#ifdef WE_HAVE_SHA3_256
152162
if (ret == 0) {
153163
PRINT_MSG("Testing with SHA3-256");
154-
ret = test_hmac_create_helper(e, data, EVP_sha3_256());
164+
ret = test_hmac_create_helper(e, data, EVP_sha3_256(), pswd, sizeof(pswd));
155165
}
156166
#endif
157167
#ifdef WE_HAVE_SHA3_384
158168
if (ret == 0) {
159169
PRINT_MSG("Testing with SHA3-384");
160-
ret = test_hmac_create_helper(e, data, EVP_sha3_384());
170+
ret = test_hmac_create_helper(e, data, EVP_sha3_384(), pswd, sizeof(pswd));
161171
}
162172
#endif
163173
#ifdef WE_HAVE_SHA3_512
164174
if (ret == 0) {
165175
PRINT_MSG("Testing with SHA3-512");
166-
ret = test_hmac_create_helper(e, data, EVP_sha3_512());
176+
ret = test_hmac_create_helper(e, data, EVP_sha3_512(), pswd, sizeof(pswd));
167177
}
168178
#endif
169179
return ret;

0 commit comments

Comments
 (0)