1 /* $NetBSD: t_hashes.c,v 1.5 2014/12/10 04:37:53 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2010, 2013 Internet Systems Consortium, Inc. ("ISC") 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* Id: t_hashes.c,v 1.5 2010/10/04 22:27:41 marka Exp */ 20 21 /* 22 * -d1 or larger shows hash or HMAC result even if correct 23 */ 24 25 #include <config.h> 26 27 #include <stdlib.h> 28 29 #include <isc/hmacmd5.h> 30 #include <isc/hmacsha.h> 31 #include <isc/md5.h> 32 #include <isc/print.h> 33 #include <isc/sha1.h> 34 #include <isc/string.h> 35 #include <isc/util.h> 36 37 #include <tests/t_api.h> 38 39 40 static int nprobs; 41 42 typedef void(*HASH_INIT)(void *); 43 typedef void(*HMAC_INIT)(void *, const unsigned char *, unsigned int); 44 typedef void(*UPDATE)(void *, const unsigned char *, unsigned int); 45 typedef void(*FINAL)(void *, const unsigned char *); 46 typedef void(*SIGN)(void *, const unsigned char *, unsigned int); 47 48 typedef struct { 49 const char *name; 50 const unsigned char *key; 51 const unsigned int key_len; 52 const unsigned char *str; 53 const unsigned int str_len; 54 } IN_; 55 #define STR_INIT(s) (const unsigned char *)(s), sizeof(s)-1 56 57 58 union { 59 unsigned char b[1024]; 60 unsigned char md5[16]; 61 unsigned char sha1[ISC_SHA1_DIGESTLENGTH]; 62 unsigned char sha224[ISC_SHA224_DIGESTLENGTH]; 63 unsigned char sha256[ISC_SHA256_DIGESTLENGTH]; 64 unsigned char sha384[ISC_SHA384_DIGESTLENGTH]; 65 unsigned char sha512[ISC_SHA512_DIGESTLENGTH]; 66 } dbuf; 67 #define DIGEST_FILL 0xdf 68 69 typedef struct { 70 const char *str; 71 const unsigned int digest_len; 72 } OUT_; 73 74 75 /* 76 * two ad hoc hash examples 77 */ 78 static IN_ abc = { "\"abc\"", NULL, 0, STR_INIT("abc")}; 79 static OUT_ abc_sha1 = { 80 "a9993e364706816aba3e25717850c26c9cd0d89d", 81 ISC_SHA1_DIGESTLENGTH}; 82 static OUT_ abc_sha224 = { 83 "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", 84 ISC_SHA224_DIGESTLENGTH}; 85 static OUT_ abc_md5 = { 86 "900150983cd24fb0d6963f7d28e17f72", 87 16}; 88 89 static IN_ abc_blah = { "\"abcdbc...\"", NULL, 0, 90 STR_INIT("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")}; 91 static OUT_ abc_blah_sha1 = { 92 "84983e441c3bd26ebaae4aa1f95129e5e54670f1", 93 ISC_SHA1_DIGESTLENGTH}; 94 static OUT_ abc_blah_sha224 = { 95 "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525", 96 ISC_SHA224_DIGESTLENGTH}; 97 static OUT_ abc_blah_md5 = { 98 "8215ef0796a20bcaaae116d3876c664a", 99 16}; 100 101 /* 102 * three HMAC-md5 examples from RFC 2104 103 */ 104 static const unsigned char rfc2104_1_key[16] = { 105 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 106 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}; 107 static IN_ rfc2104_1 = {"RFC 2104 #1", rfc2104_1_key, sizeof(rfc2104_1_key), 108 STR_INIT("Hi There")}; 109 static OUT_ rfc2104_1_hmac = { 110 "9294727a3638bb1c13f48ef8158bfc9d", 111 16}; 112 113 static IN_ rfc2104_2 = {"RFC 2104 #2", STR_INIT("Jefe"), 114 STR_INIT("what do ya want for nothing?")}; 115 static OUT_ rfc2104_2_hmac = { 116 "750c783e6ab0b503eaa86e310a5db738", 117 16}; 118 119 static const unsigned char rfc2104_3_key[16] = { 120 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 121 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}; 122 static const unsigned char rfc2104_3_s[50] = { 123 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 124 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 125 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 126 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 127 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 128 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 129 0xDD, 0xDD}; 130 static IN_ rfc2104_3 = {"RFC 2104 #3", rfc2104_3_key, sizeof(rfc2104_3_key), 131 rfc2104_3_s, sizeof(rfc2104_3_s)}; 132 static OUT_ rfc2104_3_hmac = { 133 "56be34521d144c88dbb8c733f0e8b3f6", 134 16}; 135 136 /* 137 * four three HMAC-SHA tests cut-and-pasted from RFC 4634 starting on page 86 138 */ 139 static const unsigned char rfc4634_1_key[20] = { 140 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 141 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b 142 }; 143 static IN_ rfc4634_1 = {"RFC 4634 #1", rfc4634_1_key, sizeof(rfc4634_1_key), 144 STR_INIT("Hi There")}; 145 static OUT_ rfc4634_1_sha1 = { 146 "B617318655057264E28BC0B6FB378C8EF146BE00", 147 ISC_SHA1_DIGESTLENGTH}; 148 static OUT_ rfc4634_1_sha224 = { 149 "896FB1128ABBDF196832107CD49DF33F47B4B1169912BA4F53684B22", 150 ISC_SHA224_DIGESTLENGTH}; 151 static OUT_ rfc4634_1_sha256 = { 152 "B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833DA726E9376C2E32" 153 "CFF7", 154 ISC_SHA256_DIGESTLENGTH}; 155 static OUT_ rfc4634_1_sha384 = { 156 "AFD03944D84895626B0825F4AB46907F15F9DADBE4101EC682AA034C7CEB" 157 "C59CFAEA9EA9076EDE7F4AF152E8B2FA9CB6", 158 ISC_SHA384_DIGESTLENGTH}; 159 static OUT_ rfc4634_1_sha512 = { 160 "87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2787AD0B30545E1" 161 "7CDEDAA833B7D6B8A702038B274EAEA3F4E4BE9D914EEB61F1702E696C20" 162 "3A126854", 163 ISC_SHA512_DIGESTLENGTH}; 164 165 static IN_ rfc4634_2 = {"RFC 4634 #2", STR_INIT("Jefe"), 166 STR_INIT("what do ya want for nothing?")}; 167 static OUT_ rfc4634_2_sha1 = { 168 "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79", 169 ISC_SHA1_DIGESTLENGTH}; 170 static OUT_ rfc4634_2_sha224 = { 171 "A30E01098BC6DBBF45690F3A7E9E6D0F8BBEA2A39E6148008FD05E44", 172 ISC_SHA224_DIGESTLENGTH}; 173 static OUT_ rfc4634_2_sha256 = { 174 "5BDCC146BF60754E6A042426089575C75A003F089D2739839DEC58B964EC" 175 "3843", 176 ISC_SHA256_DIGESTLENGTH}; 177 static OUT_ rfc4634_2_sha384 = { 178 "AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B47E42EC3736322" 179 "445E8E2240CA5E69E2C78B3239ECFAB21649", 180 ISC_SHA384_DIGESTLENGTH}; 181 static OUT_ rfc4634_2_sha512 = { 182 "164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831FD610270CD7EA25" 183 "05549758BF75C05A994A6D034F65F8F0E6FDCAEAB1A34D4A6B4B636E070A" 184 "38BCE737", 185 ISC_SHA512_DIGESTLENGTH}; 186 187 static const unsigned char rfc4634_3_key[20] = { 188 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 189 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa 190 }; 191 static const unsigned char rfc4634_3_s[50] = { 192 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 193 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 194 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 195 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 196 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd 197 }; 198 static IN_ rfc4634_3 = {"RFC 4634 #3", rfc4634_3_key, sizeof(rfc4634_3_key), 199 rfc4634_3_s, sizeof(rfc4634_3_s)}; 200 static OUT_ rfc4634_3_sha1 = { 201 "125D7342B9AC11CD91A39AF48AA17B4F63F175D3", 202 ISC_SHA1_DIGESTLENGTH}; 203 static OUT_ rfc4634_3_sha224 = { 204 "7FB3CB3588C6C1F6FFA9694D7D6AD2649365B0C1F65D69D1EC8333EA", 205 ISC_SHA224_DIGESTLENGTH}; 206 static OUT_ rfc4634_3_sha256 = { 207 "773EA91E36800E46854DB8EBD09181A72959098B3EF8C122D9635514CED5" 208 "65FE", 209 ISC_SHA256_DIGESTLENGTH}; 210 static OUT_ rfc4634_3_sha384 = { 211 "88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9FEBE83EF4E55966" 212 "144B2A5AB39DC13814B94E3AB6E101A34F27", 213 ISC_SHA384_DIGESTLENGTH}; 214 static OUT_ rfc4634_3_sha512 = { 215 "FA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A3655F83E33B227" 216 "9D39BF3E848279A722C806B485A47E67C807B946A337BEE8942674278859" 217 "E13292FB", 218 ISC_SHA512_DIGESTLENGTH}; 219 220 static const unsigned char rfc4634_4_key[25] = { 221 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 222 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 223 0x15, 0x16, 0x17, 0x18, 0x19 224 }; 225 static const unsigned char rfc4634_4_s[50] = { 226 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 227 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 228 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 229 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 230 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd 231 }; 232 static IN_ rfc4634_4 = {"RFC 4634 #3", rfc4634_4_key, sizeof(rfc4634_4_key), 233 rfc4634_4_s, sizeof(rfc4634_4_s)}; 234 static OUT_ rfc4634_4_sha1 = { 235 "4C9007F4026250C6BC8414F9BF50C86C2D7235DA", 236 ISC_SHA1_DIGESTLENGTH}; 237 static OUT_ rfc4634_4_sha224 = { 238 "6C11506874013CAC6A2ABC1BB382627CEC6A90D86EFC012DE7AFEC5A", 239 ISC_SHA224_DIGESTLENGTH}; 240 static OUT_ rfc4634_4_sha256 = { 241 "82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729" 242 "665B", 243 ISC_SHA256_DIGESTLENGTH}; 244 static OUT_ rfc4634_4_sha384 = { 245 "3E8A69B7783C25851933AB6290AF6CA77A9981480850009CC5577C6E1F57" 246 "3B4E6801DD23C4A7D679CCF8A386C674CFFB", 247 ISC_SHA384_DIGESTLENGTH}; 248 static OUT_ rfc4634_4_sha512 = { 249 "B0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B872DE76F8050361E" 250 "E3DBA91CA5C11AA25EB4D679275CC5788063A5F19741120C4F2DE2ADEBEB" 251 "10A298DD", 252 ISC_SHA512_DIGESTLENGTH}; 253 254 255 256 static const char * 257 d2str(char *buf, unsigned int buf_len, 258 const unsigned char *d, unsigned int d_len) 259 { 260 unsigned int i, l; 261 262 l = 0; 263 for (i = 0; i < d_len && l < buf_len-4; ++i) { 264 l += snprintf(&buf[l], buf_len-l, "%02x", d[i]); 265 } 266 if (l >= buf_len-3) { 267 REQUIRE(buf_len > sizeof("...")); 268 strcpy(&buf[l-sizeof(" ...")], " ..."); 269 } 270 return buf; 271 } 272 273 274 275 /* 276 * Compare binary digest or HMAC to string of hex digits from an RFC 277 */ 278 static void 279 ck(const char *name, const IN_ *in, const OUT_ *out) 280 { 281 char buf[sizeof(dbuf)*2+1]; 282 const char *str_name; 283 unsigned int l; 284 285 d2str(buf, sizeof(buf), dbuf.b, out->digest_len); 286 str_name = in->name != NULL ? in->name : (const char *)in->str; 287 288 if (T_debug != 0) 289 t_info("%s(%s) = %s\n", name, str_name, buf); 290 291 if (strcasecmp(buf, out->str)) { 292 t_info("%s(%s)\n%9s %s\n%9s %s\n", 293 name, str_name, 294 "is", buf, 295 "should be", out->str); 296 ++nprobs; 297 return; 298 } 299 300 /* 301 * check that the hash or HMAC is no longer than we think it is 302 */ 303 for (l = out->digest_len; l < sizeof(dbuf); ++l) { 304 if (dbuf.b[l] != DIGEST_FILL) { 305 t_info("byte #%d after end of %s(%s) changed to %02x\n", 306 l-out->digest_len, name, str_name, dbuf.b[l]); 307 ++nprobs; 308 break; 309 } 310 } 311 } 312 313 314 315 static void 316 t_hash(const char *hname, HASH_INIT init, UPDATE update, FINAL final, 317 IN_ *in, OUT_ *out) 318 { 319 union { 320 unsigned char b[1024]; 321 isc_sha1_t sha1; 322 isc_md5_t md5; 323 } ctx; 324 325 init(&ctx); 326 update(&ctx, in->str, in->str_len); 327 memset(dbuf.b, DIGEST_FILL, sizeof(dbuf)); 328 final(&ctx, dbuf.b); 329 ck(hname, in, out); 330 } 331 332 333 334 /* 335 * isc_sha224_final has a different calling sequence 336 */ 337 static void 338 t_sha224(IN_ *in, OUT_ *out) 339 { 340 isc_sha224_t ctx; 341 342 memset(dbuf.b, DIGEST_FILL, sizeof(dbuf)); 343 isc_sha224_init(&ctx); 344 isc_sha224_update(&ctx, in->str, in->str_len); 345 memset(dbuf.b, DIGEST_FILL, sizeof(dbuf)); 346 isc_sha224_final(dbuf.b, &ctx); 347 ck("SHA224", in, out); 348 } 349 350 351 352 static void 353 t_hashes(IN_ *in, OUT_ *out_sha1, OUT_ *out_sha224, OUT_ *out_md5) 354 { 355 t_hash("SHA1", (HASH_INIT)isc_sha1_init, (UPDATE)isc_sha1_update, 356 (FINAL)isc_sha1_final, in, out_sha1); 357 t_sha224(in, out_sha224); 358 t_hash("md5", (HASH_INIT)isc_md5_init, (UPDATE)isc_md5_update, 359 (FINAL)isc_md5_final, in, out_md5); 360 } 361 362 363 364 /* 365 * isc_hmacmd5_sign has a different calling sequence 366 */ 367 static void 368 t_md5hmac(IN_ *in, OUT_ *out) 369 { 370 isc_hmacmd5_t ctx; 371 372 isc_hmacmd5_init(&ctx, in->key, in->key_len); 373 isc_hmacmd5_update(&ctx, in->str, in->str_len); 374 memset(dbuf.b, DIGEST_FILL, sizeof(dbuf)); 375 isc_hmacmd5_sign(&ctx, dbuf.b); 376 ck("HMAC-md5", in, out); 377 } 378 379 380 381 static void 382 t_hmac(const char *hname, HMAC_INIT init, UPDATE update, SIGN sign, 383 IN_ *in, OUT_ *out) 384 { 385 union { 386 unsigned char b[1024]; 387 isc_hmacmd5_t hmacmd5; 388 isc_hmacsha1_t hmacsha1; 389 isc_hmacsha224_t hmacsha224; 390 isc_hmacsha256_t hmacsha256; 391 isc_hmacsha384_t hmacsha384; 392 isc_hmacsha512_t hmacsha512; 393 } ctx; 394 395 init(&ctx, in->key, in->key_len); 396 update(&ctx, in->str, in->str_len); 397 memset(dbuf.b, DIGEST_FILL, sizeof(dbuf)); 398 sign(&ctx, dbuf.b, out->digest_len); 399 ck(hname, in, out); 400 } 401 402 403 404 static void 405 t_hmacs(IN_ *in, OUT_ *out_sha1, OUT_ *out_sha224, OUT_ *out_sha256, 406 OUT_ *out_sha384, OUT_ *out_sha512) 407 { 408 t_hmac("HMAC-SHA1", (HMAC_INIT)isc_hmacsha1_init, 409 (UPDATE)isc_hmacsha1_update, (SIGN)isc_hmacsha1_sign, 410 in, out_sha1); 411 t_hmac("HMAC-SHA224", (HMAC_INIT)isc_hmacsha224_init, 412 (UPDATE)isc_hmacsha224_update, (SIGN)isc_hmacsha224_sign, 413 in, out_sha224); 414 t_hmac("HMAC-SHA256", (HMAC_INIT)isc_hmacsha256_init, 415 (UPDATE)isc_hmacsha256_update, (SIGN)isc_hmacsha256_sign, 416 in, out_sha256); 417 t_hmac("HMAC-SHA384", (HMAC_INIT)isc_hmacsha384_init, 418 (UPDATE)isc_hmacsha384_update, (SIGN)isc_hmacsha384_sign, 419 in, out_sha384); 420 t_hmac("HMAC-SHA512", (HMAC_INIT)isc_hmacsha512_init, 421 (UPDATE)isc_hmacsha512_update, (SIGN)isc_hmacsha512_sign, 422 in, out_sha512); 423 } 424 425 426 427 /* 428 * This will almost never fail, and so there is no need for the extra noise 429 * that would come from breaking it into several tests. 430 */ 431 static void 432 t1(void) 433 { 434 /* 435 * two ad hoc hash examples 436 */ 437 t_hashes(&abc, &abc_sha1, &abc_sha224, &abc_md5); 438 t_hashes(&abc_blah, &abc_blah_sha1, &abc_blah_sha224, &abc_blah_md5); 439 440 /* 441 * three HMAC-md5 examples from RFC 2104 442 */ 443 t_md5hmac(&rfc2104_1, &rfc2104_1_hmac); 444 t_md5hmac(&rfc2104_2, &rfc2104_2_hmac); 445 t_md5hmac(&rfc2104_3, &rfc2104_3_hmac); 446 447 /* 448 * four HMAC-SHA tests from RFC 4634 starting on page 86 449 */ 450 t_hmacs(&rfc4634_1, &rfc4634_1_sha1, &rfc4634_1_sha224, 451 &rfc4634_1_sha256, &rfc4634_1_sha384, &rfc4634_1_sha512); 452 t_hmacs(&rfc4634_2, &rfc4634_2_sha1, &rfc4634_2_sha224, 453 &rfc4634_2_sha256, &rfc4634_2_sha384, &rfc4634_2_sha512); 454 t_hmacs(&rfc4634_3, &rfc4634_3_sha1, &rfc4634_3_sha224, 455 &rfc4634_3_sha256, &rfc4634_3_sha384, &rfc4634_3_sha512); 456 t_hmacs(&rfc4634_4, &rfc4634_4_sha1, &rfc4634_4_sha224, 457 &rfc4634_4_sha256, &rfc4634_4_sha384, &rfc4634_4_sha512); 458 459 if (nprobs != 0) 460 t_result(T_FAIL); 461 else 462 t_result(T_PASS); 463 } 464 465 466 testspec_t T_testlist[] = { 467 { (PFV) t1, "hashes" }, 468 { (PFV) 0, NULL } 469 }; 470 471 #ifdef WIN32 472 int 473 main(int argc, char **argv) { 474 t_settests(T_testlist); 475 return (t_main(argc, argv)); 476 } 477 #endif 478