diff options
| author | cvs2svn <admin@example.com> | 2018-11-07 01:08:50 +0000 |
|---|---|---|
| committer | cvs2svn <admin@example.com> | 2018-11-07 01:08:50 +0000 |
| commit | 2035faf3f8aa95b888d9416c3cc7328c0ea18beb (patch) | |
| tree | f08a08d357c5d30455c569890f747c1d9b241316 /src/regress/lib/libcrypto/wycheproof | |
| parent | be03b61c1b8f59ccdd34dbe5f6c6b30de697d28b (diff) | |
| download | openbsd-bluhm_20181106.tar.gz openbsd-bluhm_20181106.tar.bz2 openbsd-bluhm_20181106.zip | |
This commit was manufactured by cvs2git to create tag 'bluhm_20181106'.bluhm_20181106
Diffstat (limited to 'src/regress/lib/libcrypto/wycheproof')
| -rw-r--r-- | src/regress/lib/libcrypto/wycheproof/Makefile | 25 | ||||
| -rw-r--r-- | src/regress/lib/libcrypto/wycheproof/wycheproof.go | 2211 |
2 files changed, 0 insertions, 2236 deletions
diff --git a/src/regress/lib/libcrypto/wycheproof/Makefile b/src/regress/lib/libcrypto/wycheproof/Makefile deleted file mode 100644 index 4359db438c..0000000000 --- a/src/regress/lib/libcrypto/wycheproof/Makefile +++ /dev/null | |||
| @@ -1,25 +0,0 @@ | |||
| 1 | # $OpenBSD: Makefile,v 1.2 2018/09/22 00:10:18 tb Exp $ | ||
| 2 | |||
| 3 | GO_VERSION != sh -c "(go version) 2>/dev/null || true" | ||
| 4 | |||
| 5 | .if empty(GO_VERSION) | ||
| 6 | regress: | ||
| 7 | @echo package go is required for this regress | ||
| 8 | @echo SKIPPED | ||
| 9 | .endif | ||
| 10 | |||
| 11 | CLEANFILES+=wycheproof | ||
| 12 | REGRESS_TARGETS=regress-wycheproof | ||
| 13 | |||
| 14 | audit: wycheproof | ||
| 15 | ./wycheproof -v | ||
| 16 | |||
| 17 | wycheproof: wycheproof.go | ||
| 18 | go build -o wycheproof ${.CURDIR}/wycheproof.go | ||
| 19 | |||
| 20 | regress-wycheproof: wycheproof | ||
| 21 | ./wycheproof | ||
| 22 | |||
| 23 | .PHONY: audit | ||
| 24 | |||
| 25 | .include <bsd.regress.mk> | ||
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof.go b/src/regress/lib/libcrypto/wycheproof/wycheproof.go deleted file mode 100644 index 9bc4e5fd8b..0000000000 --- a/src/regress/lib/libcrypto/wycheproof/wycheproof.go +++ /dev/null | |||
| @@ -1,2211 +0,0 @@ | |||
| 1 | /* $OpenBSD: wycheproof.go,v 1.86 2018/10/20 16:02:05 tb Exp $ */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2018 Joel Sing <jsing@openbsd.org> | ||
| 4 | * Copyright (c) 2018 Theo Buehler <tb@openbsd.org> | ||
| 5 | * | ||
| 6 | * Permission to use, copy, modify, and distribute this software for any | ||
| 7 | * purpose with or without fee is hereby granted, provided that the above | ||
| 8 | * copyright notice and this permission notice appear in all copies. | ||
| 9 | * | ||
| 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 17 | */ | ||
| 18 | |||
| 19 | // Wycheproof runs test vectors from Project Wycheproof against libcrypto. | ||
| 20 | package main | ||
| 21 | |||
| 22 | /* | ||
| 23 | #cgo LDFLAGS: -lcrypto | ||
| 24 | |||
| 25 | #include <string.h> | ||
| 26 | |||
| 27 | #include <openssl/aes.h> | ||
| 28 | #include <openssl/bio.h> | ||
| 29 | #include <openssl/bn.h> | ||
| 30 | #include <openssl/cmac.h> | ||
| 31 | #include <openssl/curve25519.h> | ||
| 32 | #include <openssl/dsa.h> | ||
| 33 | #include <openssl/ec.h> | ||
| 34 | #include <openssl/ecdsa.h> | ||
| 35 | #include <openssl/evp.h> | ||
| 36 | #include <openssl/objects.h> | ||
| 37 | #include <openssl/pem.h> | ||
| 38 | #include <openssl/x509.h> | ||
| 39 | #include <openssl/rsa.h> | ||
| 40 | */ | ||
| 41 | import "C" | ||
| 42 | |||
| 43 | import ( | ||
| 44 | "bytes" | ||
| 45 | "crypto/sha1" | ||
| 46 | "crypto/sha256" | ||
| 47 | "crypto/sha512" | ||
| 48 | "encoding/base64" | ||
| 49 | "encoding/hex" | ||
| 50 | "encoding/json" | ||
| 51 | "flag" | ||
| 52 | "fmt" | ||
| 53 | "hash" | ||
| 54 | "io/ioutil" | ||
| 55 | "log" | ||
| 56 | "os" | ||
| 57 | "path/filepath" | ||
| 58 | "sort" | ||
| 59 | "unsafe" | ||
| 60 | ) | ||
| 61 | |||
| 62 | const testVectorPath = "/usr/local/share/wycheproof/testvectors" | ||
| 63 | |||
| 64 | var acceptableAudit = false | ||
| 65 | var acceptableComments map[string]int | ||
| 66 | var acceptableFlags map[string]int | ||
| 67 | |||
| 68 | type wycheproofJWKPublic struct { | ||
| 69 | Crv string `json:"crv"` | ||
| 70 | KID string `json:"kid"` | ||
| 71 | KTY string `json:"kty"` | ||
| 72 | X string `json:"x"` | ||
| 73 | Y string `json:"y"` | ||
| 74 | } | ||
| 75 | |||
| 76 | type wycheproofJWKPrivate struct { | ||
| 77 | Crv string `json:"crv"` | ||
| 78 | D string `json:"d"` | ||
| 79 | KID string `json:"kid"` | ||
| 80 | KTY string `json:"kty"` | ||
| 81 | X string `json:"x"` | ||
| 82 | Y string `json:"y"` | ||
| 83 | } | ||
| 84 | |||
| 85 | type wycheproofTestGroupAesCbcPkcs5 struct { | ||
| 86 | IVSize int `json:"ivSize"` | ||
| 87 | KeySize int `json:"keySize"` | ||
| 88 | Type string `json:"type"` | ||
| 89 | Tests []*wycheproofTestAesCbcPkcs5 `json:"tests"` | ||
| 90 | } | ||
| 91 | |||
| 92 | type wycheproofTestAesCbcPkcs5 struct { | ||
| 93 | TCID int `json:"tcId"` | ||
| 94 | Comment string `json:"comment"` | ||
| 95 | Key string `json:"key"` | ||
| 96 | IV string `json:"iv"` | ||
| 97 | Msg string `json:"msg"` | ||
| 98 | CT string `json:"ct"` | ||
| 99 | Result string `json:"result"` | ||
| 100 | Flags []string `json:"flags"` | ||
| 101 | } | ||
| 102 | |||
| 103 | type wycheproofTestGroupAead struct { | ||
| 104 | IVSize int `json:"ivSize"` | ||
| 105 | KeySize int `json:"keySize"` | ||
| 106 | TagSize int `json:"tagSize"` | ||
| 107 | Type string `json:"type"` | ||
| 108 | Tests []*wycheproofTestAead `json:"tests"` | ||
| 109 | } | ||
| 110 | |||
| 111 | type wycheproofTestAead struct { | ||
| 112 | TCID int `json:"tcId"` | ||
| 113 | Comment string `json:"comment"` | ||
| 114 | Key string `json:"key"` | ||
| 115 | IV string `json:"iv"` | ||
| 116 | AAD string `json:"aad"` | ||
| 117 | Msg string `json:"msg"` | ||
| 118 | CT string `json:"ct"` | ||
| 119 | Tag string `json:"tag"` | ||
| 120 | Result string `json:"result"` | ||
| 121 | Flags []string `json:"flags"` | ||
| 122 | } | ||
| 123 | |||
| 124 | type wycheproofTestGroupAesCmac struct { | ||
| 125 | KeySize int `json:"keySize"` | ||
| 126 | TagSize int `json:"tagSize"` | ||
| 127 | Type string `json:"type"` | ||
| 128 | Tests []*wycheproofTestAesCmac `json:"tests"` | ||
| 129 | } | ||
| 130 | |||
| 131 | type wycheproofTestAesCmac struct { | ||
| 132 | TCID int `json:"tcId"` | ||
| 133 | Comment string `json:"comment"` | ||
| 134 | Key string `json:"key"` | ||
| 135 | Msg string `json:"msg"` | ||
| 136 | Tag string `json:"tag"` | ||
| 137 | Result string `json:"result"` | ||
| 138 | Flags []string `json:"flags"` | ||
| 139 | } | ||
| 140 | |||
| 141 | type wycheproofDSAKey struct { | ||
| 142 | G string `json:"g"` | ||
| 143 | KeySize int `json:"keySize"` | ||
| 144 | P string `json:"p"` | ||
| 145 | Q string `json:"q"` | ||
| 146 | Type string `json:"type"` | ||
| 147 | Y string `json:"y"` | ||
| 148 | } | ||
| 149 | |||
| 150 | type wycheproofTestDSA struct { | ||
| 151 | TCID int `json:"tcId"` | ||
| 152 | Comment string `json:"comment"` | ||
| 153 | Msg string `json:"msg"` | ||
| 154 | Sig string `json:"sig"` | ||
| 155 | Result string `json:"result"` | ||
| 156 | Flags []string `json:"flags"` | ||
| 157 | } | ||
| 158 | |||
| 159 | type wycheproofTestGroupDSA struct { | ||
| 160 | Key *wycheproofDSAKey `json:"key"` | ||
| 161 | KeyDER string `json:"keyDer"` | ||
| 162 | KeyPEM string `json:"keyPem"` | ||
| 163 | SHA string `json:"sha"` | ||
| 164 | Type string `json:"type"` | ||
| 165 | Tests []*wycheproofTestDSA `json:"tests"` | ||
| 166 | } | ||
| 167 | |||
| 168 | type wycheproofTestECDH struct { | ||
| 169 | TCID int `json:"tcId"` | ||
| 170 | Comment string `json:"comment"` | ||
| 171 | Public string `json:"public"` | ||
| 172 | Private string `json:"private"` | ||
| 173 | Shared string `json:"shared"` | ||
| 174 | Result string `json:"result"` | ||
| 175 | Flags []string `json:"flags"` | ||
| 176 | } | ||
| 177 | |||
| 178 | type wycheproofTestGroupECDH struct { | ||
| 179 | Curve string `json:"curve"` | ||
| 180 | Encoding string `json:"encoding"` | ||
| 181 | Type string `json:"type"` | ||
| 182 | Tests []*wycheproofTestECDH `json:"tests"` | ||
| 183 | } | ||
| 184 | |||
| 185 | type wycheproofTestECDHWebCrypto struct { | ||
| 186 | TCID int `json:"tcId"` | ||
| 187 | Comment string `json:"comment"` | ||
| 188 | Public *wycheproofJWKPublic `json:"public"` | ||
| 189 | Private *wycheproofJWKPrivate `json:"private"` | ||
| 190 | Shared string `json:"shared"` | ||
| 191 | Result string `json:"result"` | ||
| 192 | Flags []string `json:"flags"` | ||
| 193 | } | ||
| 194 | |||
| 195 | type wycheproofTestGroupECDHWebCrypto struct { | ||
| 196 | Curve string `json:"curve"` | ||
| 197 | Encoding string `json:"encoding"` | ||
| 198 | Type string `json:"type"` | ||
| 199 | Tests []*wycheproofTestECDHWebCrypto `json:"tests"` | ||
| 200 | } | ||
| 201 | |||
| 202 | type wycheproofECDSAKey struct { | ||
| 203 | Curve string `json:"curve"` | ||
| 204 | KeySize int `json:"keySize"` | ||
| 205 | Type string `json:"type"` | ||
| 206 | Uncompressed string `json:"uncompressed"` | ||
| 207 | WX string `json:"wx"` | ||
| 208 | WY string `json:"wy"` | ||
| 209 | } | ||
| 210 | |||
| 211 | type wycheproofTestECDSA struct { | ||
| 212 | TCID int `json:"tcId"` | ||
| 213 | Comment string `json:"comment"` | ||
| 214 | Msg string `json:"msg"` | ||
| 215 | Sig string `json:"sig"` | ||
| 216 | Result string `json:"result"` | ||
| 217 | Flags []string `json:"flags"` | ||
| 218 | } | ||
| 219 | |||
| 220 | type wycheproofTestGroupECDSA struct { | ||
| 221 | Key *wycheproofECDSAKey `json:"key"` | ||
| 222 | KeyDER string `json:"keyDer"` | ||
| 223 | KeyPEM string `json:"keyPem"` | ||
| 224 | SHA string `json:"sha"` | ||
| 225 | Type string `json:"type"` | ||
| 226 | Tests []*wycheproofTestECDSA `json:"tests"` | ||
| 227 | } | ||
| 228 | |||
| 229 | type wycheproofTestGroupECDSAWebCrypto struct { | ||
| 230 | JWK *wycheproofJWKPublic `json:"jwk"` | ||
| 231 | Key *wycheproofECDSAKey `json:"key"` | ||
| 232 | KeyDER string `json:"keyDer"` | ||
| 233 | KeyPEM string `json:"keyPem"` | ||
| 234 | SHA string `json:"sha"` | ||
| 235 | Type string `json:"type"` | ||
| 236 | Tests []*wycheproofTestECDSA `json:"tests"` | ||
| 237 | } | ||
| 238 | |||
| 239 | type wycheproofTestKW struct { | ||
| 240 | TCID int `json:"tcId"` | ||
| 241 | Comment string `json:"comment"` | ||
| 242 | Key string `json:"key"` | ||
| 243 | Msg string `json:"msg"` | ||
| 244 | CT string `json:"ct"` | ||
| 245 | Result string `json:"result"` | ||
| 246 | Flags []string `json:"flags"` | ||
| 247 | } | ||
| 248 | |||
| 249 | type wycheproofTestGroupKW struct { | ||
| 250 | KeySize int `json:"keySize"` | ||
| 251 | Type string `json:"type"` | ||
| 252 | Tests []*wycheproofTestKW `json:"tests"` | ||
| 253 | } | ||
| 254 | |||
| 255 | type wycheproofTestRSA struct { | ||
| 256 | TCID int `json:"tcId"` | ||
| 257 | Comment string `json:"comment"` | ||
| 258 | Msg string `json:"msg"` | ||
| 259 | Sig string `json:"sig"` | ||
| 260 | Padding string `json:"padding"` | ||
| 261 | Result string `json:"result"` | ||
| 262 | Flags []string `json:"flags"` | ||
| 263 | } | ||
| 264 | |||
| 265 | type wycheproofTestGroupRSA struct { | ||
| 266 | E string `json:"e"` | ||
| 267 | KeyASN string `json:"keyAsn"` | ||
| 268 | KeyDER string `json:"keyDer"` | ||
| 269 | KeyPEM string `json:"keyPem"` | ||
| 270 | KeySize int `json:"keysize"` | ||
| 271 | N string `json:"n"` | ||
| 272 | SHA string `json:"sha"` | ||
| 273 | Type string `json:"type"` | ||
| 274 | Tests []*wycheproofTestRSA `json:"tests"` | ||
| 275 | } | ||
| 276 | |||
| 277 | type wycheproofTestRSASSA struct { | ||
| 278 | TCID int `json:"tcId"` | ||
| 279 | Comment string `json:"comment"` | ||
| 280 | Msg string `json:"msg"` | ||
| 281 | Sig string `json:"sig"` | ||
| 282 | Result string `json:"result"` | ||
| 283 | Flags []string `json:"flags"` | ||
| 284 | } | ||
| 285 | |||
| 286 | type wycheproofTestGroupRSASSA struct { | ||
| 287 | E string `json:"e"` | ||
| 288 | KeyASN string `json:"keyAsn"` | ||
| 289 | KeyDER string `json:"keyDer"` | ||
| 290 | KeyPEM string `json:"keyPem"` | ||
| 291 | KeySize int `json:"keysize"` | ||
| 292 | MGF string `json:"mgf"` | ||
| 293 | MGFSHA string `json:"mgfSha"` | ||
| 294 | N string `json:"n"` | ||
| 295 | SLen int `json:"sLen"` | ||
| 296 | SHA string `json:"sha"` | ||
| 297 | Type string `json:"type"` | ||
| 298 | Tests []*wycheproofTestRSASSA `json:"tests"` | ||
| 299 | } | ||
| 300 | |||
| 301 | type wycheproofTestX25519 struct { | ||
| 302 | TCID int `json:"tcId"` | ||
| 303 | Comment string `json:"comment"` | ||
| 304 | Curve string `json:"curve"` | ||
| 305 | Public string `json:"public"` | ||
| 306 | Private string `json:"private"` | ||
| 307 | Shared string `json:"shared"` | ||
| 308 | Result string `json:"result"` | ||
| 309 | Flags []string `json:"flags"` | ||
| 310 | } | ||
| 311 | |||
| 312 | type wycheproofTestGroupX25519 struct { | ||
| 313 | Curve string `json:"curve"` | ||
| 314 | Tests []*wycheproofTestX25519 `json:"tests"` | ||
| 315 | } | ||
| 316 | |||
| 317 | type wycheproofTestVectors struct { | ||
| 318 | Algorithm string `json:"algorithm"` | ||
| 319 | GeneratorVersion string `json:"generatorVersion"` | ||
| 320 | Notes map[string]string `json:"notes"` | ||
| 321 | NumberOfTests int `json:"numberOfTests"` | ||
| 322 | // Header | ||
| 323 | TestGroups []json.RawMessage `json:"testGroups"` | ||
| 324 | } | ||
| 325 | |||
| 326 | var nids = map[string]int{ | ||
| 327 | "brainpoolP224r1": C.NID_brainpoolP224r1, | ||
| 328 | "brainpoolP256r1": C.NID_brainpoolP256r1, | ||
| 329 | "brainpoolP320r1": C.NID_brainpoolP320r1, | ||
| 330 | "brainpoolP384r1": C.NID_brainpoolP384r1, | ||
| 331 | "brainpoolP512r1": C.NID_brainpoolP512r1, | ||
| 332 | "brainpoolP224t1": C.NID_brainpoolP224t1, | ||
| 333 | "brainpoolP256t1": C.NID_brainpoolP256t1, | ||
| 334 | "brainpoolP320t1": C.NID_brainpoolP320t1, | ||
| 335 | "brainpoolP384t1": C.NID_brainpoolP384t1, | ||
| 336 | "brainpoolP512t1": C.NID_brainpoolP512t1, | ||
| 337 | "secp224r1": C.NID_secp224r1, | ||
| 338 | "secp256k1": C.NID_secp256k1, | ||
| 339 | "P-256K": C.NID_secp256k1, | ||
| 340 | "secp256r1": C.NID_X9_62_prime256v1, // RFC 8422, Table 4, p.32 | ||
| 341 | "P-256": C.NID_X9_62_prime256v1, | ||
| 342 | "secp384r1": C.NID_secp384r1, | ||
| 343 | "P-384": C.NID_secp384r1, | ||
| 344 | "secp521r1": C.NID_secp521r1, | ||
| 345 | "P-521": C.NID_secp521r1, | ||
| 346 | "SHA-1": C.NID_sha1, | ||
| 347 | "SHA-224": C.NID_sha224, | ||
| 348 | "SHA-256": C.NID_sha256, | ||
| 349 | "SHA-384": C.NID_sha384, | ||
| 350 | "SHA-512": C.NID_sha512, | ||
| 351 | } | ||
| 352 | |||
| 353 | func gatherAcceptableStatistics(testcase int, comment string, flags []string) { | ||
| 354 | fmt.Printf("AUDIT: Test case %d (%q) %v\n", testcase, comment, flags) | ||
| 355 | |||
| 356 | if comment == "" { | ||
| 357 | acceptableComments["No comment"]++ | ||
| 358 | } else { | ||
| 359 | acceptableComments[comment]++ | ||
| 360 | } | ||
| 361 | |||
| 362 | if len(flags) == 0 { | ||
| 363 | acceptableFlags["NoFlag"]++ | ||
| 364 | } else { | ||
| 365 | for _, flag := range flags { | ||
| 366 | acceptableFlags[flag]++ | ||
| 367 | } | ||
| 368 | } | ||
| 369 | } | ||
| 370 | |||
| 371 | func printAcceptableStatistics() { | ||
| 372 | fmt.Printf("\nComment statistics:\n") | ||
| 373 | |||
| 374 | var comments []string | ||
| 375 | for comment := range acceptableComments { | ||
| 376 | comments = append(comments, comment) | ||
| 377 | } | ||
| 378 | sort.Strings(comments) | ||
| 379 | for _, comment := range comments { | ||
| 380 | prcomment := comment | ||
| 381 | if len(comment) > 45 { | ||
| 382 | prcomment = comment[0:42] + "..." | ||
| 383 | } | ||
| 384 | fmt.Printf("%-45v %5d\n", prcomment, acceptableComments[comment]) | ||
| 385 | } | ||
| 386 | |||
| 387 | fmt.Printf("\nFlag statistics:\n") | ||
| 388 | var flags []string | ||
| 389 | for flag := range acceptableFlags { | ||
| 390 | flags = append(flags, flag) | ||
| 391 | } | ||
| 392 | sort.Strings(flags) | ||
| 393 | for _, flag := range flags { | ||
| 394 | fmt.Printf("%-45v %5d\n", flag, acceptableFlags[flag]) | ||
| 395 | } | ||
| 396 | } | ||
| 397 | |||
| 398 | func nidFromString(ns string) (int, error) { | ||
| 399 | nid, ok := nids[ns] | ||
| 400 | if ok { | ||
| 401 | return nid, nil | ||
| 402 | } | ||
| 403 | return -1, fmt.Errorf("unknown NID %q", ns) | ||
| 404 | } | ||
| 405 | |||
| 406 | func hashFromString(hs string) (hash.Hash, error) { | ||
| 407 | switch hs { | ||
| 408 | case "SHA-1": | ||
| 409 | return sha1.New(), nil | ||
| 410 | case "SHA-224": | ||
| 411 | return sha256.New224(), nil | ||
| 412 | case "SHA-256": | ||
| 413 | return sha256.New(), nil | ||
| 414 | case "SHA-384": | ||
| 415 | return sha512.New384(), nil | ||
| 416 | case "SHA-512": | ||
| 417 | return sha512.New(), nil | ||
| 418 | default: | ||
| 419 | return nil, fmt.Errorf("unknown hash %q", hs) | ||
| 420 | } | ||
| 421 | } | ||
| 422 | |||
| 423 | func hashEvpMdFromString(hs string) (*C.EVP_MD, error) { | ||
| 424 | switch hs { | ||
| 425 | case "SHA-1": | ||
| 426 | return C.EVP_sha1(), nil | ||
| 427 | case "SHA-224": | ||
| 428 | return C.EVP_sha224(), nil | ||
| 429 | case "SHA-256": | ||
| 430 | return C.EVP_sha256(), nil | ||
| 431 | case "SHA-384": | ||
| 432 | return C.EVP_sha384(), nil | ||
| 433 | case "SHA-512": | ||
| 434 | return C.EVP_sha512(), nil | ||
| 435 | default: | ||
| 436 | return nil, fmt.Errorf("unknown hash %q", hs) | ||
| 437 | } | ||
| 438 | } | ||
| 439 | |||
| 440 | func checkAesCbcPkcs5(ctx *C.EVP_CIPHER_CTX, doEncrypt int, key []byte, keyLen int, | ||
| 441 | iv []byte, ivLen int, in []byte, inLen int, out []byte, outLen int, | ||
| 442 | wt *wycheproofTestAesCbcPkcs5) bool { | ||
| 443 | var action string | ||
| 444 | if doEncrypt == 1 { | ||
| 445 | action = "encrypting" | ||
| 446 | } else { | ||
| 447 | action = "decrypting" | ||
| 448 | } | ||
| 449 | |||
| 450 | ret := C.EVP_CipherInit_ex(ctx, nil, nil, (*C.uchar)(unsafe.Pointer(&key[0])), | ||
| 451 | (*C.uchar)(unsafe.Pointer(&iv[0])), C.int(doEncrypt)) | ||
| 452 | if ret != 1 { | ||
| 453 | log.Fatalf("EVP_CipherInit_ex failed: %d", ret) | ||
| 454 | } | ||
| 455 | |||
| 456 | cipherOut := make([]byte, inLen + C.EVP_MAX_BLOCK_LENGTH) | ||
| 457 | var cipherOutLen C.int | ||
| 458 | |||
| 459 | ret = C.EVP_CipherUpdate(ctx, (*C.uchar)(unsafe.Pointer(&cipherOut[0])), &cipherOutLen, | ||
| 460 | (*C.uchar)(unsafe.Pointer(&in[0])), C.int(inLen)) | ||
| 461 | if ret != 1 { | ||
| 462 | if wt.Result == "invalid" { | ||
| 463 | fmt.Printf("INFO: Test case %d (%q) [%v] %v - EVP_CipherUpdate() = %d, want %v\n", | ||
| 464 | wt.TCID, wt.Comment, action, wt.Flags, ret, wt.Result) | ||
| 465 | return true | ||
| 466 | } | ||
| 467 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - EVP_CipherUpdate() = %d, want %v\n", | ||
| 468 | wt.TCID, wt.Comment, action, wt.Flags, ret, wt.Result) | ||
| 469 | return false | ||
| 470 | } | ||
| 471 | |||
| 472 | var finallen C.int | ||
| 473 | ret = C.EVP_CipherFinal_ex(ctx, (*C.uchar)(unsafe.Pointer(&cipherOut[cipherOutLen])), &finallen) | ||
| 474 | if ret != 1 { | ||
| 475 | if wt.Result == "invalid" { | ||
| 476 | return true | ||
| 477 | } | ||
| 478 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - EVP_CipherFinal_ex() = %d, want %v\n", | ||
| 479 | wt.TCID, wt.Comment, action, wt.Flags, ret, wt.Result) | ||
| 480 | return false | ||
| 481 | } | ||
| 482 | |||
| 483 | cipherOutLen += finallen | ||
| 484 | if cipherOutLen != C.int(outLen) && wt.Result != "invalid" { | ||
| 485 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - open length mismatch: got %d, want %d\n", | ||
| 486 | wt.TCID, wt.Comment, action, wt.Flags, cipherOutLen, outLen) | ||
| 487 | return false | ||
| 488 | } | ||
| 489 | |||
| 490 | openedMsg := out[0:cipherOutLen] | ||
| 491 | if outLen == 0 { | ||
| 492 | out = nil | ||
| 493 | } | ||
| 494 | |||
| 495 | success := false | ||
| 496 | if bytes.Equal(openedMsg, out) || wt.Result == "invalid" { | ||
| 497 | success = true | ||
| 498 | if acceptableAudit && wt.Result == "acceptable" { | ||
| 499 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 500 | } | ||
| 501 | } else { | ||
| 502 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - msg match: %t; want %v\n", | ||
| 503 | wt.TCID, wt.Comment, action, wt.Flags, bytes.Equal(openedMsg, out), wt.Result) | ||
| 504 | } | ||
| 505 | return success | ||
| 506 | } | ||
| 507 | |||
| 508 | func runAesCbcPkcs5Test(ctx *C.EVP_CIPHER_CTX, wt *wycheproofTestAesCbcPkcs5) bool { | ||
| 509 | key, err := hex.DecodeString(wt.Key) | ||
| 510 | if err != nil { | ||
| 511 | log.Fatalf("Failed to decode key %q: %v", wt.Key, err) | ||
| 512 | } | ||
| 513 | iv, err := hex.DecodeString(wt.IV) | ||
| 514 | if err != nil { | ||
| 515 | log.Fatalf("Failed to decode IV %q: %v", wt.IV, err) | ||
| 516 | } | ||
| 517 | ct, err := hex.DecodeString(wt.CT) | ||
| 518 | if err != nil { | ||
| 519 | log.Fatalf("Failed to decode CT %q: %v", wt.CT, err) | ||
| 520 | } | ||
| 521 | msg, err := hex.DecodeString(wt.Msg) | ||
| 522 | if err != nil { | ||
| 523 | log.Fatalf("Failed to decode message %q: %v", wt.Msg, err) | ||
| 524 | } | ||
| 525 | |||
| 526 | keyLen, ivLen, ctLen, msgLen := len(key), len(iv), len(ct), len(msg) | ||
| 527 | |||
| 528 | if keyLen == 0 { | ||
| 529 | key = append(key, 0) | ||
| 530 | } | ||
| 531 | if ivLen == 0 { | ||
| 532 | iv = append(iv, 0) | ||
| 533 | } | ||
| 534 | if ctLen == 0 { | ||
| 535 | ct = append(ct, 0) | ||
| 536 | } | ||
| 537 | if msgLen == 0 { | ||
| 538 | msg = append(msg, 0) | ||
| 539 | } | ||
| 540 | |||
| 541 | openSuccess := checkAesCbcPkcs5(ctx, 0, key, keyLen, iv, ivLen, ct, ctLen, msg, msgLen, wt) | ||
| 542 | sealSuccess := checkAesCbcPkcs5(ctx, 1, key, keyLen, iv, ivLen, msg, msgLen, ct, ctLen, wt) | ||
| 543 | |||
| 544 | return openSuccess && sealSuccess | ||
| 545 | } | ||
| 546 | |||
| 547 | func runAesCbcPkcs5TestGroup(algorithm string, wtg *wycheproofTestGroupAesCbcPkcs5) bool { | ||
| 548 | fmt.Printf("Running %v test group %v with IV size %d and key size %d...\n", | ||
| 549 | algorithm, wtg.Type, wtg.IVSize, wtg.KeySize) | ||
| 550 | |||
| 551 | var cipher *C.EVP_CIPHER | ||
| 552 | switch wtg.KeySize { | ||
| 553 | case 128: | ||
| 554 | cipher = C.EVP_aes_128_cbc() | ||
| 555 | case 192: | ||
| 556 | cipher = C.EVP_aes_192_cbc() | ||
| 557 | case 256: | ||
| 558 | cipher = C.EVP_aes_256_cbc() | ||
| 559 | default: | ||
| 560 | log.Fatalf("Unsupported key size: %d", wtg.KeySize) | ||
| 561 | } | ||
| 562 | |||
| 563 | ctx := C.EVP_CIPHER_CTX_new() | ||
| 564 | if ctx == nil { | ||
| 565 | log.Fatal("EVP_CIPHER_CTX_new() failed") | ||
| 566 | } | ||
| 567 | defer C.EVP_CIPHER_CTX_free(ctx) | ||
| 568 | |||
| 569 | ret := C.EVP_CipherInit_ex(ctx, cipher, nil, nil, nil, 0) | ||
| 570 | if ret != 1 { | ||
| 571 | log.Fatalf("EVP_CipherInit_ex failed: %d", ret) | ||
| 572 | } | ||
| 573 | |||
| 574 | success := true | ||
| 575 | for _, wt := range wtg.Tests { | ||
| 576 | if !runAesCbcPkcs5Test(ctx, wt) { | ||
| 577 | success = false | ||
| 578 | } | ||
| 579 | } | ||
| 580 | return success | ||
| 581 | } | ||
| 582 | |||
| 583 | func checkAesAead(algorithm string, ctx *C.EVP_CIPHER_CTX, doEncrypt int, | ||
| 584 | key []byte, keyLen int, iv []byte, ivLen int, aad []byte, aadLen int, | ||
| 585 | in []byte, inLen int, out []byte, outLen int, tag []byte, tagLen int, | ||
| 586 | wt *wycheproofTestAead) bool { | ||
| 587 | var ctrlSetIVLen C.int | ||
| 588 | var ctrlSetTag C.int | ||
| 589 | var ctrlGetTag C.int | ||
| 590 | |||
| 591 | doCCM := false | ||
| 592 | switch algorithm { | ||
| 593 | case "AES-CCM": | ||
| 594 | doCCM = true | ||
| 595 | ctrlSetIVLen = C.EVP_CTRL_CCM_SET_IVLEN | ||
| 596 | ctrlSetTag = C.EVP_CTRL_CCM_SET_TAG | ||
| 597 | ctrlGetTag = C.EVP_CTRL_CCM_GET_TAG | ||
| 598 | case "AES-GCM": | ||
| 599 | ctrlSetIVLen = C.EVP_CTRL_GCM_SET_IVLEN | ||
| 600 | ctrlSetTag = C.EVP_CTRL_GCM_SET_TAG | ||
| 601 | ctrlGetTag = C.EVP_CTRL_GCM_GET_TAG | ||
| 602 | } | ||
| 603 | |||
| 604 | setTag := unsafe.Pointer(nil) | ||
| 605 | var action string | ||
| 606 | |||
| 607 | if doEncrypt == 1 { | ||
| 608 | action = "encrypting" | ||
| 609 | } else { | ||
| 610 | action = "decrypting" | ||
| 611 | setTag = unsafe.Pointer(&tag[0]) | ||
| 612 | } | ||
| 613 | |||
| 614 | ret := C.EVP_CipherInit_ex(ctx, nil, nil, nil, nil, C.int(doEncrypt)) | ||
| 615 | if ret != 1 { | ||
| 616 | log.Fatalf("[%v] cipher init failed", action) | ||
| 617 | } | ||
| 618 | |||
| 619 | ret = C.EVP_CIPHER_CTX_ctrl(ctx, ctrlSetIVLen, C.int(ivLen), nil) | ||
| 620 | if ret != 1 { | ||
| 621 | if wt.Comment == "Nonce is too long" || wt.Comment == "Invalid nonce size" || | ||
| 622 | wt.Comment == "0 size IV is not valid" { | ||
| 623 | return true | ||
| 624 | } | ||
| 625 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - setting IV len to %d failed. got %d, want %v\n", | ||
| 626 | wt.TCID, wt.Comment, action, wt.Flags, ivLen, ret, wt.Result) | ||
| 627 | return false | ||
| 628 | } | ||
| 629 | |||
| 630 | if doEncrypt == 0 || doCCM { | ||
| 631 | ret = C.EVP_CIPHER_CTX_ctrl(ctx, ctrlSetTag, C.int(tagLen), setTag) | ||
| 632 | if ret != 1 { | ||
| 633 | if wt.Comment == "Invalid tag size" { | ||
| 634 | return true | ||
| 635 | } | ||
| 636 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - setting tag length to %d failed. got %d, want %v\n", | ||
| 637 | wt.TCID, wt.Comment, action, wt.Flags, tagLen, ret, wt.Result) | ||
| 638 | return false | ||
| 639 | } | ||
| 640 | } | ||
| 641 | |||
| 642 | ret = C.EVP_CipherInit_ex(ctx, nil, nil, (*C.uchar)(unsafe.Pointer(&key[0])), | ||
| 643 | (*C.uchar)(unsafe.Pointer(&iv[0])), C.int(doEncrypt)) | ||
| 644 | if ret != 1 { | ||
| 645 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - setting key and IV failed. got %d, want %v\n", | ||
| 646 | wt.TCID, wt.Comment, action, wt.Flags, ret, wt.Result) | ||
| 647 | return false | ||
| 648 | } | ||
| 649 | |||
| 650 | var cipherOutLen C.int | ||
| 651 | if doCCM { | ||
| 652 | ret = C.EVP_CipherUpdate(ctx, nil, &cipherOutLen, nil, C.int(inLen)) | ||
| 653 | if ret != 1 { | ||
| 654 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - setting input length to %d failed. got %d, want %v\n", | ||
| 655 | wt.TCID, wt.Comment, action, wt.Flags, inLen, ret, wt.Result) | ||
| 656 | return false | ||
| 657 | } | ||
| 658 | } | ||
| 659 | |||
| 660 | ret = C.EVP_CipherUpdate(ctx, nil, &cipherOutLen, (*C.uchar)(unsafe.Pointer(&aad[0])), C.int(aadLen)) | ||
| 661 | if ret != 1 { | ||
| 662 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - processing AAD failed. got %d, want %v\n", | ||
| 663 | wt.TCID, wt.Comment, action, wt.Flags, ret, wt.Result) | ||
| 664 | return false | ||
| 665 | } | ||
| 666 | |||
| 667 | cipherOutLen = 0 | ||
| 668 | cipherOut := make([]byte, inLen) | ||
| 669 | if inLen == 0 { | ||
| 670 | cipherOut = append(cipherOut, 0) | ||
| 671 | } | ||
| 672 | |||
| 673 | ret = C.EVP_CipherUpdate(ctx, (*C.uchar)(unsafe.Pointer(&cipherOut[0])), &cipherOutLen, | ||
| 674 | (*C.uchar)(unsafe.Pointer(&in[0])), C.int(inLen)) | ||
| 675 | if ret != 1 { | ||
| 676 | if wt.Result == "invalid" { | ||
| 677 | return true | ||
| 678 | } | ||
| 679 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - EVP_CipherUpdate() = %d, want %v\n", | ||
| 680 | wt.TCID, wt.Comment, action, wt.Flags, ret, wt.Result) | ||
| 681 | return false | ||
| 682 | } | ||
| 683 | |||
| 684 | if doEncrypt == 1 { | ||
| 685 | var tmpLen C.int | ||
| 686 | dummyOut := make([]byte, 16) | ||
| 687 | |||
| 688 | ret = C.EVP_CipherFinal_ex(ctx, (*C.uchar)(unsafe.Pointer(&dummyOut[0])), &tmpLen) | ||
| 689 | if ret != 1 { | ||
| 690 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - EVP_CipherFinal_ex() = %d, want %v\n", | ||
| 691 | wt.TCID, wt.Comment, action, wt.Flags, ret, wt.Result) | ||
| 692 | return false | ||
| 693 | } | ||
| 694 | cipherOutLen += tmpLen | ||
| 695 | } | ||
| 696 | |||
| 697 | if cipherOutLen != C.int(outLen) { | ||
| 698 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - cipherOutLen %d != outLen %d. Result %v\n", | ||
| 699 | wt.TCID, wt.Comment, action, wt.Flags, cipherOutLen, outLen, wt.Result) | ||
| 700 | return false | ||
| 701 | } | ||
| 702 | |||
| 703 | success := true | ||
| 704 | if !bytes.Equal(cipherOut, out) { | ||
| 705 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - expected and computed output do not match. Result: %v\n", | ||
| 706 | wt.TCID, wt.Comment, action, wt.Flags, wt.Result) | ||
| 707 | success = false | ||
| 708 | } | ||
| 709 | if doEncrypt == 1 { | ||
| 710 | tagOut := make([]byte, tagLen) | ||
| 711 | ret = C.EVP_CIPHER_CTX_ctrl(ctx, ctrlGetTag, C.int(tagLen), unsafe.Pointer(&tagOut[0])) | ||
| 712 | if ret != 1 { | ||
| 713 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - EVP_CIPHER_CTX_ctrl() = %d, want %v\n", | ||
| 714 | wt.TCID, wt.Comment, action, wt.Flags, ret, wt.Result) | ||
| 715 | return false | ||
| 716 | } | ||
| 717 | |||
| 718 | // There are no acceptable CCM cases. All acceptable GCM tests | ||
| 719 | // pass. They have len(IV) <= 48. NIST SP 800-38D, 5.2.1.1, p.8, | ||
| 720 | // allows 1 <= len(IV) <= 2^64-1, but notes: | ||
| 721 | // "For IVs it is recommended that implementations restrict | ||
| 722 | // support to the length of 96 bits, to promote | ||
| 723 | // interoperability, efficiency and simplicity of design." | ||
| 724 | if bytes.Equal(tagOut, tag) != (wt.Result == "valid" || wt.Result == "acceptable") { | ||
| 725 | fmt.Printf("FAIL: Test case %d (%q) [%v] %v - expected and computed tag do not match - ret: %d, Result: %v\n", | ||
| 726 | wt.TCID, wt.Comment, action, wt.Flags, ret, wt.Result) | ||
| 727 | success = false | ||
| 728 | } | ||
| 729 | if acceptableAudit && bytes.Equal(tagOut, tag) && wt.Result == "acceptable" { | ||
| 730 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 731 | } | ||
| 732 | } | ||
| 733 | return success | ||
| 734 | } | ||
| 735 | |||
| 736 | func runAesAeadTest(algorithm string, ctx *C.EVP_CIPHER_CTX, aead *C.EVP_AEAD, wt *wycheproofTestAead) bool { | ||
| 737 | key, err := hex.DecodeString(wt.Key) | ||
| 738 | if err != nil { | ||
| 739 | log.Fatalf("Failed to decode key %q: %v", wt.Key, err) | ||
| 740 | } | ||
| 741 | |||
| 742 | iv, err := hex.DecodeString(wt.IV) | ||
| 743 | if err != nil { | ||
| 744 | log.Fatalf("Failed to decode IV %q: %v", wt.IV, err) | ||
| 745 | } | ||
| 746 | |||
| 747 | aad, err := hex.DecodeString(wt.AAD) | ||
| 748 | if err != nil { | ||
| 749 | log.Fatalf("Failed to decode AAD %q: %v", wt.AAD, err) | ||
| 750 | } | ||
| 751 | |||
| 752 | msg, err := hex.DecodeString(wt.Msg) | ||
| 753 | if err != nil { | ||
| 754 | log.Fatalf("Failed to decode msg %q: %v", wt.Msg, err) | ||
| 755 | } | ||
| 756 | |||
| 757 | ct, err := hex.DecodeString(wt.CT) | ||
| 758 | if err != nil { | ||
| 759 | log.Fatalf("Failed to decode CT %q: %v", wt.CT, err) | ||
| 760 | } | ||
| 761 | |||
| 762 | tag, err := hex.DecodeString(wt.Tag) | ||
| 763 | if err != nil { | ||
| 764 | log.Fatalf("Failed to decode tag %q: %v", wt.Tag, err) | ||
| 765 | } | ||
| 766 | |||
| 767 | keyLen, ivLen, aadLen, msgLen, ctLen, tagLen := len(key), len(iv), len(aad), len(msg), len(ct), len(tag) | ||
| 768 | |||
| 769 | if keyLen == 0 { | ||
| 770 | key = append(key, 0) | ||
| 771 | } | ||
| 772 | if ivLen == 0 { | ||
| 773 | iv = append(iv, 0) | ||
| 774 | } | ||
| 775 | if aadLen == 0 { | ||
| 776 | aad = append(aad, 0) | ||
| 777 | } | ||
| 778 | if msgLen == 0 { | ||
| 779 | msg = append(msg, 0) | ||
| 780 | } | ||
| 781 | if ctLen == 0 { | ||
| 782 | ct = append(ct, 0) | ||
| 783 | } | ||
| 784 | if tagLen == 0 { | ||
| 785 | tag = append(tag, 0) | ||
| 786 | } | ||
| 787 | |||
| 788 | openEvp := checkAesAead(algorithm, ctx, 0, key, keyLen, iv, ivLen, aad, aadLen, ct, ctLen, msg, msgLen, tag, tagLen, wt) | ||
| 789 | sealEvp := checkAesAead(algorithm, ctx, 1, key, keyLen, iv, ivLen, aad, aadLen, msg, msgLen, ct, ctLen, tag, tagLen, wt) | ||
| 790 | |||
| 791 | openAead, sealAead := true, true | ||
| 792 | if aead != nil { | ||
| 793 | var ctx C.EVP_AEAD_CTX | ||
| 794 | if C.EVP_AEAD_CTX_init(&ctx, aead, (*C.uchar)(unsafe.Pointer(&key[0])), C.size_t(keyLen), C.size_t(tagLen), nil) != 1 { | ||
| 795 | log.Fatal("Failed to initialize AEAD context") | ||
| 796 | } | ||
| 797 | defer C.EVP_AEAD_CTX_cleanup(&ctx) | ||
| 798 | |||
| 799 | // Make sure we don't accidentally prepend or compare against a 0. | ||
| 800 | if ctLen == 0 { | ||
| 801 | ct = nil | ||
| 802 | } | ||
| 803 | |||
| 804 | openAead = checkAeadOpen(&ctx, iv, ivLen, aad, aadLen, msg, msgLen, ct, ctLen, tag, tagLen, wt) | ||
| 805 | sealAead = checkAeadSeal(&ctx, iv, ivLen, aad, aadLen, msg, msgLen, ct, ctLen, tag, tagLen, wt) | ||
| 806 | } | ||
| 807 | |||
| 808 | return openEvp && sealEvp && openAead && sealAead | ||
| 809 | } | ||
| 810 | |||
| 811 | func runAesAeadTestGroup(algorithm string, wtg *wycheproofTestGroupAead) bool { | ||
| 812 | fmt.Printf("Running %v test group %v with IV size %d, key size %d and tag size %d...\n", | ||
| 813 | algorithm, wtg.Type, wtg.IVSize, wtg.KeySize, wtg.TagSize) | ||
| 814 | |||
| 815 | var cipher *C.EVP_CIPHER | ||
| 816 | var aead *C.EVP_AEAD | ||
| 817 | switch algorithm { | ||
| 818 | case "AES-CCM": | ||
| 819 | switch wtg.KeySize { | ||
| 820 | case 128: | ||
| 821 | cipher = C.EVP_aes_128_ccm() | ||
| 822 | case 192: | ||
| 823 | cipher = C.EVP_aes_192_ccm() | ||
| 824 | case 256: | ||
| 825 | cipher = C.EVP_aes_256_ccm() | ||
| 826 | default: | ||
| 827 | fmt.Printf("INFO: Skipping tests with invalid key size %d\n", wtg.KeySize) | ||
| 828 | return true | ||
| 829 | } | ||
| 830 | case "AES-GCM": | ||
| 831 | switch wtg.KeySize { | ||
| 832 | case 128: | ||
| 833 | cipher = C.EVP_aes_128_gcm() | ||
| 834 | aead = C.EVP_aead_aes_128_gcm() | ||
| 835 | case 192: | ||
| 836 | cipher = C.EVP_aes_192_gcm() | ||
| 837 | case 256: | ||
| 838 | cipher = C.EVP_aes_256_gcm() | ||
| 839 | aead = C.EVP_aead_aes_256_gcm() | ||
| 840 | default: | ||
| 841 | fmt.Printf("INFO: Skipping tests with invalid key size %d\n", wtg.KeySize) | ||
| 842 | return true | ||
| 843 | } | ||
| 844 | default: | ||
| 845 | log.Fatalf("runAesAeadTestGroup() - unhandled algorithm: %v", algorithm) | ||
| 846 | } | ||
| 847 | |||
| 848 | ctx := C.EVP_CIPHER_CTX_new() | ||
| 849 | if ctx == nil { | ||
| 850 | log.Fatal("EVP_CIPHER_CTX_new() failed") | ||
| 851 | } | ||
| 852 | defer C.EVP_CIPHER_CTX_free(ctx) | ||
| 853 | |||
| 854 | C.EVP_CipherInit_ex(ctx, cipher, nil, nil, nil, 1) | ||
| 855 | |||
| 856 | success := true | ||
| 857 | for _, wt := range wtg.Tests { | ||
| 858 | if !runAesAeadTest(algorithm, ctx, aead, wt) { | ||
| 859 | success = false | ||
| 860 | } | ||
| 861 | } | ||
| 862 | return success | ||
| 863 | } | ||
| 864 | |||
| 865 | func runAesCmacTest(cipher *C.EVP_CIPHER, wt *wycheproofTestAesCmac) bool { | ||
| 866 | key, err := hex.DecodeString(wt.Key) | ||
| 867 | if err != nil { | ||
| 868 | log.Fatalf("Failed to decode key %q: %v", wt.Key, err) | ||
| 869 | } | ||
| 870 | |||
| 871 | msg, err := hex.DecodeString(wt.Msg) | ||
| 872 | if err != nil { | ||
| 873 | log.Fatalf("Failed to decode msg %q: %v", wt.Msg, err) | ||
| 874 | } | ||
| 875 | |||
| 876 | tag, err := hex.DecodeString(wt.Tag) | ||
| 877 | if err != nil { | ||
| 878 | log.Fatalf("Failed to decode tag %q: %v", wt.Tag, err) | ||
| 879 | } | ||
| 880 | |||
| 881 | keyLen, msgLen, tagLen := len(key), len(msg), len(tag) | ||
| 882 | |||
| 883 | if keyLen == 0 { | ||
| 884 | key = append(key, 0) | ||
| 885 | } | ||
| 886 | if msgLen == 0 { | ||
| 887 | msg = append(msg, 0) | ||
| 888 | } | ||
| 889 | if tagLen == 0 { | ||
| 890 | tag = append(tag, 0) | ||
| 891 | } | ||
| 892 | |||
| 893 | ctx := C.CMAC_CTX_new() | ||
| 894 | if ctx == nil { | ||
| 895 | log.Fatal("CMAC_CTX_new failed") | ||
| 896 | } | ||
| 897 | defer C.CMAC_CTX_free(ctx) | ||
| 898 | |||
| 899 | ret := C.CMAC_Init(ctx, unsafe.Pointer(&key[0]), C.size_t(keyLen), cipher, nil) | ||
| 900 | if ret != 1 { | ||
| 901 | fmt.Printf("FAIL: Test case %d (%q) %v - CMAC_Init() = %d, want %v\n", | ||
| 902 | wt.TCID, wt.Comment, wt.Flags, ret, wt.Result) | ||
| 903 | return false | ||
| 904 | } | ||
| 905 | |||
| 906 | ret = C.CMAC_Update(ctx, unsafe.Pointer(&msg[0]), C.size_t(msgLen)) | ||
| 907 | if ret != 1 { | ||
| 908 | fmt.Printf("FAIL: Test case %d (%q) %v - CMAC_Update() = %d, want %v\n", | ||
| 909 | wt.TCID, wt.Comment, wt.Flags, ret, wt.Result) | ||
| 910 | return false | ||
| 911 | } | ||
| 912 | |||
| 913 | var outLen C.size_t | ||
| 914 | outTag := make([]byte, 16) | ||
| 915 | |||
| 916 | ret = C.CMAC_Final(ctx, (*C.uchar)(unsafe.Pointer(&outTag[0])), &outLen) | ||
| 917 | if ret != 1 { | ||
| 918 | fmt.Printf("FAIL: Test case %d (%q) %v - CMAC_Final() = %d, want %v\n", | ||
| 919 | wt.TCID, wt.Comment, wt.Flags, ret, wt.Result) | ||
| 920 | return false | ||
| 921 | } | ||
| 922 | |||
| 923 | outTag = outTag[0:tagLen] | ||
| 924 | |||
| 925 | success := true | ||
| 926 | if bytes.Equal(tag, outTag) != (wt.Result == "valid") { | ||
| 927 | fmt.Printf("FAIL: Test case %d (%q) %v - want %v\n", | ||
| 928 | wt.TCID, wt.Comment, wt.Flags, wt.Result) | ||
| 929 | success = false | ||
| 930 | } | ||
| 931 | return success | ||
| 932 | } | ||
| 933 | |||
| 934 | func runAesCmacTestGroup(algorithm string, wtg *wycheproofTestGroupAesCmac) bool { | ||
| 935 | fmt.Printf("Running %v test group %v with key size %d and tag size %d...\n", | ||
| 936 | algorithm, wtg.Type, wtg.KeySize, wtg.TagSize) | ||
| 937 | var cipher *C.EVP_CIPHER | ||
| 938 | |||
| 939 | switch wtg.KeySize { | ||
| 940 | case 128: | ||
| 941 | cipher = C.EVP_aes_128_cbc() | ||
| 942 | case 192: | ||
| 943 | cipher = C.EVP_aes_192_cbc() | ||
| 944 | case 256: | ||
| 945 | cipher = C.EVP_aes_256_cbc() | ||
| 946 | default: | ||
| 947 | fmt.Printf("INFO: Skipping tests with invalid key size %d\n", wtg.KeySize) | ||
| 948 | return true | ||
| 949 | } | ||
| 950 | |||
| 951 | success := true | ||
| 952 | for _, wt := range wtg.Tests { | ||
| 953 | if !runAesCmacTest(cipher, wt) { | ||
| 954 | success = false | ||
| 955 | } | ||
| 956 | } | ||
| 957 | return success | ||
| 958 | } | ||
| 959 | |||
| 960 | func checkAeadOpen(ctx *C.EVP_AEAD_CTX, iv []byte, ivLen int, aad []byte, aadLen int, msg []byte, msgLen int, | ||
| 961 | ct []byte, ctLen int, tag []byte, tagLen int, wt *wycheproofTestAead) bool { | ||
| 962 | maxOutLen := ctLen + tagLen | ||
| 963 | |||
| 964 | opened := make([]byte, maxOutLen) | ||
| 965 | var openedMsgLen C.size_t | ||
| 966 | |||
| 967 | catCtTag := append(ct, tag...) | ||
| 968 | openRet := C.EVP_AEAD_CTX_open(ctx, (*C.uint8_t)(unsafe.Pointer(&opened[0])), | ||
| 969 | (*C.size_t)(unsafe.Pointer(&openedMsgLen)), C.size_t(maxOutLen), | ||
| 970 | (*C.uint8_t)(unsafe.Pointer(&iv[0])), C.size_t(ivLen), | ||
| 971 | (*C.uint8_t)(unsafe.Pointer(&catCtTag[0])), C.size_t(len(catCtTag)), | ||
| 972 | (*C.uint8_t)(unsafe.Pointer(&aad[0])), C.size_t(aadLen)) | ||
| 973 | |||
| 974 | if openRet != 1 { | ||
| 975 | if wt.Result == "invalid" { | ||
| 976 | return true | ||
| 977 | } | ||
| 978 | fmt.Printf("FAIL: Test case %d (%q) %v - EVP_AEAD_CTX_open() = %d, want %v\n", | ||
| 979 | wt.TCID, wt.Comment, wt.Flags, int(openRet), wt.Result) | ||
| 980 | return false | ||
| 981 | } | ||
| 982 | |||
| 983 | if openedMsgLen != C.size_t(msgLen) { | ||
| 984 | fmt.Printf("FAIL: Test case %d (%q) %v - open length mismatch: got %d, want %d\n", | ||
| 985 | wt.TCID, wt.Comment, wt.Flags, openedMsgLen, msgLen) | ||
| 986 | return false | ||
| 987 | } | ||
| 988 | |||
| 989 | openedMsg := opened[0:openedMsgLen] | ||
| 990 | if msgLen == 0 { | ||
| 991 | msg = nil | ||
| 992 | } | ||
| 993 | |||
| 994 | success := false | ||
| 995 | if bytes.Equal(openedMsg, msg) || wt.Result == "invalid" { | ||
| 996 | if acceptableAudit && wt.Result == "acceptable" { | ||
| 997 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 998 | } | ||
| 999 | success = true | ||
| 1000 | } else { | ||
| 1001 | fmt.Printf("FAIL: Test case %d (%q) %v - msg match: %t; want %v\n", | ||
| 1002 | wt.TCID, wt.Comment, wt.Flags, bytes.Equal(openedMsg, msg), wt.Result) | ||
| 1003 | } | ||
| 1004 | return success | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | func checkAeadSeal(ctx *C.EVP_AEAD_CTX, iv []byte, ivLen int, aad []byte, aadLen int, msg []byte, | ||
| 1008 | msgLen int, ct []byte, ctLen int, tag []byte, tagLen int, wt *wycheproofTestAead) bool { | ||
| 1009 | maxOutLen := msgLen + tagLen | ||
| 1010 | |||
| 1011 | sealed := make([]byte, maxOutLen) | ||
| 1012 | var sealedLen C.size_t | ||
| 1013 | |||
| 1014 | sealRet := C.EVP_AEAD_CTX_seal(ctx, (*C.uint8_t)(unsafe.Pointer(&sealed[0])), | ||
| 1015 | (*C.size_t)(unsafe.Pointer(&sealedLen)), C.size_t(maxOutLen), | ||
| 1016 | (*C.uint8_t)(unsafe.Pointer(&iv[0])), C.size_t(ivLen), | ||
| 1017 | (*C.uint8_t)(unsafe.Pointer(&msg[0])), C.size_t(msgLen), | ||
| 1018 | (*C.uint8_t)(unsafe.Pointer(&aad[0])), C.size_t(aadLen)) | ||
| 1019 | |||
| 1020 | if sealRet != 1 { | ||
| 1021 | fmt.Printf("FAIL: Test case %d (%q) %v - EVP_AEAD_CTX_seal() = %d, want %v\n", | ||
| 1022 | wt.TCID, wt.Comment, wt.Flags, int(sealRet), wt.Result) | ||
| 1023 | return false | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | if sealedLen != C.size_t(maxOutLen) { | ||
| 1027 | fmt.Printf("FAIL: Test case %d (%q) %v - seal length mismatch: got %d, want %d\n", | ||
| 1028 | wt.TCID, wt.Comment, wt.Flags, sealedLen, maxOutLen) | ||
| 1029 | return false | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | sealedCt := sealed[0:msgLen] | ||
| 1033 | sealedTag := sealed[msgLen:maxOutLen] | ||
| 1034 | |||
| 1035 | success := false | ||
| 1036 | if bytes.Equal(sealedCt, ct) && bytes.Equal(sealedTag, tag) || wt.Result == "invalid" { | ||
| 1037 | if acceptableAudit && wt.Result == "acceptable" { | ||
| 1038 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 1039 | } | ||
| 1040 | success = true | ||
| 1041 | } else { | ||
| 1042 | fmt.Printf("FAIL: Test case %d (%q) %v - EVP_AEAD_CTX_seal() = %d, ct match: %t, tag match: %t; want %v\n", | ||
| 1043 | wt.TCID, wt.Comment, wt.Flags, int(sealRet), | ||
| 1044 | bytes.Equal(sealedCt, ct), bytes.Equal(sealedTag, tag), wt.Result) | ||
| 1045 | } | ||
| 1046 | return success | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | func runChaCha20Poly1305Test(wt *wycheproofTestAead) bool { | ||
| 1050 | aead := C.EVP_aead_chacha20_poly1305() | ||
| 1051 | |||
| 1052 | key, err := hex.DecodeString(wt.Key) | ||
| 1053 | if err != nil { | ||
| 1054 | log.Fatalf("Failed to decode key %q: %v", wt.Key, err) | ||
| 1055 | } | ||
| 1056 | iv, err := hex.DecodeString(wt.IV) | ||
| 1057 | if err != nil { | ||
| 1058 | log.Fatalf("Failed to decode key %q: %v", wt.IV, err) | ||
| 1059 | } | ||
| 1060 | aad, err := hex.DecodeString(wt.AAD) | ||
| 1061 | if err != nil { | ||
| 1062 | log.Fatalf("Failed to decode AAD %q: %v", wt.AAD, err) | ||
| 1063 | } | ||
| 1064 | msg, err := hex.DecodeString(wt.Msg) | ||
| 1065 | if err != nil { | ||
| 1066 | log.Fatalf("Failed to decode msg %q: %v", wt.Msg, err) | ||
| 1067 | } | ||
| 1068 | ct, err := hex.DecodeString(wt.CT) | ||
| 1069 | if err != nil { | ||
| 1070 | log.Fatalf("Failed to decode ct %q: %v", wt.CT, err) | ||
| 1071 | } | ||
| 1072 | tag, err := hex.DecodeString(wt.Tag) | ||
| 1073 | if err != nil { | ||
| 1074 | log.Fatalf("Failed to decode tag %q: %v", wt.Tag, err) | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | keyLen, ivLen, aadLen, msgLen, ctLen, tagLen := len(key), len(iv), len(aad), len(msg), len(ct), len(tag) | ||
| 1078 | |||
| 1079 | if ivLen == 0 { | ||
| 1080 | iv = append(iv, 0) | ||
| 1081 | } | ||
| 1082 | if aadLen == 0 { | ||
| 1083 | aad = append(aad, 0) | ||
| 1084 | } | ||
| 1085 | if msgLen == 0 { | ||
| 1086 | msg = append(msg, 0) | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | var ctx C.EVP_AEAD_CTX | ||
| 1090 | if C.EVP_AEAD_CTX_init(&ctx, aead, (*C.uchar)(unsafe.Pointer(&key[0])), C.size_t(keyLen), C.size_t(tagLen), nil) != 1 { | ||
| 1091 | log.Fatal("Failed to initialize AEAD context") | ||
| 1092 | } | ||
| 1093 | defer C.EVP_AEAD_CTX_cleanup(&ctx) | ||
| 1094 | |||
| 1095 | openSuccess := checkAeadOpen(&ctx, iv, ivLen, aad, aadLen, msg, msgLen, ct, ctLen, tag, tagLen, wt) | ||
| 1096 | sealSuccess := checkAeadSeal(&ctx, iv, ivLen, aad, aadLen, msg, msgLen, ct, ctLen, tag, tagLen, wt) | ||
| 1097 | |||
| 1098 | return openSuccess && sealSuccess | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | func runChaCha20Poly1305TestGroup(algorithm string, wtg *wycheproofTestGroupAead) bool { | ||
| 1102 | // We currently only support nonces of length 12 (96 bits) | ||
| 1103 | if wtg.IVSize != 96 { | ||
| 1104 | return true | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | fmt.Printf("Running %v test group %v with IV size %d, key size %d, tag size %d...\n", | ||
| 1108 | algorithm, wtg.Type, wtg.IVSize, wtg.KeySize, wtg.TagSize) | ||
| 1109 | |||
| 1110 | success := true | ||
| 1111 | for _, wt := range wtg.Tests { | ||
| 1112 | if !runChaCha20Poly1305Test(wt) { | ||
| 1113 | success = false | ||
| 1114 | } | ||
| 1115 | } | ||
| 1116 | return success | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | func runDSATest(dsa *C.DSA, h hash.Hash, wt *wycheproofTestDSA) bool { | ||
| 1120 | msg, err := hex.DecodeString(wt.Msg) | ||
| 1121 | if err != nil { | ||
| 1122 | log.Fatalf("Failed to decode message %q: %v", wt.Msg, err) | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | h.Reset() | ||
| 1126 | h.Write(msg) | ||
| 1127 | msg = h.Sum(nil) | ||
| 1128 | |||
| 1129 | sig, err := hex.DecodeString(wt.Sig) | ||
| 1130 | if err != nil { | ||
| 1131 | log.Fatalf("Failed to decode signature %q: %v", wt.Sig, err) | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | msgLen, sigLen := len(msg), len(sig) | ||
| 1135 | if msgLen == 0 { | ||
| 1136 | msg = append(msg, 0) | ||
| 1137 | } | ||
| 1138 | if sigLen == 0 { | ||
| 1139 | sig = append(msg, 0) | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | ret := C.DSA_verify(0, (*C.uchar)(unsafe.Pointer(&msg[0])), C.int(msgLen), | ||
| 1143 | (*C.uchar)(unsafe.Pointer(&sig[0])), C.int(sigLen), dsa) | ||
| 1144 | |||
| 1145 | success := true | ||
| 1146 | if ret == 1 != (wt.Result == "valid") { | ||
| 1147 | fmt.Printf("FAIL: Test case %d (%q) %v - DSA_verify() = %d, want %v\n", | ||
| 1148 | wt.TCID, wt.Comment, wt.Flags, ret, wt.Result) | ||
| 1149 | success = false | ||
| 1150 | } | ||
| 1151 | return success | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | func runDSATestGroup(algorithm string, wtg *wycheproofTestGroupDSA) bool { | ||
| 1155 | fmt.Printf("Running %v test group %v, key size %d and %v...\n", | ||
| 1156 | algorithm, wtg.Type, wtg.Key.KeySize, wtg.SHA) | ||
| 1157 | |||
| 1158 | dsa := C.DSA_new() | ||
| 1159 | if dsa == nil { | ||
| 1160 | log.Fatal("DSA_new failed") | ||
| 1161 | } | ||
| 1162 | defer C.DSA_free(dsa) | ||
| 1163 | |||
| 1164 | var bnG *C.BIGNUM | ||
| 1165 | wg := C.CString(wtg.Key.G) | ||
| 1166 | if C.BN_hex2bn(&bnG, wg) == 0 { | ||
| 1167 | log.Fatal("Failed to decode g") | ||
| 1168 | } | ||
| 1169 | C.free(unsafe.Pointer(wg)) | ||
| 1170 | |||
| 1171 | var bnP *C.BIGNUM | ||
| 1172 | wp := C.CString(wtg.Key.P) | ||
| 1173 | if C.BN_hex2bn(&bnP, wp) == 0 { | ||
| 1174 | log.Fatal("Failed to decode p") | ||
| 1175 | } | ||
| 1176 | C.free(unsafe.Pointer(wp)) | ||
| 1177 | |||
| 1178 | var bnQ *C.BIGNUM | ||
| 1179 | wq := C.CString(wtg.Key.Q) | ||
| 1180 | if C.BN_hex2bn(&bnQ, wq) == 0 { | ||
| 1181 | log.Fatal("Failed to decode q") | ||
| 1182 | } | ||
| 1183 | C.free(unsafe.Pointer(wq)) | ||
| 1184 | |||
| 1185 | ret := C.DSA_set0_pqg(dsa, bnP, bnQ, bnG) | ||
| 1186 | if ret != 1 { | ||
| 1187 | log.Fatalf("DSA_set0_pqg returned %d", ret) | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | var bnY *C.BIGNUM | ||
| 1191 | wy := C.CString(wtg.Key.Y) | ||
| 1192 | if C.BN_hex2bn(&bnY, wy) == 0 { | ||
| 1193 | log.Fatal("Failed to decode y") | ||
| 1194 | } | ||
| 1195 | C.free(unsafe.Pointer(wy)) | ||
| 1196 | |||
| 1197 | ret = C.DSA_set0_key(dsa, bnY, nil) | ||
| 1198 | if ret != 1 { | ||
| 1199 | log.Fatalf("DSA_set0_key returned %d", ret) | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | h, err := hashFromString(wtg.SHA) | ||
| 1203 | if err != nil { | ||
| 1204 | log.Fatalf("Failed to get hash: %v", err) | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | der, err := hex.DecodeString(wtg.KeyDER) | ||
| 1208 | if err != nil { | ||
| 1209 | log.Fatalf("Failed to decode DER encoded key: %v", err) | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | derLen := len(der) | ||
| 1213 | if derLen == 0 { | ||
| 1214 | der = append(der, 0) | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | Cder := (*C.uchar)(C.malloc(C.ulong(derLen))) | ||
| 1218 | if Cder == nil { | ||
| 1219 | log.Fatal("malloc failed") | ||
| 1220 | } | ||
| 1221 | C.memcpy(unsafe.Pointer(Cder), unsafe.Pointer(&der[0]), C.ulong(derLen)) | ||
| 1222 | |||
| 1223 | p := (*C.uchar)(Cder) | ||
| 1224 | dsaDER := C.d2i_DSA_PUBKEY(nil, (**C.uchar)(&p), C.long(derLen)) | ||
| 1225 | defer C.DSA_free(dsaDER) | ||
| 1226 | C.free(unsafe.Pointer(Cder)) | ||
| 1227 | |||
| 1228 | keyPEM := C.CString(wtg.KeyPEM) | ||
| 1229 | bio := C.BIO_new_mem_buf(unsafe.Pointer(keyPEM), C.int(len(wtg.KeyPEM))) | ||
| 1230 | if bio == nil { | ||
| 1231 | log.Fatal("BIO_new_mem_buf failed") | ||
| 1232 | } | ||
| 1233 | defer C.free(unsafe.Pointer(keyPEM)) | ||
| 1234 | defer C.BIO_free(bio) | ||
| 1235 | |||
| 1236 | dsaPEM := C.PEM_read_bio_DSA_PUBKEY(bio, nil, nil, nil) | ||
| 1237 | if dsaPEM == nil { | ||
| 1238 | log.Fatal("PEM_read_bio_DSA_PUBKEY failed") | ||
| 1239 | } | ||
| 1240 | defer C.DSA_free(dsaPEM) | ||
| 1241 | |||
| 1242 | success := true | ||
| 1243 | for _, wt := range wtg.Tests { | ||
| 1244 | if !runDSATest(dsa, h, wt) { | ||
| 1245 | success = false | ||
| 1246 | } | ||
| 1247 | if !runDSATest(dsaDER, h, wt) { | ||
| 1248 | success = false | ||
| 1249 | } | ||
| 1250 | if !runDSATest(dsaPEM, h, wt) { | ||
| 1251 | success = false | ||
| 1252 | } | ||
| 1253 | } | ||
| 1254 | return success | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | func runECDHTest(nid int, doECpoint bool, wt *wycheproofTestECDH) bool { | ||
| 1258 | privKey := C.EC_KEY_new_by_curve_name(C.int(nid)) | ||
| 1259 | if privKey == nil { | ||
| 1260 | log.Fatalf("EC_KEY_new_by_curve_name failed") | ||
| 1261 | } | ||
| 1262 | defer C.EC_KEY_free(privKey) | ||
| 1263 | |||
| 1264 | var bnPriv *C.BIGNUM | ||
| 1265 | wPriv := C.CString(wt.Private) | ||
| 1266 | if C.BN_hex2bn(&bnPriv, wPriv) == 0 { | ||
| 1267 | log.Fatal("Failed to decode wPriv") | ||
| 1268 | } | ||
| 1269 | C.free(unsafe.Pointer(wPriv)) | ||
| 1270 | defer C.BN_free(bnPriv) | ||
| 1271 | |||
| 1272 | ret := C.EC_KEY_set_private_key(privKey, bnPriv) | ||
| 1273 | if ret != 1 { | ||
| 1274 | fmt.Printf("FAIL: Test case %d (%q) %v - EC_KEY_set_private_key() = %d, want %v\n", | ||
| 1275 | wt.TCID, wt.Comment, wt.Flags, ret, wt.Result) | ||
| 1276 | return false | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | pub, err := hex.DecodeString(wt.Public) | ||
| 1280 | if err != nil { | ||
| 1281 | log.Fatalf("Failed to decode public key: %v", err) | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | pubLen := len(pub) | ||
| 1285 | if pubLen == 0 { | ||
| 1286 | pub = append(pub, 0) | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | Cpub := (*C.uchar)(C.malloc(C.ulong(pubLen))) | ||
| 1290 | if Cpub == nil { | ||
| 1291 | log.Fatal("malloc failed") | ||
| 1292 | } | ||
| 1293 | C.memcpy(unsafe.Pointer(Cpub), unsafe.Pointer(&pub[0]), C.ulong(pubLen)) | ||
| 1294 | |||
| 1295 | p := (*C.uchar)(Cpub) | ||
| 1296 | var pubKey *C.EC_KEY | ||
| 1297 | if doECpoint { | ||
| 1298 | pubKey = C.EC_KEY_new_by_curve_name(C.int(nid)) | ||
| 1299 | if pubKey == nil { | ||
| 1300 | log.Fatal("EC_KEY_new_by_curve_name failed") | ||
| 1301 | } | ||
| 1302 | pubKey = C.o2i_ECPublicKey(&pubKey, (**C.uchar)(&p), C.long(pubLen)) | ||
| 1303 | } else { | ||
| 1304 | pubKey = C.d2i_EC_PUBKEY(nil, (**C.uchar)(&p), C.long(pubLen)) | ||
| 1305 | } | ||
| 1306 | defer C.EC_KEY_free(pubKey) | ||
| 1307 | C.free(unsafe.Pointer(Cpub)) | ||
| 1308 | |||
| 1309 | if pubKey == nil { | ||
| 1310 | if wt.Result == "invalid" || wt.Result == "acceptable" { | ||
| 1311 | return true | ||
| 1312 | } | ||
| 1313 | fmt.Printf("FAIL: Test case %d (%q) %v - ASN decoding failed: want %v\n", | ||
| 1314 | wt.TCID, wt.Comment, wt.Flags, wt.Result) | ||
| 1315 | return false | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | privGroup := C.EC_KEY_get0_group(privKey) | ||
| 1319 | |||
| 1320 | secLen := (C.EC_GROUP_get_degree(privGroup) + 7) / 8 | ||
| 1321 | |||
| 1322 | secret := make([]byte, secLen) | ||
| 1323 | if secLen == 0 { | ||
| 1324 | secret = append(secret, 0) | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | pubPoint := C.EC_KEY_get0_public_key(pubKey) | ||
| 1328 | |||
| 1329 | ret = C.ECDH_compute_key(unsafe.Pointer(&secret[0]), C.ulong(secLen), pubPoint, privKey, nil) | ||
| 1330 | if ret != C.int(secLen) { | ||
| 1331 | if wt.Result == "invalid" { | ||
| 1332 | return true | ||
| 1333 | } | ||
| 1334 | fmt.Printf("FAIL: Test case %d (%q) %v - ECDH_compute_key() = %d, want %d, result: %v\n", | ||
| 1335 | wt.TCID, wt.Comment, wt.Flags, ret, int(secLen), wt.Result) | ||
| 1336 | return false | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | shared, err := hex.DecodeString(wt.Shared) | ||
| 1340 | if err != nil { | ||
| 1341 | log.Fatalf("Failed to decode shared secret: %v", err) | ||
| 1342 | } | ||
| 1343 | |||
| 1344 | success := true | ||
| 1345 | if !bytes.Equal(shared, secret) { | ||
| 1346 | fmt.Printf("FAIL: Test case %d (%q) %v - expected and computed shared secret do not match, want %v\n", | ||
| 1347 | wt.TCID, wt.Comment, wt.Flags, wt.Result) | ||
| 1348 | success = false | ||
| 1349 | } | ||
| 1350 | if acceptableAudit && success && wt.Result == "acceptable" { | ||
| 1351 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 1352 | } | ||
| 1353 | return success | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | func runECDHTestGroup(algorithm string, wtg *wycheproofTestGroupECDH) bool { | ||
| 1357 | doECpoint := false | ||
| 1358 | if wtg.Encoding == "ecpoint" { | ||
| 1359 | doECpoint = true | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | fmt.Printf("Running %v test group %v with curve %v and %v encoding...\n", | ||
| 1363 | algorithm, wtg.Type, wtg.Curve, wtg.Encoding) | ||
| 1364 | |||
| 1365 | nid, err := nidFromString(wtg.Curve) | ||
| 1366 | if err != nil { | ||
| 1367 | log.Fatalf("Failed to get nid for curve: %v", err) | ||
| 1368 | } | ||
| 1369 | |||
| 1370 | success := true | ||
| 1371 | for _, wt := range wtg.Tests { | ||
| 1372 | if !runECDHTest(nid, doECpoint, wt) { | ||
| 1373 | success = false | ||
| 1374 | } | ||
| 1375 | } | ||
| 1376 | return success | ||
| 1377 | } | ||
| 1378 | |||
| 1379 | func runECDHWebCryptoTest(nid int, wt *wycheproofTestECDHWebCrypto) bool { | ||
| 1380 | privKey := C.EC_KEY_new_by_curve_name(C.int(nid)) | ||
| 1381 | if privKey == nil { | ||
| 1382 | log.Fatalf("EC_KEY_new_by_curve_name failed") | ||
| 1383 | } | ||
| 1384 | defer C.EC_KEY_free(privKey) | ||
| 1385 | |||
| 1386 | d, err := base64.RawURLEncoding.DecodeString(wt.Private.D) | ||
| 1387 | if err != nil { | ||
| 1388 | log.Fatalf("Failed to base64 decode d: %v", err) | ||
| 1389 | } | ||
| 1390 | bnD := C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&d[0])), C.int(len(d)), nil) | ||
| 1391 | if bnD == nil { | ||
| 1392 | log.Fatal("Failed to decode D") | ||
| 1393 | } | ||
| 1394 | defer C.BN_free(bnD) | ||
| 1395 | |||
| 1396 | ret := C.EC_KEY_set_private_key(privKey, bnD) | ||
| 1397 | if ret != 1 { | ||
| 1398 | fmt.Printf("FAIL: Test case %d (%q) %v - EC_KEY_set_private_key() = %d, want %v\n", | ||
| 1399 | wt.TCID, wt.Comment, wt.Flags, ret, wt.Result) | ||
| 1400 | return false | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | x, err := base64.RawURLEncoding.DecodeString(wt.Public.X) | ||
| 1404 | if err != nil { | ||
| 1405 | log.Fatalf("Failed to base64 decode x: %v", err) | ||
| 1406 | } | ||
| 1407 | bnX := C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&x[0])), C.int(len(x)), nil) | ||
| 1408 | if bnX == nil { | ||
| 1409 | log.Fatal("Failed to decode X") | ||
| 1410 | } | ||
| 1411 | defer C.BN_free(bnX) | ||
| 1412 | |||
| 1413 | y, err := base64.RawURLEncoding.DecodeString(wt.Public.Y) | ||
| 1414 | if err != nil { | ||
| 1415 | log.Fatalf("Failed to base64 decode y: %v", err) | ||
| 1416 | } | ||
| 1417 | bnY := C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&y[0])), C.int(len(y)), nil) | ||
| 1418 | if bnY == nil { | ||
| 1419 | log.Fatal("Failed to decode Y") | ||
| 1420 | } | ||
| 1421 | defer C.BN_free(bnY) | ||
| 1422 | |||
| 1423 | pubKey := C.EC_KEY_new_by_curve_name(C.int(nid)) | ||
| 1424 | if pubKey == nil { | ||
| 1425 | log.Fatal("Failed to create EC_KEY") | ||
| 1426 | } | ||
| 1427 | defer C.EC_KEY_free(pubKey) | ||
| 1428 | |||
| 1429 | ret = C.EC_KEY_set_public_key_affine_coordinates(pubKey, bnX, bnY) | ||
| 1430 | if ret != 1 { | ||
| 1431 | if wt.Result == "invalid" { | ||
| 1432 | return true | ||
| 1433 | } | ||
| 1434 | fmt.Printf("FAIL: Test case %d (%q) %v - EC_KEY_set_public_key_affine_coordinates() = %d, want %v\n", | ||
| 1435 | wt.TCID, wt.Comment, wt.Flags, ret, wt.Result) | ||
| 1436 | return false | ||
| 1437 | } | ||
| 1438 | pubPoint := C.EC_KEY_get0_public_key(pubKey) | ||
| 1439 | |||
| 1440 | privGroup := C.EC_KEY_get0_group(privKey) | ||
| 1441 | |||
| 1442 | secLen := (C.EC_GROUP_get_degree(privGroup) + 7) / 8 | ||
| 1443 | |||
| 1444 | secret := make([]byte, secLen) | ||
| 1445 | if secLen == 0 { | ||
| 1446 | secret = append(secret, 0) | ||
| 1447 | } | ||
| 1448 | |||
| 1449 | ret = C.ECDH_compute_key(unsafe.Pointer(&secret[0]), C.ulong(secLen), pubPoint, privKey, nil) | ||
| 1450 | if ret != C.int(secLen) { | ||
| 1451 | if wt.Result == "invalid" { | ||
| 1452 | return true | ||
| 1453 | } | ||
| 1454 | fmt.Printf("FAIL: Test case %d (%q) %v - ECDH_compute_key() = %d, want %d, result: %v\n", | ||
| 1455 | wt.TCID, wt.Comment, wt.Flags, ret, int(secLen), wt.Result) | ||
| 1456 | return false | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | shared, err := hex.DecodeString(wt.Shared) | ||
| 1460 | if err != nil { | ||
| 1461 | log.Fatalf("Failed to decode shared secret: %v", err) | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | success := true | ||
| 1465 | if !bytes.Equal(shared, secret) { | ||
| 1466 | fmt.Printf("FAIL: Test case %d (%q) %v - expected and computed shared secret do not match, want %v\n", | ||
| 1467 | wt.TCID, wt.Comment, wt.Flags, wt.Result) | ||
| 1468 | success = false | ||
| 1469 | } | ||
| 1470 | if acceptableAudit && success && wt.Result == "acceptable" { | ||
| 1471 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 1472 | } | ||
| 1473 | return success | ||
| 1474 | } | ||
| 1475 | |||
| 1476 | func runECDHWebCryptoTestGroup(algorithm string, wtg *wycheproofTestGroupECDHWebCrypto) bool { | ||
| 1477 | fmt.Printf("Running %v test group %v with curve %v and %v encoding...\n", | ||
| 1478 | algorithm, wtg.Type, wtg.Curve, wtg.Encoding) | ||
| 1479 | |||
| 1480 | nid, err := nidFromString(wtg.Curve) | ||
| 1481 | if err != nil { | ||
| 1482 | log.Fatalf("Failed to get nid for curve: %v", err) | ||
| 1483 | } | ||
| 1484 | |||
| 1485 | success := true | ||
| 1486 | for _, wt := range wtg.Tests { | ||
| 1487 | if !runECDHWebCryptoTest(nid, wt) { | ||
| 1488 | success = false | ||
| 1489 | } | ||
| 1490 | } | ||
| 1491 | return success | ||
| 1492 | } | ||
| 1493 | |||
| 1494 | func runECDSATest(ecKey *C.EC_KEY, nid int, h hash.Hash, webcrypto bool, wt *wycheproofTestECDSA) bool { | ||
| 1495 | msg, err := hex.DecodeString(wt.Msg) | ||
| 1496 | if err != nil { | ||
| 1497 | log.Fatalf("Failed to decode message %q: %v", wt.Msg, err) | ||
| 1498 | } | ||
| 1499 | |||
| 1500 | h.Reset() | ||
| 1501 | h.Write(msg) | ||
| 1502 | msg = h.Sum(nil) | ||
| 1503 | |||
| 1504 | msgLen := len(msg) | ||
| 1505 | if msgLen == 0 { | ||
| 1506 | msg = append(msg, 0) | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | var ret C.int | ||
| 1510 | if webcrypto { | ||
| 1511 | cDer, derLen := encodeECDSAWebCryptoSig(wt.Sig) | ||
| 1512 | if cDer == nil { | ||
| 1513 | fmt.Print("FAIL: unable to decode signature") | ||
| 1514 | return false | ||
| 1515 | } | ||
| 1516 | defer C.free(unsafe.Pointer(cDer)) | ||
| 1517 | |||
| 1518 | ret = C.ECDSA_verify(0, (*C.uchar)(unsafe.Pointer(&msg[0])), C.int(msgLen), | ||
| 1519 | (*C.uchar)(unsafe.Pointer(cDer)), C.int(derLen), ecKey) | ||
| 1520 | } else { | ||
| 1521 | sig, err := hex.DecodeString(wt.Sig) | ||
| 1522 | if err != nil { | ||
| 1523 | log.Fatalf("Failed to decode signature %q: %v", wt.Sig, err) | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | sigLen := len(sig) | ||
| 1527 | if sigLen == 0 { | ||
| 1528 | sig = append(sig, 0) | ||
| 1529 | } | ||
| 1530 | ret = C.ECDSA_verify(0, (*C.uchar)(unsafe.Pointer(&msg[0])), C.int(msgLen), | ||
| 1531 | (*C.uchar)(unsafe.Pointer(&sig[0])), C.int(sigLen), ecKey) | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | // XXX audit acceptable cases... | ||
| 1535 | success := true | ||
| 1536 | if ret == 1 != (wt.Result == "valid") && wt.Result != "acceptable" { | ||
| 1537 | fmt.Printf("FAIL: Test case %d (%q) %v - ECDSA_verify() = %d, want %v\n", | ||
| 1538 | wt.TCID, wt.Comment, wt.Flags, int(ret), wt.Result) | ||
| 1539 | success = false | ||
| 1540 | } | ||
| 1541 | if acceptableAudit && ret == 1 && wt.Result == "acceptable" { | ||
| 1542 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 1543 | } | ||
| 1544 | return success | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | func runECDSATestGroup(algorithm string, wtg *wycheproofTestGroupECDSA) bool { | ||
| 1548 | fmt.Printf("Running %v test group %v with curve %v, key size %d and %v...\n", | ||
| 1549 | algorithm, wtg.Type, wtg.Key.Curve, wtg.Key.KeySize, wtg.SHA) | ||
| 1550 | |||
| 1551 | nid, err := nidFromString(wtg.Key.Curve) | ||
| 1552 | if err != nil { | ||
| 1553 | log.Fatalf("Failed to get nid for curve: %v", err) | ||
| 1554 | } | ||
| 1555 | ecKey := C.EC_KEY_new_by_curve_name(C.int(nid)) | ||
| 1556 | if ecKey == nil { | ||
| 1557 | log.Fatal("EC_KEY_new_by_curve_name failed") | ||
| 1558 | } | ||
| 1559 | defer C.EC_KEY_free(ecKey) | ||
| 1560 | |||
| 1561 | var bnX *C.BIGNUM | ||
| 1562 | wx := C.CString(wtg.Key.WX) | ||
| 1563 | if C.BN_hex2bn(&bnX, wx) == 0 { | ||
| 1564 | log.Fatal("Failed to decode WX") | ||
| 1565 | } | ||
| 1566 | C.free(unsafe.Pointer(wx)) | ||
| 1567 | defer C.BN_free(bnX) | ||
| 1568 | |||
| 1569 | var bnY *C.BIGNUM | ||
| 1570 | wy := C.CString(wtg.Key.WY) | ||
| 1571 | if C.BN_hex2bn(&bnY, wy) == 0 { | ||
| 1572 | log.Fatal("Failed to decode WY") | ||
| 1573 | } | ||
| 1574 | C.free(unsafe.Pointer(wy)) | ||
| 1575 | defer C.BN_free(bnY) | ||
| 1576 | |||
| 1577 | if C.EC_KEY_set_public_key_affine_coordinates(ecKey, bnX, bnY) != 1 { | ||
| 1578 | log.Fatal("Failed to set EC public key") | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | nid, err = nidFromString(wtg.SHA) | ||
| 1582 | if err != nil { | ||
| 1583 | log.Fatalf("Failed to get MD NID: %v", err) | ||
| 1584 | } | ||
| 1585 | h, err := hashFromString(wtg.SHA) | ||
| 1586 | if err != nil { | ||
| 1587 | log.Fatalf("Failed to get hash: %v", err) | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | success := true | ||
| 1591 | for _, wt := range wtg.Tests { | ||
| 1592 | if !runECDSATest(ecKey, nid, h, false, wt) { | ||
| 1593 | success = false | ||
| 1594 | } | ||
| 1595 | } | ||
| 1596 | return success | ||
| 1597 | } | ||
| 1598 | |||
| 1599 | // DER encode the signature (so that ECDSA_verify() can decode and encode it again...) | ||
| 1600 | func encodeECDSAWebCryptoSig(wtSig string) (*C.uchar, C.int) { | ||
| 1601 | cSig := C.ECDSA_SIG_new() | ||
| 1602 | if cSig == nil { | ||
| 1603 | log.Fatal("ECDSA_SIG_new() failed") | ||
| 1604 | } | ||
| 1605 | defer C.ECDSA_SIG_free(cSig) | ||
| 1606 | |||
| 1607 | sigLen := len(wtSig) | ||
| 1608 | r := C.CString(wtSig[:sigLen/2]) | ||
| 1609 | s := C.CString(wtSig[sigLen/2:]) | ||
| 1610 | defer C.free(unsafe.Pointer(r)) | ||
| 1611 | defer C.free(unsafe.Pointer(s)) | ||
| 1612 | if C.BN_hex2bn(&cSig.r, r) == 0 { | ||
| 1613 | return nil, 0 | ||
| 1614 | } | ||
| 1615 | if C.BN_hex2bn(&cSig.s, s) == 0 { | ||
| 1616 | return nil, 0 | ||
| 1617 | } | ||
| 1618 | |||
| 1619 | derLen := C.i2d_ECDSA_SIG(cSig, nil) | ||
| 1620 | if derLen == 0 { | ||
| 1621 | return nil, 0 | ||
| 1622 | } | ||
| 1623 | cDer := (*C.uchar)(C.malloc(C.ulong(derLen))) | ||
| 1624 | if cDer == nil { | ||
| 1625 | log.Fatal("malloc failed") | ||
| 1626 | } | ||
| 1627 | |||
| 1628 | p := cDer | ||
| 1629 | ret := C.i2d_ECDSA_SIG(cSig, (**C.uchar)(&p)) | ||
| 1630 | if ret == 0 || ret != derLen { | ||
| 1631 | C.free(unsafe.Pointer(cDer)) | ||
| 1632 | return nil, 0 | ||
| 1633 | } | ||
| 1634 | |||
| 1635 | return cDer, derLen | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | func runECDSAWebCryptoTestGroup(algorithm string, wtg *wycheproofTestGroupECDSAWebCrypto) bool { | ||
| 1639 | fmt.Printf("Running %v test group %v with curve %v, key size %d and %v...\n", | ||
| 1640 | algorithm, wtg.Type, wtg.Key.Curve, wtg.Key.KeySize, wtg.SHA) | ||
| 1641 | |||
| 1642 | nid, err := nidFromString(wtg.JWK.Crv) | ||
| 1643 | if err != nil { | ||
| 1644 | log.Fatalf("Failed to get nid for curve: %v", err) | ||
| 1645 | } | ||
| 1646 | ecKey := C.EC_KEY_new_by_curve_name(C.int(nid)) | ||
| 1647 | if ecKey == nil { | ||
| 1648 | log.Fatal("EC_KEY_new_by_curve_name failed") | ||
| 1649 | } | ||
| 1650 | defer C.EC_KEY_free(ecKey) | ||
| 1651 | |||
| 1652 | x, err := base64.RawURLEncoding.DecodeString(wtg.JWK.X) | ||
| 1653 | if err != nil { | ||
| 1654 | log.Fatalf("Failed to base64 decode X: %v", err) | ||
| 1655 | } | ||
| 1656 | bnX := C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&x[0])), C.int(len(x)), nil) | ||
| 1657 | if bnX == nil { | ||
| 1658 | log.Fatal("Failed to decode X") | ||
| 1659 | } | ||
| 1660 | defer C.BN_free(bnX) | ||
| 1661 | |||
| 1662 | y, err := base64.RawURLEncoding.DecodeString(wtg.JWK.Y) | ||
| 1663 | if err != nil { | ||
| 1664 | log.Fatalf("Failed to base64 decode Y: %v", err) | ||
| 1665 | } | ||
| 1666 | bnY := C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&y[0])), C.int(len(y)), nil) | ||
| 1667 | if bnY == nil { | ||
| 1668 | log.Fatal("Failed to decode Y") | ||
| 1669 | } | ||
| 1670 | defer C.BN_free(bnY) | ||
| 1671 | |||
| 1672 | if C.EC_KEY_set_public_key_affine_coordinates(ecKey, bnX, bnY) != 1 { | ||
| 1673 | log.Fatal("Failed to set EC public key") | ||
| 1674 | } | ||
| 1675 | |||
| 1676 | nid, err = nidFromString(wtg.SHA) | ||
| 1677 | if err != nil { | ||
| 1678 | log.Fatalf("Failed to get MD NID: %v", err) | ||
| 1679 | } | ||
| 1680 | h, err := hashFromString(wtg.SHA) | ||
| 1681 | if err != nil { | ||
| 1682 | log.Fatalf("Failed to get hash: %v", err) | ||
| 1683 | } | ||
| 1684 | |||
| 1685 | success := true | ||
| 1686 | for _, wt := range wtg.Tests { | ||
| 1687 | if !runECDSATest(ecKey, nid, h, true, wt) { | ||
| 1688 | success = false | ||
| 1689 | } | ||
| 1690 | } | ||
| 1691 | return success | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | func runKWTestWrap(keySize int, key []byte, keyLen int, msg []byte, msgLen int, ct []byte, ctLen int, wt *wycheproofTestKW) bool { | ||
| 1695 | var aesKey C.AES_KEY | ||
| 1696 | |||
| 1697 | ret := C.AES_set_encrypt_key((*C.uchar)(unsafe.Pointer(&key[0])), (C.int)(keySize), (*C.AES_KEY)(unsafe.Pointer(&aesKey))) | ||
| 1698 | if ret != 0 { | ||
| 1699 | fmt.Printf("FAIL: Test case %d (%q) %v - AES_set_encrypt_key() = %d, want %v\n", | ||
| 1700 | wt.TCID, wt.Comment, wt.Flags, int(ret), wt.Result) | ||
| 1701 | return false | ||
| 1702 | } | ||
| 1703 | |||
| 1704 | outLen := msgLen + 8 | ||
| 1705 | out := make([]byte, outLen) | ||
| 1706 | ret = C.AES_wrap_key((*C.AES_KEY)(unsafe.Pointer(&aesKey)), nil, (*C.uchar)(unsafe.Pointer(&out[0])), (*C.uchar)(unsafe.Pointer(&msg[0])), (C.uint)(msgLen)) | ||
| 1707 | success := false | ||
| 1708 | if ret == C.int(outLen) && bytes.Equal(out, ct) { | ||
| 1709 | if acceptableAudit && wt.Result == "acceptable" { | ||
| 1710 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 1711 | } | ||
| 1712 | if wt.Result != "invalid" { | ||
| 1713 | success = true | ||
| 1714 | } | ||
| 1715 | } else if wt.Result != "valid" { | ||
| 1716 | success = true | ||
| 1717 | } | ||
| 1718 | if !success { | ||
| 1719 | fmt.Printf("FAIL: Test case %d (%q) %v - msgLen = %d, AES_wrap_key() = %d, want %v\n", | ||
| 1720 | wt.TCID, wt.Comment, wt.Flags, msgLen, int(ret), wt.Result) | ||
| 1721 | } | ||
| 1722 | return success | ||
| 1723 | } | ||
| 1724 | |||
| 1725 | func runKWTestUnWrap(keySize int, key []byte, keyLen int, msg []byte, msgLen int, ct []byte, ctLen int, wt *wycheproofTestKW) bool { | ||
| 1726 | var aesKey C.AES_KEY | ||
| 1727 | |||
| 1728 | ret := C.AES_set_decrypt_key((*C.uchar)(unsafe.Pointer(&key[0])), (C.int)(keySize), (*C.AES_KEY)(unsafe.Pointer(&aesKey))) | ||
| 1729 | if ret != 0 { | ||
| 1730 | fmt.Printf("FAIL: Test case %d (%q) %v - AES_set_encrypt_key() = %d, want %v\n", | ||
| 1731 | wt.TCID, wt.Comment, wt.Flags, int(ret), wt.Result) | ||
| 1732 | return false | ||
| 1733 | } | ||
| 1734 | |||
| 1735 | out := make([]byte, ctLen) | ||
| 1736 | if ctLen == 0 { | ||
| 1737 | out = append(out, 0) | ||
| 1738 | } | ||
| 1739 | ret = C.AES_unwrap_key((*C.AES_KEY)(unsafe.Pointer(&aesKey)), nil, (*C.uchar)(unsafe.Pointer(&out[0])), (*C.uchar)(unsafe.Pointer(&ct[0])), (C.uint)(ctLen)) | ||
| 1740 | success := false | ||
| 1741 | if ret == C.int(ctLen - 8) && bytes.Equal(out[0:ret], msg[0:ret]) { | ||
| 1742 | if acceptableAudit && wt.Result == "acceptable" { | ||
| 1743 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 1744 | } | ||
| 1745 | if wt.Result != "invalid" { | ||
| 1746 | success = true | ||
| 1747 | } | ||
| 1748 | } else if wt.Result != "valid" { | ||
| 1749 | success = true | ||
| 1750 | } | ||
| 1751 | if !success { | ||
| 1752 | fmt.Printf("FAIL: Test case %d (%q) %v - keyLen = %d, AES_unwrap_key() = %d, want %v\n", | ||
| 1753 | wt.TCID, wt.Comment, wt.Flags, keyLen, int(ret), wt.Result) | ||
| 1754 | } | ||
| 1755 | return success | ||
| 1756 | } | ||
| 1757 | |||
| 1758 | func runKWTest(keySize int, wt *wycheproofTestKW) bool { | ||
| 1759 | key, err := hex.DecodeString(wt.Key) | ||
| 1760 | if err != nil { | ||
| 1761 | log.Fatalf("Failed to decode key %q: %v", wt.Key, err) | ||
| 1762 | } | ||
| 1763 | msg, err := hex.DecodeString(wt.Msg) | ||
| 1764 | if err != nil { | ||
| 1765 | log.Fatalf("Failed to decode msg %q: %v", wt.Msg, err) | ||
| 1766 | } | ||
| 1767 | ct, err := hex.DecodeString(wt.CT) | ||
| 1768 | if err != nil { | ||
| 1769 | log.Fatalf("Failed to decode ct %q: %v", wt.CT, err) | ||
| 1770 | } | ||
| 1771 | |||
| 1772 | keyLen, msgLen, ctLen := len(key), len(msg), len(ct) | ||
| 1773 | |||
| 1774 | if keyLen == 0 { | ||
| 1775 | key = append(key, 0) | ||
| 1776 | } | ||
| 1777 | if msgLen == 0 { | ||
| 1778 | msg = append(msg, 0) | ||
| 1779 | } | ||
| 1780 | if ctLen == 0 { | ||
| 1781 | ct = append(ct, 0) | ||
| 1782 | } | ||
| 1783 | |||
| 1784 | wrapSuccess := runKWTestWrap(keySize, key, keyLen, msg, msgLen, ct, ctLen, wt) | ||
| 1785 | unwrapSuccess := runKWTestUnWrap(keySize, key, keyLen, msg, msgLen, ct, ctLen, wt) | ||
| 1786 | |||
| 1787 | return wrapSuccess && unwrapSuccess | ||
| 1788 | } | ||
| 1789 | |||
| 1790 | func runKWTestGroup(algorithm string, wtg *wycheproofTestGroupKW) bool { | ||
| 1791 | fmt.Printf("Running %v test group %v with key size %d...\n", | ||
| 1792 | algorithm, wtg.Type, wtg.KeySize) | ||
| 1793 | |||
| 1794 | success := true | ||
| 1795 | for _, wt := range wtg.Tests { | ||
| 1796 | if !runKWTest(wtg.KeySize, wt) { | ||
| 1797 | success = false | ||
| 1798 | } | ||
| 1799 | } | ||
| 1800 | return success | ||
| 1801 | } | ||
| 1802 | |||
| 1803 | func runRSASSATest(rsa *C.RSA, h hash.Hash, sha *C.EVP_MD, mgfSha *C.EVP_MD, sLen int, wt *wycheproofTestRSASSA) bool { | ||
| 1804 | msg, err := hex.DecodeString(wt.Msg) | ||
| 1805 | if err != nil { | ||
| 1806 | log.Fatalf("Failed to decode message %q: %v", wt.Msg, err) | ||
| 1807 | } | ||
| 1808 | |||
| 1809 | h.Reset() | ||
| 1810 | h.Write(msg) | ||
| 1811 | msg = h.Sum(nil) | ||
| 1812 | |||
| 1813 | sig, err := hex.DecodeString(wt.Sig) | ||
| 1814 | if err != nil { | ||
| 1815 | log.Fatalf("Failed to decode signature %q: %v", wt.Sig, err) | ||
| 1816 | } | ||
| 1817 | |||
| 1818 | msgLen, sigLen := len(msg), len(sig) | ||
| 1819 | if msgLen == 0 { | ||
| 1820 | msg = append(msg, 0) | ||
| 1821 | } | ||
| 1822 | if sigLen == 0 { | ||
| 1823 | sig = append(sig, 0) | ||
| 1824 | } | ||
| 1825 | |||
| 1826 | sigOut := make([]byte, C.RSA_size(rsa) - 11) | ||
| 1827 | if sigLen == 0 { | ||
| 1828 | sigOut = append(sigOut, 0) | ||
| 1829 | } | ||
| 1830 | |||
| 1831 | ret := C.RSA_public_decrypt(C.int(sigLen), (*C.uchar)(unsafe.Pointer(&sig[0])), | ||
| 1832 | (*C.uchar)(unsafe.Pointer(&sigOut[0])), rsa, C.RSA_NO_PADDING) | ||
| 1833 | if ret == -1 { | ||
| 1834 | if wt.Result == "invalid" { | ||
| 1835 | return true | ||
| 1836 | } | ||
| 1837 | fmt.Printf("FAIL: Test case %d (%q) %v - RSA_public_decrypt() = %d, want %v\n", | ||
| 1838 | wt.TCID, wt.Comment, wt.Flags, int(ret), wt.Result) | ||
| 1839 | return false | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | ret = C.RSA_verify_PKCS1_PSS_mgf1(rsa, (*C.uchar)(unsafe.Pointer(&msg[0])), sha, mgfSha, | ||
| 1843 | (*C.uchar)(unsafe.Pointer(&sigOut[0])), C.int(sLen)) | ||
| 1844 | |||
| 1845 | success := false | ||
| 1846 | if ret == 1 && (wt.Result == "valid" || wt.Result == "acceptable") { | ||
| 1847 | // All acceptable cases that pass use SHA-1 and are flagged: | ||
| 1848 | // "WeakHash" : "The key for this test vector uses a weak hash function." | ||
| 1849 | if acceptableAudit && wt.Result == "acceptable" { | ||
| 1850 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 1851 | } | ||
| 1852 | success = true | ||
| 1853 | } else if ret == 0 && (wt.Result == "invalid" || wt.Result == "acceptable") { | ||
| 1854 | success = true | ||
| 1855 | } else { | ||
| 1856 | fmt.Printf("FAIL: Test case %d (%q) %v - RSA_verify_PKCS1_PSS_mgf1() = %d, want %v\n", | ||
| 1857 | wt.TCID, wt.Comment, wt.Flags, int(ret), wt.Result) | ||
| 1858 | } | ||
| 1859 | return success | ||
| 1860 | } | ||
| 1861 | |||
| 1862 | func runRSASSATestGroup(algorithm string, wtg *wycheproofTestGroupRSASSA) bool { | ||
| 1863 | fmt.Printf("Running %v test group %v with key size %d and %v...\n", | ||
| 1864 | algorithm, wtg.Type, wtg.KeySize, wtg.SHA) | ||
| 1865 | rsa := C.RSA_new() | ||
| 1866 | if rsa == nil { | ||
| 1867 | log.Fatal("RSA_new failed") | ||
| 1868 | } | ||
| 1869 | defer C.RSA_free(rsa) | ||
| 1870 | |||
| 1871 | e := C.CString(wtg.E) | ||
| 1872 | if C.BN_hex2bn(&rsa.e, e) == 0 { | ||
| 1873 | log.Fatal("Failed to set RSA e") | ||
| 1874 | } | ||
| 1875 | C.free(unsafe.Pointer(e)) | ||
| 1876 | |||
| 1877 | n := C.CString(wtg.N) | ||
| 1878 | if C.BN_hex2bn(&rsa.n, n) == 0 { | ||
| 1879 | log.Fatal("Failed to set RSA n") | ||
| 1880 | } | ||
| 1881 | C.free(unsafe.Pointer(n)) | ||
| 1882 | |||
| 1883 | h, err := hashFromString(wtg.SHA) | ||
| 1884 | if err != nil { | ||
| 1885 | log.Fatalf("Failed to get hash: %v", err) | ||
| 1886 | } | ||
| 1887 | |||
| 1888 | sha, err := hashEvpMdFromString(wtg.SHA) | ||
| 1889 | if err != nil { | ||
| 1890 | log.Fatalf("Failed to get hash: %v", err) | ||
| 1891 | } | ||
| 1892 | |||
| 1893 | mgfSha, err := hashEvpMdFromString(wtg.MGFSHA) | ||
| 1894 | if err != nil { | ||
| 1895 | log.Fatalf("Failed to get MGF hash: %v", err) | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | success := true | ||
| 1899 | for _, wt := range wtg.Tests { | ||
| 1900 | if !runRSASSATest(rsa, h, sha, mgfSha, wtg.SLen, wt) { | ||
| 1901 | success = false | ||
| 1902 | } | ||
| 1903 | } | ||
| 1904 | return success | ||
| 1905 | } | ||
| 1906 | |||
| 1907 | func runRSATest(rsa *C.RSA, nid int, h hash.Hash, wt *wycheproofTestRSA) bool { | ||
| 1908 | msg, err := hex.DecodeString(wt.Msg) | ||
| 1909 | if err != nil { | ||
| 1910 | log.Fatalf("Failed to decode message %q: %v", wt.Msg, err) | ||
| 1911 | } | ||
| 1912 | |||
| 1913 | h.Reset() | ||
| 1914 | h.Write(msg) | ||
| 1915 | msg = h.Sum(nil) | ||
| 1916 | |||
| 1917 | sig, err := hex.DecodeString(wt.Sig) | ||
| 1918 | if err != nil { | ||
| 1919 | log.Fatalf("Failed to decode signature %q: %v", wt.Sig, err) | ||
| 1920 | } | ||
| 1921 | |||
| 1922 | msgLen, sigLen := len(msg), len(sig) | ||
| 1923 | if msgLen == 0 { | ||
| 1924 | msg = append(msg, 0) | ||
| 1925 | } | ||
| 1926 | if sigLen == 0 { | ||
| 1927 | sig = append(sig, 0) | ||
| 1928 | } | ||
| 1929 | |||
| 1930 | ret := C.RSA_verify(C.int(nid), (*C.uchar)(unsafe.Pointer(&msg[0])), C.uint(msgLen), | ||
| 1931 | (*C.uchar)(unsafe.Pointer(&sig[0])), C.uint(sigLen), rsa) | ||
| 1932 | |||
| 1933 | // XXX audit acceptable cases... | ||
| 1934 | success := true | ||
| 1935 | if ret == 1 != (wt.Result == "valid") && wt.Result != "acceptable" { | ||
| 1936 | fmt.Printf("FAIL: Test case %d (%q) %v - RSA_verify() = %d, want %v\n", | ||
| 1937 | wt.TCID, wt.Comment, wt.Flags, int(ret), wt.Result) | ||
| 1938 | success = false | ||
| 1939 | } | ||
| 1940 | if acceptableAudit && ret == 1 && wt.Result == "acceptable" { | ||
| 1941 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 1942 | } | ||
| 1943 | return success | ||
| 1944 | } | ||
| 1945 | |||
| 1946 | func runRSATestGroup(algorithm string, wtg *wycheproofTestGroupRSA) bool { | ||
| 1947 | fmt.Printf("Running %v test group %v with key size %d and %v...\n", | ||
| 1948 | algorithm, wtg.Type, wtg.KeySize, wtg.SHA) | ||
| 1949 | |||
| 1950 | rsa := C.RSA_new() | ||
| 1951 | if rsa == nil { | ||
| 1952 | log.Fatal("RSA_new failed") | ||
| 1953 | } | ||
| 1954 | defer C.RSA_free(rsa) | ||
| 1955 | |||
| 1956 | e := C.CString(wtg.E) | ||
| 1957 | if C.BN_hex2bn(&rsa.e, e) == 0 { | ||
| 1958 | log.Fatal("Failed to set RSA e") | ||
| 1959 | } | ||
| 1960 | C.free(unsafe.Pointer(e)) | ||
| 1961 | |||
| 1962 | n := C.CString(wtg.N) | ||
| 1963 | if C.BN_hex2bn(&rsa.n, n) == 0 { | ||
| 1964 | log.Fatal("Failed to set RSA n") | ||
| 1965 | } | ||
| 1966 | C.free(unsafe.Pointer(n)) | ||
| 1967 | |||
| 1968 | nid, err := nidFromString(wtg.SHA) | ||
| 1969 | if err != nil { | ||
| 1970 | log.Fatalf("Failed to get MD NID: %v", err) | ||
| 1971 | } | ||
| 1972 | h, err := hashFromString(wtg.SHA) | ||
| 1973 | if err != nil { | ||
| 1974 | log.Fatalf("Failed to get hash: %v", err) | ||
| 1975 | } | ||
| 1976 | |||
| 1977 | success := true | ||
| 1978 | for _, wt := range wtg.Tests { | ||
| 1979 | if !runRSATest(rsa, nid, h, wt) { | ||
| 1980 | success = false | ||
| 1981 | } | ||
| 1982 | } | ||
| 1983 | return success | ||
| 1984 | } | ||
| 1985 | |||
| 1986 | func runX25519Test(wt *wycheproofTestX25519) bool { | ||
| 1987 | public, err := hex.DecodeString(wt.Public) | ||
| 1988 | if err != nil { | ||
| 1989 | log.Fatalf("Failed to decode public %q: %v", wt.Public, err) | ||
| 1990 | } | ||
| 1991 | private, err := hex.DecodeString(wt.Private) | ||
| 1992 | if err != nil { | ||
| 1993 | log.Fatalf("Failed to decode private %q: %v", wt.Private, err) | ||
| 1994 | } | ||
| 1995 | shared, err := hex.DecodeString(wt.Shared) | ||
| 1996 | if err != nil { | ||
| 1997 | log.Fatalf("Failed to decode shared %q: %v", wt.Shared, err) | ||
| 1998 | } | ||
| 1999 | |||
| 2000 | got := make([]byte, C.X25519_KEY_LENGTH) | ||
| 2001 | result := true | ||
| 2002 | |||
| 2003 | if C.X25519((*C.uint8_t)(unsafe.Pointer(&got[0])), (*C.uint8_t)(unsafe.Pointer(&private[0])), (*C.uint8_t)(unsafe.Pointer(&public[0]))) != 1 { | ||
| 2004 | result = false | ||
| 2005 | } else { | ||
| 2006 | result = bytes.Equal(got, shared) | ||
| 2007 | } | ||
| 2008 | |||
| 2009 | // XXX audit acceptable cases... | ||
| 2010 | success := true | ||
| 2011 | if result != (wt.Result == "valid") && wt.Result != "acceptable" { | ||
| 2012 | fmt.Printf("FAIL: Test case %d (%q) %v - X25519(), want %v\n", | ||
| 2013 | wt.TCID, wt.Comment, wt.Flags, wt.Result) | ||
| 2014 | success = false | ||
| 2015 | } | ||
| 2016 | if acceptableAudit && result && wt.Result == "acceptable" { | ||
| 2017 | gatherAcceptableStatistics(wt.TCID, wt.Comment, wt.Flags) | ||
| 2018 | } | ||
| 2019 | return success | ||
| 2020 | } | ||
| 2021 | |||
| 2022 | func runX25519TestGroup(algorithm string, wtg *wycheproofTestGroupX25519) bool { | ||
| 2023 | fmt.Printf("Running %v test group with curve %v...\n", algorithm, wtg.Curve) | ||
| 2024 | |||
| 2025 | success := true | ||
| 2026 | for _, wt := range wtg.Tests { | ||
| 2027 | if !runX25519Test(wt) { | ||
| 2028 | success = false | ||
| 2029 | } | ||
| 2030 | } | ||
| 2031 | return success | ||
| 2032 | } | ||
| 2033 | |||
| 2034 | func runTestVectors(path string, webcrypto bool) bool { | ||
| 2035 | b, err := ioutil.ReadFile(path) | ||
| 2036 | if err != nil { | ||
| 2037 | log.Fatalf("Failed to read test vectors: %v", err) | ||
| 2038 | } | ||
| 2039 | wtv := &wycheproofTestVectors{} | ||
| 2040 | if err := json.Unmarshal(b, wtv); err != nil { | ||
| 2041 | log.Fatalf("Failed to unmarshal JSON: %v", err) | ||
| 2042 | } | ||
| 2043 | fmt.Printf("Loaded Wycheproof test vectors for %v with %d tests from %q\n", | ||
| 2044 | wtv.Algorithm, wtv.NumberOfTests, filepath.Base(path)) | ||
| 2045 | |||
| 2046 | var wtg interface{} | ||
| 2047 | switch wtv.Algorithm { | ||
| 2048 | case "AES-CBC-PKCS5": | ||
| 2049 | wtg = &wycheproofTestGroupAesCbcPkcs5{} | ||
| 2050 | case "AES-CCM": | ||
| 2051 | wtg = &wycheproofTestGroupAead{} | ||
| 2052 | case "AES-CMAC": | ||
| 2053 | wtg = &wycheproofTestGroupAesCmac{} | ||
| 2054 | case "AES-GCM": | ||
| 2055 | wtg = &wycheproofTestGroupAead{} | ||
| 2056 | case "CHACHA20-POLY1305": | ||
| 2057 | wtg = &wycheproofTestGroupAead{} | ||
| 2058 | case "DSA": | ||
| 2059 | wtg = &wycheproofTestGroupDSA{} | ||
| 2060 | case "ECDH": | ||
| 2061 | if webcrypto { | ||
| 2062 | wtg = &wycheproofTestGroupECDHWebCrypto{} | ||
| 2063 | } else { | ||
| 2064 | wtg = &wycheproofTestGroupECDH{} | ||
| 2065 | } | ||
| 2066 | case "ECDSA": | ||
| 2067 | if webcrypto { | ||
| 2068 | wtg = &wycheproofTestGroupECDSAWebCrypto{} | ||
| 2069 | } else { | ||
| 2070 | wtg = &wycheproofTestGroupECDSA{} | ||
| 2071 | } | ||
| 2072 | case "KW": | ||
| 2073 | wtg = &wycheproofTestGroupKW{} | ||
| 2074 | case "RSASSA-PSS": | ||
| 2075 | wtg = &wycheproofTestGroupRSASSA{} | ||
| 2076 | case "RSASig": | ||
| 2077 | wtg = &wycheproofTestGroupRSA{} | ||
| 2078 | case "X25519": | ||
| 2079 | wtg = &wycheproofTestGroupX25519{} | ||
| 2080 | default: | ||
| 2081 | log.Fatalf("Unknown test vector algorithm %q", wtv.Algorithm) | ||
| 2082 | } | ||
| 2083 | |||
| 2084 | success := true | ||
| 2085 | for _, tg := range wtv.TestGroups { | ||
| 2086 | if err := json.Unmarshal(tg, wtg); err != nil { | ||
| 2087 | log.Fatalf("Failed to unmarshal test groups JSON: %v", err) | ||
| 2088 | } | ||
| 2089 | switch wtv.Algorithm { | ||
| 2090 | case "AES-CBC-PKCS5": | ||
| 2091 | if !runAesCbcPkcs5TestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupAesCbcPkcs5)) { | ||
| 2092 | success = false | ||
| 2093 | } | ||
| 2094 | case "AES-CCM": | ||
| 2095 | if !runAesAeadTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupAead)) { | ||
| 2096 | success = false | ||
| 2097 | } | ||
| 2098 | case "AES-CMAC": | ||
| 2099 | if !runAesCmacTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupAesCmac)) { | ||
| 2100 | success = false | ||
| 2101 | } | ||
| 2102 | case "AES-GCM": | ||
| 2103 | if !runAesAeadTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupAead)) { | ||
| 2104 | success = false | ||
| 2105 | } | ||
| 2106 | case "CHACHA20-POLY1305": | ||
| 2107 | if !runChaCha20Poly1305TestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupAead)) { | ||
| 2108 | success = false | ||
| 2109 | } | ||
| 2110 | case "DSA": | ||
| 2111 | if !runDSATestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupDSA)) { | ||
| 2112 | success = false | ||
| 2113 | } | ||
| 2114 | case "ECDH": | ||
| 2115 | if webcrypto { | ||
| 2116 | if !runECDHWebCryptoTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDHWebCrypto)) { | ||
| 2117 | success = false | ||
| 2118 | } | ||
| 2119 | } else { | ||
| 2120 | if !runECDHTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDH)) { | ||
| 2121 | success = false | ||
| 2122 | } | ||
| 2123 | } | ||
| 2124 | case "ECDSA": | ||
| 2125 | if webcrypto { | ||
| 2126 | if !runECDSAWebCryptoTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDSAWebCrypto)) { | ||
| 2127 | success = false | ||
| 2128 | } | ||
| 2129 | } else { | ||
| 2130 | if !runECDSATestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupECDSA)) { | ||
| 2131 | success = false | ||
| 2132 | } | ||
| 2133 | } | ||
| 2134 | case "KW": | ||
| 2135 | if !runKWTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupKW)) { | ||
| 2136 | success = false | ||
| 2137 | } | ||
| 2138 | case "RSASSA-PSS": | ||
| 2139 | if !runRSASSATestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupRSASSA)) { | ||
| 2140 | success = false | ||
| 2141 | } | ||
| 2142 | case "RSASig": | ||
| 2143 | if !runRSATestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupRSA)) { | ||
| 2144 | success = false | ||
| 2145 | } | ||
| 2146 | case "X25519": | ||
| 2147 | if !runX25519TestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupX25519)) { | ||
| 2148 | success = false | ||
| 2149 | } | ||
| 2150 | default: | ||
| 2151 | log.Fatalf("Unknown test vector algorithm %q", wtv.Algorithm) | ||
| 2152 | } | ||
| 2153 | } | ||
| 2154 | return success | ||
| 2155 | } | ||
| 2156 | |||
| 2157 | func main() { | ||
| 2158 | if _, err := os.Stat(testVectorPath); os.IsNotExist(err) { | ||
| 2159 | fmt.Printf("package wycheproof-testvectors is required for this regress\n") | ||
| 2160 | fmt.Printf("SKIPPED\n") | ||
| 2161 | os.Exit(0) | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | flag.BoolVar(&acceptableAudit, "v", false, "audit acceptable cases") | ||
| 2165 | flag.Parse() | ||
| 2166 | |||
| 2167 | acceptableComments = make(map[string]int) | ||
| 2168 | acceptableFlags = make(map[string]int) | ||
| 2169 | |||
| 2170 | tests := []struct { | ||
| 2171 | name string | ||
| 2172 | pattern string | ||
| 2173 | }{ | ||
| 2174 | {"AES", "aes_[cg]*[^xv]_test.json"}, // Skip AES-EAX, AES-GCM-SIV and AES-SIV-CMAC. | ||
| 2175 | {"ChaCha20-Poly1305", "chacha20_poly1305_test.json"}, | ||
| 2176 | {"DSA", "dsa_test.json"}, | ||
| 2177 | {"ECDH", "ecdh_[^w]*test.json"}, | ||
| 2178 | {"ECDHWebCrypto", "ecdh_w*_test.json"}, | ||
| 2179 | {"ECDSA", "ecdsa_[^w]*test.json"}, | ||
| 2180 | {"ECDSAWebCrypto", "ecdsa_w*_test.json"}, | ||
| 2181 | {"KW", "kw_test.json"}, | ||
| 2182 | {"RSA", "rsa_*test.json"}, | ||
| 2183 | {"X25519", "x25519_*test.json"}, | ||
| 2184 | } | ||
| 2185 | |||
| 2186 | success := true | ||
| 2187 | |||
| 2188 | for _, test := range tests { | ||
| 2189 | webcrypto := test.name == "ECDSAWebCrypto" || test.name == "ECDHWebCrypto" | ||
| 2190 | tvs, err := filepath.Glob(filepath.Join(testVectorPath, test.pattern)) | ||
| 2191 | if err != nil { | ||
| 2192 | log.Fatalf("Failed to glob %v test vectors: %v", test.name, err) | ||
| 2193 | } | ||
| 2194 | if len(tvs) == 0 { | ||
| 2195 | log.Fatalf("Failed to find %v test vectors at %q\n", test.name, testVectorPath) | ||
| 2196 | } | ||
| 2197 | for _, tv := range tvs { | ||
| 2198 | if !runTestVectors(tv, webcrypto) { | ||
| 2199 | success = false | ||
| 2200 | } | ||
| 2201 | } | ||
| 2202 | } | ||
| 2203 | |||
| 2204 | if acceptableAudit { | ||
| 2205 | printAcceptableStatistics() | ||
| 2206 | } | ||
| 2207 | |||
| 2208 | if !success { | ||
| 2209 | os.Exit(1) | ||
| 2210 | } | ||
| 2211 | } | ||
