diff options
author | tb <> | 2018-10-06 09:27:40 +0000 |
---|---|---|
committer | tb <> | 2018-10-06 09:27:40 +0000 |
commit | 68398a11c328b8a379c929ba0344d74a29a074c9 (patch) | |
tree | 5a3276f7a6a92101e06882531a7112efe991d380 | |
parent | 911cbfac0e722a581b0a8151823d1a2db2ff3d1e (diff) | |
download | openbsd-68398a11c328b8a379c929ba0344d74a29a074c9.tar.gz openbsd-68398a11c328b8a379c929ba0344d74a29a074c9.tar.bz2 openbsd-68398a11c328b8a379c929ba0344d74a29a074c9.zip |
Run Wycheproof ECDH Web Crypto test vectors against libcrypto.
-rw-r--r-- | src/regress/lib/libcrypto/wycheproof/wycheproof.go | 161 |
1 files changed, 155 insertions, 6 deletions
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof.go b/src/regress/lib/libcrypto/wycheproof/wycheproof.go index abf0d1da02..61dec505a8 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.73 2018/10/06 08:16:48 tb Exp $ */ | 1 | /* $OpenBSD: wycheproof.go,v 1.74 2018/10/06 09:27:40 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> |
@@ -72,6 +72,15 @@ type wycheproofJWKPublic struct { | |||
72 | Y string `json:"y"` | 72 | Y string `json:"y"` |
73 | } | 73 | } |
74 | 74 | ||
75 | type wycheproofJWKPrivate struct { | ||
76 | Crv string `json:"crv"` | ||
77 | D string `json:"d"` | ||
78 | KID string `json:"kid"` | ||
79 | KTY string `json:"kty"` | ||
80 | X string `json:"x"` | ||
81 | Y string `json:"y"` | ||
82 | } | ||
83 | |||
75 | type wycheproofTestGroupAesCbcPkcs5 struct { | 84 | type wycheproofTestGroupAesCbcPkcs5 struct { |
76 | IVSize int `json:"ivSize"` | 85 | IVSize int `json:"ivSize"` |
77 | KeySize int `json:"keySize"` | 86 | KeySize int `json:"keySize"` |
@@ -172,6 +181,23 @@ type wycheproofTestGroupECDH struct { | |||
172 | Tests []*wycheproofTestECDH `json:"tests"` | 181 | Tests []*wycheproofTestECDH `json:"tests"` |
173 | } | 182 | } |
174 | 183 | ||
184 | type wycheproofTestECDHWebCrypto struct { | ||
185 | TCID int `json:"tcId"` | ||
186 | Comment string `json:"comment"` | ||
187 | Public *wycheproofJWKPublic `json:"public"` | ||
188 | Private *wycheproofJWKPrivate `json:"private"` | ||
189 | Shared string `json:"shared"` | ||
190 | Result string `json:"result"` | ||
191 | Flags []string `json:"flags"` | ||
192 | } | ||
193 | |||
194 | type wycheproofTestGroupECDHWebCrypto struct { | ||
195 | Curve string `json:"curve"` | ||
196 | Encoding string `json:"encoding"` | ||
197 | Type string `json:"type"` | ||
198 | Tests []*wycheproofTestECDHWebCrypto `json:"tests"` | ||
199 | } | ||
200 | |||
175 | type wycheproofECDSAKey struct { | 201 | type wycheproofECDSAKey struct { |
176 | Curve string `json:"curve"` | 202 | Curve string `json:"curve"` |
177 | KeySize int `json:"keySize"` | 203 | KeySize int `json:"keySize"` |
@@ -1269,6 +1295,117 @@ func runECDHTestGroup(algorithm string, wtg *wycheproofTestGroupECDH) bool { | |||
1269 | return success | 1295 | return success |
1270 | } | 1296 | } |
1271 | 1297 | ||
1298 | func runECDHWebCryptoTest(nid int, wt *wycheproofTestECDHWebCrypto) bool { | ||
1299 | privKey := C.EC_KEY_new_by_curve_name(C.int(nid)) | ||
1300 | if privKey == nil { | ||
1301 | log.Fatalf("EC_KEY_new_by_curve_name failed") | ||
1302 | } | ||
1303 | defer C.EC_KEY_free(privKey) | ||
1304 | |||
1305 | var bnD *C.BIGNUM | ||
1306 | d, err := base64.RawURLEncoding.DecodeString(wt.Private.D) | ||
1307 | if err != nil { | ||
1308 | log.Fatalf("Failed to base64 decode d: %v", err) | ||
1309 | } | ||
1310 | bnD = C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&d[0])), (C.int)(len(d)), nil) | ||
1311 | if bnD == nil { | ||
1312 | log.Fatal("Failed to decode D") | ||
1313 | } | ||
1314 | defer C.BN_free(bnD) | ||
1315 | |||
1316 | ret := C.EC_KEY_set_private_key(privKey, bnD) | ||
1317 | if ret != 1 { | ||
1318 | fmt.Printf("FAIL: Test case %d (%q) %v - EC_KEY_set_private_key() = %d, want %v\n", wt.TCID, wt.Comment, wt.Flags, ret, wt.Result) | ||
1319 | return false | ||
1320 | } | ||
1321 | |||
1322 | group := C.EC_GROUP_new_by_curve_name(C.int(nid)) | ||
1323 | if group == nil { | ||
1324 | log.Fatal("Failed to get EC_GROUP") | ||
1325 | } | ||
1326 | pubPoint := C.EC_POINT_new(group) | ||
1327 | if pubPoint == nil { | ||
1328 | log.Fatal("Failed to create EC_POINT") | ||
1329 | } | ||
1330 | |||
1331 | var bnX *C.BIGNUM | ||
1332 | x, err := base64.RawURLEncoding.DecodeString(wt.Public.X) | ||
1333 | if err != nil { | ||
1334 | log.Fatalf("Failed to base64 decode x: %v", err) | ||
1335 | } | ||
1336 | bnX = C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&x[0])), (C.int)(len(x)), nil) | ||
1337 | if bnX == nil { | ||
1338 | log.Fatal("Failed to decode X") | ||
1339 | } | ||
1340 | defer C.BN_free(bnX) | ||
1341 | |||
1342 | var bnY *C.BIGNUM | ||
1343 | y, err := base64.RawURLEncoding.DecodeString(wt.Public.Y) | ||
1344 | if err != nil { | ||
1345 | log.Fatalf("Failed to base64 decode y: %v", err) | ||
1346 | } | ||
1347 | bnY = C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&y[0])), (C.int)(len(y)), nil) | ||
1348 | if bnY == nil { | ||
1349 | log.Fatal("Failed to decode Y") | ||
1350 | } | ||
1351 | defer C.BN_free(bnY) | ||
1352 | |||
1353 | ret = C.EC_POINT_set_affine_coordinates_GFp(group, pubPoint, bnX, bnY, nil) | ||
1354 | if ret != 1 { | ||
1355 | log.Fatal("Failed to set public key") | ||
1356 | } | ||
1357 | |||
1358 | privGroup := C.EC_KEY_get0_group(privKey) | ||
1359 | |||
1360 | secLen := (C.EC_GROUP_get_degree(privGroup) + 7) / 8 | ||
1361 | |||
1362 | secret := make([]byte, secLen) | ||
1363 | if secLen == 0 { | ||
1364 | secret = append(secret, 0) | ||
1365 | } | ||
1366 | |||
1367 | ret = C.ECDH_compute_key(unsafe.Pointer(&secret[0]), C.ulong(secLen), pubPoint, privKey, nil) | ||
1368 | if ret != C.int(secLen) { | ||
1369 | if wt.Result == "invalid" { | ||
1370 | return true | ||
1371 | } | ||
1372 | fmt.Printf("FAIL: Test case %d (%q) %v - ECDH_compute_key() = %d, want %d, result: %v\n", wt.TCID, wt.Comment, wt.Flags, ret, int(secLen), wt.Result) | ||
1373 | return false | ||
1374 | } | ||
1375 | |||
1376 | shared, err := hex.DecodeString(wt.Shared) | ||
1377 | if err != nil{ | ||
1378 | log.Fatalf("Failed to decode shared secret: %v", err) | ||
1379 | } | ||
1380 | |||
1381 | success := true | ||
1382 | if !bytes.Equal(shared, secret) { | ||
1383 | fmt.Printf("FAIL: Test case %d (%q) %v - expected and computed shared secret do not match, want %v\n", wt.TCID, wt.Comment, wt.Flags, wt.Result) | ||
1384 | success = false | ||
1385 | } | ||
1386 | if acceptableAudit && success && wt.Result == "acceptable" { | ||
1387 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
1388 | } | ||
1389 | return success | ||
1390 | } | ||
1391 | |||
1392 | func runECDHWebCryptoTestGroup(algorithm string, wtg *wycheproofTestGroupECDHWebCrypto) bool { | ||
1393 | fmt.Printf("Running %v test group %v with curve %v and %v encoding...\n", algorithm, wtg.Type, wtg.Curve, wtg.Encoding) | ||
1394 | |||
1395 | nid, err := nidFromString(wtg.Curve) | ||
1396 | if err != nil { | ||
1397 | log.Fatalf("Failed to get nid for curve: %v", err) | ||
1398 | } | ||
1399 | |||
1400 | success := true | ||
1401 | for _, wt := range wtg.Tests { | ||
1402 | if !runECDHWebCryptoTest(nid, wt) { | ||
1403 | success = false | ||
1404 | } | ||
1405 | } | ||
1406 | return success | ||
1407 | } | ||
1408 | |||
1272 | func runECDSATest(ecKey *C.EC_KEY, nid int, h hash.Hash, webcrypto bool, wt *wycheproofTestECDSA) bool { | 1409 | func runECDSATest(ecKey *C.EC_KEY, nid int, h hash.Hash, webcrypto bool, wt *wycheproofTestECDSA) bool { |
1273 | msg, err := hex.DecodeString(wt.Msg) | 1410 | msg, err := hex.DecodeString(wt.Msg) |
1274 | if err != nil { | 1411 | if err != nil { |
@@ -1717,7 +1854,11 @@ func runTestVectors(path string, webcrypto bool) bool { | |||
1717 | case "DSA": | 1854 | case "DSA": |
1718 | wtg = &wycheproofTestGroupDSA{} | 1855 | wtg = &wycheproofTestGroupDSA{} |
1719 | case "ECDH": | 1856 | case "ECDH": |
1720 | wtg = &wycheproofTestGroupECDH{} | 1857 | if webcrypto { |
1858 | wtg = &wycheproofTestGroupECDHWebCrypto{} | ||
1859 | } else { | ||
1860 | wtg = &wycheproofTestGroupECDH{} | ||
1861 | } | ||
1721 | case "ECDSA": | 1862 | case "ECDSA": |
1722 | if webcrypto { | 1863 | if webcrypto { |
1723 | wtg = &wycheproofTestGroupECDSAWebCrypto{} | 1864 | wtg = &wycheproofTestGroupECDSAWebCrypto{} |
@@ -1766,9 +1907,16 @@ func runTestVectors(path string, webcrypto bool) bool { | |||
1766 | success = false | 1907 | success = false |
1767 | } | 1908 | } |
1768 | case "ECDH": | 1909 | case "ECDH": |
1769 | if !runECDHTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDH)) { | 1910 | if webcrypto { |
1770 | success = false | 1911 | if !runECDHWebCryptoTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDHWebCrypto)) { |
1912 | success = false | ||
1913 | } | ||
1914 | } else { | ||
1915 | if !runECDHTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDH)) { | ||
1916 | success = false | ||
1917 | } | ||
1771 | } | 1918 | } |
1919 | |||
1772 | case "ECDSA": | 1920 | case "ECDSA": |
1773 | if webcrypto { | 1921 | if webcrypto { |
1774 | if !runECDSAWebCryptoTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDSAWebCrypto)) { | 1922 | if !runECDSAWebCryptoTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDSAWebCrypto)) { |
@@ -1818,7 +1966,8 @@ func main() { | |||
1818 | {"AES", "aes_[cg]*[^xv]_test.json"}, // Skip AES-EAX, AES-GCM-SIV and AES-SIV-CMAC. | 1966 | {"AES", "aes_[cg]*[^xv]_test.json"}, // Skip AES-EAX, AES-GCM-SIV and AES-SIV-CMAC. |
1819 | {"ChaCha20-Poly1305", "chacha20_poly1305_test.json"}, | 1967 | {"ChaCha20-Poly1305", "chacha20_poly1305_test.json"}, |
1820 | {"DSA", "dsa_test.json"}, | 1968 | {"DSA", "dsa_test.json"}, |
1821 | {"ECDH", "ecdh_[^w]*test.json"}, // Skip ecdh_webcrypto_test.json for now. | 1969 | {"ECDH", "ecdh_[^w]*test.json"}, |
1970 | {"ECDHWebCrypto", "ecdh_w*_test.json"}, | ||
1822 | {"ECDSA", "ecdsa_[^w]*test.json"}, | 1971 | {"ECDSA", "ecdsa_[^w]*test.json"}, |
1823 | {"ECDSAWebCrypto", "ecdsa_w*_test.json"}, | 1972 | {"ECDSAWebCrypto", "ecdsa_w*_test.json"}, |
1824 | {"RSA", "rsa_*test.json"}, | 1973 | {"RSA", "rsa_*test.json"}, |
@@ -1828,7 +1977,7 @@ func main() { | |||
1828 | success := true | 1977 | success := true |
1829 | 1978 | ||
1830 | for _, test := range tests { | 1979 | for _, test := range tests { |
1831 | webcrypto := (test.name == "ECDSAWebCrypto") | 1980 | webcrypto := (test.name == "ECDSAWebCrypto") || test.name == "ECDHWebCrypto" |
1832 | tvs, err := filepath.Glob(filepath.Join(testVectorPath, test.pattern)) | 1981 | tvs, err := filepath.Glob(filepath.Join(testVectorPath, test.pattern)) |
1833 | if err != nil { | 1982 | if err != nil { |
1834 | log.Fatalf("Failed to glob %v test vectors: %v", test.name, err) | 1983 | log.Fatalf("Failed to glob %v test vectors: %v", test.name, err) |