diff options
Diffstat (limited to '')
| -rw-r--r-- | src/regress/lib/libcrypto/wycheproof/wycheproof.go | 190 |
1 files changed, 189 insertions, 1 deletions
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof.go b/src/regress/lib/libcrypto/wycheproof/wycheproof.go index dbe4f0272e..5e2b4c9758 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.22 2018/08/26 17:35:40 tb Exp $ */ | 1 | /* $OpenBSD: wycheproof.go,v 1.23 2018/08/26 17:38:16 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> |
| @@ -56,6 +56,24 @@ import ( | |||
| 56 | 56 | ||
| 57 | const testVectorPath = "/usr/local/share/wycheproof/testvectors" | 57 | const testVectorPath = "/usr/local/share/wycheproof/testvectors" |
| 58 | 58 | ||
| 59 | type wycheproofTestGroupAesCbcPkcs5 struct { | ||
| 60 | IVSize int `json:"ivSize"` | ||
| 61 | KeySize int `json:"keySize"` | ||
| 62 | Type string `json:"type"` | ||
| 63 | Tests []*wycheproofTestAesCbcPkcs5 `json:"tests"` | ||
| 64 | } | ||
| 65 | |||
| 66 | type wycheproofTestAesCbcPkcs5 struct { | ||
| 67 | TCID int `json:"tcId"` | ||
| 68 | Comment string `json:"comment"` | ||
| 69 | Key string `json:"key"` | ||
| 70 | IV string `json:"iv"` | ||
| 71 | Msg string `json:"msg"` | ||
| 72 | CT string `json:"ct"` | ||
| 73 | Result string `json:"result"` | ||
| 74 | Flags []string `json:"flags"` | ||
| 75 | } | ||
| 76 | |||
| 59 | type wycheproofTestGroupChaCha20Poly1305 struct { | 77 | type wycheproofTestGroupChaCha20Poly1305 struct { |
| 60 | IVSize int `json:"ivSize"` | 78 | IVSize int `json:"ivSize"` |
| 61 | KeySize int `json:"keySize"` | 79 | KeySize int `json:"keySize"` |
| @@ -225,6 +243,169 @@ func hashFromString(hs string) (hash.Hash, error) { | |||
| 225 | } | 243 | } |
| 226 | } | 244 | } |
| 227 | 245 | ||
| 246 | func checkAesCbcPkcs5Open(ctx *C.EVP_CIPHER_CTX, key []byte, keyLen int, iv []byte, ivLen int, ct []byte, ctLen int, msg []byte, msgLen int, wt *wycheproofTestAesCbcPkcs5) bool { | ||
| 247 | C.EVP_CipherInit_ex(ctx, nil, nil, (*C.uchar)(unsafe.Pointer(&key[0])), (*C.uchar)(unsafe.Pointer(&iv[0])), 0) | ||
| 248 | |||
| 249 | out := make([]byte, ctLen) | ||
| 250 | var outlen C.int | ||
| 251 | |||
| 252 | ret := C.EVP_CipherUpdate(ctx, (*C.uchar)(unsafe.Pointer(&out[0])), &outlen, (*C.uchar)(unsafe.Pointer(&ct[0])), C.int(ctLen)) | ||
| 253 | if ret != 1 { | ||
| 254 | if wt.Result == "invalid" { | ||
| 255 | fmt.Printf("INFO: Test case %d (%q) - EVP_CipherUpdate() = %d, want %v\n", wt.TCID, wt.Comment, ret, wt.Result) | ||
| 256 | return true | ||
| 257 | } | ||
| 258 | fmt.Printf("FAIL: Test case %d (%q) - EVP_CipherUpdate() = %d, want %v\n", wt.TCID, wt.Comment, ret, wt.Result) | ||
| 259 | return false | ||
| 260 | } | ||
| 261 | |||
| 262 | var finallen C.int | ||
| 263 | ret = C.EVP_CipherFinal_ex(ctx, (*C.uchar)(unsafe.Pointer(&out[outlen])), &finallen) | ||
| 264 | if ret != 1 { | ||
| 265 | if wt.Result == "invalid" { | ||
| 266 | return true | ||
| 267 | } | ||
| 268 | fmt.Printf("FAIL: Test case %d (%q) - EVP_CipherFinal_ex() = %d, want %v\n", wt.TCID, wt.Comment, ret, wt.Result) | ||
| 269 | return false | ||
| 270 | } | ||
| 271 | |||
| 272 | outlen += finallen | ||
| 273 | if (outlen != C.int(msgLen)) { | ||
| 274 | fmt.Printf("FAIL: Test case %d (%q) - open length mismatch: got %d, want %d\n", wt.TCID, wt.Comment, outlen, msgLen) | ||
| 275 | return false | ||
| 276 | } | ||
| 277 | |||
| 278 | openedMsg := out[0:outlen] | ||
| 279 | if (msgLen == 0) { | ||
| 280 | msg = nil | ||
| 281 | } | ||
| 282 | |||
| 283 | success := false | ||
| 284 | if (bytes.Equal(openedMsg, msg)) || wt.Result == "invalid" { | ||
| 285 | success = true | ||
| 286 | } else { | ||
| 287 | fmt.Printf("FAIL: Test case %d (%q) - msg match: %t; want %v\n", wt.TCID, wt.Comment, bytes.Equal(openedMsg, msg), wt.Result) | ||
| 288 | } | ||
| 289 | return success | ||
| 290 | } | ||
| 291 | |||
| 292 | func checkAesCbcPkcs5Seal(ctx *C.EVP_CIPHER_CTX, key []byte, keyLen int, iv []byte, ivLen int, ct []byte, ctLen int, msg []byte, msgLen int, wt *wycheproofTestAesCbcPkcs5) bool { | ||
| 293 | C.EVP_CipherInit_ex(ctx, nil, nil, (*C.uchar)(unsafe.Pointer(&key[0])), (*C.uchar)(unsafe.Pointer(&iv[0])), 1) | ||
| 294 | |||
| 295 | out := make([]byte, msgLen + C.EVP_MAX_BLOCK_LENGTH) | ||
| 296 | var outlen C.int | ||
| 297 | |||
| 298 | ret := C.EVP_CipherUpdate(ctx, (*C.uchar)(unsafe.Pointer(&out[0])), &outlen, (*C.uchar)(unsafe.Pointer(&msg[0])), C.int(msgLen)) | ||
| 299 | if ret != 1 { | ||
| 300 | if wt.Result == "invalid" { | ||
| 301 | fmt.Printf("INFO: Test case %d (%q) - EVP_CipherUpdate() = %d, want %v\n", wt.TCID, wt.Comment, ret, wt.Result) | ||
| 302 | return true | ||
| 303 | } | ||
| 304 | fmt.Printf("FAIL: Test case %d (%q) - EVP_CipherUpdate() = %d, want %v\n", wt.TCID, wt.Comment, ret, wt.Result) | ||
| 305 | return false | ||
| 306 | } | ||
| 307 | |||
| 308 | var finallen C.int | ||
| 309 | ret = C.EVP_CipherFinal_ex(ctx, (*C.uchar)(unsafe.Pointer(&out[outlen])), &finallen) | ||
| 310 | if ret != 1 { | ||
| 311 | if wt.Result == "invalid" { | ||
| 312 | return true | ||
| 313 | } | ||
| 314 | fmt.Printf("FAIL: Test case %d (%q) - EVP_CipherFinal_ex() = %d, want %v\n", wt.TCID, wt.Comment, ret, wt.Result) | ||
| 315 | return false | ||
| 316 | } | ||
| 317 | |||
| 318 | outlen += finallen | ||
| 319 | if (outlen != C.int(ctLen) && wt.Result != "invalid") { | ||
| 320 | fmt.Printf("FAIL: Test case %d (%q) - open length mismatch: got %d, want %d; result: %v\n", wt.TCID, wt.Comment, outlen, msgLen, wt.Result) | ||
| 321 | return false | ||
| 322 | } | ||
| 323 | |||
| 324 | sealedMsg := out[0:outlen] | ||
| 325 | if (ctLen == 0) { | ||
| 326 | ct = nil | ||
| 327 | } | ||
| 328 | |||
| 329 | success := false | ||
| 330 | if (bytes.Equal(sealedMsg, ct)) || wt.Result == "invalid" { | ||
| 331 | success = true | ||
| 332 | } else { | ||
| 333 | fmt.Printf("FAIL: Test case %d (%q) - msg match: %t; want %v\n", wt.TCID, wt.Comment, bytes.Equal(sealedMsg, ct), wt.Result) | ||
| 334 | } | ||
| 335 | return success | ||
| 336 | } | ||
| 337 | |||
| 338 | func runAesCbcPkcs5Test(ctx *C.EVP_CIPHER_CTX, wt *wycheproofTestAesCbcPkcs5) bool { | ||
| 339 | key, err := hex.DecodeString(wt.Key) | ||
| 340 | if err != nil { | ||
| 341 | log.Fatalf("Failed to decode key %q: %v", wt.Key, err) | ||
| 342 | } | ||
| 343 | iv, err := hex.DecodeString(wt.IV) | ||
| 344 | if err != nil { | ||
| 345 | log.Fatalf("Failed to decode IV %q: %v", wt.IV, err) | ||
| 346 | } | ||
| 347 | ct, err := hex.DecodeString(wt.CT) | ||
| 348 | if err != nil { | ||
| 349 | log.Fatalf("Failed to decode CT %q: %v", wt.CT, err) | ||
| 350 | } | ||
| 351 | msg, err := hex.DecodeString(wt.Msg) | ||
| 352 | if err != nil { | ||
| 353 | log.Fatalf("Failed to decode message %q: %v", wt.Msg, err) | ||
| 354 | } | ||
| 355 | |||
| 356 | keyLen, ivLen, ctLen, msgLen := len(key), len(iv), len(ct), len(msg) | ||
| 357 | |||
| 358 | if (keyLen == 0) { | ||
| 359 | key = append(key, 0) | ||
| 360 | } | ||
| 361 | if (ivLen == 0) { | ||
| 362 | iv = append(iv, 0) | ||
| 363 | } | ||
| 364 | if (ctLen == 0) { | ||
| 365 | ct = append(ct, 0) | ||
| 366 | } | ||
| 367 | if (msgLen == 0) { | ||
| 368 | msg = append(msg, 0) | ||
| 369 | } | ||
| 370 | |||
| 371 | openSuccess := checkAesCbcPkcs5Open(ctx, key, keyLen, iv, ivLen, ct, ctLen, msg, msgLen, wt) | ||
| 372 | sealSuccess := checkAesCbcPkcs5Seal(ctx, key, keyLen, iv, ivLen, ct, ctLen, msg, msgLen, wt) | ||
| 373 | |||
| 374 | return openSuccess && sealSuccess | ||
| 375 | } | ||
| 376 | |||
| 377 | func runAesCbcPkcs5TestGroup(wtg *wycheproofTestGroupAesCbcPkcs5) bool { | ||
| 378 | fmt.Printf("Running AES-CBC-PKCS5 test group %v with IV size %d and key size %d\n", wtg.Type, wtg.IVSize, wtg.KeySize) | ||
| 379 | |||
| 380 | var cipher *C.EVP_CIPHER | ||
| 381 | switch wtg.KeySize { | ||
| 382 | case 128: | ||
| 383 | cipher = C.EVP_aes_128_cbc() | ||
| 384 | case 192: | ||
| 385 | cipher = C.EVP_aes_192_cbc() | ||
| 386 | case 256: | ||
| 387 | cipher = C.EVP_aes_256_cbc() | ||
| 388 | default: | ||
| 389 | log.Fatalf("Unsupported key size: %d", wtg.KeySize) | ||
| 390 | } | ||
| 391 | |||
| 392 | ctx := C.EVP_CIPHER_CTX_new() | ||
| 393 | if ctx == nil { | ||
| 394 | log.Fatal("EVP_CIPHER_CTX_new() failed") | ||
| 395 | } | ||
| 396 | defer C.EVP_CIPHER_CTX_free(ctx) | ||
| 397 | |||
| 398 | C.EVP_CipherInit_ex(ctx, cipher, nil, nil, nil, 0) | ||
| 399 | |||
| 400 | success := true | ||
| 401 | for _, wt := range wtg.Tests { | ||
| 402 | if !runAesCbcPkcs5Test(ctx, wt) { | ||
| 403 | success = false | ||
| 404 | } | ||
| 405 | } | ||
| 406 | return success | ||
| 407 | } | ||
| 408 | |||
| 228 | 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 { | 409 | 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 { |
| 229 | maxOutLen := ctLen + tagLen | 410 | maxOutLen := ctLen + tagLen |
| 230 | 411 | ||
| @@ -728,6 +909,8 @@ func runTestVectors(path string) bool { | |||
| 728 | 909 | ||
| 729 | var wtg interface{} | 910 | var wtg interface{} |
| 730 | switch wtv.Algorithm { | 911 | switch wtv.Algorithm { |
| 912 | case "AES-CBC-PKCS5": | ||
| 913 | wtg = &wycheproofTestGroupAesCbcPkcs5{} | ||
| 731 | case "CHACHA20-POLY1305": | 914 | case "CHACHA20-POLY1305": |
| 732 | wtg = &wycheproofTestGroupChaCha20Poly1305{} | 915 | wtg = &wycheproofTestGroupChaCha20Poly1305{} |
| 733 | case "DSA": | 916 | case "DSA": |
| @@ -748,6 +931,10 @@ func runTestVectors(path string) bool { | |||
| 748 | log.Fatalf("Failed to unmarshal test groups JSON: %v", err) | 931 | log.Fatalf("Failed to unmarshal test groups JSON: %v", err) |
| 749 | } | 932 | } |
| 750 | switch wtv.Algorithm { | 933 | switch wtv.Algorithm { |
| 934 | case "AES-CBC-PKCS5": | ||
| 935 | if !runAesCbcPkcs5TestGroup(wtg.(*wycheproofTestGroupAesCbcPkcs5)) { | ||
| 936 | success = false | ||
| 937 | } | ||
| 751 | case "CHACHA20-POLY1305": | 938 | case "CHACHA20-POLY1305": |
| 752 | if !runChaCha20Poly1305TestGroup(wtg.(*wycheproofTestGroupChaCha20Poly1305)) { | 939 | if !runChaCha20Poly1305TestGroup(wtg.(*wycheproofTestGroupChaCha20Poly1305)) { |
| 753 | success = false | 940 | success = false |
| @@ -787,6 +974,7 @@ func main() { | |||
| 787 | name string | 974 | name string |
| 788 | pattern string | 975 | pattern string |
| 789 | }{ | 976 | }{ |
| 977 | {"AES", "aes_cbc*test.json"}, | ||
| 790 | {"ChaCha20-Poly1305", "chacha20_poly1305_test.json"}, | 978 | {"ChaCha20-Poly1305", "chacha20_poly1305_test.json"}, |
| 791 | {"DSA", "dsa_test.json"}, | 979 | {"DSA", "dsa_test.json"}, |
| 792 | {"ECDSA", "ecdsa_[^w]*test.json"}, // Skip ecdsa_webcrypto_test.json for now. | 980 | {"ECDSA", "ecdsa_[^w]*test.json"}, // Skip ecdsa_webcrypto_test.json for now. |
