blob: 539c39d430a530cba960aa5ac52ae311dbcea5df [file] [log] [blame]
Paul Bakker33b43f12013-08-20 11:48:36 +02001/* BEGIN_HEADER */
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +00002#include "mbedtls/ecdsa.h"
Przemek Stekiel40afdd22022-09-06 13:08:28 +02003#include "hash_info.h"
Manuel Pégourié-Gonnard07018f92022-09-15 11:29:35 +02004#include "mbedtls/legacy_or_psa.h"
Gilles Peskine449bd832023-01-11 14:50:10 +01005#if (defined(MBEDTLS_ECDSA_DETERMINISTIC) && defined(MBEDTLS_SHA256_C)) || \
6 (!defined(MBEDTLS_ECDSA_DETERMINISTIC) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA))
Andrzej Kurek9f42c062022-08-08 03:49:10 -04007#define MBEDTLS_HAS_ALG_SHA_256_VIA_MD_IF_DETERMINISTIC
8#endif
Paul Bakker33b43f12013-08-20 11:48:36 +02009/* END_HEADER */
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010010
Paul Bakker33b43f12013-08-20 11:48:36 +020011/* BEGIN_DEPENDENCIES
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020012 * depends_on:MBEDTLS_ECDSA_C
Paul Bakker33b43f12013-08-20 11:48:36 +020013 * END_DEPENDENCIES
14 */
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010015
Paul Bakker33b43f12013-08-20 11:48:36 +020016/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010017void ecdsa_prim_zero(int id)
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010018{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020019 mbedtls_ecp_group grp;
20 mbedtls_ecp_point Q;
21 mbedtls_mpi d, r, s;
Ronald Cron351f0ee2020-06-10 12:12:18 +020022 mbedtls_test_rnd_pseudo_info rnd_info;
Przemek Stekiel40afdd22022-09-06 13:08:28 +020023 unsigned char buf[MBEDTLS_HASH_MAX_SIZE];
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010024
Gilles Peskine449bd832023-01-11 14:50:10 +010025 mbedtls_ecp_group_init(&grp);
26 mbedtls_ecp_point_init(&Q);
27 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
28 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
29 memset(buf, 0, sizeof(buf));
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010030
Gilles Peskine449bd832023-01-11 14:50:10 +010031 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
32 TEST_ASSERT(mbedtls_ecp_gen_keypair(&grp, &d, &Q,
33 &mbedtls_test_rnd_pseudo_rand,
34 &rnd_info) == 0);
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010035
Gilles Peskine449bd832023-01-11 14:50:10 +010036 TEST_ASSERT(mbedtls_ecdsa_sign(&grp, &r, &s, &d, buf, sizeof(buf),
37 &mbedtls_test_rnd_pseudo_rand,
38 &rnd_info) == 0);
39 TEST_ASSERT(mbedtls_ecdsa_verify(&grp, buf, sizeof(buf), &Q, &r, &s) == 0);
TRodziewicz5feb6702021-04-06 19:55:17 +020040
TRodziewicz40de3c92021-04-07 19:16:18 +020041exit:
Gilles Peskine449bd832023-01-11 14:50:10 +010042 mbedtls_ecp_group_free(&grp);
43 mbedtls_ecp_point_free(&Q);
44 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
TRodziewicz40de3c92021-04-07 19:16:18 +020045}
46/* END_CASE */
47
48/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010049void ecdsa_prim_random(int id)
TRodziewicz40de3c92021-04-07 19:16:18 +020050{
51 mbedtls_ecp_group grp;
52 mbedtls_ecp_point Q;
53 mbedtls_mpi d, r, s;
54 mbedtls_test_rnd_pseudo_info rnd_info;
Przemek Stekiel40afdd22022-09-06 13:08:28 +020055 unsigned char buf[MBEDTLS_HASH_MAX_SIZE];
TRodziewicz40de3c92021-04-07 19:16:18 +020056
Gilles Peskine449bd832023-01-11 14:50:10 +010057 mbedtls_ecp_group_init(&grp);
58 mbedtls_ecp_point_init(&Q);
59 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
60 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
61 memset(buf, 0, sizeof(buf));
TRodziewicz40de3c92021-04-07 19:16:18 +020062
63 /* prepare material for signature */
Gilles Peskine449bd832023-01-11 14:50:10 +010064 TEST_ASSERT(mbedtls_test_rnd_pseudo_rand(&rnd_info,
65 buf, sizeof(buf)) == 0);
66 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
67 TEST_ASSERT(mbedtls_ecp_gen_keypair(&grp, &d, &Q,
68 &mbedtls_test_rnd_pseudo_rand,
69 &rnd_info) == 0);
TRodziewicz40de3c92021-04-07 19:16:18 +020070
Gilles Peskine449bd832023-01-11 14:50:10 +010071 TEST_ASSERT(mbedtls_ecdsa_sign(&grp, &r, &s, &d, buf, sizeof(buf),
72 &mbedtls_test_rnd_pseudo_rand,
73 &rnd_info) == 0);
74 TEST_ASSERT(mbedtls_ecdsa_verify(&grp, buf, sizeof(buf), &Q, &r, &s) == 0);
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010075
Paul Bakkerbd51b262014-07-10 15:26:12 +020076exit:
Gilles Peskine449bd832023-01-11 14:50:10 +010077 mbedtls_ecp_group_free(&grp);
78 mbedtls_ecp_point_free(&Q);
79 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010080}
Paul Bakker33b43f12013-08-20 11:48:36 +020081/* END_CASE */
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010082
Paul Bakker33b43f12013-08-20 11:48:36 +020083/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010084void ecdsa_prim_test_vectors(int id, char *d_str, char *xQ_str,
85 char *yQ_str, data_t *rnd_buf,
86 data_t *hash, char *r_str, char *s_str,
87 int result)
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010088{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089 mbedtls_ecp_group grp;
90 mbedtls_ecp_point Q;
Manuel Pégourié-Gonnardec528932022-04-21 09:25:23 +020091 mbedtls_mpi d, r, s, r_check, s_check, zero;
Ronald Cron351f0ee2020-06-10 12:12:18 +020092 mbedtls_test_rnd_buf_info rnd_info;
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010093
Gilles Peskine449bd832023-01-11 14:50:10 +010094 mbedtls_ecp_group_init(&grp);
95 mbedtls_ecp_point_init(&Q);
96 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
97 mbedtls_mpi_init(&r_check); mbedtls_mpi_init(&s_check);
98 mbedtls_mpi_init(&zero);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010099
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
101 TEST_ASSERT(mbedtls_ecp_point_read_string(&Q, 16, xQ_str, yQ_str) == 0);
102 TEST_ASSERT(mbedtls_test_read_mpi(&d, d_str) == 0);
103 TEST_ASSERT(mbedtls_test_read_mpi(&r_check, r_str) == 0);
104 TEST_ASSERT(mbedtls_test_read_mpi(&s_check, s_str) == 0);
Gilles Peskineecacc3c2021-03-24 00:48:57 +0100105 rnd_info.fallback_f_rng = mbedtls_test_rnd_std_rand;
106 rnd_info.fallback_p_rng = NULL;
Azim Khand30ca132017-06-09 04:32:58 +0100107 rnd_info.buf = rnd_buf->x;
108 rnd_info.length = rnd_buf->len;
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100109
Azim Khand30ca132017-06-09 04:32:58 +0100110 /* Fix rnd_buf->x by shifting it left if necessary */
Gilles Peskine449bd832023-01-11 14:50:10 +0100111 if (grp.nbits % 8 != 0) {
112 unsigned char shift = 8 - (grp.nbits % 8);
Manuel Pégourié-Gonnardfae079e2014-01-06 11:00:07 +0100113 size_t i;
114
Gilles Peskine449bd832023-01-11 14:50:10 +0100115 for (i = 0; i < rnd_info.length - 1; i++) {
116 rnd_buf->x[i] = rnd_buf->x[i] << shift | rnd_buf->x[i+1] >> (8 - shift);
117 }
Manuel Pégourié-Gonnardfae079e2014-01-06 11:00:07 +0100118
Azim Khand30ca132017-06-09 04:32:58 +0100119 rnd_buf->x[rnd_info.length-1] <<= shift;
Manuel Pégourié-Gonnardfae079e2014-01-06 11:00:07 +0100120 }
121
Gilles Peskine449bd832023-01-11 14:50:10 +0100122 TEST_ASSERT(mbedtls_ecdsa_sign(&grp, &r, &s, &d, hash->x, hash->len,
123 mbedtls_test_rnd_buffer_rand, &rnd_info) == result);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100124
Gilles Peskine449bd832023-01-11 14:50:10 +0100125 if (result == 0) {
Manuel Pégourié-Gonnardec528932022-04-21 09:25:23 +0200126 /* Check we generated the expected values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100127 TEST_EQUAL(mbedtls_mpi_cmp_mpi(&r, &r_check), 0);
128 TEST_EQUAL(mbedtls_mpi_cmp_mpi(&s, &s_check), 0);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100129
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200130 /* Valid signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len,
132 &Q, &r_check, &s_check), 0);
Manuel Pégourié-Gonnardd0a66cc2018-06-13 09:53:21 +0200133
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200134 /* Invalid signature: wrong public key (G instead of Q) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100135 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len,
136 &grp.G, &r_check, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd0a66cc2018-06-13 09:53:21 +0200137
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200138 /* Invalid signatures: r or s or both one off */
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 TEST_EQUAL(mbedtls_mpi_sub_int(&r, &r_check, 1), 0);
140 TEST_EQUAL(mbedtls_mpi_add_int(&s, &s_check, 1), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200141
Gilles Peskine449bd832023-01-11 14:50:10 +0100142 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
143 &r, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
144 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
145 &r_check, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
146 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
147 &r, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200148
149 /* Invalid signatures: r, s or both (CVE-2022-21449) are zero */
Gilles Peskine449bd832023-01-11 14:50:10 +0100150 TEST_EQUAL(mbedtls_mpi_lset(&zero, 0), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200151
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
153 &zero, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
154 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
155 &r_check, &zero), MBEDTLS_ERR_ECP_VERIFY_FAILED);
156 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
157 &zero, &zero), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200158
159 /* Invalid signatures: r, s or both are == N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100160 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
161 &grp.N, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
162 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
163 &r_check, &grp.N), MBEDTLS_ERR_ECP_VERIFY_FAILED);
164 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
165 &grp.N, &grp.N), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardec528932022-04-21 09:25:23 +0200166
167 /* Invalid signatures: r, s or both are negative */
Gilles Peskine449bd832023-01-11 14:50:10 +0100168 TEST_EQUAL(mbedtls_mpi_sub_mpi(&r, &r_check, &grp.N), 0);
169 TEST_EQUAL(mbedtls_mpi_sub_mpi(&s, &s_check, &grp.N), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200170
Gilles Peskine449bd832023-01-11 14:50:10 +0100171 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
172 &r, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
173 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
174 &r_check, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
175 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
176 &r, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200177
178 /* Invalid signatures: r or s or both are > N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100179 TEST_EQUAL(mbedtls_mpi_add_mpi(&r, &r_check, &grp.N), 0);
180 TEST_EQUAL(mbedtls_mpi_add_mpi(&s, &s_check, &grp.N), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200181
Gilles Peskine449bd832023-01-11 14:50:10 +0100182 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
183 &r, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
184 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
185 &r_check, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
186 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
187 &r, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Darryl Greenf5bcbed2017-11-17 17:09:31 +0000188 }
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100189
Paul Bakkerbd51b262014-07-10 15:26:12 +0200190exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 mbedtls_ecp_group_free(&grp);
192 mbedtls_ecp_point_free(&Q);
193 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
194 mbedtls_mpi_free(&r_check); mbedtls_mpi_free(&s_check);
195 mbedtls_mpi_free(&zero);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100196}
Paul Bakker33b43f12013-08-20 11:48:36 +0200197/* END_CASE */
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_DETERMINISTIC */
Gilles Peskine449bd832023-01-11 14:50:10 +0100200void ecdsa_det_test_vectors(int id, char *d_str, int md_alg, data_t *hash,
201 char *r_str, char *s_str)
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100202{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 mbedtls_ecp_group grp;
204 mbedtls_mpi d, r, s, r_check, s_check;
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100205
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 mbedtls_ecp_group_init(&grp);
207 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
208 mbedtls_mpi_init(&r_check); mbedtls_mpi_init(&s_check);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100209
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
211 TEST_ASSERT(mbedtls_test_read_mpi(&d, d_str) == 0);
212 TEST_ASSERT(mbedtls_test_read_mpi(&r_check, r_str) == 0);
213 TEST_ASSERT(mbedtls_test_read_mpi(&s_check, s_str) == 0);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100214
Janos Follath651eac82019-01-04 15:51:24 +0000215 TEST_ASSERT(
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 mbedtls_ecdsa_sign_det_ext(&grp, &r, &s, &d,
217 hash->x, hash->len, md_alg,
218 mbedtls_test_rnd_std_rand,
219 NULL)
220 == 0);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100221
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&r, &r_check) == 0);
223 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&s, &s_check) == 0);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100224
Paul Bakkerbd51b262014-07-10 15:26:12 +0200225exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 mbedtls_ecp_group_free(&grp);
227 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
228 mbedtls_mpi_free(&r_check); mbedtls_mpi_free(&s_check);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100229}
230/* END_CASE */
231
Andrzej Kurek9f42c062022-08-08 03:49:10 -0400232/* BEGIN_CASE depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_IF_DETERMINISTIC */
Gilles Peskine449bd832023-01-11 14:50:10 +0100233void ecdsa_write_read_zero(int id)
TRodziewicz40de3c92021-04-07 19:16:18 +0200234{
235 mbedtls_ecdsa_context ctx;
236 mbedtls_test_rnd_pseudo_info rnd_info;
237 unsigned char hash[32];
238 unsigned char sig[200];
239 size_t sig_len, i;
240
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 mbedtls_ecdsa_init(&ctx);
242 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
243 memset(hash, 0, sizeof(hash));
244 memset(sig, 0x2a, sizeof(sig));
TRodziewicz40de3c92021-04-07 19:16:18 +0200245
246 /* generate signing key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 TEST_ASSERT(mbedtls_ecdsa_genkey(&ctx, id,
248 &mbedtls_test_rnd_pseudo_rand,
249 &rnd_info) == 0);
TRodziewicz40de3c92021-04-07 19:16:18 +0200250
251 /* generate and write signature, then read and verify it */
Gilles Peskine449bd832023-01-11 14:50:10 +0100252 TEST_ASSERT(mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256,
253 hash, sizeof(hash),
254 sig, sizeof(sig), &sig_len,
255 &mbedtls_test_rnd_pseudo_rand,
256 &rnd_info) == 0);
257 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
258 sig, sig_len) == 0);
TRodziewicz40de3c92021-04-07 19:16:18 +0200259
260 /* check we didn't write past the announced length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 for (i = sig_len; i < sizeof(sig); i++) {
262 TEST_ASSERT(sig[i] == 0x2a);
263 }
TRodziewicz40de3c92021-04-07 19:16:18 +0200264
265 /* try verification with invalid length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
267 sig, sig_len - 1) != 0);
268 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
269 sig, sig_len + 1) != 0);
TRodziewicz40de3c92021-04-07 19:16:18 +0200270
271 /* try invalid sequence tag */
272 sig[0]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
274 sig, sig_len) != 0);
TRodziewicz40de3c92021-04-07 19:16:18 +0200275 sig[0]--;
276
277 /* try modifying r */
278 sig[10]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
280 sig, sig_len) == MBEDTLS_ERR_ECP_VERIFY_FAILED);
TRodziewicz40de3c92021-04-07 19:16:18 +0200281 sig[10]--;
282
283 /* try modifying s */
284 sig[sig_len - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
286 sig, sig_len) == MBEDTLS_ERR_ECP_VERIFY_FAILED);
TRodziewicz40de3c92021-04-07 19:16:18 +0200287 sig[sig_len - 1]--;
288
289exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100290 mbedtls_ecdsa_free(&ctx);
TRodziewicz40de3c92021-04-07 19:16:18 +0200291}
292/* END_CASE */
293
Andrzej Kurek9f42c062022-08-08 03:49:10 -0400294/* BEGIN_CASE depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_IF_DETERMINISTIC */
Gilles Peskine449bd832023-01-11 14:50:10 +0100295void ecdsa_write_read_random(int id)
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200296{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297 mbedtls_ecdsa_context ctx;
Ronald Cron351f0ee2020-06-10 12:12:18 +0200298 mbedtls_test_rnd_pseudo_info rnd_info;
Manuel Pégourié-Gonnarddfdcac92015-03-31 11:41:42 +0200299 unsigned char hash[32];
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200300 unsigned char sig[200];
301 size_t sig_len, i;
302
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 mbedtls_ecdsa_init(&ctx);
304 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
305 memset(hash, 0, sizeof(hash));
306 memset(sig, 0x2a, sizeof(sig));
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200307
TRodziewicz40de3c92021-04-07 19:16:18 +0200308 /* prepare material for signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100309 TEST_ASSERT(mbedtls_test_rnd_pseudo_rand(&rnd_info,
310 hash, sizeof(hash)) == 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200311
TRodziewicz40de3c92021-04-07 19:16:18 +0200312 /* generate signing key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100313 TEST_ASSERT(mbedtls_ecdsa_genkey(&ctx, id,
314 &mbedtls_test_rnd_pseudo_rand,
315 &rnd_info) == 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200316
TRodziewicz40de3c92021-04-07 19:16:18 +0200317 /* generate and write signature, then read and verify it */
Gilles Peskine449bd832023-01-11 14:50:10 +0100318 TEST_ASSERT(mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256,
319 hash, sizeof(hash),
320 sig, sizeof(sig), &sig_len,
321 &mbedtls_test_rnd_pseudo_rand,
322 &rnd_info) == 0);
323 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
324 sig, sig_len) == 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200325
TRodziewicz40de3c92021-04-07 19:16:18 +0200326 /* check we didn't write past the announced length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100327 for (i = sig_len; i < sizeof(sig); i++) {
328 TEST_ASSERT(sig[i] == 0x2a);
329 }
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200330
TRodziewicz40de3c92021-04-07 19:16:18 +0200331 /* try verification with invalid length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
333 sig, sig_len - 1) != 0);
334 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
335 sig, sig_len + 1) != 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200336
TRodziewicz40de3c92021-04-07 19:16:18 +0200337 /* try invalid sequence tag */
338 sig[0]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
340 sig, sig_len) != 0);
TRodziewicz40de3c92021-04-07 19:16:18 +0200341 sig[0]--;
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200342
TRodziewicz40de3c92021-04-07 19:16:18 +0200343 /* try modifying r */
344 sig[10]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
346 sig, sig_len) == MBEDTLS_ERR_ECP_VERIFY_FAILED);
TRodziewicz40de3c92021-04-07 19:16:18 +0200347 sig[10]--;
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200348
TRodziewicz40de3c92021-04-07 19:16:18 +0200349 /* try modifying s */
350 sig[sig_len - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
352 sig, sig_len) == MBEDTLS_ERR_ECP_VERIFY_FAILED);
TRodziewicz40de3c92021-04-07 19:16:18 +0200353 sig[sig_len - 1]--;
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200354
Paul Bakkerbd51b262014-07-10 15:26:12 +0200355exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100356 mbedtls_ecdsa_free(&ctx);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200357}
358/* END_CASE */
Manuel Pégourié-Gonnard937340b2014-01-06 10:27:16 +0100359
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200360/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100361void ecdsa_read_restart(int id, data_t *pk, data_t *hash, data_t *sig,
362 int max_ops, int min_restart, int max_restart)
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200363{
364 mbedtls_ecdsa_context ctx;
365 mbedtls_ecdsa_restart_ctx rs_ctx;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200366 int ret, cnt_restart;
367
Gilles Peskine449bd832023-01-11 14:50:10 +0100368 mbedtls_ecdsa_init(&ctx);
369 mbedtls_ecdsa_restart_init(&rs_ctx);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200370
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 TEST_ASSERT(mbedtls_ecp_group_load(&ctx.grp, id) == 0);
372 TEST_ASSERT(mbedtls_ecp_point_read_binary(&ctx.grp, &ctx.Q,
373 pk->x, pk->len) == 0);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200374
Gilles Peskine449bd832023-01-11 14:50:10 +0100375 mbedtls_ecp_set_max_ops(max_ops);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200376
377 cnt_restart = 0;
378 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
380 hash->x, hash->len, sig->x, sig->len,
381 &rs_ctx);
382 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200383
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 TEST_ASSERT(ret == 0);
385 TEST_ASSERT(cnt_restart >= min_restart);
386 TEST_ASSERT(cnt_restart <= max_restart);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200387
388 /* try modifying r */
Ronald Cron9ed40732020-06-25 09:03:34 +0200389
Gilles Peskine449bd832023-01-11 14:50:10 +0100390 TEST_ASSERT(sig->len > 10);
Ronald Cron9ed40732020-06-25 09:03:34 +0200391 sig->x[10]++;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200392 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
394 hash->x, hash->len, sig->x, sig->len,
395 &rs_ctx);
396 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
397 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_VERIFY_FAILED);
Ronald Cron9ed40732020-06-25 09:03:34 +0200398 sig->x[10]--;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200399
400 /* try modifying s */
Ronald Cron9ed40732020-06-25 09:03:34 +0200401 sig->x[sig->len - 1]++;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200402 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100403 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
404 hash->x, hash->len, sig->x, sig->len,
405 &rs_ctx);
406 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
407 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_VERIFY_FAILED);
Ronald Cron9ed40732020-06-25 09:03:34 +0200408 sig->x[sig->len - 1]--;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200409
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200410 /* Do we leak memory when aborting an operation?
411 * This test only makes sense when we actually restart */
Gilles Peskine449bd832023-01-11 14:50:10 +0100412 if (min_restart > 0) {
413 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
414 hash->x, hash->len, sig->x, sig->len,
415 &rs_ctx);
416 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200417 }
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200418
419exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100420 mbedtls_ecdsa_free(&ctx);
421 mbedtls_ecdsa_restart_free(&rs_ctx);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200422}
423/* END_CASE */
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200424
425/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE:MBEDTLS_ECDSA_DETERMINISTIC */
Gilles Peskine449bd832023-01-11 14:50:10 +0100426void ecdsa_write_restart(int id, char *d_str, int md_alg,
427 data_t *hash, data_t *sig_check,
428 int max_ops, int min_restart, int max_restart)
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200429{
430 int ret, cnt_restart;
431 mbedtls_ecdsa_restart_ctx rs_ctx;
432 mbedtls_ecdsa_context ctx;
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200433 unsigned char sig[MBEDTLS_ECDSA_MAX_LEN];
Neil Armstrong5ea65172022-07-19 16:54:28 +0200434 size_t slen;
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200435
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 mbedtls_ecdsa_restart_init(&rs_ctx);
437 mbedtls_ecdsa_init(&ctx);
438 memset(sig, 0, sizeof(sig));
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200439
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 TEST_ASSERT(mbedtls_ecp_group_load(&ctx.grp, id) == 0);
441 TEST_ASSERT(mbedtls_test_read_mpi(&ctx.d, d_str) == 0);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200442
Gilles Peskine449bd832023-01-11 14:50:10 +0100443 mbedtls_ecp_set_max_ops(max_ops);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 slen = sizeof(sig);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200446 cnt_restart = 0;
447 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 ret = mbedtls_ecdsa_write_signature_restartable(&ctx,
449 md_alg,
450 hash->x,
451 hash->len,
452 sig,
453 sizeof(sig),
454 &slen,
455 mbedtls_test_rnd_std_rand,
456 NULL,
457 &rs_ctx);
458 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200459
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 TEST_ASSERT(ret == 0);
461 TEST_ASSERT(slen == sig_check->len);
462 TEST_ASSERT(memcmp(sig, sig_check->x, slen) == 0);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200463
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 TEST_ASSERT(cnt_restart >= min_restart);
465 TEST_ASSERT(cnt_restart <= max_restart);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200466
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200467 /* Do we leak memory when aborting an operation?
468 * This test only makes sense when we actually restart */
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 if (min_restart > 0) {
470 ret = mbedtls_ecdsa_write_signature_restartable(&ctx,
471 md_alg,
472 hash->x,
473 hash->len,
474 sig,
475 sizeof(sig),
476 &slen,
477 mbedtls_test_rnd_std_rand,
478 NULL,
479 &rs_ctx);
480 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200481 }
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200482
483exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100484 mbedtls_ecdsa_restart_free(&rs_ctx);
485 mbedtls_ecdsa_free(&ctx);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200486}
487/* END_CASE */
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100488
489/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100490void ecdsa_verify(int grp_id, char *x, char *y, char *r, char *s, data_t *content, int expected)
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100491{
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100492 mbedtls_ecdsa_context ctx;
493 mbedtls_mpi sig_r, sig_s;
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100494
Gilles Peskine449bd832023-01-11 14:50:10 +0100495 mbedtls_ecdsa_init(&ctx);
496 mbedtls_mpi_init(&sig_r);
497 mbedtls_mpi_init(&sig_s);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100498
499 /* Prepare ECP group context */
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 TEST_EQUAL(mbedtls_ecp_group_load(&ctx.grp, grp_id), 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100501
502 /* Prepare public key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 TEST_EQUAL(mbedtls_test_read_mpi(&ctx.Q.X, x), 0);
504 TEST_EQUAL(mbedtls_test_read_mpi(&ctx.Q.Y, y), 0);
505 TEST_EQUAL(mbedtls_mpi_lset(&ctx.Q.Z, 1), 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100506
507 /* Prepare signature R & S */
Gilles Peskine449bd832023-01-11 14:50:10 +0100508 TEST_EQUAL(mbedtls_test_read_mpi(&sig_r, r), 0);
509 TEST_EQUAL(mbedtls_test_read_mpi(&sig_s, s), 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100510
511 /* Test whether public key has expected validity */
Gilles Peskine449bd832023-01-11 14:50:10 +0100512 TEST_EQUAL(mbedtls_ecp_check_pubkey(&ctx.grp, &ctx.Q),
513 expected == MBEDTLS_ERR_ECP_INVALID_KEY ? MBEDTLS_ERR_ECP_INVALID_KEY : 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100514
515 /* Verification */
Gilles Peskine449bd832023-01-11 14:50:10 +0100516 int result = mbedtls_ecdsa_verify(&ctx.grp, content->x, content->len, &ctx.Q, &sig_r, &sig_s);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100517
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 TEST_EQUAL(result, expected);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100519exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100520 mbedtls_ecdsa_free(&ctx);
521 mbedtls_mpi_free(&sig_r);
522 mbedtls_mpi_free(&sig_s);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100523}
Dave Rodgman56cfb312022-08-10 12:21:23 +0100524/* END_CASE */