1 #include <stdio.h> 2 #include <string.h> 3 #include <assert.h> 4 5 #include "nspr.h" 6 7 /* nss headers */ 8 #include "prtypes.h" 9 #include "plgetopt.h" 10 #include "hasht.h" 11 #include "nsslowhash.h" 12 #include "secport.h" 13 #include "hasht.h" 14 #include "basicutil.h" 15 16 static char *progName = NULL; 17 18 static int 19 test_long_message(NSSLOWInitContext *initCtx, 20 HASH_HashType algoType, unsigned int hashLen, 21 const PRUint8 expected[], PRUint8 results[]) 22 { 23 unsigned int len, i, rv = 0; 24 NSSLOWHASHContext *ctx; 25 26 /* The message is meant to be 'a' repeated 1,000,000 times. 27 * This is too much to allocate on the stack so we will use a 1,000 char 28 * buffer and call update 1,000 times. 29 */ 30 unsigned char buf[1000]; 31 (void)PORT_Memset(buf, 'a', sizeof(buf)); 32 33 ctx = NSSLOWHASH_NewContext(initCtx, algoType); 34 if (ctx == NULL) { 35 SECU_PrintError(progName, "Couldn't get hash context\n"); 36 return 1; 37 } 38 39 NSSLOWHASH_Begin(ctx); 40 for (i = 0; i < 1000; ++i) { 41 NSSLOWHASH_Update(ctx, buf, 1000); 42 } 43 44 NSSLOWHASH_End(ctx, results, &len, hashLen); 45 PR_ASSERT(len == hashLen); 46 PR_ASSERT(PORT_Memcmp(expected, results, hashLen) == 0); 47 if (PORT_Memcmp(expected, results, len) != 0) { 48 SECU_PrintError(progName, "Hash mismatch\n"); 49 SECU_PrintBuf(stdout, "Expected: ", expected, hashLen); 50 SECU_PrintBuf(stdout, "Actual: ", results, len); 51 rv = 1; 52 } 53 54 NSSLOWHASH_Destroy(ctx); 55 NSSLOW_Shutdown(initCtx); 56 57 return rv; 58 } 59 60 static int 61 test_long_message_sha1(NSSLOWInitContext *initCtx) 62 { 63 PRUint8 results[SHA1_LENGTH]; 64 /* Test vector from FIPS 180-2: appendix B.3. */ 65 66 /* 34aa973c d4c4daa4 f61eeb2b dbad2731 6534016f. */ 67 static const PRUint8 expected[SHA256_LENGTH] = 68 { 0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, 0xa4, 0xf6, 0x1e, 0xeb, 0x2b, 69 0xdb, 0xad, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6f }; 70 unsigned char buf[1000]; 71 (void)PORT_Memset(buf, 'a', sizeof(buf)); 72 return test_long_message(initCtx, HASH_AlgSHA1, 73 SHA1_LENGTH, &expected[0], results); 74 } 75 76 static int 77 test_long_message_sha256(NSSLOWInitContext *initCtx) 78 { 79 PRUint8 results[SHA256_LENGTH]; 80 /* cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0. */ 81 static const PRUint8 expected[SHA256_LENGTH] = 82 { 0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67, 83 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e, 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0 }; 84 unsigned char buf[1000]; 85 (void)PORT_Memset(buf, 'a', sizeof(buf)); 86 return test_long_message(initCtx, HASH_AlgSHA256, 87 SHA256_LENGTH, &expected[0], results); 88 } 89 90 static int 91 test_long_message_sha384(NSSLOWInitContext *initCtx) 92 { 93 PRUint8 results[SHA384_LENGTH]; 94 /* Test vector from FIPS 180-2: appendix B.3. */ 95 /* 96 9d0e1809716474cb 97 086e834e310a4a1c 98 ed149e9c00f24852 99 7972cec5704c2a5b 100 07b8b3dc38ecc4eb 101 ae97ddd87f3d8985. 102 */ 103 static const PRUint8 expected[SHA384_LENGTH] = 104 { 0x9d, 0x0e, 0x18, 0x09, 0x71, 0x64, 0x74, 0xcb, 105 0x08, 0x6e, 0x83, 0x4e, 0x31, 0x0a, 0x4a, 0x1c, 106 0xed, 0x14, 0x9e, 0x9c, 0x00, 0xf2, 0x48, 0x52, 107 0x79, 0x72, 0xce, 0xc5, 0x70, 0x4c, 0x2a, 0x5b, 108 0x07, 0xb8, 0xb3, 0xdc, 0x38, 0xec, 0xc4, 0xeb, 109 0xae, 0x97, 0xdd, 0xd8, 0x7f, 0x3d, 0x89, 0x85 }; 110 unsigned char buf[1000]; 111 (void)PORT_Memset(buf, 'a', sizeof(buf)); 112 113 return test_long_message(initCtx, HASH_AlgSHA384, 114 SHA384_LENGTH, &expected[0], results); 115 } 116 117 static int 118 test_long_message_sha512(NSSLOWInitContext *initCtx) 119 { 120 PRUint8 results[SHA512_LENGTH]; 121 /* Test vector from FIPS 180-2: appendix B.3. */ 122 static const PRUint8 expected[SHA512_LENGTH] = 123 { 0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64, 0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63, 124 0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28, 0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb, 125 0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a, 0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b, 126 0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e, 0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b }; 127 unsigned char buf[1000]; 128 (void)PORT_Memset(buf, 'a', sizeof(buf)); 129 130 return test_long_message(initCtx, HASH_AlgSHA512, 131 SHA512_LENGTH, &expected[0], results); 132 } 133 134 static int 135 testMessageDigest(NSSLOWInitContext *initCtx, 136 HASH_HashType algoType, unsigned int hashLen, 137 const unsigned char *message, 138 const PRUint8 expected[], PRUint8 results[]) 139 { 140 NSSLOWHASHContext *ctx; 141 unsigned int len; 142 int rv = 0; 143 144 ctx = NSSLOWHASH_NewContext(initCtx, algoType); 145 if (ctx == NULL) { 146 SECU_PrintError(progName, "Couldn't get hash context\n"); 147 return 1; 148 } 149 150 NSSLOWHASH_Begin(ctx); 151 NSSLOWHASH_Update(ctx, message, PORT_Strlen((const char *)message)); 152 NSSLOWHASH_End(ctx, results, &len, hashLen); 153 PR_ASSERT(len == hashLen); 154 PR_ASSERT(PORT_Memcmp(expected, results, len) == 0); 155 156 if (PORT_Memcmp(expected, results, len) != 0) { 157 SECU_PrintError(progName, "Hash mismatch\n"); 158 SECU_PrintBuf(stdout, "Expected: ", expected, hashLen); 159 SECU_PrintBuf(stdout, "Actual: ", results, len); 160 rv = 1; 161 } 162 163 NSSLOWHASH_Destroy(ctx); 164 NSSLOW_Shutdown(initCtx); 165 166 return rv; 167 } 168 169 static int 170 testMD5(NSSLOWInitContext *initCtx) 171 { 172 /* test vectors that glibc, our API main client, uses */ 173 174 static const struct { 175 const unsigned char *input; 176 const PRUint8 result[MD5_LENGTH]; 177 } md5tests[] = { 178 { (unsigned char *)"", 179 { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, 180 { (unsigned char *)"a", 181 { 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, 182 { (unsigned char *)"abc", 183 { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, 184 { (unsigned char *)"message digest", 185 { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, 186 { (unsigned char *)"abcdefghijklmnopqrstuvwxyz", 187 { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, 188 { (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 189 { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, 190 { (unsigned char *)"123456789012345678901234567890123456789012345678901234567890" 191 "12345678901234567890", 192 { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } } 193 }; 194 PRUint8 results[MD5_LENGTH]; 195 int rv = 0, cnt, numTests; 196 197 numTests = sizeof(md5tests) / sizeof(md5tests[0]); 198 for (cnt = 0; cnt < numTests; cnt++) { 199 rv += testMessageDigest(initCtx, HASH_AlgMD5, MD5_LENGTH, 200 (const unsigned char *)md5tests[cnt].input, 201 md5tests[cnt].result, &results[0]); 202 } 203 return rv; 204 } 205 206 /* 207 * Tests with test vectors from FIPS 180-2 Appendixes B.1, B.2, B.3, C, and D 208 * 209 */ 210 211 static int 212 testSHA1(NSSLOWInitContext *initCtx) 213 { 214 static const struct { 215 const unsigned char *input; 216 const PRUint8 result[SHA1_LENGTH]; 217 } sha1tests[] = { 218 /* one block messsage */ 219 { 220 (const unsigned char *)"abc", 221 /* a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d. */ 222 223 { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, /* a9993e36 4706816a */ 224 0xba, 0x3e, 0x25, 0x71, /* ba3e2571 */ 225 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d } /* 7850c26c 9cd0d89d */ 226 }, 227 { (const unsigned char *)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 228 /* 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1. */ 229 { 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae, 0x4a, 0xa1, 230 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1 } } 231 }; 232 233 PRUint8 results[SHA1_LENGTH]; 234 int rv = 0, cnt, numTests; 235 236 numTests = sizeof(sha1tests) / sizeof(sha1tests[0]); 237 for (cnt = 0; cnt < numTests; cnt++) { 238 rv += testMessageDigest(initCtx, HASH_AlgSHA1, SHA1_LENGTH, 239 (const unsigned char *)sha1tests[cnt].input, 240 sha1tests[cnt].result, &results[0]); 241 } 242 243 rv += test_long_message_sha1(initCtx); 244 return rv; 245 } 246 247 static int 248 testSHA224(NSSLOWInitContext *initCtx) 249 { 250 static const struct { 251 const unsigned char *input; 252 const PRUint8 result[SHA224_LENGTH]; 253 } sha224tests[] = { 254 /* one block messsage */ 255 { (const unsigned char *)"abc", 256 { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, 257 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, 0xE3, 0x6C, 0x9D, 0xA7 } }, 258 /* two block message */ 259 { (const unsigned char *)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 260 { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, 261 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, 0x52, 0x52, 0x25, 0x25 } } 262 }; 263 264 PRUint8 results[SHA224_LENGTH]; 265 int rv = 0, cnt, numTests; 266 267 numTests = sizeof(sha224tests) / sizeof(sha224tests[0]); 268 for (cnt = 0; cnt < numTests; cnt++) { 269 rv += testMessageDigest(initCtx, HASH_AlgSHA224, SHA224_LENGTH, 270 (const unsigned char *)sha224tests[cnt].input, 271 sha224tests[cnt].result, &results[0]); 272 } 273 274 return rv; 275 } 276 277 static int 278 testSHA256(NSSLOWInitContext *initCtx) 279 { 280 static const struct { 281 const unsigned char *input; 282 const PRUint8 result[SHA256_LENGTH]; 283 } sha256tests[] = { 284 /* Test vectors from FIPS 180-2: appendix B.1. */ 285 { (unsigned char *)"abc", 286 { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 287 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } }, 288 /* Test vectors from FIPS 180-2: appendix B.2. */ 289 { (unsigned char *)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 290 { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 291 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } } 292 }; 293 294 PRUint8 results[SHA256_LENGTH]; 295 int rv = 0, cnt, numTests; 296 297 numTests = sizeof(sha256tests) / sizeof(sha256tests[0]); 298 for (cnt = 0; cnt < numTests; cnt++) { 299 rv += testMessageDigest(initCtx, HASH_AlgSHA256, SHA256_LENGTH, 300 (const unsigned char *)sha256tests[cnt].input, 301 sha256tests[cnt].result, &results[0]); 302 } 303 304 rv += test_long_message_sha256(initCtx); 305 return rv; 306 } 307 308 static int 309 testSHA384(NSSLOWInitContext *initCtx) 310 { 311 static const struct { 312 const unsigned char *input; 313 const PRUint8 result[SHA384_LENGTH]; 314 } sha384tests[] = { 315 /* Test vector from FIPS 180-2: appendix D, single-block message. */ 316 { (unsigned char *)"abc", 317 { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, 318 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, 319 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, 320 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, 321 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, 322 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 } }, 323 324 /* Test vectors from FIPS 180-2: appendix D, multi-block message. */ 325 { (unsigned char *)"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" 326 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 327 /* 328 09330c33f71147e8 329 3d192fc782cd1b47 330 53111b173b3b05d2 331 2fa08086e3b0f712 332 fcc7c71a557e2db9 333 66c3e9fa91746039. 334 */ 335 { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, 336 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, 337 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, 338 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, 339 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, 340 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 } } 341 }; 342 343 PRUint8 results[SHA384_LENGTH]; 344 int rv = 0, cnt, numTests; 345 346 numTests = sizeof(sha384tests) / sizeof(sha384tests[0]); 347 for (cnt = 0; cnt < numTests; cnt++) { 348 rv += testMessageDigest(initCtx, HASH_AlgSHA384, SHA384_LENGTH, 349 (const unsigned char *)sha384tests[cnt].input, 350 sha384tests[cnt].result, &results[0]); 351 } 352 rv += test_long_message_sha384(initCtx); 353 354 return rv; 355 } 356 357 int 358 testSHA512(NSSLOWInitContext *initCtx) 359 { 360 static const struct { 361 const unsigned char *input; 362 const PRUint8 result[SHA512_LENGTH]; 363 } sha512tests[] = { 364 /* Test vectors from FIPS 180-2: appendix C.1. */ 365 { (unsigned char *)"abc", 366 { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, 367 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 368 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, 369 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } }, 370 /* Test vectors from FIPS 180-2: appendix C.2. */ 371 { (unsigned char *)"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" 372 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 373 { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, 374 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, 375 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, 376 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } } 377 }; 378 379 PRUint8 results[SHA512_LENGTH]; 380 int rv = 0, cnt, numTests; 381 382 numTests = sizeof(sha512tests) / sizeof(sha512tests[0]); 383 for (cnt = 0; cnt < numTests; cnt++) { 384 rv = testMessageDigest(initCtx, HASH_AlgSHA512, SHA512_LENGTH, 385 (const unsigned char *)sha512tests[cnt].input, 386 sha512tests[cnt].result, &results[0]); 387 } 388 rv += test_long_message_sha512(initCtx); 389 return rv; 390 } 391 392 static void 393 Usage() 394 { 395 fprintf(stderr, "Usage: %s [algorithm]\n", 396 progName); 397 fprintf(stderr, "algorithm must be one of %s\n", 398 "{ MD5 | SHA1 | SHA224 | SHA256 | SHA384 | SHA512 }"); 399 fprintf(stderr, "default is to test all\n"); 400 exit(-1); 401 } 402 403 int 404 main(int argc, char **argv) 405 { 406 NSSLOWInitContext *initCtx; 407 int rv = 0; /* counts the number of failures */ 408 409 progName = strrchr(argv[0], '/'); 410 progName = progName ? progName + 1 : argv[0]; 411 412 initCtx = NSSLOW_Init(); 413 if (initCtx == NULL) { 414 SECU_PrintError(progName, "Couldn't initialize for hashing\n"); 415 return 1; 416 } 417 418 if (argc < 2 || !argv[1] || strlen(argv[1]) == 0) { 419 rv += testMD5(initCtx); 420 rv += testSHA1(initCtx); 421 rv += testSHA224(initCtx); 422 rv += testSHA256(initCtx); 423 rv += testSHA384(initCtx); 424 rv += testSHA512(initCtx); 425 } else if (strcmp(argv[1], "MD5") == 0) { 426 rv += testMD5(initCtx); 427 } else if (strcmp(argv[1], "SHA1") == 0) { 428 rv += testSHA1(initCtx); 429 } else if (strcmp(argv[1], "SHA224") == 0) { 430 rv += testSHA224(initCtx); 431 } else if (strcmp(argv[1], "SHA256") == 0) { 432 rv += testSHA256(initCtx); 433 } else if (strcmp(argv[1], "SHA384") == 0) { 434 rv += testSHA384(initCtx); 435 } else if (strcmp(argv[1], "SHA512") == 0) { 436 rv += testSHA512(initCtx); 437 } else { 438 SECU_PrintError(progName, "Unsupported hash type %s\n", argv[0]); 439 Usage(); 440 } 441 442 NSSLOW_Shutdown(initCtx); 443 444 return (rv == 0) ? 0 : 1; 445 } 446