diff options
Diffstat (limited to 'src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c')
| -rw-r--r-- | src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c | 198 |
1 files changed, 129 insertions, 69 deletions
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c index 7214dd8a80..be1aff3d04 100644 --- a/src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c +++ b/src/regress/lib/libcrypto/mlkem/mlkem768_keygen_tests.c | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | /* $OpenBSD: mlkem768_keygen_tests.c,v 1.4 2024/12/17 07:20:10 tb Exp $ */ | 1 | /* $OpenBSD: mlkem768_keygen_tests.c,v 1.5 2024/12/20 00:07:12 tb Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2024, Google Inc. | 3 | * Copyright (c) 2024 Google Inc. |
| 4 | * Copyright (c) 2024, Bob Beck <beck@obtuse.com> | 4 | * Copyright (c) 2024 Bob Beck <beck@obtuse.com> |
| 5 | * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> | ||
| 5 | * | 6 | * |
| 6 | * Permission to use, copy, modify, and/or distribute this software for any | 7 | * Permission to use, copy, modify, and/or distribute this software for any |
| 7 | * purpose with or without fee is hereby granted, provided that the above | 8 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -16,115 +17,174 @@ | |||
| 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 17 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 17 | */ | 18 | */ |
| 18 | 19 | ||
| 20 | #include <assert.h> | ||
| 21 | #include <err.h> | ||
| 19 | #include <stdint.h> | 22 | #include <stdint.h> |
| 20 | #include <stdio.h> | 23 | #include <stdio.h> |
| 21 | #include <stdlib.h> | 24 | #include <stdlib.h> |
| 22 | #include <string.h> | ||
| 23 | 25 | ||
| 24 | #include <openssl/bytestring.h> | 26 | #include "bytestring.h" |
| 25 | #include <openssl/mlkem.h> | 27 | #include "mlkem.h" |
| 26 | 28 | ||
| 27 | #include "mlkem_internal.h" | 29 | #include "mlkem_internal.h" |
| 28 | #include "mlkem_tests_util.h" | 30 | #include "mlkem_tests_util.h" |
| 29 | 31 | ||
| 30 | static int | 32 | static int |
| 31 | encode_private_key(const struct MLKEM768_private_key *priv, uint8_t **out_buf, | 33 | MlkemKeygenFileTest(CBB *seed_cbb, CBB *public_key_cbb, CBB *private_key_cbb, |
| 32 | size_t *out_len) | 34 | size_t line) |
| 33 | { | ||
| 34 | CBB cbb; | ||
| 35 | if (!CBB_init(&cbb, MLKEM768_PUBLIC_KEY_BYTES)) | ||
| 36 | return 0; | ||
| 37 | if (!MLKEM768_marshal_private_key(&cbb, priv)) | ||
| 38 | return 0; | ||
| 39 | if (!CBB_finish(&cbb, out_buf, out_len)) | ||
| 40 | return 0; | ||
| 41 | CBB_cleanup(&cbb); | ||
| 42 | return 1; | ||
| 43 | } | ||
| 44 | |||
| 45 | static void | ||
| 46 | MlkemKeygenFileTest(CBS *seed, CBS *public_key, CBS *private_key) | ||
| 47 | { | 35 | { |
| 48 | struct MLKEM768_private_key priv; | 36 | struct MLKEM768_private_key priv; |
| 37 | uint8_t *seed = NULL, *public_key = NULL, *private_key = NULL; | ||
| 38 | size_t seed_len = 0, public_key_len = 0, private_key_len = 0; | ||
| 49 | uint8_t *encoded_private_key = NULL; | 39 | uint8_t *encoded_private_key = NULL; |
| 50 | uint8_t encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES]; | 40 | uint8_t encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES]; |
| 51 | size_t len; | 41 | size_t len; |
| 42 | int failed = 1; | ||
| 43 | |||
| 44 | if (!CBB_finish(seed_cbb, &seed, &seed_len)) | ||
| 45 | goto err; | ||
| 46 | if (!compare_length(MLKEM_SEED_BYTES, seed_len, line, "seed length")) | ||
| 47 | goto err; | ||
| 48 | if (!CBB_finish(public_key_cbb, &public_key, &public_key_len)) | ||
| 49 | goto err; | ||
| 50 | if (!compare_length(MLKEM768_PUBLIC_KEY_BYTES, public_key_len, line, | ||
| 51 | "public key length")) | ||
| 52 | goto err; | ||
| 53 | if (!CBB_finish(private_key_cbb, &private_key, &private_key_len)) | ||
| 54 | goto err; | ||
| 55 | if (!compare_length(MLKEM768_PUBLIC_KEY_BYTES, public_key_len, line, | ||
| 56 | "public key length")) | ||
| 57 | goto err; | ||
| 52 | 58 | ||
| 53 | TEST(CBS_len(seed) != MLKEM_SEED_BYTES, "seed len bogus"); | ||
| 54 | TEST(CBS_len(private_key) != MLKEM768_PRIVATE_KEY_BYTES, | ||
| 55 | "expected private key len bogus"); | ||
| 56 | TEST(CBS_len(public_key) != MLKEM768_PUBLIC_KEY_BYTES, | ||
| 57 | "expected public key len bogus"); | ||
| 58 | MLKEM768_generate_key_external_entropy(encoded_public_key, &priv, | 59 | MLKEM768_generate_key_external_entropy(encoded_public_key, &priv, |
| 59 | CBS_data(seed)); | 60 | seed); |
| 60 | TEST(!encode_private_key(&priv, &encoded_private_key, | 61 | if (!mlkem768_encode_private_key(&priv, &encoded_private_key, &len)) { |
| 61 | &len), "encode_private_key"); | 62 | warnx("#%zu: encoded_private_key", line); |
| 62 | TEST(len != MLKEM768_PRIVATE_KEY_BYTES, "private key len bogus"); | 63 | goto err; |
| 63 | TEST_DATAEQ(encoded_public_key, CBS_data(public_key), | 64 | } |
| 64 | MLKEM768_PUBLIC_KEY_BYTES, "public key"); | 65 | |
| 65 | TEST_DATAEQ(encoded_private_key, CBS_data(private_key), | 66 | if (!compare_length(MLKEM768_PRIVATE_KEY_BYTES, len, line, |
| 66 | MLKEM768_PRIVATE_KEY_BYTES, "private key"); | 67 | "private key length")) |
| 68 | goto err; | ||
| 69 | |||
| 70 | failed = compare_data(private_key, encoded_private_key, | ||
| 71 | MLKEM768_PRIVATE_KEY_BYTES, line, "private key"); | ||
| 72 | failed |= compare_data(public_key, encoded_public_key, | ||
| 73 | MLKEM768_PUBLIC_KEY_BYTES, line, "public key"); | ||
| 74 | |||
| 75 | err: | ||
| 76 | CBB_cleanup(seed_cbb); | ||
| 77 | CBB_cleanup(public_key_cbb); | ||
| 78 | CBB_cleanup(private_key_cbb); | ||
| 79 | freezero(seed, seed_len); | ||
| 80 | freezero(public_key, public_key_len); | ||
| 81 | freezero(private_key, private_key_len); | ||
| 67 | free(encoded_private_key); | 82 | free(encoded_private_key); |
| 83 | |||
| 84 | return failed; | ||
| 68 | } | 85 | } |
| 69 | 86 | ||
| 70 | #define S_START 0 | 87 | #define S_START 0 |
| 71 | #define S_SEED 1 | 88 | #define S_COMMENT 1 |
| 72 | #define S_PUBLIC_KEY 2 | 89 | #define S_SEED 2 |
| 73 | #define S_PRIVATE_KEY 3 | 90 | #define S_PUBLIC_KEY 3 |
| 91 | #define S_PRIVATE_KEY 4 | ||
| 92 | |||
| 93 | #define S2S(x) case x: return #x | ||
| 94 | |||
| 95 | static const char * | ||
| 96 | state2str(int state) | ||
| 97 | { | ||
| 98 | switch (state) { | ||
| 99 | S2S(S_START); | ||
| 100 | S2S(S_COMMENT); | ||
| 101 | S2S(S_SEED); | ||
| 102 | S2S(S_PUBLIC_KEY); | ||
| 103 | S2S(S_PRIVATE_KEY); | ||
| 104 | default: | ||
| 105 | errx(1, "unknown state %d", state); | ||
| 106 | } | ||
| 107 | } | ||
| 74 | 108 | ||
| 75 | int | 109 | int |
| 76 | main(int argc, char **argv) | 110 | main(int argc, char **argv) |
| 77 | { | 111 | { |
| 78 | CBS seed, public_key, private_key; | 112 | CBB seed = { 0 }, public_key = { 0 }, private_key = { 0 }; |
| 79 | char *buf; | 113 | const char *test; |
| 114 | size_t line = 0; | ||
| 115 | char *buf = NULL; | ||
| 116 | size_t buflen = 0; | ||
| 117 | ssize_t len; | ||
| 80 | FILE *fp; | 118 | FILE *fp; |
| 81 | int state; | 119 | int state; |
| 120 | int failed = 0; | ||
| 121 | |||
| 122 | if (argc < 2) | ||
| 123 | errx(1, "%s: missing test file", argv[0]); | ||
| 124 | |||
| 125 | test = argv[1]; | ||
| 126 | |||
| 127 | if ((fp = fopen(test, "r")) == NULL) | ||
| 128 | err(1, "cant't open test file"); | ||
| 129 | |||
| 130 | state = S_COMMENT; | ||
| 131 | line = 0; | ||
| 132 | |||
| 133 | while ((len = getline(&buf, &buflen, fp)) != -1) { | ||
| 134 | const char *msg = state2str(state); | ||
| 135 | CBS cbs; | ||
| 136 | uint8_t u8; | ||
| 137 | |||
| 138 | line++; | ||
| 139 | CBS_init(&cbs, buf, len); | ||
| 140 | |||
| 141 | if (!CBS_get_last_u8(&cbs, &u8)) | ||
| 142 | errx(1, "#%zu %s: CBB_get_last_u8", line, msg); | ||
| 143 | assert(u8 == '\n'); | ||
| 82 | 144 | ||
| 83 | fprintf(stderr, "Testing keygen test vectors in %s\n", argv[1]); | ||
| 84 | TEST((fp = fopen(argv[1], "r")) == NULL, "can't open test file"); | ||
| 85 | MALLOC(buf, 16*1024); | ||
| 86 | state = S_SEED; | ||
| 87 | test_number = 1; | ||
| 88 | while (fgets(buf, 16*1024, fp) != NULL) { | ||
| 89 | switch (state) { | 145 | switch (state) { |
| 90 | case S_START: | 146 | case S_START: |
| 91 | if (strcmp(buf, "\n") != 0) | 147 | state = S_COMMENT; |
| 92 | break; | 148 | break; |
| 149 | case S_COMMENT: | ||
| 150 | if (!CBS_get_u8(&cbs, &u8)) | ||
| 151 | errx(1, "#%zu %s: CBB_get_u8", line, msg); | ||
| 152 | assert(u8 == '#'); | ||
| 153 | if (!CBS_skip(&cbs, CBS_len(&cbs))) | ||
| 154 | errx(1, "#%zu %s: CBB_skip", line, msg); | ||
| 93 | state = S_SEED; | 155 | state = S_SEED; |
| 94 | break; | 156 | break; |
| 95 | case S_SEED: | 157 | case S_SEED: |
| 96 | if (strncmp(buf, "seed: ", strlen("seed: ")) != 0) { | 158 | if (!get_string_cbs(&cbs, "seed: ", line, msg)) |
| 97 | break; | 159 | errx(1, "#%zu %s: get_string_cbs", line, msg); |
| 98 | } | 160 | hex_decode_cbs(&cbs, &seed, line, msg); |
| 99 | grab_data(&seed, buf, strlen("seed: ")); | ||
| 100 | state = S_PUBLIC_KEY; | 161 | state = S_PUBLIC_KEY; |
| 101 | break; | 162 | break; |
| 102 | case S_PUBLIC_KEY: | 163 | case S_PUBLIC_KEY: |
| 103 | if (strncmp(buf, "public_key: ", | 164 | if (!get_string_cbs(&cbs, "public_key: ", line, msg)) |
| 104 | strlen("public_key: ")) != 0) | 165 | errx(1, "#%zu %s: get_string_cbs", line, msg); |
| 105 | break; | 166 | hex_decode_cbs(&cbs, &public_key, line, msg); |
| 106 | grab_data(&public_key, buf, strlen("public_key: ")); | ||
| 107 | state = S_PRIVATE_KEY; | 167 | state = S_PRIVATE_KEY; |
| 108 | break; | 168 | break; |
| 109 | case S_PRIVATE_KEY: | 169 | case S_PRIVATE_KEY: |
| 110 | if (strncmp(buf, "private_key: ", | 170 | if (!get_string_cbs(&cbs, "private_key: ", line, msg)) |
| 111 | strlen("private_key: ")) != 0) | 171 | errx(1, "#%zu %s: get_string_cbs", line, msg); |
| 112 | break; | 172 | hex_decode_cbs(&cbs, &private_key, line, msg); |
| 113 | grab_data(&private_key, buf, strlen("private_key: ")); | ||
| 114 | state = S_START; | ||
| 115 | 173 | ||
| 116 | MlkemKeygenFileTest(&seed, &public_key, &private_key); | 174 | failed |= MlkemKeygenFileTest(&seed, &public_key, |
| 117 | free((void *)CBS_data(&seed)); | 175 | &private_key, line); |
| 118 | free((void *)CBS_data(&public_key)); | ||
| 119 | free((void *)CBS_data(&private_key)); | ||
| 120 | 176 | ||
| 121 | test_number++; | ||
| 122 | state = S_START; | 177 | state = S_START; |
| 123 | break; | 178 | break; |
| 124 | } | 179 | } |
| 180 | if (CBS_len(&cbs) > 0) | ||
| 181 | errx(1, "#%zu %s: CBS_len", line, msg); | ||
| 125 | } | 182 | } |
| 126 | |||
| 127 | free(buf); | 183 | free(buf); |
| 184 | |||
| 185 | if (ferror(fp)) | ||
| 186 | err(1, NULL); | ||
| 128 | fclose(fp); | 187 | fclose(fp); |
| 129 | exit(failure); | 188 | |
| 189 | return failed; | ||
| 130 | } | 190 | } |
