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"}, |
