diff options
author | tb <> | 2018-08-27 20:58:02 +0000 |
---|---|---|
committer | tb <> | 2018-08-27 20:58:02 +0000 |
commit | 0b0ed1b25513323adfcddff2f06752e192bfbed0 (patch) | |
tree | 6a4ae91e1cf155155c9fa1de7485205ad04bf264 /src | |
parent | cf973d93a931fa3a2f6c7127e5bfbb0693d1d1a8 (diff) | |
download | openbsd-0b0ed1b25513323adfcddff2f06752e192bfbed0.tar.gz openbsd-0b0ed1b25513323adfcddff2f06752e192bfbed0.tar.bz2 openbsd-0b0ed1b25513323adfcddff2f06752e192bfbed0.zip |
Run Wycheproof AES-CCM testvectors against libcrypto.
Diffstat (limited to 'src')
-rw-r--r-- | src/regress/lib/libcrypto/wycheproof/wycheproof.go | 202 |
1 files changed, 200 insertions, 2 deletions
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof.go b/src/regress/lib/libcrypto/wycheproof/wycheproof.go index 76e384fe55..ee9f533523 100644 --- a/src/regress/lib/libcrypto/wycheproof/wycheproof.go +++ b/src/regress/lib/libcrypto/wycheproof/wycheproof.go | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: wycheproof.go,v 1.24 2018/08/26 17:43:39 tb Exp $ */ | 1 | /* $OpenBSD: wycheproof.go,v 1.25 2018/08/27 20:58:02 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2018 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018 Joel Sing <jsing@openbsd.org> |
4 | * Copyright (c) 2018 Theo Buehler <tb@openbsd.org> | 4 | * Copyright (c) 2018 Theo Buehler <tb@openbsd.org> |
@@ -74,6 +74,27 @@ type wycheproofTestAesCbcPkcs5 struct { | |||
74 | Flags []string `json:"flags"` | 74 | Flags []string `json:"flags"` |
75 | } | 75 | } |
76 | 76 | ||
77 | type wycheproofTestGroupAesCcm struct { | ||
78 | IVSize int `json:"ivSize"` | ||
79 | KeySize int `json:"keySize"` | ||
80 | TagSize int `json:"tagSize"` | ||
81 | Type string `json:"type"` | ||
82 | Tests []*wycheproofTestAesCcm `json:"tests"` | ||
83 | } | ||
84 | |||
85 | type wycheproofTestAesCcm struct { | ||
86 | TCID int `json:"tcId"` | ||
87 | Comment string `json:"comment"` | ||
88 | Key string `json:"key"` | ||
89 | IV string `json:"iv"` | ||
90 | AAD string `json:"aad"` | ||
91 | Msg string `json:"msg"` | ||
92 | CT string `json:"ct"` | ||
93 | Tag string `json:"tag"` | ||
94 | Result string `json:"result"` | ||
95 | Flags []string `json:"flags"` | ||
96 | } | ||
97 | |||
77 | type wycheproofTestGroupChaCha20Poly1305 struct { | 98 | type wycheproofTestGroupChaCha20Poly1305 struct { |
78 | IVSize int `json:"ivSize"` | 99 | IVSize int `json:"ivSize"` |
79 | KeySize int `json:"keySize"` | 100 | KeySize int `json:"keySize"` |
@@ -415,6 +436,177 @@ func runAesCbcPkcs5TestGroup(wtg *wycheproofTestGroupAesCbcPkcs5) bool { | |||
415 | return success | 436 | return success |
416 | } | 437 | } |
417 | 438 | ||
439 | func checkAesCcm(ctx *C.EVP_CIPHER_CTX, doEncrypt int, key []byte, keyLen int, iv []byte, ivLen int, aad []byte, aadLen int, in []byte, inLen int, out []byte, outLen int, tag []byte, tagLen int, wt *wycheproofTestAesCcm) bool { | ||
440 | setTag := unsafe.Pointer(nil) | ||
441 | var action string | ||
442 | |||
443 | if doEncrypt == 1 { | ||
444 | action = "encrypting" | ||
445 | } else { | ||
446 | action = "decrypting" | ||
447 | setTag = unsafe.Pointer(&tag[0]) | ||
448 | } | ||
449 | |||
450 | ret := C.EVP_CipherInit_ex(ctx, nil, nil, nil, nil, C.int(doEncrypt)) | ||
451 | if ret != 1 { | ||
452 | log.Fatalf("[%v] cipher init failed", action) | ||
453 | } | ||
454 | |||
455 | ret = C.EVP_CIPHER_CTX_ctrl(ctx, C.EVP_CTRL_CCM_SET_IVLEN, C.int(ivLen), nil) | ||
456 | if ret != 1 { | ||
457 | if (wt.Comment == "Nonce is too long" || wt.Comment == "Invalid nonce size") { | ||
458 | return true | ||
459 | } | ||
460 | fmt.Printf("FAIL: Test case %d (%q) [%v]: setting IV len to %d failed. got %d, want %v\n", wt.TCID, wt.Comment, action, ivLen, ret, wt.Result) | ||
461 | return false | ||
462 | } | ||
463 | |||
464 | ret = C.EVP_CIPHER_CTX_ctrl(ctx, C.EVP_CTRL_CCM_SET_TAG, C.int(tagLen), setTag) | ||
465 | if ret != 1 { | ||
466 | if (wt.Comment == "Invalid tag size") { | ||
467 | return true | ||
468 | } | ||
469 | fmt.Printf("FAIL: Test case %d (%q) [%v]: setting tag length to %d failed. got %d, want %v\n", wt.TCID, wt.Comment, action, tagLen, ret, wt.Result) | ||
470 | return false | ||
471 | } | ||
472 | |||
473 | ret = C.EVP_CipherInit_ex(ctx, nil, nil, (*C.uchar)(unsafe.Pointer(&key[0])), (*C.uchar)(unsafe.Pointer(&iv[0])), C.int(doEncrypt)) | ||
474 | if ret != 1 { | ||
475 | fmt.Printf("FAIL: Test case %d (%q) [%v]: setting key and IV failed. got %d, want %v\n", wt.TCID, wt.Comment, action, ret, wt.Result) | ||
476 | return false | ||
477 | } | ||
478 | |||
479 | var cipherOutLen C.int | ||
480 | ret = C.EVP_CipherUpdate(ctx, nil, &cipherOutLen, nil, C.int(inLen)) | ||
481 | if ret != 1 { | ||
482 | fmt.Printf("FAIL: Test case %d (%q) [%v]: setting input length to %d failed. got %d, want %v\n", wt.TCID, wt.Comment, action, inLen, ret, wt.Result) | ||
483 | return false | ||
484 | } | ||
485 | |||
486 | ret = C.EVP_CipherUpdate(ctx, nil, &cipherOutLen, (*C.uchar)(unsafe.Pointer(&aad[0])), C.int(aadLen)) | ||
487 | if ret != 1 { | ||
488 | fmt.Printf("FAIL: Test case %d (%q) [%v]: processing AAD failed. got %d, want %v\n", wt.TCID, wt.Comment, action, ret, wt.Result) | ||
489 | return false | ||
490 | } | ||
491 | |||
492 | cipherOutLen = 0 | ||
493 | cipherOut := make([]byte, inLen) | ||
494 | if inLen == 0 { | ||
495 | cipherOut = append(cipherOut, 0) | ||
496 | } | ||
497 | |||
498 | ret = C.EVP_CipherUpdate(ctx, (*C.uchar)(unsafe.Pointer(&cipherOut[0])), &cipherOutLen, (*C.uchar)(unsafe.Pointer(&in[0])), C.int(inLen)) | ||
499 | if ret != 1 { | ||
500 | if wt.Result == "invalid" { | ||
501 | return true | ||
502 | } | ||
503 | fmt.Printf("FAIL: Test case %d (%q) [%v]: EVP_CipherUpdate failed: got %d, want %v\n", wt.TCID, wt.Comment, action, ret, wt.Result) | ||
504 | return false | ||
505 | } | ||
506 | |||
507 | if cipherOutLen != C.int(outLen) { | ||
508 | fmt.Printf("FAIL: Test case %d (%q) [%v]: cipherOutLen %d != outLen %d. Result %v\n", wt.TCID, wt.Comment, cipherOutLen, action, outLen, wt.Result) | ||
509 | return false | ||
510 | } | ||
511 | |||
512 | success := true | ||
513 | if !bytes.Equal(cipherOut, out) { | ||
514 | fmt.Printf("FAIL: Test case %d (%q) [%v]: expected and computed output do not match. Result.%v\n", wt.TCID, wt.Comment, action, wt.Result) | ||
515 | success = false | ||
516 | } | ||
517 | return success | ||
518 | } | ||
519 | |||
520 | func runAesCcmTest(ctx *C.EVP_CIPHER_CTX, wt *wycheproofTestAesCcm) bool { | ||
521 | key, err := hex.DecodeString(wt.Key) | ||
522 | if err != nil { | ||
523 | log.Fatalf("Failed to decode key %q: %v", wt.Key, err) | ||
524 | } | ||
525 | |||
526 | iv, err := hex.DecodeString(wt.IV) | ||
527 | if err != nil { | ||
528 | log.Fatalf("Failed to decode IV %q: %v", wt.IV, err) | ||
529 | } | ||
530 | |||
531 | aad, err := hex.DecodeString(wt.AAD) | ||
532 | if err != nil { | ||
533 | log.Fatalf("Failed to decode AAD %q: %v", wt.AAD, err) | ||
534 | } | ||
535 | |||
536 | msg, err := hex.DecodeString(wt.Msg) | ||
537 | if err != nil { | ||
538 | log.Fatalf("Failed to decode msg %q: %v", wt.Msg, err) | ||
539 | } | ||
540 | |||
541 | ct, err := hex.DecodeString(wt.CT) | ||
542 | if err != nil { | ||
543 | log.Fatalf("Failed to decode CT %q: %v", wt.CT, err) | ||
544 | } | ||
545 | |||
546 | tag, err := hex.DecodeString(wt.Tag) | ||
547 | if err != nil { | ||
548 | log.Fatalf("Failed to decode tag %q: %v", wt.Tag, err) | ||
549 | } | ||
550 | |||
551 | keyLen, ivLen, aadLen, msgLen, ctLen, tagLen := len(key), len(iv), len(aad), len(msg), len(ct), len(tag) | ||
552 | |||
553 | if keyLen == 0 { | ||
554 | key = append(key, 0) | ||
555 | } | ||
556 | if ivLen == 0 { | ||
557 | iv = append(iv, 0) | ||
558 | } | ||
559 | if aadLen == 0 { | ||
560 | aad = append(aad, 0) | ||
561 | } | ||
562 | if msgLen == 0 { | ||
563 | msg = append(msg, 0) | ||
564 | } | ||
565 | if ctLen == 0 { | ||
566 | ct = append(ct, 0) | ||
567 | } | ||
568 | if tagLen == 0 { | ||
569 | tag = append(tag, 0) | ||
570 | } | ||
571 | |||
572 | openSuccess := checkAesCcm(ctx, 0, key, keyLen, iv, ivLen, aad, aadLen, ct, ctLen, msg, msgLen, tag, tagLen, wt) | ||
573 | sealSuccess := checkAesCcm(ctx, 1, key, keyLen, iv, ivLen, aad, aadLen, msg, msgLen, ct, ctLen, tag, tagLen, wt) | ||
574 | |||
575 | return openSuccess && sealSuccess | ||
576 | } | ||
577 | |||
578 | func runAesCcmTestGroup(wtg *wycheproofTestGroupAesCcm) bool { | ||
579 | fmt.Printf("Running AES-CCM test group %v with IV size %d, key size %d and tag size %d\n", wtg.Type, wtg.IVSize, wtg.KeySize, wtg.TagSize) | ||
580 | |||
581 | var cipher *C.EVP_CIPHER | ||
582 | switch wtg.KeySize { | ||
583 | case 128: | ||
584 | cipher = C.EVP_aes_128_ccm() | ||
585 | case 192: | ||
586 | cipher = C.EVP_aes_192_ccm() | ||
587 | case 256: | ||
588 | cipher = C.EVP_aes_256_ccm() | ||
589 | default: | ||
590 | log.Fatalf("Unsupported key size: %d", wtg.KeySize) | ||
591 | } | ||
592 | |||
593 | ctx := C.EVP_CIPHER_CTX_new() | ||
594 | if ctx == nil { | ||
595 | log.Fatal("EVP_CIPHER_CTX_new() failed") | ||
596 | } | ||
597 | defer C.EVP_CIPHER_CTX_free(ctx) | ||
598 | |||
599 | C.EVP_CipherInit_ex(ctx, cipher, nil, nil, nil, 1) | ||
600 | |||
601 | success := true | ||
602 | for _, wt := range wtg.Tests { | ||
603 | if !runAesCcmTest(ctx, wt) { | ||
604 | success = false | ||
605 | } | ||
606 | } | ||
607 | return success | ||
608 | } | ||
609 | |||
418 | func checkChaCha20Poly1305Open(ctx *C.EVP_AEAD_CTX, iv []byte, ivLen int, aad []byte, aadLen int, msg []byte, msgLen int, ct []byte, ctLen int, tag []byte, tagLen int, wt *wycheproofTestChaCha20Poly1305) bool { | 610 | func checkChaCha20Poly1305Open(ctx *C.EVP_AEAD_CTX, iv []byte, ivLen int, aad []byte, aadLen int, msg []byte, msgLen int, ct []byte, ctLen int, tag []byte, tagLen int, wt *wycheproofTestChaCha20Poly1305) bool { |
419 | maxOutLen := ctLen + tagLen | 611 | maxOutLen := ctLen + tagLen |
420 | 612 | ||
@@ -920,6 +1112,8 @@ func runTestVectors(path string) bool { | |||
920 | switch wtv.Algorithm { | 1112 | switch wtv.Algorithm { |
921 | case "AES-CBC-PKCS5": | 1113 | case "AES-CBC-PKCS5": |
922 | wtg = &wycheproofTestGroupAesCbcPkcs5{} | 1114 | wtg = &wycheproofTestGroupAesCbcPkcs5{} |
1115 | case "AES-CCM": | ||
1116 | wtg = &wycheproofTestGroupAesCcm{} | ||
923 | case "CHACHA20-POLY1305": | 1117 | case "CHACHA20-POLY1305": |
924 | wtg = &wycheproofTestGroupChaCha20Poly1305{} | 1118 | wtg = &wycheproofTestGroupChaCha20Poly1305{} |
925 | case "DSA": | 1119 | case "DSA": |
@@ -944,6 +1138,10 @@ func runTestVectors(path string) bool { | |||
944 | if !runAesCbcPkcs5TestGroup(wtg.(*wycheproofTestGroupAesCbcPkcs5)) { | 1138 | if !runAesCbcPkcs5TestGroup(wtg.(*wycheproofTestGroupAesCbcPkcs5)) { |
945 | success = false | 1139 | success = false |
946 | } | 1140 | } |
1141 | case "AES-CCM": | ||
1142 | if !runAesCcmTestGroup(wtg.(*wycheproofTestGroupAesCcm)) { | ||
1143 | success = false | ||
1144 | } | ||
947 | case "CHACHA20-POLY1305": | 1145 | case "CHACHA20-POLY1305": |
948 | if !runChaCha20Poly1305TestGroup(wtg.(*wycheproofTestGroupChaCha20Poly1305)) { | 1146 | if !runChaCha20Poly1305TestGroup(wtg.(*wycheproofTestGroupChaCha20Poly1305)) { |
949 | success = false | 1147 | success = false |
@@ -983,7 +1181,7 @@ func main() { | |||
983 | name string | 1181 | name string |
984 | pattern string | 1182 | pattern string |
985 | }{ | 1183 | }{ |
986 | {"AES", "aes_cbc*test.json"}, | 1184 | {"AES", "aes_c[bc]*test.json"}, |
987 | {"ChaCha20-Poly1305", "chacha20_poly1305_test.json"}, | 1185 | {"ChaCha20-Poly1305", "chacha20_poly1305_test.json"}, |
988 | {"DSA", "dsa_test.json"}, | 1186 | {"DSA", "dsa_test.json"}, |
989 | {"ECDSA", "ecdsa_[^w]*test.json"}, // Skip ecdsa_webcrypto_test.json for now. | 1187 | {"ECDSA", "ecdsa_[^w]*test.json"}, // Skip ecdsa_webcrypto_test.json for now. |