summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2018-10-06 09:27:40 +0000
committertb <>2018-10-06 09:27:40 +0000
commit68398a11c328b8a379c929ba0344d74a29a074c9 (patch)
tree5a3276f7a6a92101e06882531a7112efe991d380
parent911cbfac0e722a581b0a8151823d1a2db2ff3d1e (diff)
downloadopenbsd-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.go161
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
75type 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
75type wycheproofTestGroupAesCbcPkcs5 struct { 84type 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
184type 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
194type wycheproofTestGroupECDHWebCrypto struct {
195 Curve string `json:"curve"`
196 Encoding string `json:"encoding"`
197 Type string `json:"type"`
198 Tests []*wycheproofTestECDHWebCrypto `json:"tests"`
199}
200
175type wycheproofECDSAKey struct { 201type 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
1298func 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
1392func 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
1272func runECDSATest(ecKey *C.EC_KEY, nid int, h hash.Hash, webcrypto bool, wt *wycheproofTestECDSA) bool { 1409func 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)