diff options
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. |
