summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/wycheproof
diff options
context:
space:
mode:
authorcvs2svn <admin@example.com>2018-11-07 01:08:50 +0000
committercvs2svn <admin@example.com>2018-11-07 01:08:50 +0000
commit2035faf3f8aa95b888d9416c3cc7328c0ea18beb (patch)
treef08a08d357c5d30455c569890f747c1d9b241316 /src/regress/lib/libcrypto/wycheproof
parentbe03b61c1b8f59ccdd34dbe5f6c6b30de697d28b (diff)
downloadopenbsd-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/Makefile25
-rw-r--r--src/regress/lib/libcrypto/wycheproof/wycheproof.go2211
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
3GO_VERSION != sh -c "(go version) 2>/dev/null || true"
4
5.if empty(GO_VERSION)
6regress:
7 @echo package go is required for this regress
8 @echo SKIPPED
9.endif
10
11CLEANFILES+=wycheproof
12REGRESS_TARGETS=regress-wycheproof
13
14audit: wycheproof
15 ./wycheproof -v
16
17wycheproof: wycheproof.go
18 go build -o wycheproof ${.CURDIR}/wycheproof.go
19
20regress-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.
20package 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*/
41import "C"
42
43import (
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
62const testVectorPath = "/usr/local/share/wycheproof/testvectors"
63
64var acceptableAudit = false
65var acceptableComments map[string]int
66var acceptableFlags map[string]int
67
68type 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
76type 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
85type wycheproofTestGroupAesCbcPkcs5 struct {
86 IVSize int `json:"ivSize"`
87 KeySize int `json:"keySize"`
88 Type string `json:"type"`
89 Tests []*wycheproofTestAesCbcPkcs5 `json:"tests"`
90}
91
92type 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
103type 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
111type 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
124type wycheproofTestGroupAesCmac struct {
125 KeySize int `json:"keySize"`
126 TagSize int `json:"tagSize"`
127 Type string `json:"type"`
128 Tests []*wycheproofTestAesCmac `json:"tests"`
129}
130
131type 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
141type 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
150type 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
159type 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
168type 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
178type wycheproofTestGroupECDH struct {
179 Curve string `json:"curve"`
180 Encoding string `json:"encoding"`
181 Type string `json:"type"`
182 Tests []*wycheproofTestECDH `json:"tests"`
183}
184
185type 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
195type wycheproofTestGroupECDHWebCrypto struct {
196 Curve string `json:"curve"`
197 Encoding string `json:"encoding"`
198 Type string `json:"type"`
199 Tests []*wycheproofTestECDHWebCrypto `json:"tests"`
200}
201
202type 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
211type 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
220type 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
229type 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
239type 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
249type wycheproofTestGroupKW struct {
250 KeySize int `json:"keySize"`
251 Type string `json:"type"`
252 Tests []*wycheproofTestKW `json:"tests"`
253}
254
255type 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
265type 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
277type 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
286type 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
301type 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
312type wycheproofTestGroupX25519 struct {
313 Curve string `json:"curve"`
314 Tests []*wycheproofTestX25519 `json:"tests"`
315}
316
317type 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
326var 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
353func 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
371func 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
398func 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
406func 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
423func 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
440func 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
508func 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
547func 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
583func 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
736func 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
811func 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
865func 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
934func 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
960func 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
1007func 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
1049func 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
1101func 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
1119func 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
1154func 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
1257func 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
1356func 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
1379func 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
1476func 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
1494func 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
1547func 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...)
1600func 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
1638func 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
1694func 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
1725func 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
1758func 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
1790func 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
1803func 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
1862func 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
1907func 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
1946func 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
1986func 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
2022func 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
2034func 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
2157func 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}