diff options
| author | jsing <> | 2018-08-10 16:22:58 +0000 |
|---|---|---|
| committer | jsing <> | 2018-08-10 16:22:58 +0000 |
| commit | 0ff3e48e08d4a139168e53beaaba5365134eef0b (patch) | |
| tree | fb3a69e57f165cff00e728e11466873646c3b963 /src | |
| parent | e5088e1e5d239cf506a36b2edf7c7aa236badb52 (diff) | |
| download | openbsd-0ff3e48e08d4a139168e53beaaba5365134eef0b.tar.gz openbsd-0ff3e48e08d4a139168e53beaaba5365134eef0b.tar.bz2 openbsd-0ff3e48e08d4a139168e53beaaba5365134eef0b.zip | |
Run the wycheproof ECDSA test vectors against libcrypto.
Skip the ecdsa_webcrypto_test.json vectors for the time being, as these
likely need some extra glue.
Diffstat (limited to '')
| -rw-r--r-- | src/regress/lib/libcrypto/wycheproof/wycheproof.go | 154 |
1 files changed, 147 insertions, 7 deletions
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof.go b/src/regress/lib/libcrypto/wycheproof/wycheproof.go index 427dc47aec..d145723877 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.4 2018/08/10 16:18:55 jsing Exp $ */ | 1 | /* $OpenBSD: wycheproof.go,v 1.5 2018/08/10 16:22:58 jsing Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2018 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -23,6 +23,8 @@ package main | |||
| 23 | 23 | ||
| 24 | #include <openssl/bn.h> | 24 | #include <openssl/bn.h> |
| 25 | #include <openssl/curve25519.h> | 25 | #include <openssl/curve25519.h> |
| 26 | #include <openssl/ec.h> | ||
| 27 | #include <openssl/ecdsa.h> | ||
| 26 | #include <openssl/objects.h> | 28 | #include <openssl/objects.h> |
| 27 | #include <openssl/rsa.h> | 29 | #include <openssl/rsa.h> |
| 28 | */ | 30 | */ |
| @@ -46,6 +48,33 @@ import ( | |||
| 46 | 48 | ||
| 47 | const testVectorPath = "/usr/local/share/wycheproof/testvectors" | 49 | const testVectorPath = "/usr/local/share/wycheproof/testvectors" |
| 48 | 50 | ||
| 51 | type wycheproofECDSAKey struct { | ||
| 52 | Curve string `json:"curve"` | ||
| 53 | KeySize int `json:"keySize"` | ||
| 54 | Type string `json:"type"` | ||
| 55 | Uncompressed string `json:"uncompressed"` | ||
| 56 | WX string `json:"wx"` | ||
| 57 | WY string `json:"wy"` | ||
| 58 | } | ||
| 59 | |||
| 60 | type wycheproofTestECDSA struct { | ||
| 61 | TCID int `json:"tcId"` | ||
| 62 | Comment string `json:"comment"` | ||
| 63 | Msg string `json:"msg"` | ||
| 64 | Sig string `json:"sig"` | ||
| 65 | Result string `json:"result"` | ||
| 66 | Flags []string `json:"flags"` | ||
| 67 | } | ||
| 68 | |||
| 69 | type wycheproofTestGroupECDSA struct { | ||
| 70 | Key *wycheproofECDSAKey `json:"key"` | ||
| 71 | KeyDER string `json:"keyDer"` | ||
| 72 | KeyPEM string `json:"keyPem"` | ||
| 73 | SHA string `json:"sha"` | ||
| 74 | Type string `json:"type"` | ||
| 75 | Tests []*wycheproofTestECDSA `json:"tests"` | ||
| 76 | } | ||
| 77 | |||
| 49 | type wycheproofTestRSA struct { | 78 | type wycheproofTestRSA struct { |
| 50 | TCID int `json:"tcId"` | 79 | TCID int `json:"tcId"` |
| 51 | Comment string `json:"comment"` | 80 | Comment string `json:"comment"` |
| @@ -94,11 +123,25 @@ type wycheproofTestVectors struct { | |||
| 94 | } | 123 | } |
| 95 | 124 | ||
| 96 | var nids = map[string]int{ | 125 | var nids = map[string]int{ |
| 97 | "SHA-1": C.NID_sha1, | 126 | "brainpoolP224r1": C.NID_brainpoolP224r1, |
| 98 | "SHA-224": C.NID_sha224, | 127 | "brainpoolP256r1": C.NID_brainpoolP256r1, |
| 99 | "SHA-256": C.NID_sha256, | 128 | "brainpoolP320r1": C.NID_brainpoolP320r1, |
| 100 | "SHA-384": C.NID_sha384, | 129 | "brainpoolP384r1": C.NID_brainpoolP384r1, |
| 101 | "SHA-512": C.NID_sha512, | 130 | "brainpoolP512r1": C.NID_brainpoolP512r1, |
| 131 | "brainpoolP224t1": C.NID_brainpoolP224t1, | ||
| 132 | "brainpoolP256t1": C.NID_brainpoolP256t1, | ||
| 133 | "brainpoolP320t1": C.NID_brainpoolP320t1, | ||
| 134 | "brainpoolP384t1": C.NID_brainpoolP384t1, | ||
| 135 | "brainpoolP512t1": C.NID_brainpoolP512t1, | ||
| 136 | "secp224r1": C.NID_secp224r1, | ||
| 137 | "secp256k1": C.NID_secp256k1, | ||
| 138 | "secp384r1": C.NID_secp384r1, | ||
| 139 | "secp521r1": C.NID_secp521r1, | ||
| 140 | "SHA-1": C.NID_sha1, | ||
| 141 | "SHA-224": C.NID_sha224, | ||
| 142 | "SHA-256": C.NID_sha256, | ||
| 143 | "SHA-384": C.NID_sha384, | ||
| 144 | "SHA-512": C.NID_sha512, | ||
| 102 | } | 145 | } |
| 103 | 146 | ||
| 104 | func nidFromString(ns string) (int, error) { | 147 | func nidFromString(ns string) (int, error) { |
| @@ -126,6 +169,96 @@ func hashFromString(hs string) (hash.Hash, error) { | |||
| 126 | } | 169 | } |
| 127 | } | 170 | } |
| 128 | 171 | ||
| 172 | func runECDSATest(ecKey *C.EC_KEY, nid int, h hash.Hash, wt *wycheproofTestECDSA) bool { | ||
| 173 | msg, err := hex.DecodeString(wt.Msg) | ||
| 174 | if err != nil { | ||
| 175 | log.Fatalf("Failed to decode message %q: %v", wt.Msg, err) | ||
| 176 | } | ||
| 177 | |||
| 178 | h.Reset() | ||
| 179 | h.Write(msg) | ||
| 180 | msg = h.Sum(nil) | ||
| 181 | |||
| 182 | sig, err := hex.DecodeString(wt.Sig) | ||
| 183 | if err != nil { | ||
| 184 | log.Fatalf("Failed to decode signature %q: %v", wt.Sig, err) | ||
| 185 | } | ||
| 186 | |||
| 187 | msgLen, sigLen := len(msg), len(sig) | ||
| 188 | if msgLen == 0 { | ||
| 189 | msg = append(msg, 0) | ||
| 190 | } | ||
| 191 | if sigLen == 0 { | ||
| 192 | sig = append(sig, 0) | ||
| 193 | } | ||
| 194 | ret := C.ECDSA_verify(0, (*C.uchar)(unsafe.Pointer(&msg[0])), C.int(msgLen), | ||
| 195 | (*C.uchar)(unsafe.Pointer(&sig[0])), C.int(sigLen), ecKey) | ||
| 196 | |||
| 197 | // XXX audit acceptable cases... | ||
| 198 | success := true | ||
| 199 | if (ret == 1) != (wt.Result == "valid") && wt.Result != "acceptable" { | ||
| 200 | fmt.Printf("FAIL: Test case %d (%q) - ECDSA_verify() = %d, want %v\n", wt.TCID, wt.Comment, int(ret), wt.Result) | ||
| 201 | success = false | ||
| 202 | } | ||
| 203 | return success | ||
| 204 | } | ||
| 205 | |||
| 206 | func runECDSATestGroup(wtg *wycheproofTestGroupECDSA) bool { | ||
| 207 | // No secp256r1 support. | ||
| 208 | if wtg.Key.Curve == "secp256r1" { | ||
| 209 | return true | ||
| 210 | } | ||
| 211 | |||
| 212 | fmt.Printf("Running ECDSA test group %v with curve %v, key size %d and %v...\n", wtg.Type, wtg.Key.Curve, wtg.Key.KeySize, wtg.SHA) | ||
| 213 | |||
| 214 | nid, err := nidFromString(wtg.Key.Curve) | ||
| 215 | if err != nil { | ||
| 216 | log.Fatalf("Failed to get nid for curve: %v", err) | ||
| 217 | } | ||
| 218 | ecKey := C.EC_KEY_new_by_curve_name(C.int(nid)) | ||
| 219 | if ecKey == nil { | ||
| 220 | log.Fatal("EC_KEY_new_by_curve_name failed") | ||
| 221 | } | ||
| 222 | defer C.EC_KEY_free(ecKey) | ||
| 223 | |||
| 224 | var bnX *C.BIGNUM | ||
| 225 | wx := C.CString(wtg.Key.WX) | ||
| 226 | if C.BN_hex2bn(&bnX, wx) == 0 { | ||
| 227 | log.Fatal("Failed to decode WX") | ||
| 228 | } | ||
| 229 | C.free(unsafe.Pointer(wx)) | ||
| 230 | defer C.BN_free(bnX) | ||
| 231 | |||
| 232 | var bnY *C.BIGNUM | ||
| 233 | wy := C.CString(wtg.Key.WY) | ||
| 234 | if C.BN_hex2bn(&bnY, wy) == 0 { | ||
| 235 | log.Fatal("Failed to decode WY") | ||
| 236 | } | ||
| 237 | C.free(unsafe.Pointer(wy)) | ||
| 238 | defer C.BN_free(bnY) | ||
| 239 | |||
| 240 | if C.EC_KEY_set_public_key_affine_coordinates(ecKey, bnX, bnY) != 1 { | ||
| 241 | log.Fatal("Failed to set EC public key") | ||
| 242 | } | ||
| 243 | |||
| 244 | nid, err = nidFromString(wtg.SHA) | ||
| 245 | if err != nil { | ||
| 246 | log.Fatalf("Failed to get MD NID: %v", err) | ||
| 247 | } | ||
| 248 | h, err := hashFromString(wtg.SHA) | ||
| 249 | if err != nil { | ||
| 250 | log.Fatalf("Failed to get hash: %v", err) | ||
| 251 | } | ||
| 252 | |||
| 253 | success := true | ||
| 254 | for _, wt := range wtg.Tests { | ||
| 255 | if !runECDSATest(ecKey, nid, h, wt) { | ||
| 256 | success = false | ||
| 257 | } | ||
| 258 | } | ||
| 259 | return success | ||
| 260 | } | ||
| 261 | |||
| 129 | func runRSATest(rsa *C.RSA, nid int, h hash.Hash, wt *wycheproofTestRSA) bool { | 262 | func runRSATest(rsa *C.RSA, nid int, h hash.Hash, wt *wycheproofTestRSA) bool { |
| 130 | msg, err := hex.DecodeString(wt.Msg) | 263 | msg, err := hex.DecodeString(wt.Msg) |
| 131 | if err != nil { | 264 | if err != nil { |
| @@ -257,6 +390,8 @@ func runTestVectors(path string) bool { | |||
| 257 | 390 | ||
| 258 | var wtg interface{} | 391 | var wtg interface{} |
| 259 | switch wtv.Algorithm { | 392 | switch wtv.Algorithm { |
| 393 | case "ECDSA": | ||
| 394 | wtg = &wycheproofTestGroupECDSA{} | ||
| 260 | case "RSASig": | 395 | case "RSASig": |
| 261 | wtg = &wycheproofTestGroupRSA{} | 396 | wtg = &wycheproofTestGroupRSA{} |
| 262 | case "X25519": | 397 | case "X25519": |
| @@ -271,6 +406,10 @@ func runTestVectors(path string) bool { | |||
| 271 | log.Fatalf("Failed to unmarshal test groups JSON: %v", err) | 406 | log.Fatalf("Failed to unmarshal test groups JSON: %v", err) |
| 272 | } | 407 | } |
| 273 | switch wtv.Algorithm { | 408 | switch wtv.Algorithm { |
| 409 | case "ECDSA": | ||
| 410 | if !runECDSATestGroup(wtg.(*wycheproofTestGroupECDSA)) { | ||
| 411 | success = false | ||
| 412 | } | ||
| 274 | case "RSASig": | 413 | case "RSASig": |
| 275 | if !runRSATestGroup(wtg.(*wycheproofTestGroupRSA)) { | 414 | if !runRSATestGroup(wtg.(*wycheproofTestGroupRSA)) { |
| 276 | success = false | 415 | success = false |
| @@ -293,11 +432,12 @@ func main() { | |||
| 293 | os.Exit(0) | 432 | os.Exit(0) |
| 294 | } | 433 | } |
| 295 | 434 | ||
| 296 | // TODO: AES, Chacha20Poly1305, DSA, ECDH, ECDSA, RSA-PSS. | 435 | // AES, Chacha20Poly1305, DSA, ECDH |
| 297 | tests := []struct { | 436 | tests := []struct { |
| 298 | name string | 437 | name string |
| 299 | pattern string | 438 | pattern string |
| 300 | }{ | 439 | }{ |
| 440 | {"ECDSA", "ecdsa_[^w]*test.json"}, // Skip ecdsa_webcrypto_test.json for now. | ||
| 301 | {"RSA signature", "rsa_signature_*test.json"}, | 441 | {"RSA signature", "rsa_signature_*test.json"}, |
| 302 | {"X25519", "x25519_*test.json"}, | 442 | {"X25519", "x25519_*test.json"}, |
| 303 | } | 443 | } |
