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