1 /* $OpenBSD: sha_test.c,v 1.1 2022/09/01 14:02:41 tb Exp $ */ 2 /* 3 * Copyright (c) 2022 Joshua Sing <joshua@hypera.dev> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <openssl/evp.h> 19 #include <openssl/sha.h> 20 21 #include <stdint.h> 22 #include <string.h> 23 24 struct sha_test { 25 const int algorithm; 26 const uint8_t in[128]; 27 const size_t in_len; 28 const uint8_t out[EVP_MAX_MD_SIZE]; 29 }; 30 31 struct sha_test sha_tests[] = { 32 /* SHA-1 */ 33 { 34 .algorithm = NID_sha1, 35 .in = "abc", 36 .in_len = 3, 37 .out = { 38 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 39 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 40 0x9c, 0xd0, 0xd8, 0x9d, 41 } 42 }, 43 { 44 .algorithm = NID_sha1, 45 .in = "", 46 .in_len = 0, 47 .out = { 48 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 49 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 50 0xaf, 0xd8, 0x07, 0x09, 51 } 52 }, 53 { 54 .algorithm = NID_sha1, 55 .in = 56 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" 57 "mnopnopq", 58 .in_len = 56, 59 .out = { 60 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 61 0xba, 0xae, 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, 62 0xe5, 0x46, 0x70, 0xf1, 63 } 64 }, 65 { 66 .algorithm = NID_sha1, 67 .in = 68 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" 69 "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" 70 "mnopqrstnopqrstu", 71 .in_len = 112, 72 .out = { 73 0xa4, 0x9b, 0x24, 0x46, 0xa0, 0x2c, 0x64, 0x5b, 74 0xf4, 0x19, 0xf9, 0x95, 0xb6, 0x70, 0x91, 0x25, 75 0x3a, 0x04, 0xa2, 0x59, 76 } 77 }, 78 79 /* SHA-224 */ 80 { 81 .algorithm = NID_sha224, 82 .in = "abc", 83 .in_len = 3, 84 .out = { 85 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, 0x22, 86 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, 0x55, 0xb3, 87 0x2a, 0xad, 0xbc, 0xe4, 0xbd, 0xa0, 0xb3, 0xf7, 88 0xe3, 0x6c, 0x9d, 0xa7, 89 } 90 }, 91 { 92 .algorithm = NID_sha224, 93 .in = "", 94 .in_len = 0, 95 .out = { 96 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 97 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4, 98 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, 99 0xc5, 0xb3, 0xe4, 0x2f, 100 } 101 }, 102 { 103 .algorithm = NID_sha224, 104 .in = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" 105 "mnopnopq", 106 .in_len = 56, 107 .out = { 108 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, 0xcc, 109 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, 0x01, 0x50, 110 0xb0, 0xc6, 0x45, 0x5c, 0xb4, 0xf5, 0x8b, 0x19, 111 0x52, 0x52, 0x25, 0x25, 112 } 113 }, 114 { 115 .algorithm = NID_sha224, 116 .in = 117 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" 118 "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" 119 "mnopqrstnopqrstu", 120 .in_len = 112, 121 .out = { 122 0xc9, 0x7c, 0xa9, 0xa5, 0x59, 0x85, 0x0c, 0xe9, 123 0x7a, 0x04, 0xa9, 0x6d, 0xef, 0x6d, 0x99, 0xa9, 124 0xe0, 0xe0, 0xe2, 0xab, 0x14, 0xe6, 0xb8, 0xdf, 125 0x26, 0x5f, 0xc0, 0xb3, 126 } 127 }, 128 129 /* SHA-256 */ 130 { 131 .algorithm = NID_sha256, 132 .in = "abc", 133 .in_len = 3, 134 .out = { 135 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 136 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 137 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 138 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad, 139 } 140 }, 141 { 142 .algorithm = NID_sha256, 143 .in = "", 144 .in_len = 0, 145 .out = { 146 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 147 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 148 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 149 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, 150 } 151 }, 152 { 153 .algorithm = NID_sha256, 154 .in = 155 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" 156 "mnopnopq", 157 .in_len = 56, 158 .out = { 159 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 160 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 161 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 162 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1, 163 } 164 }, 165 { 166 .algorithm = NID_sha256, 167 .in = 168 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" 169 "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" 170 "mnopqrstnopqrstu", 171 .in_len = 112, 172 .out = { 173 0xcf, 0x5b, 0x16, 0xa7, 0x78, 0xaf, 0x83, 0x80, 174 0x03, 0x6c, 0xe5, 0x9e, 0x7b, 0x04, 0x92, 0x37, 175 0x0b, 0x24, 0x9b, 0x11, 0xe8, 0xf0, 0x7a, 0x51, 176 0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1, 177 } 178 }, 179 180 /* SHA-384 */ 181 { 182 .algorithm = NID_sha384, 183 .in = "abc", 184 .in_len = 3, 185 .out = { 186 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, 187 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, 188 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, 189 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, 190 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, 191 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7, 192 } 193 }, 194 { 195 .algorithm = NID_sha384, 196 .in = "", 197 .in_len = 0, 198 .out = { 199 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 200 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, 201 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 202 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 203 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 204 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b, 205 } 206 }, 207 { 208 .algorithm = NID_sha384, 209 .in = 210 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" 211 "mnopnopq", 212 .in_len = 56, 213 .out = { 214 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39, 215 0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39, 216 0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab, 217 0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6, 218 0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f, 219 0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b, 220 } 221 }, 222 { 223 .algorithm = NID_sha384, 224 .in = 225 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" 226 "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" 227 "mnopqrstnopqrstu", 228 .in_len = 112, 229 .out = { 230 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, 231 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, 232 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, 233 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, 234 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, 235 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39, 236 } 237 }, 238 239 /* SHA-512 */ 240 { 241 .algorithm = NID_sha512, 242 .in = "abc", 243 .in_len = 3, 244 .out = { 245 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 246 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, 247 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 248 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 249 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 250 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, 251 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 252 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f, 253 } 254 }, 255 { 256 .algorithm = NID_sha512, 257 .in = "", 258 .in_len = 0, 259 .out = { 260 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 261 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, 262 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 263 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 264 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 265 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, 266 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 267 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e, 268 } 269 }, 270 { 271 .algorithm = NID_sha512, 272 .in = 273 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" 274 "mnopnopq", 275 .in_len = 56, 276 .out = { 277 0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a, 278 0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16, 279 0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8, 280 0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35, 281 0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9, 282 0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0, 283 0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03, 284 0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45, 285 } 286 }, 287 { 288 .algorithm = NID_sha512, 289 .in = 290 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" 291 "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" 292 "mnopqrstnopqrstu", 293 .in_len = 112, 294 .out = { 295 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 296 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, 297 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, 298 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, 299 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 300 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, 301 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, 302 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09, 303 } 304 }, 305 }; 306 307 #define N_SHA_TESTS (sizeof(sha_tests) / sizeof(sha_tests[0])) 308 309 static int 310 sha_test(void) 311 { 312 unsigned char *(*sha_func)(const unsigned char *, size_t, unsigned char *); 313 struct sha_test *st; 314 EVP_MD_CTX *hash = NULL; 315 const EVP_MD *md; 316 uint8_t out[EVP_MAX_MD_SIZE]; 317 size_t in_len, out_len; 318 size_t i; 319 const char *label; 320 int failed = 1; 321 322 if ((hash = EVP_MD_CTX_new()) == NULL) { 323 fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n"); 324 goto failed; 325 } 326 327 for (i = 0; i < N_SHA_TESTS; i++) { 328 st = &sha_tests[i]; 329 switch (st->algorithm) { 330 case NID_sha1: 331 sha_func = SHA1; 332 md = EVP_sha1(); 333 out_len = SHA_DIGEST_LENGTH; 334 label = SN_sha1; 335 break; 336 case NID_sha224: 337 sha_func = SHA224; 338 md = EVP_sha224(); 339 out_len = SHA224_DIGEST_LENGTH; 340 label = SN_sha224; 341 break; 342 case NID_sha256: 343 sha_func = SHA256; 344 md = EVP_sha256(); 345 out_len = SHA256_DIGEST_LENGTH; 346 label = SN_sha256; 347 break; 348 case NID_sha384: 349 sha_func = SHA384; 350 md = EVP_sha384(); 351 out_len = SHA384_DIGEST_LENGTH; 352 label = SN_sha384; 353 break; 354 case NID_sha512: 355 sha_func = SHA512; 356 md = EVP_sha512(); 357 out_len = SHA512_DIGEST_LENGTH; 358 label = SN_sha512; 359 break; 360 default: 361 fprintf(stderr, "FAIL: unknown algorithm (%d)\n", 362 st->algorithm); 363 goto failed; 364 } 365 366 /* Digest */ 367 memset(out, 0, sizeof(out)); 368 sha_func(st->in, st->in_len, out); 369 if (memcmp(st->out, out, out_len) != 0) { 370 fprintf(stderr, "FAIL (%s): mismatch\n", label); 371 goto failed; 372 } 373 374 /* EVP single-shot digest */ 375 memset(out, 0, sizeof(out)); 376 if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) { 377 fprintf(stderr, "FAIL (%s): EVP_Digest failed\n", label); 378 goto failed; 379 } 380 381 if (memcmp(st->out, out, out_len) != 0) { 382 fprintf(stderr, "FAIL (%s): EVP single-shot mismatch\n", 383 label); 384 goto failed; 385 } 386 387 /* EVP digest */ 388 memset(out, 0, sizeof(out)); 389 if (!EVP_DigestInit_ex(hash, md, NULL)) { 390 fprintf(stderr, "FAIL (%s): EVP_DigestInit_ex failed\n", 391 label); 392 goto failed; 393 } 394 395 in_len = st->in_len / 2; 396 if (!EVP_DigestUpdate(hash, st->in, in_len)) { 397 fprintf(stderr, 398 "FAIL (%s): EVP_DigestUpdate first half failed\n", 399 label); 400 goto failed; 401 } 402 403 if (!EVP_DigestUpdate(hash, st->in + in_len, 404 st->in_len - in_len)) { 405 fprintf(stderr, 406 "FAIL (%s): EVP_DigestUpdate second half failed\n", 407 label); 408 goto failed; 409 } 410 411 if (!EVP_DigestFinal_ex(hash, out, NULL)) { 412 fprintf(stderr, 413 "FAIL (%s): EVP_DigestFinal_ex failed\n", 414 label); 415 goto failed; 416 } 417 418 if (memcmp(st->out, out, out_len) != 0) { 419 fprintf(stderr, "FAIL (%s): EVP mismatch\n", label); 420 goto failed; 421 } 422 } 423 424 failed = 0; 425 426 failed: 427 EVP_MD_CTX_free(hash); 428 return failed; 429 } 430 431 int 432 main(int argc, char **argv) 433 { 434 int failed = 0; 435 436 failed |= sha_test(); 437 438 return failed; 439 } 440