diff options
author | tb <> | 2025-09-05 14:01:56 +0000 |
---|---|---|
committer | tb <> | 2025-09-05 14:01:56 +0000 |
commit | a52f774428b343a9da61050f2a817d96cb494261 (patch) | |
tree | 08406d014b3d044ee1231165d17f5dbfbe7ad2da /src | |
parent | 472f58fac15ad5c1fc0917e726d4a95b388127fc (diff) | |
download | openbsd-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/regress/lib/libcrypto/wycheproof/wycheproof.go | 67 |
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 | ||
127 | var testc *testCoordinator | 128 | var testc *testCoordinator |
128 | 129 | ||
130 | type BigInt struct { | ||
131 | *big.Int | ||
132 | } | ||
133 | |||
134 | func 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 | |||
152 | func (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 | |||
129 | type wycheproofJWKPublic struct { | 183 | type 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 { | |||
432 | type wycheproofTestPrimality struct { | 486 | type 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 | ||
2236 | func runPrimalityTest(wt *wycheproofTestPrimality) bool { | 2290 | func 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}, |