1 /* 2 * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 /* 11 * HMAC low level APIs are deprecated for public use, but still ok for internal 12 * use. 13 */ 14 #include "internal/deprecated.h" 15 16 #include <stdio.h> 17 #include <string.h> 18 #include <stdlib.h> 19 20 #include "internal/nelem.h" 21 22 # include <openssl/hmac.h> 23 # include <openssl/sha.h> 24 # ifndef OPENSSL_NO_MD5 25 # include <openssl/md5.h> 26 # endif 27 28 # ifdef CHARSET_EBCDIC 29 # include <openssl/ebcdic.h> 30 # endif 31 32 #include "testutil.h" 33 34 # ifndef OPENSSL_NO_MD5 35 static struct test_st { 36 const char key[16]; 37 int key_len; 38 const unsigned char data[64]; 39 int data_len; 40 const char *digest; 41 } test[8] = { 42 { 43 "", 0, "More text test vectors to stuff up EBCDIC machines :-)", 54, 44 "e9139d1e6ee064ef8cf514fc7dc83e86", 45 }, 46 { 47 "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 48 16, "Hi There", 8, 49 "9294727a3638bb1c13f48ef8158bfc9d", 50 }, 51 { 52 "Jefe", 4, "what do ya want for nothing?", 28, 53 "750c783e6ab0b503eaa86e310a5db738", 54 }, 55 { 56 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 57 16, { 58 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 59 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 60 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 61 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 62 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd 63 }, 50, "56be34521d144c88dbb8c733f0e8b3f6", 64 }, 65 { 66 "", 0, "My test data", 12, 67 "61afdecb95429ef494d61fdee15990cabf0826fc" 68 }, 69 { 70 "", 0, "My test data", 12, 71 "2274b195d90ce8e03406f4b526a47e0787a88a65479938f1a5baa3ce0f079776" 72 }, 73 { 74 "123456", 6, "My test data", 12, 75 "bab53058ae861a7f191abe2d0145cbb123776a6369ee3f9d79ce455667e411dd" 76 }, 77 { 78 "12345", 5, "My test data again", 18, 79 "a12396ceddd2a85f4c656bc1e0aa50c78cffde3e" 80 } 81 }; 82 # endif 83 84 static char *pt(unsigned char *md, unsigned int len); 85 86 87 # ifndef OPENSSL_NO_MD5 88 static int test_hmac_md5(int idx) 89 { 90 char *p; 91 # ifdef CHARSET_EBCDIC 92 ebcdic2ascii(test[0].data, test[0].data, test[0].data_len); 93 ebcdic2ascii(test[1].data, test[1].data, test[1].data_len); 94 ebcdic2ascii(test[2].key, test[2].key, test[2].key_len); 95 ebcdic2ascii(test[2].data, test[2].data, test[2].data_len); 96 # endif 97 98 p = pt(HMAC(EVP_md5(), 99 test[idx].key, test[idx].key_len, 100 test[idx].data, test[idx].data_len, NULL, NULL), 101 MD5_DIGEST_LENGTH); 102 103 return TEST_ptr(p) && TEST_str_eq(p, test[idx].digest); 104 } 105 # endif 106 107 static int test_hmac_bad(void) 108 { 109 HMAC_CTX *ctx = NULL; 110 int ret = 0; 111 112 ctx = HMAC_CTX_new(); 113 if (!TEST_ptr(ctx) 114 || !TEST_ptr_null(HMAC_CTX_get_md(ctx)) 115 || !TEST_false(HMAC_Init_ex(ctx, NULL, 0, NULL, NULL)) 116 || !TEST_false(HMAC_Update(ctx, test[4].data, test[4].data_len)) 117 || !TEST_false(HMAC_Init_ex(ctx, NULL, 0, EVP_sha1(), NULL)) 118 || !TEST_false(HMAC_Update(ctx, test[4].data, test[4].data_len))) 119 goto err; 120 121 ret = 1; 122 err: 123 HMAC_CTX_free(ctx); 124 return ret; 125 } 126 127 static int test_hmac_run(void) 128 { 129 char *p; 130 HMAC_CTX *ctx = NULL; 131 unsigned char buf[EVP_MAX_MD_SIZE]; 132 unsigned int len; 133 int ret = 0; 134 135 if (!TEST_ptr(ctx = HMAC_CTX_new())) 136 return 0; 137 HMAC_CTX_reset(ctx); 138 139 if (!TEST_ptr(ctx) 140 || !TEST_ptr_null(HMAC_CTX_get_md(ctx)) 141 || !TEST_false(HMAC_Init_ex(ctx, NULL, 0, NULL, NULL)) 142 || !TEST_false(HMAC_Update(ctx, test[4].data, test[4].data_len)) 143 || !TEST_false(HMAC_Init_ex(ctx, test[4].key, -1, EVP_sha1(), NULL))) 144 goto err; 145 146 if (!TEST_true(HMAC_Init_ex(ctx, test[4].key, test[4].key_len, EVP_sha1(), NULL)) 147 || !TEST_true(HMAC_Update(ctx, test[4].data, test[4].data_len)) 148 || !TEST_true(HMAC_Final(ctx, buf, &len))) 149 goto err; 150 151 p = pt(buf, len); 152 if (!TEST_ptr(p) || !TEST_str_eq(p, test[4].digest)) 153 goto err; 154 155 if (!TEST_false(HMAC_Init_ex(ctx, NULL, 0, EVP_sha256(), NULL))) 156 goto err; 157 158 if (!TEST_true(HMAC_Init_ex(ctx, test[5].key, test[5].key_len, EVP_sha256(), NULL)) 159 || !TEST_ptr_eq(HMAC_CTX_get_md(ctx), EVP_sha256()) 160 || !TEST_true(HMAC_Update(ctx, test[5].data, test[5].data_len)) 161 || !TEST_true(HMAC_Final(ctx, buf, &len))) 162 goto err; 163 164 p = pt(buf, len); 165 if (!TEST_ptr(p) || !TEST_str_eq(p, test[5].digest)) 166 goto err; 167 168 if (!TEST_true(HMAC_Init_ex(ctx, test[6].key, test[6].key_len, NULL, NULL)) 169 || !TEST_true(HMAC_Update(ctx, test[6].data, test[6].data_len)) 170 || !TEST_true(HMAC_Final(ctx, buf, &len))) 171 goto err; 172 p = pt(buf, len); 173 if (!TEST_ptr(p) || !TEST_str_eq(p, test[6].digest)) 174 goto err; 175 176 /* Test reusing a key */ 177 if (!TEST_true(HMAC_Init_ex(ctx, NULL, 0, NULL, NULL)) 178 || !TEST_true(HMAC_Update(ctx, test[6].data, test[6].data_len)) 179 || !TEST_true(HMAC_Final(ctx, buf, &len))) 180 goto err; 181 p = pt(buf, len); 182 if (!TEST_ptr(p) || !TEST_str_eq(p, test[6].digest)) 183 goto err; 184 185 /* 186 * Test reusing a key where the digest is provided again but is the same as 187 * last time 188 */ 189 if (!TEST_true(HMAC_Init_ex(ctx, NULL, 0, EVP_sha256(), NULL)) 190 || !TEST_true(HMAC_Update(ctx, test[6].data, test[6].data_len)) 191 || !TEST_true(HMAC_Final(ctx, buf, &len))) 192 goto err; 193 p = pt(buf, len); 194 if (!TEST_ptr(p) || !TEST_str_eq(p, test[6].digest)) 195 goto err; 196 197 ret = 1; 198 err: 199 HMAC_CTX_free(ctx); 200 return ret; 201 } 202 203 204 static int test_hmac_single_shot(void) 205 { 206 char *p; 207 208 /* Test single-shot with NULL key. */ 209 p = pt(HMAC(EVP_sha1(), NULL, 0, test[4].data, test[4].data_len, 210 NULL, NULL), SHA_DIGEST_LENGTH); 211 if (!TEST_ptr(p) || !TEST_str_eq(p, test[4].digest)) 212 return 0; 213 214 return 1; 215 } 216 217 /* https://github.com/openssl/openssl/issues/13210 */ 218 static int test_hmac_final_update_fail(void) 219 { 220 HMAC_CTX *ctx = NULL; 221 unsigned char buf[EVP_MAX_MD_SIZE]; 222 unsigned int len; 223 int ret = 0; 224 225 /* HMAC_Update() after HMAC_Final() must return an error. */ 226 if (!TEST_ptr(ctx = HMAC_CTX_new())) 227 goto err; 228 if (!TEST_true(HMAC_Init_ex(ctx, test[5].key, test[5].key_len, EVP_sha256(), NULL)) 229 || !TEST_true(HMAC_Update(ctx, test[5].data, test[5].data_len)) 230 || !TEST_true(HMAC_Final(ctx, buf, &len)) 231 || !TEST_false(HMAC_Update(ctx, test[5].data, test[5].data_len)) 232 || !TEST_false(HMAC_Final(ctx, buf, &len))) 233 goto err; 234 235 ret = 1; 236 err: 237 HMAC_CTX_free(ctx); 238 return ret; 239 } 240 241 static int test_hmac_copy(void) 242 { 243 char *p; 244 HMAC_CTX *ctx = NULL, *ctx2 = NULL; 245 unsigned char buf[EVP_MAX_MD_SIZE]; 246 unsigned int len; 247 int ret = 0; 248 249 ctx = HMAC_CTX_new(); 250 ctx2 = HMAC_CTX_new(); 251 if (!TEST_ptr(ctx) || !TEST_ptr(ctx2)) 252 goto err; 253 254 if (!TEST_true(HMAC_Init_ex(ctx, test[7].key, test[7].key_len, EVP_sha1(), NULL)) 255 || !TEST_true(HMAC_Update(ctx, test[7].data, test[7].data_len)) 256 || !TEST_true(HMAC_CTX_copy(ctx2, ctx)) 257 || !TEST_true(HMAC_Final(ctx2, buf, &len))) 258 goto err; 259 260 p = pt(buf, len); 261 if (!TEST_ptr(p) || !TEST_str_eq(p, test[7].digest)) 262 goto err; 263 264 ret = 1; 265 err: 266 HMAC_CTX_free(ctx2); 267 HMAC_CTX_free(ctx); 268 return ret; 269 } 270 271 static int test_hmac_copy_uninited(void) 272 { 273 const unsigned char key[24] = {0}; 274 const unsigned char ct[166] = {0}; 275 EVP_PKEY *pkey = NULL; 276 EVP_MD_CTX *ctx = NULL; 277 EVP_MD_CTX *ctx_tmp = NULL; 278 int res = 0; 279 280 if (!TEST_ptr(ctx = EVP_MD_CTX_new()) 281 || !TEST_ptr(pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, 282 key, sizeof(key))) 283 || !TEST_true(EVP_DigestSignInit(ctx, NULL, EVP_sha1(), NULL, pkey)) 284 || !TEST_ptr(ctx_tmp = EVP_MD_CTX_new()) 285 || !TEST_true(EVP_MD_CTX_copy(ctx_tmp, ctx))) 286 goto err; 287 EVP_MD_CTX_free(ctx); 288 ctx = ctx_tmp; 289 ctx_tmp = NULL; 290 291 if (!TEST_true(EVP_DigestSignUpdate(ctx, ct, sizeof(ct)))) 292 goto err; 293 res = 1; 294 err: 295 EVP_MD_CTX_free(ctx); 296 EVP_MD_CTX_free(ctx_tmp); 297 EVP_PKEY_free(pkey); 298 return res; 299 } 300 301 #ifndef OPENSSL_NO_MD5 302 # define OSSL_HEX_CHARS_PER_BYTE 2 303 static char *pt(unsigned char *md, unsigned int len) 304 { 305 unsigned int i; 306 static char buf[201]; 307 308 if (md == NULL) 309 return NULL; 310 for (i = 0; i < len && (i + 1) * OSSL_HEX_CHARS_PER_BYTE < sizeof(buf); i++) 311 BIO_snprintf(buf + i * OSSL_HEX_CHARS_PER_BYTE, 312 OSSL_HEX_CHARS_PER_BYTE + 1, "%02x", md[i]); 313 return buf; 314 } 315 #endif 316 317 static struct test_chunks_st { 318 const char *md_name; 319 char key[256]; 320 int key_len; 321 int chunks; 322 int chunk_size[10]; 323 const char *digest; 324 } test_chunks[12] = { 325 { 326 "SHA224", 327 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 64, 328 4, { 1, 50, 200, 4000 }, 329 "40821a39dd54f01443b3f96b9370a15023fbdd819a074ffc4b703c77" 330 }, 331 { 332 "SHA224", 333 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 334 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 335 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 192, 336 10, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 337 "55ffa85e53e9a68f41c8d653c60b4ada9566d22aed3811834882661c" 338 }, 339 { 340 "SHA224", "0123456789abcdef0123456789abcdef", 32, 341 4, { 100, 4096, 100, 3896 }, 342 "0fd18e7d8e974f401b29bf0502a71f6a9b77804e9191380ce9f48377" 343 }, 344 { 345 "SHA256", 346 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 64, 347 4, { 1, 50, 200, 4000 }, 348 "f67a46fa77c66d3ea5b3ffb9a10afb3e501eaadd16b15978fdee9f014a782140" 349 }, 350 { 351 "SHA256", 352 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 353 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 354 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 192, 355 10, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 356 "21a6f61ed6dbec30b58557a80988ff610d69b50b2e96d75863ab50f99da58c9d" 357 }, 358 { 359 "SHA256", "0123456789abcdef0123456789abcdef", 32, 360 4, { 100, 4096, 100, 3896 }, 361 "7bfd45c1bdde9b79244816b0aea0a67ea954a182e74c60410bfbc1fdc4842660" 362 }, 363 { 364 "SHA384", 365 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 64, 366 4, { 1, 50, 200, 4000 }, 367 "e270e3c8ca3f2796a0c29cc7569fcec7584b04db26da64326aca0d17bd7731de" 368 "938694b273f3dafe6e2dc123cde26640" 369 }, 370 { 371 "SHA384", 372 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 373 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 374 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 192, 375 10, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 376 "7036fd7d251298975acd18938471243e92fffe67be158f16c910c400576592d2" 377 "618c3c077ef25d703312668bd2d813ff" 378 }, 379 { 380 "SHA384", "0123456789abcdef0123456789abcdef", 32, 381 4, { 100, 8192, 100, 8092 }, 382 "0af8224145bd0812d2e34ba1f980ed4d218461271a54cce75dc43d36eda01e4e" 383 "ff4299c1ebf533a7ae636fa3e6aff903" 384 }, 385 { 386 "SHA512", 387 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 64, 388 4, { 1, 50, 200, 4000 }, 389 "4016e960e2342553d4b9d34fb57355ab8b7f33af5dc2676fc1189e94b38f2b2c" 390 "a0ec8dc3c8b95fb1109d58480cea1e8f88e02f34ad79b303e4809373c46c1b16" 391 }, 392 { 393 "SHA512", 394 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 395 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 396 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 192, 397 10, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 398 "7ceb6a421fc19434bcb7ec9c8a15ea524dbfb896c24f5f517513f06597de99b1" 399 "918eb6b2472e52215ec7d1b5544766f79ff6ac6d1eb456f19a93819fa2d43c29" 400 }, 401 { 402 "SHA512", "0123456789abcdef0123456789abcdef", 32, 403 4, { 100, 8192, 100, 8092 }, 404 "cebf722ffdff5f0e4cbfbd480cd086101d4627d30d42f1f7cf21c43251018069" 405 "854d8e030b5a54cec1e2245d5b4629ff928806d4eababb427d751ec7c274047f" 406 }, 407 }; 408 409 static int test_hmac_chunks(int idx) 410 { 411 char *p; 412 HMAC_CTX *ctx = NULL; 413 unsigned char buf[32768]; 414 unsigned int len; 415 const EVP_MD *md; 416 int i, ret = 0; 417 418 if (!TEST_ptr(md = EVP_get_digestbyname(test_chunks[idx].md_name))) 419 goto err; 420 421 if (!TEST_ptr(ctx = HMAC_CTX_new())) 422 goto err; 423 424 #ifdef CHARSET_EBCDIC 425 ebcdic2ascii(test_chunks[idx].key, test_chunks[idx].key, 426 test_chunks[idx].key_len); 427 #endif 428 429 if (!TEST_true(HMAC_Init_ex(ctx, test_chunks[idx].key, 430 test_chunks[idx].key_len, md, NULL))) 431 goto err; 432 433 for (i = 0; i < test_chunks[idx].chunks; i++) { 434 if (!TEST_true((test_chunks[idx].chunk_size[i] < (int)sizeof(buf)))) 435 goto err; 436 memset(buf, i, test_chunks[idx].chunk_size[i]); 437 if (!TEST_true(HMAC_Update(ctx, buf, test_chunks[idx].chunk_size[i]))) 438 goto err; 439 } 440 441 if (!TEST_true(HMAC_Final(ctx, buf, &len))) 442 goto err; 443 444 p = pt(buf, len); 445 if (!TEST_ptr(p) || !TEST_str_eq(p, test_chunks[idx].digest)) 446 goto err; 447 448 ret = 1; 449 450 err: 451 HMAC_CTX_free(ctx); 452 return ret; 453 } 454 455 int setup_tests(void) 456 { 457 ADD_ALL_TESTS(test_hmac_md5, 4); 458 ADD_TEST(test_hmac_single_shot); 459 ADD_TEST(test_hmac_bad); 460 ADD_TEST(test_hmac_run); 461 ADD_TEST(test_hmac_final_update_fail); 462 ADD_TEST(test_hmac_copy); 463 ADD_TEST(test_hmac_copy_uninited); 464 ADD_ALL_TESTS(test_hmac_chunks, 465 sizeof(test_chunks) / sizeof(struct test_chunks_st)); 466 return 1; 467 } 468 469