diff options
author | tb <> | 2018-08-26 17:38:16 +0000 |
---|---|---|
committer | tb <> | 2018-08-26 17:38:16 +0000 |
commit | 4088c520e78b350eb99a6827074a3e93b4239fa4 (patch) | |
tree | e6286d314ba542dbbc0a4d4b681e34f5e9899759 /src | |
parent | 61d5fc0435582bb13dda9052c4ad758c3c1cc569 (diff) | |
download | openbsd-4088c520e78b350eb99a6827074a3e93b4239fa4.tar.gz openbsd-4088c520e78b350eb99a6827074a3e93b4239fa4.tar.bz2 openbsd-4088c520e78b350eb99a6827074a3e93b4239fa4.zip |
Run Wycheproof AES-CBC-PKCS5 testvectors against libcrypto.
Diffstat (limited to 'src')
-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. |