diff options
| author | tb <> | 2018-10-06 09:27:40 +0000 |
|---|---|---|
| committer | tb <> | 2018-10-06 09:27:40 +0000 |
| commit | 25c4bf7ab2da937ff4e90d394484609c7f981a72 (patch) | |
| tree | 5a3276f7a6a92101e06882531a7112efe991d380 /src | |
| parent | 08eb61d508d6b9a23293518f0212ea945bb4d7dd (diff) | |
| download | openbsd-25c4bf7ab2da937ff4e90d394484609c7f981a72.tar.gz openbsd-25c4bf7ab2da937ff4e90d394484609c7f981a72.tar.bz2 openbsd-25c4bf7ab2da937ff4e90d394484609c7f981a72.zip | |
Run Wycheproof ECDH Web Crypto test vectors against libcrypto.
Diffstat (limited to '')
| -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) |
