diff options
author | jsing <> | 2018-08-10 16:22:58 +0000 |
---|---|---|
committer | jsing <> | 2018-08-10 16:22:58 +0000 |
commit | e6625680fe64e577e004e285005ccd4500eb7437 (patch) | |
tree | fb3a69e57f165cff00e728e11466873646c3b963 /src | |
parent | 147f7e731ee7fba4625e336ab845bf98406dff14 (diff) | |
download | openbsd-e6625680fe64e577e004e285005ccd4500eb7437.tar.gz openbsd-e6625680fe64e577e004e285005ccd4500eb7437.tar.bz2 openbsd-e6625680fe64e577e004e285005ccd4500eb7437.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 'src')
-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 | } |