summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2018-10-05 21:12:43 +0000
committertb <>2018-10-05 21:12:43 +0000
commit9b0ed526414df2e8b8ce6bc6293db69f42780270 (patch)
treec5aeb0b7f0d83b3593ce7913e9afcfe5766f9f4d
parentf8454e233d03abfbf8cdc6a3468948f72b0acb67 (diff)
downloadopenbsd-9b0ed526414df2e8b8ce6bc6293db69f42780270.tar.gz
openbsd-9b0ed526414df2e8b8ce6bc6293db69f42780270.tar.bz2
openbsd-9b0ed526414df2e8b8ce6bc6293db69f42780270.zip
Run Wycheproof ECDSA Web Crypto test vectors against libcrypto.
-rw-r--r--src/regress/lib/libcrypto/wycheproof/wycheproof.go173
1 files changed, 166 insertions, 7 deletions
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof.go b/src/regress/lib/libcrypto/wycheproof/wycheproof.go
index 7f693d04b0..ee99050b3e 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.69 2018/10/04 18:37:07 tb Exp $ */ 1/* $OpenBSD: wycheproof.go,v 1.70 2018/10/05 21:12:43 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>
@@ -45,6 +45,7 @@ import (
45 "crypto/sha256" 45 "crypto/sha256"
46 "crypto/sha512" 46 "crypto/sha512"
47 "encoding/hex" 47 "encoding/hex"
48 "encoding/base64"
48 "encoding/json" 49 "encoding/json"
49 "flag" 50 "flag"
50 "fmt" 51 "fmt"
@@ -63,6 +64,14 @@ var acceptableAudit = false
63var acceptableComments map[string]int 64var acceptableComments map[string]int
64var acceptableFlags map[string]int 65var acceptableFlags map[string]int
65 66
67type wycheproofJWKPublic struct {
68 Crv string `json:"crv"`
69 KID string `json:"kid"`
70 KTY string `json:"kty"`
71 X string `json:"x"`
72 Y string `json:"y"`
73}
74
66type wycheproofTestGroupAesCbcPkcs5 struct { 75type wycheproofTestGroupAesCbcPkcs5 struct {
67 IVSize int `json:"ivSize"` 76 IVSize int `json:"ivSize"`
68 KeySize int `json:"keySize"` 77 KeySize int `json:"keySize"`
@@ -190,6 +199,16 @@ type wycheproofTestGroupECDSA struct {
190 Tests []*wycheproofTestECDSA `json:"tests"` 199 Tests []*wycheproofTestECDSA `json:"tests"`
191} 200}
192 201
202type wycheproofTestGroupECDSAWebCrypto struct {
203 JWK *wycheproofJWKPublic `json:"jwk"`
204 Key *wycheproofECDSAKey `json:"key"`
205 KeyDER string `json:"keyDer"`
206 KeyPEM string `json:"keyPem"`
207 SHA string `json:"sha"`
208 Type string `json:"type"`
209 Tests []*wycheproofTestECDSA `json:"tests"`
210}
211
193type wycheproofTestRSA struct { 212type wycheproofTestRSA struct {
194 TCID int `json:"tcId"` 213 TCID int `json:"tcId"`
195 Comment string `json:"comment"` 214 Comment string `json:"comment"`
@@ -274,9 +293,13 @@ var nids = map[string]int{
274 "brainpoolP512t1": C.NID_brainpoolP512t1, 293 "brainpoolP512t1": C.NID_brainpoolP512t1,
275 "secp224r1": C.NID_secp224r1, 294 "secp224r1": C.NID_secp224r1,
276 "secp256k1": C.NID_secp256k1, 295 "secp256k1": C.NID_secp256k1,
296 "P-256K": C.NID_secp256k1,
277 "secp256r1": C.NID_X9_62_prime256v1, // RFC 8422, Table 4, p.32 297 "secp256r1": C.NID_X9_62_prime256v1, // RFC 8422, Table 4, p.32
298 "P-256": C.NID_X9_62_prime256v1,
278 "secp384r1": C.NID_secp384r1, 299 "secp384r1": C.NID_secp384r1,
300 "P-384": C.NID_secp384r1,
279 "secp521r1": C.NID_secp521r1, 301 "secp521r1": C.NID_secp521r1,
302 "P-521": C.NID_secp521r1,
280 "SHA-1": C.NID_sha1, 303 "SHA-1": C.NID_sha1,
281 "SHA-224": C.NID_sha224, 304 "SHA-224": C.NID_sha224,
282 "SHA-256": C.NID_sha256, 305 "SHA-256": C.NID_sha256,
@@ -1334,6 +1357,129 @@ func runECDSATestGroup(algorithm string, wtg *wycheproofTestGroupECDSA) bool {
1334 return success 1357 return success
1335} 1358}
1336 1359
1360func runECDSAWebCryptoTest(ecKey *C.EC_KEY, nid int, h hash.Hash, wt *wycheproofTestECDSA) bool {
1361 msg, err := hex.DecodeString(wt.Msg)
1362 if err != nil {
1363 log.Fatalf("Failed to decode message %q: %v", wt.Msg, err)
1364 }
1365
1366 h.Reset()
1367 h.Write(msg)
1368 msg = h.Sum(nil)
1369
1370 msgLen := len(msg)
1371 if msgLen == 0 {
1372 msg = append(msg, 0)
1373 }
1374
1375 // DER encode the signature (so that ECDSA_verify() can decode and encode it again...)
1376 sigLen := len(wt.Sig)
1377 r := C.CString(wt.Sig[:sigLen/2])
1378 s := C.CString(wt.Sig[sigLen/2:])
1379
1380 cSig := C.ECDSA_SIG_new()
1381 defer C.ECDSA_SIG_free(cSig)
1382
1383 if cSig == nil {
1384 log.Fatal("ECDSA_SIG_new() failed")
1385 }
1386 if C.BN_hex2bn(&cSig.r, r) == 0 {
1387 log.Fatal("Failed to set ECDSA r")
1388 }
1389 if C.BN_hex2bn(&cSig.s, s) == 0 {
1390 log.Fatal("Failed to set ECDSA s")
1391 }
1392 C.free(unsafe.Pointer(r))
1393 C.free(unsafe.Pointer(s))
1394
1395 derLen := C.i2d_ECDSA_SIG(cSig, nil)
1396 if derLen == 0 {
1397 log.Fatal("i2d_ECDSA_SIG(cSig, nil) failed")
1398 }
1399
1400 cDer := (*C.uchar)(C.malloc(C.ulong(derLen)))
1401 if cDer == nil {
1402 log.Fatal("malloc failed")
1403 }
1404 p := cDer
1405 defer C.free(unsafe.Pointer(cDer))
1406 ret := C.i2d_ECDSA_SIG(cSig, (**C.uchar)(&p))
1407 if ret == 0 || ret != derLen {
1408 log.Fatalf("i2d_ECDSA_SIG(cSig, nil) failed, got %d, want %d", ret, derLen)
1409 }
1410
1411 ret = C.ECDSA_verify(0, (*C.uchar)(unsafe.Pointer(&msg[0])), C.int(msgLen),
1412 (*C.uchar)(unsafe.Pointer(cDer)), C.int(derLen), ecKey)
1413
1414 // XXX audit acceptable cases...
1415 success := true
1416 if (ret == 1) != (wt.Result == "valid") && wt.Result != "acceptable" {
1417 fmt.Printf("FAIL: Test case %d (%q) %v - ECDSA_verify() = %d, want %v\n", wt.TCID, wt.Comment, wt.Flags, int(ret), wt.Result)
1418 success = false
1419 }
1420 if acceptableAudit && ret == 1 && wt.Result == "acceptable" {
1421 gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags)
1422 }
1423 return success
1424}
1425
1426func runECDSAWebCryptoTestGroup(algorithm string, wtg *wycheproofTestGroupECDSAWebCrypto) bool {
1427 fmt.Printf("Running %v test group %v with curve %v, key size %d and %v...\n", algorithm, wtg.Type, wtg.Key.Curve, wtg.Key.KeySize, wtg.SHA)
1428
1429 nid, err := nidFromString(wtg.JWK.Crv)
1430 if err != nil {
1431 log.Fatalf("Failed to get nid for curve: %v", err)
1432 }
1433 ecKey := C.EC_KEY_new_by_curve_name(C.int(nid))
1434 if ecKey == nil {
1435 log.Fatal("EC_KEY_new_by_curve_name failed")
1436 }
1437 defer C.EC_KEY_free(ecKey)
1438
1439 x, err := base64.RawURLEncoding.DecodeString(wtg.JWK.X)
1440 if err != nil {
1441 log.Fatalf("Failed to base64 decode X: %v", err)
1442 }
1443 var bnX *C.BIGNUM
1444 bnX = C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&x[0])), (C.int)(len(x)), nil)
1445 if bnX == nil {
1446 log.Fatal("Failed to decode X")
1447 }
1448 defer C.BN_free(bnX)
1449
1450 y, err := base64.RawURLEncoding.DecodeString(wtg.JWK.Y)
1451 if err != nil {
1452 log.Fatalf("Failed to base64 decode Y: %v", err)
1453 }
1454 var bnY *C.BIGNUM
1455 bnY = C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&y[0])), (C.int)(len(y)), nil)
1456 if bnY == nil {
1457 log.Fatal("Failed to decode Y")
1458 }
1459 defer C.BN_free(bnY)
1460
1461 if C.EC_KEY_set_public_key_affine_coordinates(ecKey, bnX, bnY) != 1 {
1462 log.Fatal("Failed to set EC public key")
1463 }
1464
1465 nid, err = nidFromString(wtg.SHA)
1466 if err != nil {
1467 log.Fatalf("Failed to get MD NID: %v", err)
1468 }
1469 h, err := hashFromString(wtg.SHA)
1470 if err != nil {
1471 log.Fatalf("Failed to get hash: %v", err)
1472 }
1473
1474 success := true
1475 for _, wt := range wtg.Tests {
1476 if !runECDSAWebCryptoTest(ecKey, nid, h, wt) {
1477 success = false
1478 }
1479 }
1480 return success
1481}
1482
1337func runRSASSATest(rsa *C.RSA, h hash.Hash, sha *C.EVP_MD, mgfSha *C.EVP_MD, sLen int, wt *wycheproofTestRSASSA) bool { 1483func runRSASSATest(rsa *C.RSA, h hash.Hash, sha *C.EVP_MD, mgfSha *C.EVP_MD, sLen int, wt *wycheproofTestRSASSA) bool {
1338 msg, err := hex.DecodeString(wt.Msg) 1484 msg, err := hex.DecodeString(wt.Msg)
1339 if err != nil { 1485 if err != nil {
@@ -1557,7 +1703,7 @@ func runX25519TestGroup(algorithm string, wtg *wycheproofTestGroupX25519) bool {
1557 return success 1703 return success
1558} 1704}
1559 1705
1560func runTestVectors(path string) bool { 1706func runTestVectors(path string, webcrypto bool) bool {
1561 b, err := ioutil.ReadFile(path) 1707 b, err := ioutil.ReadFile(path)
1562 if err != nil { 1708 if err != nil {
1563 log.Fatalf("Failed to read test vectors: %v", err) 1709 log.Fatalf("Failed to read test vectors: %v", err)
@@ -1585,7 +1731,12 @@ func runTestVectors(path string) bool {
1585 case "ECDH": 1731 case "ECDH":
1586 wtg = &wycheproofTestGroupECDH{} 1732 wtg = &wycheproofTestGroupECDH{}
1587 case "ECDSA": 1733 case "ECDSA":
1588 wtg = &wycheproofTestGroupECDSA{} 1734 if webcrypto {
1735 wtg = &wycheproofTestGroupECDSAWebCrypto{}
1736 } else {
1737 wtg = &wycheproofTestGroupECDSA{}
1738 }
1739
1589 case "RSASSA-PSS": 1740 case "RSASSA-PSS":
1590 wtg = &wycheproofTestGroupRSASSA{} 1741 wtg = &wycheproofTestGroupRSASSA{}
1591 case "RSASig": 1742 case "RSASig":
@@ -1631,8 +1782,14 @@ func runTestVectors(path string) bool {
1631 success = false 1782 success = false
1632 } 1783 }
1633 case "ECDSA": 1784 case "ECDSA":
1634 if !runECDSATestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDSA)) { 1785 if webcrypto {
1635 success = false 1786 if !runECDSAWebCryptoTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDSAWebCrypto)) {
1787 success = false
1788 }
1789 } else {
1790 if !runECDSATestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDSA)) {
1791 success = false
1792 }
1636 } 1793 }
1637 case "RSASSA-PSS": 1794 case "RSASSA-PSS":
1638 if !runRSASSATestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupRSASSA)) { 1795 if !runRSASSATestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupRSASSA)) {
@@ -1674,7 +1831,8 @@ func main() {
1674 {"ChaCha20-Poly1305", "chacha20_poly1305_test.json"}, 1831 {"ChaCha20-Poly1305", "chacha20_poly1305_test.json"},
1675 {"DSA", "dsa_test.json"}, 1832 {"DSA", "dsa_test.json"},
1676 {"ECDH", "ecdh_[^w]*test.json"}, // Skip ecdh_webcrypto_test.json for now. 1833 {"ECDH", "ecdh_[^w]*test.json"}, // Skip ecdh_webcrypto_test.json for now.
1677 {"ECDSA", "ecdsa_[^w]*test.json"}, // Skip ecdsa_webcrypto_test.json for now. 1834 {"ECDSA", "ecdsa_[^w]*test.json"},
1835 {"ECDSAWebCrypto", "ecdsa_w*_test.json"},
1678 {"RSA", "rsa_*test.json"}, 1836 {"RSA", "rsa_*test.json"},
1679 {"X25519", "x25519_*test.json"}, 1837 {"X25519", "x25519_*test.json"},
1680 } 1838 }
@@ -1682,6 +1840,7 @@ func main() {
1682 success := true 1840 success := true
1683 1841
1684 for _, test := range tests { 1842 for _, test := range tests {
1843 webcrypto := (test.name == "ECDSAWebCrypto")
1685 tvs, err := filepath.Glob(filepath.Join(testVectorPath, test.pattern)) 1844 tvs, err := filepath.Glob(filepath.Join(testVectorPath, test.pattern))
1686 if err != nil { 1845 if err != nil {
1687 log.Fatalf("Failed to glob %v test vectors: %v", test.name, err) 1846 log.Fatalf("Failed to glob %v test vectors: %v", test.name, err)
@@ -1690,7 +1849,7 @@ func main() {
1690 log.Fatalf("Failed to find %v test vectors at %q\n", test.name, testVectorPath) 1849 log.Fatalf("Failed to find %v test vectors at %q\n", test.name, testVectorPath)
1691 } 1850 }
1692 for _, tv := range tvs { 1851 for _, tv := range tvs {
1693 if !runTestVectors(tv) { 1852 if !runTestVectors(tv, webcrypto) {
1694 success = false 1853 success = false
1695 } 1854 }
1696 } 1855 }