summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2025-09-05 14:01:56 +0000
committertb <>2025-09-05 14:01:56 +0000
commita52f774428b343a9da61050f2a817d96cb494261 (patch)
tree08406d014b3d044ee1231165d17f5dbfbe7ad2da
parent472f58fac15ad5c1fc0917e726d4a95b388127fc (diff)
downloadopenbsd-a52f774428b343a9da61050f2a817d96cb494261.tar.gz
openbsd-a52f774428b343a9da61050f2a817d96cb494261.tar.bz2
openbsd-a52f774428b343a9da61050f2a817d96cb494261.zip
wycheproof: add custom JSON unmarshaler big integers
Since the wycheproof tests were written in Java, they inherited some of that language's weirdnesses. For example, the hex representation may have odd length, is 2-complement and needs zero-padding if the top bit of a nibble is set, similar to ASN.1 integers. This is needed for correctly decoding the Primality test cases, which worked nicely in v0 but no longer for v1. Convert the Primality test to use this.
-rw-r--r--src/regress/lib/libcrypto/wycheproof/wycheproof.go67
1 files changed, 58 insertions, 9 deletions
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof.go b/src/regress/lib/libcrypto/wycheproof/wycheproof.go
index f161211d3e..5a0c0d68ef 100644
--- a/src/regress/lib/libcrypto/wycheproof/wycheproof.go
+++ b/src/regress/lib/libcrypto/wycheproof/wycheproof.go
@@ -1,4 +1,4 @@
1/* $OpenBSD: wycheproof.go,v 1.176 2025/09/05 13:47:41 tb Exp $ */ 1/* $OpenBSD: wycheproof.go,v 1.177 2025/09/05 14:01:56 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2018,2023 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2018,2023 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2018,2019,2022-2024 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2018,2019,2022-2024 Theo Buehler <tb@openbsd.org>
@@ -81,6 +81,7 @@ import (
81 "fmt" 81 "fmt"
82 "io/ioutil" 82 "io/ioutil"
83 "log" 83 "log"
84 "math/big"
84 "os" 85 "os"
85 "path/filepath" 86 "path/filepath"
86 "regexp" 87 "regexp"
@@ -126,6 +127,59 @@ func wycheproofFormatTestCase(tcid int, comment string, flags []string, result s
126 127
127var testc *testCoordinator 128var testc *testCoordinator
128 129
130type BigInt struct {
131 *big.Int
132}
133
134func mustConvertBigIntToBigNum(bi *BigInt) *C.BIGNUM {
135 value := bi.Bytes()
136 if len(value) == 0 {
137 value = append(value, 0)
138 }
139 bn := C.BN_new()
140 if bn == nil {
141 log.Fatal("BN_new failed")
142 }
143 if C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&value[0])), C.int(len(value)), bn) == nil {
144 log.Fatal("BN_bin2bn failed")
145 }
146 if bi.Sign() == -1 {
147 C.BN_set_negative(bn, C.int(1))
148 }
149 return bn
150}
151
152func (bi *BigInt) UnmarshalJSON(data []byte) error {
153 if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' {
154 log.Fatalf("Failed to decode %q: too short or unquoted", data)
155 }
156 data = data[1 : len(data)-1]
157 if len(data)%2 == 1 {
158 pad := make([]byte, 1, len(data)+1)
159 if data[0] >= '0' && data[0] <= '7' {
160 pad[0] = '0'
161 } else {
162 pad[0] = 'f'
163 }
164 data = append(pad, data...)
165 }
166
167 src := make([]byte, hex.DecodedLen(len(data)))
168 _, err := hex.Decode(src, data)
169 if err != nil {
170 log.Fatalf("Failed to decode %q: %v", data, err)
171 }
172
173 bi.Int = &big.Int{}
174 bi.Int.SetBytes(src)
175 if data[0] >= '8' {
176 y := &big.Int{}
177 y.SetBit(y, 4*len(data), 1)
178 bi.Int.Sub(bi.Int, y)
179 }
180 return nil
181}
182
129type wycheproofJWKPublic struct { 183type wycheproofJWKPublic struct {
130 Crv string `json:"crv"` 184 Crv string `json:"crv"`
131 KID string `json:"kid"` 185 KID string `json:"kid"`
@@ -432,7 +486,7 @@ type wycheproofTestGroupKW struct {
432type wycheproofTestPrimality struct { 486type wycheproofTestPrimality struct {
433 TCID int `json:"tcId"` 487 TCID int `json:"tcId"`
434 Comment string `json:"comment"` 488 Comment string `json:"comment"`
435 Value string `json:"value"` 489 Value *BigInt `json:"value"`
436 Result string `json:"result"` 490 Result string `json:"result"`
437 Flags []string `json:"flags"` 491 Flags []string `json:"flags"`
438} 492}
@@ -2234,12 +2288,7 @@ func (wtg *wycheproofTestGroupKW) run(algorithm string, variant testVariant) boo
2234} 2288}
2235 2289
2236func runPrimalityTest(wt *wycheproofTestPrimality) bool { 2290func runPrimalityTest(wt *wycheproofTestPrimality) bool {
2237 var bnValue *C.BIGNUM 2291 bnValue := mustConvertBigIntToBigNum(wt.Value)
2238 value := C.CString(wt.Value)
2239 if C.BN_hex2bn(&bnValue, value) == 0 {
2240 log.Fatal("Failed to set bnValue")
2241 }
2242 C.free(unsafe.Pointer(value))
2243 defer C.BN_free(bnValue) 2292 defer C.BN_free(bnValue)
2244 2293
2245 ret := C.BN_is_prime_ex(bnValue, C.BN_prime_checks, (*C.BN_CTX)(unsafe.Pointer(nil)), (*C.BN_GENCB)(unsafe.Pointer(nil))) 2294 ret := C.BN_is_prime_ex(bnValue, C.BN_prime_checks, (*C.BN_CTX)(unsafe.Pointer(nil)), (*C.BN_GENCB)(unsafe.Pointer(nil)))
@@ -2810,7 +2859,7 @@ func main() {
2810 {v1, "HMAC", "hmac_sha*_test.json", Normal}, 2859 {v1, "HMAC", "hmac_sha*_test.json", Normal},
2811 {v0, "JSON webcrypto", "json_web_*_test.json", Skip}, 2860 {v0, "JSON webcrypto", "json_web_*_test.json", Skip},
2812 {v0, "KW", "kw_test.json", Normal}, 2861 {v0, "KW", "kw_test.json", Normal},
2813 {v0, "Primality test", "primality_test.json", Normal}, 2862 {v1, "Primality test", "primality_test.json", Normal},
2814 {v1, "RSA", "rsa_*test.json", Normal}, 2863 {v1, "RSA", "rsa_*test.json", Normal},
2815 {v1, "X25519", "x25519_test.json", Normal}, 2864 {v1, "X25519", "x25519_test.json", Normal},
2816 {v1, "X25519 ASN", "x25519_asn_test.json", Skip}, 2865 {v1, "X25519 ASN", "x25519_asn_test.json", Skip},