summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2022-07-07 20:01:20 +0000
committertb <>2022-07-07 20:01:20 +0000
commitb836d66591e0c2a45519653d065d29807d70ac5d (patch)
tree676c18a467cb0fc9fdc91292b157f3fe2fe38905 /src
parentdad327347e69c9005cad59140fe50274b5e469e6 (diff)
downloadopenbsd-b836d66591e0c2a45519653d065d29807d70ac5d.tar.gz
openbsd-b836d66591e0c2a45519653d065d29807d70ac5d.tar.bz2
openbsd-b836d66591e0c2a45519653d065d29807d70ac5d.zip
Add support for primality checking
Project Wycheproof's primality_tests.json contain a set of 280 numbers that trigger edge cases in Miller-Rabin and related checks. libcrypto's Miller-Rabin test is known to be rather poor, hopefully we will soon see a diff on tech that improves on this. This extends the Go test in the usual way and also adds a perl script that allows testing on non-Go architectures. Deliberately not yet linked to regress since the tests are flaky with the current BN_is_prime_ex() implementatation.
Diffstat (limited to 'src')
-rw-r--r--src/regress/lib/libcrypto/wycheproof/Makefile43
-rw-r--r--src/regress/lib/libcrypto/wycheproof/wycheproof-json.pl71
-rw-r--r--src/regress/lib/libcrypto/wycheproof/wycheproof-primes.c63
-rw-r--r--src/regress/lib/libcrypto/wycheproof/wycheproof.go51
4 files changed, 218 insertions, 10 deletions
diff --git a/src/regress/lib/libcrypto/wycheproof/Makefile b/src/regress/lib/libcrypto/wycheproof/Makefile
index 0fcde086f7..2e1d16b165 100644
--- a/src/regress/lib/libcrypto/wycheproof/Makefile
+++ b/src/regress/lib/libcrypto/wycheproof/Makefile
@@ -1,17 +1,21 @@
1# $OpenBSD: Makefile,v 1.3 2019/04/24 20:25:19 bluhm Exp $ 1# $OpenBSD: Makefile,v 1.4 2022/07/07 20:01:20 tb Exp $
2 2
3.if ! (make(clean) || make(cleandir) || make(obj)) 3WYCHEPROOF_TESTVECTORS = /usr/local/share/wycheproof/testvectors/
4GO_VERSION != sh -c "(go version) 2>/dev/null || true"
5.endif
6 4
7.if empty(GO_VERSION) 5.if !exists(${WYCHEPROOF_TESTVECTORS})
8regress: 6regress:
9 @echo package go is required for this regress 7 @echo package wycheproof-testvectors is required for this regress
8 @echo package go should be installed if available
10 @echo SKIPPED 9 @echo SKIPPED
11.endif 10.else
11
12# REGRESS_TARGETS += regress-wycheproof-primes
13
14. if exists(/usr/local/bin/go)
12 15
13CLEANFILES+=wycheproof 16REGRESS_TARGETS += regress-wycheproof
14REGRESS_TARGETS=regress-wycheproof 17
18CLEANFILES += wycheproof
15 19
16audit: wycheproof 20audit: wycheproof
17 ./wycheproof -v 21 ./wycheproof -v
@@ -24,4 +28,25 @@ regress-wycheproof: wycheproof
24 28
25.PHONY: audit 29.PHONY: audit
26 30
31. endif
32
33PROGS += wycheproof-primes
34
35LDADD = -lcrypto
36DPADD = ${LIBCRYPTO}
37CFLAGS = -I${.CURDIR} -I${.OBJDIR}
38
39primality_testcases.h: wycheproof-json.pl ${WYCHEPROOF_TESTVECTORS}/primality_test.json
40 perl ${.CURDIR}/wycheproof-json.pl > $@.tmp
41 mv -f $@.tmp $@
42
43wycheproof-primes: wycheproof-primes.c primality_testcases.h
44
45regress-wycheproof-primes: primality_testcases.h wycheproof-primes
46 ./wycheproof-primes
47
48CLEANFILES += primality_testcases.h
49
50.endif
51
27.include <bsd.regress.mk> 52.include <bsd.regress.mk>
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof-json.pl b/src/regress/lib/libcrypto/wycheproof/wycheproof-json.pl
new file mode 100644
index 0000000000..01fa66f7f7
--- /dev/null
+++ b/src/regress/lib/libcrypto/wycheproof/wycheproof-json.pl
@@ -0,0 +1,71 @@
1# $OpenBSD: wycheproof-json.pl,v 1.1 2022/07/07 20:01:20 tb Exp $
2
3# Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
4# Copyright (c) 2022 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
18use JSON::PP;
19
20$test_vector_path = "/usr/local/share/wycheproof/testvectors";
21
22open JSON, "$test_vector_path/primality_test.json" or die;
23@json = <JSON>;
24close JSON;
25
26$tv = JSON::PP::decode_json(join "\n", @json);
27$test_groups = %$tv{"testGroups"};
28
29my $wycheproof_struct = <<"EOL";
30struct wycheproof_testcase {
31 int id;
32 const char *value;
33 int acceptable;
34 int result;
35};
36
37struct wycheproof_testcase testcases[] = {
38EOL
39
40print $wycheproof_struct;
41
42foreach $test_group (@$test_groups) {
43 $test_group_type = %$test_group{"type"};
44 $test_group_tests = %$test_group{"tests"};
45
46 foreach $test_case (@$test_group_tests) {
47 %tc = %$test_case;
48
49 $tc_id = $tc{"tcId"};
50 $tc_value = $tc{"value"};
51 $tc_result = $tc{"result"};
52 $tc_flags = @{$tc{"flags"}};
53
54 my $result = $tc_result eq "valid" ? 1 : 0;
55
56 print "\t{\n";
57 print "\t\t.id = $tc_id,\n";
58 print "\t\t.value = \"$tc_value\",\n";
59 print "\t\t.result = $result,\n";
60
61 if ($tc_result eq "acceptable") {
62 print "\t\t.acceptable = 1,\n";
63 }
64
65 print "\t},\n";
66 }
67}
68
69print "};\n\n";
70
71print "#define N_TESTS (sizeof(testcases) / sizeof(testcases[0]))\n"
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof-primes.c b/src/regress/lib/libcrypto/wycheproof/wycheproof-primes.c
new file mode 100644
index 0000000000..669531d135
--- /dev/null
+++ b/src/regress/lib/libcrypto/wycheproof/wycheproof-primes.c
@@ -0,0 +1,63 @@
1/* $OpenBSD: wycheproof-primes.c,v 1.1 2022/07/07 20:01:20 tb Exp $ */
2/*
3 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <err.h>
19#include <stdio.h>
20
21#include <openssl/bn.h>
22
23#include "primality_testcases.h"
24
25int
26primality_test(struct wycheproof_testcase *test)
27{
28 BIGNUM *value = NULL;
29 int ret;
30 int failed = 1;
31
32 if (!BN_hex2bn(&value, test->value))
33 errx(1, "%d: failed to set value \"%s\"", test->id, test->value);
34
35 if ((ret = BN_is_prime_ex(value, BN_prime_checks, NULL, NULL)) < 0)
36 errx(1, "%d: BN_is_prime_ex errored", test->id);
37
38 if (ret != test->result && !test->acceptable) {
39 fprintf(stderr, "%d failed, want %d, got %d\n", test->id,
40 test->result, ret);
41 goto err;
42 }
43
44 failed = 0;
45 err:
46 BN_free(value);
47
48 return failed;
49}
50
51int
52main(void)
53{
54 size_t i;
55 int failed = 0;
56
57 for (i = 0; i < N_TESTS; i++)
58 failed |= primality_test(&testcases[i]);
59
60 printf("%s\n", failed ? "FAILED" : "SUCCESS");
61
62 return failed;
63}
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof.go b/src/regress/lib/libcrypto/wycheproof/wycheproof.go
index bd45a733b4..a638d0fdd9 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.126 2022/05/05 18:34:27 tb Exp $ */ 1/* $OpenBSD: wycheproof.go,v 1.127 2022/07/07 20:01:20 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2018 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2018 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2018,2019,2022 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2018,2019,2022 Theo Buehler <tb@openbsd.org>
@@ -349,6 +349,19 @@ type wycheproofTestGroupKW struct {
349 Tests []*wycheproofTestKW `json:"tests"` 349 Tests []*wycheproofTestKW `json:"tests"`
350} 350}
351 351
352type wycheproofTestPrimality struct {
353 TCID int `json:"tcId"`
354 Comment string `json:"comment"`
355 Value string `json:"value"`
356 Result string `json:"result"`
357 Flags []string `json:"flags"`
358}
359
360type wycheproofTestGroupPrimality struct {
361 Type string `json:"type"`
362 Tests []*wycheproofTestPrimality `json:"tests"`
363}
364
352type wycheproofTestRSA struct { 365type wycheproofTestRSA struct {
353 TCID int `json:"tcId"` 366 TCID int `json:"tcId"`
354 Comment string `json:"comment"` 367 Comment string `json:"comment"`
@@ -2223,6 +2236,35 @@ func runKWTestGroup(algorithm string, wtg *wycheproofTestGroupKW) bool {
2223 return success 2236 return success
2224} 2237}
2225 2238
2239func runPrimalityTest(wt *wycheproofTestPrimality) bool {
2240 var bnValue *C.BIGNUM
2241 value := C.CString(wt.Value)
2242 if C.BN_hex2bn(&bnValue, value) == 0 {
2243 log.Fatal("Failed to set bnValue")
2244 }
2245 C.free(unsafe.Pointer(value))
2246 defer C.BN_free(bnValue)
2247
2248 ret := C.BN_is_prime_ex(bnValue, C.BN_prime_checks, (*C.BN_CTX)(unsafe.Pointer(nil)), (*C.BN_GENCB)(unsafe.Pointer(nil)))
2249 success := wt.Result == "acceptable" || (ret == 0 && wt.Result == "invalid") || (ret == 1 && wt.Result == "valid")
2250 if !success {
2251 fmt.Printf("FAIL: Test case %d (%q) %v failed - got %d, want %v\n", wt.TCID, wt.Comment, wt.Flags, ret, wt.Result)
2252 }
2253 return success
2254}
2255
2256func runPrimalityTestGroup(algorithm string, wtg *wycheproofTestGroupPrimality) bool {
2257 fmt.Printf("Running %v test group...\n", algorithm)
2258
2259 success := true
2260 for _, wt := range wtg.Tests {
2261 if !runPrimalityTest(wt) {
2262 success = false
2263 }
2264 }
2265 return success
2266}
2267
2226func runRsaesOaepTest(rsa *C.RSA, sha *C.EVP_MD, mgfSha *C.EVP_MD, wt *wycheproofTestRsaes) bool { 2268func runRsaesOaepTest(rsa *C.RSA, sha *C.EVP_MD, mgfSha *C.EVP_MD, wt *wycheproofTestRsaes) bool {
2227 ct, err := hex.DecodeString(wt.CT) 2269 ct, err := hex.DecodeString(wt.CT)
2228 if err != nil { 2270 if err != nil {
@@ -2733,6 +2775,8 @@ func runTestVectors(path string, variant testVariant) bool {
2733 wtg = &wycheproofTestGroupHmac{} 2775 wtg = &wycheproofTestGroupHmac{}
2734 case "KW": 2776 case "KW":
2735 wtg = &wycheproofTestGroupKW{} 2777 wtg = &wycheproofTestGroupKW{}
2778 case "PrimalityTest":
2779 wtg = &wycheproofTestGroupPrimality{}
2736 case "RSAES-OAEP": 2780 case "RSAES-OAEP":
2737 wtg = &wycheproofTestGroupRsaesOaep{} 2781 wtg = &wycheproofTestGroupRsaesOaep{}
2738 case "RSAES-PKCS1-v1_5": 2782 case "RSAES-PKCS1-v1_5":
@@ -2812,6 +2856,10 @@ func runTestVectors(path string, variant testVariant) bool {
2812 if !runKWTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupKW)) { 2856 if !runKWTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupKW)) {
2813 success = false 2857 success = false
2814 } 2858 }
2859 case "PrimalityTest":
2860 if !runPrimalityTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupPrimality)) {
2861 success = false
2862 }
2815 case "RSAES-OAEP": 2863 case "RSAES-OAEP":
2816 if !runRsaesOaepTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupRsaesOaep)) { 2864 if !runRsaesOaepTestGroup(wtv.Algorithm, wtg.(*wycheproofTestGroupRsaesOaep)) {
2817 success = false 2865 success = false
@@ -2875,6 +2923,7 @@ func main() {
2875 {"HKDF", "hkdf_sha*_test.json", Normal}, 2923 {"HKDF", "hkdf_sha*_test.json", Normal},
2876 {"HMAC", "hmac_sha*_test.json", Normal}, 2924 {"HMAC", "hmac_sha*_test.json", Normal},
2877 {"KW", "kw_test.json", Normal}, 2925 {"KW", "kw_test.json", Normal},
2926 {"Primality test", "primality_test.json", Skip}, // XXX
2878 {"RSA", "rsa_*test.json", Normal}, 2927 {"RSA", "rsa_*test.json", Normal},
2879 {"X25519", "x25519_test.json", Normal}, 2928 {"X25519", "x25519_test.json", Normal},
2880 {"X25519 ASN", "x25519_asn_test.json", Skip}, 2929 {"X25519 ASN", "x25519_asn_test.json", Skip},