diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/regress/lib/libcrypto/wycheproof/wycheproof.go | 142 |
1 files changed, 141 insertions, 1 deletions
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof.go b/src/regress/lib/libcrypto/wycheproof/wycheproof.go index d145723877..c00a869f6f 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.5 2018/08/10 16:22:58 jsing Exp $ */ | 1 | /* $OpenBSD: wycheproof.go,v 1.6 2018/08/20 17:06:18 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2018 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -25,6 +25,7 @@ package main | |||
25 | #include <openssl/curve25519.h> | 25 | #include <openssl/curve25519.h> |
26 | #include <openssl/ec.h> | 26 | #include <openssl/ec.h> |
27 | #include <openssl/ecdsa.h> | 27 | #include <openssl/ecdsa.h> |
28 | #include <openssl/evp.h> | ||
28 | #include <openssl/objects.h> | 29 | #include <openssl/objects.h> |
29 | #include <openssl/rsa.h> | 30 | #include <openssl/rsa.h> |
30 | */ | 31 | */ |
@@ -48,6 +49,27 @@ import ( | |||
48 | 49 | ||
49 | const testVectorPath = "/usr/local/share/wycheproof/testvectors" | 50 | const testVectorPath = "/usr/local/share/wycheproof/testvectors" |
50 | 51 | ||
52 | type wycheproofTestGroupChaCha20Poly1305 struct { | ||
53 | IVSize int `json:"ivSize"` | ||
54 | KeySize int `json:"keySize"` | ||
55 | TagSize int `json:"tagSize"` | ||
56 | Type string `json:"type"` | ||
57 | Tests []*wycheproofTestChaCha20Poly1305 `json:"tests"` | ||
58 | } | ||
59 | |||
60 | type wycheproofTestChaCha20Poly1305 struct { | ||
61 | TCID int `json:"tcId"` | ||
62 | Comment string `json:"comment"` | ||
63 | Key string `json:"key"` | ||
64 | IV string `json:"iv"` | ||
65 | AAD string `json:"aad"` | ||
66 | Msg string `json:"msg"` | ||
67 | CT string `json:"ct"` | ||
68 | Tag string `json:"tag"` | ||
69 | Result string `json:"result"` | ||
70 | Flags []string `json:"flags"` | ||
71 | } | ||
72 | |||
51 | type wycheproofECDSAKey struct { | 73 | type wycheproofECDSAKey struct { |
52 | Curve string `json:"curve"` | 74 | Curve string `json:"curve"` |
53 | KeySize int `json:"keySize"` | 75 | KeySize int `json:"keySize"` |
@@ -169,6 +191,117 @@ func hashFromString(hs string) (hash.Hash, error) { | |||
169 | } | 191 | } |
170 | } | 192 | } |
171 | 193 | ||
194 | func runChaCha20Poly1305Test(iv_len int, key_len int, tag_len int, wt *wycheproofTestChaCha20Poly1305) bool { | ||
195 | aead := C.EVP_aead_chacha20_poly1305() | ||
196 | if aead == nil { | ||
197 | log.Fatal("EVP_aead_chacha20_poly1305 failed") | ||
198 | } | ||
199 | |||
200 | key, err := hex.DecodeString(wt.Key) | ||
201 | if err != nil { | ||
202 | log.Fatalf("Failed to decode key %q: %v", wt.Key, err) | ||
203 | } | ||
204 | if key_len != len(key) { | ||
205 | log.Fatalf("Key length mismatch: got %d, want %d", len(key), key_len) | ||
206 | } | ||
207 | |||
208 | var ctx C.EVP_AEAD_CTX | ||
209 | if C.EVP_AEAD_CTX_init((*C.EVP_AEAD_CTX)(unsafe.Pointer(&ctx)), aead, (*C.uchar)(unsafe.Pointer(&key[0])), C.size_t(key_len), C.size_t(tag_len), nil) != 1 { | ||
210 | log.Fatalf("Failed to initialize AEAD context") | ||
211 | } | ||
212 | |||
213 | iv, err := hex.DecodeString(wt.IV) | ||
214 | if err != nil { | ||
215 | log.Fatalf("Failed to decode key %q: %v", wt.IV, err) | ||
216 | } | ||
217 | if iv_len != len(iv) { | ||
218 | log.Fatalf("IV length mismatch: got %d, want %d", len(iv), iv_len) | ||
219 | } | ||
220 | aad, err := hex.DecodeString(wt.AAD) | ||
221 | if err != nil { | ||
222 | log.Fatalf("Failed to decode AAD %q: %v", wt.AAD, err) | ||
223 | } | ||
224 | msg, err := hex.DecodeString(wt.Msg) | ||
225 | if err != nil { | ||
226 | log.Fatalf("Failed to decode msg %q: %v", wt.Msg, err) | ||
227 | } | ||
228 | |||
229 | ivLen, aadLen, msgLen := len(iv), len(aad), len(msg) | ||
230 | if ivLen == 0 { | ||
231 | iv = append(iv, 0) | ||
232 | } | ||
233 | if aadLen == 0 { | ||
234 | aad = append(aad, 0) | ||
235 | } | ||
236 | if msgLen == 0 { | ||
237 | msg = append(msg, 0) | ||
238 | } | ||
239 | |||
240 | maxOutLen := msgLen + tag_len | ||
241 | out := make([]byte, maxOutLen) | ||
242 | var outLen C.size_t | ||
243 | |||
244 | ret := C.EVP_AEAD_CTX_seal((*C.EVP_AEAD_CTX)(unsafe.Pointer(&ctx)), (*C.uint8_t)(unsafe.Pointer(&out[0])), (*C.size_t)(unsafe.Pointer(&outLen)), C.size_t(maxOutLen), (*C.uint8_t)(unsafe.Pointer(&iv[0])), C.size_t(ivLen), (*C.uint8_t)(unsafe.Pointer(&msg[0])), C.size_t(msgLen), (*C.uint8_t)(unsafe.Pointer(&aad[0])), C.size_t(aadLen)) | ||
245 | |||
246 | C.EVP_AEAD_CTX_cleanup((*C.EVP_AEAD_CTX)(unsafe.Pointer(&ctx))) | ||
247 | |||
248 | if ret != 1 && wt.Result == "invalid" { | ||
249 | fmt.Printf("INFO: Test case %d (%q) - EVP_AEAD_CTX_seal() = %d, want %v\n", wt.TCID, wt.Comment, int(ret), wt.Result) | ||
250 | return true | ||
251 | } | ||
252 | |||
253 | if (outLen != C.size_t(maxOutLen)) { | ||
254 | fmt.Printf("FAIL: Test case %d (%q) - ChaCha output length mismatch: got %d, want %d", wt.TCID, wt.Comment, outLen, maxOutLen) | ||
255 | return false | ||
256 | } | ||
257 | |||
258 | outCt := out[0:msgLen] | ||
259 | outTag := out[msgLen: maxOutLen] | ||
260 | |||
261 | ct, err := hex.DecodeString(wt.CT) | ||
262 | if err != nil { | ||
263 | log.Fatalf("Failed to decode ct %q: %v", wt.CT, err) | ||
264 | } | ||
265 | if len(ct) != msgLen { | ||
266 | fmt.Printf("FAIL: Test case %d (%q) - msg length %d doesn't match ct length %d", wt.TCID, wt.Comment, msgLen, len(ct)) | ||
267 | return false | ||
268 | } | ||
269 | tag, err := hex.DecodeString(wt.Tag) | ||
270 | if err != nil { | ||
271 | log.Fatalf("Failed to decode tag %q: %v", wt.Tag, err) | ||
272 | } | ||
273 | if len(tag) != tag_len { | ||
274 | fmt.Printf("FAIL: Test case %d (%q) tag length: got %d, want %d", wt.TCID, wt.Comment, len(tag), tag_len) | ||
275 | return false | ||
276 | } | ||
277 | |||
278 | success := false | ||
279 | if (bytes.Equal(outCt, ct) && bytes.Equal(outTag, tag)) || wt.Result == "invalid" { | ||
280 | success = true | ||
281 | } else { | ||
282 | fmt.Printf("FAIL: Test case %d (%q) - EVP_AEAD_CTX_seal() = %d, ct match: %t, tag match: %t; want %v\n", wt.TCID, wt.Comment, int(ret), bytes.Equal(outCt, ct), bytes.Equal(outTag, tag), wt.Result) | ||
283 | } | ||
284 | |||
285 | return success | ||
286 | } | ||
287 | |||
288 | func runChaCha20Poly1305TestGroup(wtg *wycheproofTestGroupChaCha20Poly1305) bool { | ||
289 | // We currently only support nonces of length 12 (96 bits) | ||
290 | if wtg.IVSize != 96 { | ||
291 | return true | ||
292 | } | ||
293 | |||
294 | fmt.Printf("Running ChaCha20-Poly1305 test group %v with IV size %d, key size %d, tag size %d...\n", wtg.Type, wtg.IVSize, wtg.KeySize, wtg.TagSize) | ||
295 | |||
296 | success := true | ||
297 | for _, wt := range wtg.Tests { | ||
298 | if !runChaCha20Poly1305Test(wtg.IVSize / 8, wtg.KeySize / 8, wtg.TagSize / 8, wt) { | ||
299 | success = false | ||
300 | } | ||
301 | } | ||
302 | return success | ||
303 | } | ||
304 | |||
172 | func runECDSATest(ecKey *C.EC_KEY, nid int, h hash.Hash, wt *wycheproofTestECDSA) bool { | 305 | func runECDSATest(ecKey *C.EC_KEY, nid int, h hash.Hash, wt *wycheproofTestECDSA) bool { |
173 | msg, err := hex.DecodeString(wt.Msg) | 306 | msg, err := hex.DecodeString(wt.Msg) |
174 | if err != nil { | 307 | if err != nil { |
@@ -390,6 +523,8 @@ func runTestVectors(path string) bool { | |||
390 | 523 | ||
391 | var wtg interface{} | 524 | var wtg interface{} |
392 | switch wtv.Algorithm { | 525 | switch wtv.Algorithm { |
526 | case "CHACHA20-POLY1305": | ||
527 | wtg = &wycheproofTestGroupChaCha20Poly1305{} | ||
393 | case "ECDSA": | 528 | case "ECDSA": |
394 | wtg = &wycheproofTestGroupECDSA{} | 529 | wtg = &wycheproofTestGroupECDSA{} |
395 | case "RSASig": | 530 | case "RSASig": |
@@ -406,6 +541,10 @@ func runTestVectors(path string) bool { | |||
406 | log.Fatalf("Failed to unmarshal test groups JSON: %v", err) | 541 | log.Fatalf("Failed to unmarshal test groups JSON: %v", err) |
407 | } | 542 | } |
408 | switch wtv.Algorithm { | 543 | switch wtv.Algorithm { |
544 | case "CHACHA20-POLY1305": | ||
545 | if !runChaCha20Poly1305TestGroup(wtg.(*wycheproofTestGroupChaCha20Poly1305)) { | ||
546 | success = false | ||
547 | } | ||
409 | case "ECDSA": | 548 | case "ECDSA": |
410 | if !runECDSATestGroup(wtg.(*wycheproofTestGroupECDSA)) { | 549 | if !runECDSATestGroup(wtg.(*wycheproofTestGroupECDSA)) { |
411 | success = false | 550 | success = false |
@@ -437,6 +576,7 @@ func main() { | |||
437 | name string | 576 | name string |
438 | pattern string | 577 | pattern string |
439 | }{ | 578 | }{ |
579 | {"ChaCha20-Poly1305", "chacha20_poly1305_test.json"}, | ||
440 | {"ECDSA", "ecdsa_[^w]*test.json"}, // Skip ecdsa_webcrypto_test.json for now. | 580 | {"ECDSA", "ecdsa_[^w]*test.json"}, // Skip ecdsa_webcrypto_test.json for now. |
441 | {"RSA signature", "rsa_signature_*test.json"}, | 581 | {"RSA signature", "rsa_signature_*test.json"}, |
442 | {"X25519", "x25519_*test.json"}, | 582 | {"X25519", "x25519_*test.json"}, |