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 "", 44 0, 45 "More text test vectors to stuff up EBCDIC machines :-)", 46 54, 47 "e9139d1e6ee064ef8cf514fc7dc83e86", 48 }, 49 { 50 "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 51 16, 52 "Hi There", 53 8, 54 "9294727a3638bb1c13f48ef8158bfc9d", 55 }, 56 { 57 "Jefe", 58 4, 59 "what do ya want for nothing?", 60 28, 61 "750c783e6ab0b503eaa86e310a5db738", 62 }, 63 { 64 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 65 16, 66 { 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 67 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 68 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 69 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 70 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd }, 71 50, 72 "56be34521d144c88dbb8c733f0e8b3f6", 73 }, 74 { "", 0, "My test data", 12, 75 "61afdecb95429ef494d61fdee15990cabf0826fc" }, 76 { "", 0, "My test data", 12, 77 "2274b195d90ce8e03406f4b526a47e0787a88a65479938f1a5baa3ce0f079776" }, 78 { "123456", 6, "My test data", 12, 79 "bab53058ae861a7f191abe2d0145cbb123776a6369ee3f9d79ce455667e411dd" }, 80 { "12345", 5, "My test data again", 18, 81 "a12396ceddd2a85f4c656bc1e0aa50c78cffde3e" } 82 }; 83 #endif 84 85 static char *pt(unsigned char *md, unsigned int len); 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 static int test_hmac_single_shot(void) 204 { 205 char *p; 206 207 /* Test single-shot with NULL key. */ 208 p = pt(HMAC(EVP_sha1(), NULL, 0, test[4].data, test[4].data_len, 209 NULL, NULL), 210 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 { "SHA224", 326 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 64, 327 4, { 1, 50, 200, 4000 }, 328 "40821a39dd54f01443b3f96b9370a15023fbdd819a074ffc4b703c77" }, 329 { "SHA224", 330 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 331 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 332 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 333 192, 334 10, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 335 "55ffa85e53e9a68f41c8d653c60b4ada9566d22aed3811834882661c" }, 336 { "SHA224", "0123456789abcdef0123456789abcdef", 32, 337 4, { 100, 4096, 100, 3896 }, 338 "0fd18e7d8e974f401b29bf0502a71f6a9b77804e9191380ce9f48377" }, 339 { "SHA256", 340 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 64, 341 4, { 1, 50, 200, 4000 }, 342 "f67a46fa77c66d3ea5b3ffb9a10afb3e501eaadd16b15978fdee9f014a782140" }, 343 { "SHA256", 344 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 345 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 346 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 347 192, 348 10, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 349 "21a6f61ed6dbec30b58557a80988ff610d69b50b2e96d75863ab50f99da58c9d" }, 350 { "SHA256", "0123456789abcdef0123456789abcdef", 32, 351 4, { 100, 4096, 100, 3896 }, 352 "7bfd45c1bdde9b79244816b0aea0a67ea954a182e74c60410bfbc1fdc4842660" }, 353 { "SHA384", 354 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 64, 355 4, { 1, 50, 200, 4000 }, 356 "e270e3c8ca3f2796a0c29cc7569fcec7584b04db26da64326aca0d17bd7731de" 357 "938694b273f3dafe6e2dc123cde26640" }, 358 { "SHA384", 359 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 360 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 361 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 362 192, 363 10, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 364 "7036fd7d251298975acd18938471243e92fffe67be158f16c910c400576592d2" 365 "618c3c077ef25d703312668bd2d813ff" }, 366 { "SHA384", "0123456789abcdef0123456789abcdef", 32, 367 4, { 100, 8192, 100, 8092 }, 368 "0af8224145bd0812d2e34ba1f980ed4d218461271a54cce75dc43d36eda01e4e" 369 "ff4299c1ebf533a7ae636fa3e6aff903" }, 370 { "SHA512", 371 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 64, 372 4, { 1, 50, 200, 4000 }, 373 "4016e960e2342553d4b9d34fb57355ab8b7f33af5dc2676fc1189e94b38f2b2c" 374 "a0ec8dc3c8b95fb1109d58480cea1e8f88e02f34ad79b303e4809373c46c1b16" }, 375 { "SHA512", 376 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 377 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" 378 "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 379 192, 380 10, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 381 "7ceb6a421fc19434bcb7ec9c8a15ea524dbfb896c24f5f517513f06597de99b1" 382 "918eb6b2472e52215ec7d1b5544766f79ff6ac6d1eb456f19a93819fa2d43c29" }, 383 { "SHA512", "0123456789abcdef0123456789abcdef", 32, 384 4, { 100, 8192, 100, 8092 }, 385 "cebf722ffdff5f0e4cbfbd480cd086101d4627d30d42f1f7cf21c43251018069" 386 "854d8e030b5a54cec1e2245d5b4629ff928806d4eababb427d751ec7c274047f" }, 387 }; 388 389 static int test_hmac_chunks(int idx) 390 { 391 char *p; 392 HMAC_CTX *ctx = NULL; 393 unsigned char buf[32768]; 394 unsigned int len; 395 const EVP_MD *md; 396 int i, ret = 0; 397 398 if (!TEST_ptr(md = EVP_get_digestbyname(test_chunks[idx].md_name))) 399 goto err; 400 401 if (!TEST_ptr(ctx = HMAC_CTX_new())) 402 goto err; 403 404 #ifdef CHARSET_EBCDIC 405 ebcdic2ascii(test_chunks[idx].key, test_chunks[idx].key, 406 test_chunks[idx].key_len); 407 #endif 408 409 if (!TEST_true(HMAC_Init_ex(ctx, test_chunks[idx].key, 410 test_chunks[idx].key_len, md, NULL))) 411 goto err; 412 413 for (i = 0; i < test_chunks[idx].chunks; i++) { 414 if (!TEST_true((test_chunks[idx].chunk_size[i] < (int)sizeof(buf)))) 415 goto err; 416 memset(buf, i, test_chunks[idx].chunk_size[i]); 417 if (!TEST_true(HMAC_Update(ctx, buf, test_chunks[idx].chunk_size[i]))) 418 goto err; 419 } 420 421 if (!TEST_true(HMAC_Final(ctx, buf, &len))) 422 goto err; 423 424 p = pt(buf, len); 425 if (!TEST_ptr(p) || !TEST_str_eq(p, test_chunks[idx].digest)) 426 goto err; 427 428 ret = 1; 429 430 err: 431 HMAC_CTX_free(ctx); 432 return ret; 433 } 434 435 int setup_tests(void) 436 { 437 ADD_ALL_TESTS(test_hmac_md5, 4); 438 ADD_TEST(test_hmac_single_shot); 439 ADD_TEST(test_hmac_bad); 440 ADD_TEST(test_hmac_run); 441 ADD_TEST(test_hmac_final_update_fail); 442 ADD_TEST(test_hmac_copy); 443 ADD_TEST(test_hmac_copy_uninited); 444 ADD_ALL_TESTS(test_hmac_chunks, 445 sizeof(test_chunks) / sizeof(struct test_chunks_st)); 446 return 1; 447 } 448