blob: 14fe2f058b2f574bec70a932c9dd6254e23bf828 [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"
Paul Bakker33b43f12013-08-20 11:48:36 +02004/* END_HEADER */
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +01005
Paul Bakker33b43f12013-08-20 11:48:36 +02006/* BEGIN_DEPENDENCIES
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02007 * depends_on:MBEDTLS_ECDSA_C
Paul Bakker33b43f12013-08-20 11:48:36 +02008 * END_DEPENDENCIES
9 */
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010010
Paul Bakker33b43f12013-08-20 11:48:36 +020011/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010012void ecdsa_prim_zero(int id)
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010013{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020014 mbedtls_ecp_group grp;
15 mbedtls_ecp_point Q;
16 mbedtls_mpi d, r, s;
Ronald Cron351f0ee2020-06-10 12:12:18 +020017 mbedtls_test_rnd_pseudo_info rnd_info;
Manuel Pégourié-Gonnard88579842023-03-28 11:20:23 +020018 unsigned char buf[MBEDTLS_MD_MAX_SIZE];
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010019
Gilles Peskine449bd832023-01-11 14:50:10 +010020 mbedtls_ecp_group_init(&grp);
21 mbedtls_ecp_point_init(&Q);
22 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
23 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
24 memset(buf, 0, sizeof(buf));
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010025
Gilles Peskine449bd832023-01-11 14:50:10 +010026 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
27 TEST_ASSERT(mbedtls_ecp_gen_keypair(&grp, &d, &Q,
28 &mbedtls_test_rnd_pseudo_rand,
29 &rnd_info) == 0);
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010030
Gilles Peskine449bd832023-01-11 14:50:10 +010031 TEST_ASSERT(mbedtls_ecdsa_sign(&grp, &r, &s, &d, buf, sizeof(buf),
32 &mbedtls_test_rnd_pseudo_rand,
33 &rnd_info) == 0);
34 TEST_ASSERT(mbedtls_ecdsa_verify(&grp, buf, sizeof(buf), &Q, &r, &s) == 0);
TRodziewicz5feb6702021-04-06 19:55:17 +020035
TRodziewicz40de3c92021-04-07 19:16:18 +020036exit:
Gilles Peskine449bd832023-01-11 14:50:10 +010037 mbedtls_ecp_group_free(&grp);
38 mbedtls_ecp_point_free(&Q);
39 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
TRodziewicz40de3c92021-04-07 19:16:18 +020040}
41/* END_CASE */
42
43/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010044void ecdsa_prim_random(int id)
TRodziewicz40de3c92021-04-07 19:16:18 +020045{
46 mbedtls_ecp_group grp;
47 mbedtls_ecp_point Q;
48 mbedtls_mpi d, r, s;
49 mbedtls_test_rnd_pseudo_info rnd_info;
Manuel Pégourié-Gonnard88579842023-03-28 11:20:23 +020050 unsigned char buf[MBEDTLS_MD_MAX_SIZE];
TRodziewicz40de3c92021-04-07 19:16:18 +020051
Gilles Peskine449bd832023-01-11 14:50:10 +010052 mbedtls_ecp_group_init(&grp);
53 mbedtls_ecp_point_init(&Q);
54 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
55 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
56 memset(buf, 0, sizeof(buf));
TRodziewicz40de3c92021-04-07 19:16:18 +020057
58 /* prepare material for signature */
Gilles Peskine449bd832023-01-11 14:50:10 +010059 TEST_ASSERT(mbedtls_test_rnd_pseudo_rand(&rnd_info,
60 buf, sizeof(buf)) == 0);
61 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
62 TEST_ASSERT(mbedtls_ecp_gen_keypair(&grp, &d, &Q,
63 &mbedtls_test_rnd_pseudo_rand,
64 &rnd_info) == 0);
TRodziewicz40de3c92021-04-07 19:16:18 +020065
Gilles Peskine449bd832023-01-11 14:50:10 +010066 TEST_ASSERT(mbedtls_ecdsa_sign(&grp, &r, &s, &d, buf, sizeof(buf),
67 &mbedtls_test_rnd_pseudo_rand,
68 &rnd_info) == 0);
69 TEST_ASSERT(mbedtls_ecdsa_verify(&grp, buf, sizeof(buf), &Q, &r, &s) == 0);
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010070
Paul Bakkerbd51b262014-07-10 15:26:12 +020071exit:
Gilles Peskine449bd832023-01-11 14:50:10 +010072 mbedtls_ecp_group_free(&grp);
73 mbedtls_ecp_point_free(&Q);
74 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010075}
Paul Bakker33b43f12013-08-20 11:48:36 +020076/* END_CASE */
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010077
Paul Bakker33b43f12013-08-20 11:48:36 +020078/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010079void ecdsa_prim_test_vectors(int id, char *d_str, char *xQ_str,
80 char *yQ_str, data_t *rnd_buf,
81 data_t *hash, char *r_str, char *s_str,
82 int result)
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010083{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084 mbedtls_ecp_group grp;
85 mbedtls_ecp_point Q;
Manuel Pégourié-Gonnardec528932022-04-21 09:25:23 +020086 mbedtls_mpi d, r, s, r_check, s_check, zero;
Ronald Cron351f0ee2020-06-10 12:12:18 +020087 mbedtls_test_rnd_buf_info rnd_info;
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010088
Gilles Peskine449bd832023-01-11 14:50:10 +010089 mbedtls_ecp_group_init(&grp);
90 mbedtls_ecp_point_init(&Q);
91 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
92 mbedtls_mpi_init(&r_check); mbedtls_mpi_init(&s_check);
93 mbedtls_mpi_init(&zero);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010094
Gilles Peskine449bd832023-01-11 14:50:10 +010095 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
96 TEST_ASSERT(mbedtls_ecp_point_read_string(&Q, 16, xQ_str, yQ_str) == 0);
97 TEST_ASSERT(mbedtls_test_read_mpi(&d, d_str) == 0);
98 TEST_ASSERT(mbedtls_test_read_mpi(&r_check, r_str) == 0);
99 TEST_ASSERT(mbedtls_test_read_mpi(&s_check, s_str) == 0);
Gilles Peskineecacc3c2021-03-24 00:48:57 +0100100 rnd_info.fallback_f_rng = mbedtls_test_rnd_std_rand;
101 rnd_info.fallback_p_rng = NULL;
Azim Khand30ca132017-06-09 04:32:58 +0100102 rnd_info.buf = rnd_buf->x;
103 rnd_info.length = rnd_buf->len;
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100104
Azim Khand30ca132017-06-09 04:32:58 +0100105 /* Fix rnd_buf->x by shifting it left if necessary */
Gilles Peskine449bd832023-01-11 14:50:10 +0100106 if (grp.nbits % 8 != 0) {
107 unsigned char shift = 8 - (grp.nbits % 8);
Manuel Pégourié-Gonnardfae079e2014-01-06 11:00:07 +0100108 size_t i;
109
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 for (i = 0; i < rnd_info.length - 1; i++) {
111 rnd_buf->x[i] = rnd_buf->x[i] << shift | rnd_buf->x[i+1] >> (8 - shift);
112 }
Manuel Pégourié-Gonnardfae079e2014-01-06 11:00:07 +0100113
Azim Khand30ca132017-06-09 04:32:58 +0100114 rnd_buf->x[rnd_info.length-1] <<= shift;
Manuel Pégourié-Gonnardfae079e2014-01-06 11:00:07 +0100115 }
116
Gilles Peskine449bd832023-01-11 14:50:10 +0100117 TEST_ASSERT(mbedtls_ecdsa_sign(&grp, &r, &s, &d, hash->x, hash->len,
118 mbedtls_test_rnd_buffer_rand, &rnd_info) == result);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100119
Gilles Peskine449bd832023-01-11 14:50:10 +0100120 if (result == 0) {
Manuel Pégourié-Gonnardec528932022-04-21 09:25:23 +0200121 /* Check we generated the expected values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100122 TEST_EQUAL(mbedtls_mpi_cmp_mpi(&r, &r_check), 0);
123 TEST_EQUAL(mbedtls_mpi_cmp_mpi(&s, &s_check), 0);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100124
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200125 /* Valid signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100126 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len,
127 &Q, &r_check, &s_check), 0);
Manuel Pégourié-Gonnardd0a66cc2018-06-13 09:53:21 +0200128
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200129 /* Invalid signature: wrong public key (G instead of Q) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100130 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len,
131 &grp.G, &r_check, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd0a66cc2018-06-13 09:53:21 +0200132
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200133 /* Invalid signatures: r or s or both one off */
Gilles Peskine449bd832023-01-11 14:50:10 +0100134 TEST_EQUAL(mbedtls_mpi_sub_int(&r, &r_check, 1), 0);
135 TEST_EQUAL(mbedtls_mpi_add_int(&s, &s_check, 1), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200136
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
138 &r, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
139 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
140 &r_check, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
141 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
142 &r, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200143
144 /* Invalid signatures: r, s or both (CVE-2022-21449) are zero */
Gilles Peskine449bd832023-01-11 14:50:10 +0100145 TEST_EQUAL(mbedtls_mpi_lset(&zero, 0), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200146
Gilles Peskine449bd832023-01-11 14:50:10 +0100147 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
148 &zero, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
149 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
150 &r_check, &zero), MBEDTLS_ERR_ECP_VERIFY_FAILED);
151 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
152 &zero, &zero), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200153
154 /* Invalid signatures: r, s or both are == N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100155 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
156 &grp.N, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
157 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
158 &r_check, &grp.N), MBEDTLS_ERR_ECP_VERIFY_FAILED);
159 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
160 &grp.N, &grp.N), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardec528932022-04-21 09:25:23 +0200161
162 /* Invalid signatures: r, s or both are negative */
Gilles Peskine449bd832023-01-11 14:50:10 +0100163 TEST_EQUAL(mbedtls_mpi_sub_mpi(&r, &r_check, &grp.N), 0);
164 TEST_EQUAL(mbedtls_mpi_sub_mpi(&s, &s_check, &grp.N), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200165
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
167 &r, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
168 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
169 &r_check, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
170 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
171 &r, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200172
173 /* Invalid signatures: r or s or both are > N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 TEST_EQUAL(mbedtls_mpi_add_mpi(&r, &r_check, &grp.N), 0);
175 TEST_EQUAL(mbedtls_mpi_add_mpi(&s, &s_check, &grp.N), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200176
Gilles Peskine449bd832023-01-11 14:50:10 +0100177 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
178 &r, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
179 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
180 &r_check, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
181 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
182 &r, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Darryl Greenf5bcbed2017-11-17 17:09:31 +0000183 }
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100184
Paul Bakkerbd51b262014-07-10 15:26:12 +0200185exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100186 mbedtls_ecp_group_free(&grp);
187 mbedtls_ecp_point_free(&Q);
188 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
189 mbedtls_mpi_free(&r_check); mbedtls_mpi_free(&s_check);
190 mbedtls_mpi_free(&zero);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100191}
Paul Bakker33b43f12013-08-20 11:48:36 +0200192/* END_CASE */
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200193
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200194/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_DETERMINISTIC */
Gilles Peskine449bd832023-01-11 14:50:10 +0100195void ecdsa_det_test_vectors(int id, char *d_str, int md_alg, data_t *hash,
196 char *r_str, char *s_str)
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100197{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200198 mbedtls_ecp_group grp;
199 mbedtls_mpi d, r, s, r_check, s_check;
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100200
Manuel Pégourié-Gonnardebef58d2023-03-16 12:48:24 +0100201 MD_PSA_INIT();
202
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 mbedtls_ecp_group_init(&grp);
204 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
205 mbedtls_mpi_init(&r_check); mbedtls_mpi_init(&s_check);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100206
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
208 TEST_ASSERT(mbedtls_test_read_mpi(&d, d_str) == 0);
209 TEST_ASSERT(mbedtls_test_read_mpi(&r_check, r_str) == 0);
210 TEST_ASSERT(mbedtls_test_read_mpi(&s_check, s_str) == 0);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100211
Janos Follath651eac82019-01-04 15:51:24 +0000212 TEST_ASSERT(
Gilles Peskine449bd832023-01-11 14:50:10 +0100213 mbedtls_ecdsa_sign_det_ext(&grp, &r, &s, &d,
214 hash->x, hash->len, md_alg,
215 mbedtls_test_rnd_std_rand,
216 NULL)
217 == 0);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100218
Gilles Peskine449bd832023-01-11 14:50:10 +0100219 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&r, &r_check) == 0);
220 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&s, &s_check) == 0);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100221
Paul Bakkerbd51b262014-07-10 15:26:12 +0200222exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100223 mbedtls_ecp_group_free(&grp);
224 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
225 mbedtls_mpi_free(&r_check); mbedtls_mpi_free(&s_check);
Manuel Pégourié-Gonnardebef58d2023-03-16 12:48:24 +0100226 MD_PSA_DONE();
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100227}
228/* END_CASE */
229
Manuel Pégourié-Gonnardebef58d2023-03-16 12:48:24 +0100230/* BEGIN_CASE depends_on:MBEDTLS_MD_CAN_SHA256 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100231void ecdsa_write_read_zero(int id)
TRodziewicz40de3c92021-04-07 19:16:18 +0200232{
233 mbedtls_ecdsa_context ctx;
234 mbedtls_test_rnd_pseudo_info rnd_info;
235 unsigned char hash[32];
236 unsigned char sig[200];
237 size_t sig_len, i;
238
Manuel Pégourié-Gonnard91cc8bb2023-03-20 11:02:12 +0100239 MD_PSA_INIT();
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);
Manuel Pégourié-Gonnard91cc8bb2023-03-20 11:02:12 +0100291 MD_PSA_DONE();
TRodziewicz40de3c92021-04-07 19:16:18 +0200292}
293/* END_CASE */
294
Manuel Pégourié-Gonnardebef58d2023-03-16 12:48:24 +0100295/* BEGIN_CASE depends_on:MBEDTLS_MD_CAN_SHA256 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100296void ecdsa_write_read_random(int id)
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200297{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298 mbedtls_ecdsa_context ctx;
Ronald Cron351f0ee2020-06-10 12:12:18 +0200299 mbedtls_test_rnd_pseudo_info rnd_info;
Manuel Pégourié-Gonnarddfdcac92015-03-31 11:41:42 +0200300 unsigned char hash[32];
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200301 unsigned char sig[200];
302 size_t sig_len, i;
303
Manuel Pégourié-Gonnard91cc8bb2023-03-20 11:02:12 +0100304 MD_PSA_INIT();
305
Gilles Peskine449bd832023-01-11 14:50:10 +0100306 mbedtls_ecdsa_init(&ctx);
307 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
308 memset(hash, 0, sizeof(hash));
309 memset(sig, 0x2a, sizeof(sig));
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200310
TRodziewicz40de3c92021-04-07 19:16:18 +0200311 /* prepare material for signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 TEST_ASSERT(mbedtls_test_rnd_pseudo_rand(&rnd_info,
313 hash, sizeof(hash)) == 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200314
TRodziewicz40de3c92021-04-07 19:16:18 +0200315 /* generate signing key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100316 TEST_ASSERT(mbedtls_ecdsa_genkey(&ctx, id,
317 &mbedtls_test_rnd_pseudo_rand,
318 &rnd_info) == 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200319
TRodziewicz40de3c92021-04-07 19:16:18 +0200320 /* generate and write signature, then read and verify it */
Gilles Peskine449bd832023-01-11 14:50:10 +0100321 TEST_ASSERT(mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256,
322 hash, sizeof(hash),
323 sig, sizeof(sig), &sig_len,
324 &mbedtls_test_rnd_pseudo_rand,
325 &rnd_info) == 0);
326 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
327 sig, sig_len) == 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200328
TRodziewicz40de3c92021-04-07 19:16:18 +0200329 /* check we didn't write past the announced length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 for (i = sig_len; i < sizeof(sig); i++) {
331 TEST_ASSERT(sig[i] == 0x2a);
332 }
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200333
TRodziewicz40de3c92021-04-07 19:16:18 +0200334 /* try verification with invalid length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100335 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
336 sig, sig_len - 1) != 0);
337 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
338 sig, sig_len + 1) != 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200339
TRodziewicz40de3c92021-04-07 19:16:18 +0200340 /* try invalid sequence tag */
341 sig[0]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100342 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
343 sig, sig_len) != 0);
TRodziewicz40de3c92021-04-07 19:16:18 +0200344 sig[0]--;
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200345
TRodziewicz40de3c92021-04-07 19:16:18 +0200346 /* try modifying r */
347 sig[10]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100348 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
349 sig, sig_len) == MBEDTLS_ERR_ECP_VERIFY_FAILED);
TRodziewicz40de3c92021-04-07 19:16:18 +0200350 sig[10]--;
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200351
TRodziewicz40de3c92021-04-07 19:16:18 +0200352 /* try modifying s */
353 sig[sig_len - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
355 sig, sig_len) == MBEDTLS_ERR_ECP_VERIFY_FAILED);
TRodziewicz40de3c92021-04-07 19:16:18 +0200356 sig[sig_len - 1]--;
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200357
Paul Bakkerbd51b262014-07-10 15:26:12 +0200358exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100359 mbedtls_ecdsa_free(&ctx);
Manuel Pégourié-Gonnard91cc8bb2023-03-20 11:02:12 +0100360 MD_PSA_DONE();
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200361}
362/* END_CASE */
Manuel Pégourié-Gonnard937340b2014-01-06 10:27:16 +0100363
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200364/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100365void ecdsa_read_restart(int id, data_t *pk, data_t *hash, data_t *sig,
366 int max_ops, int min_restart, int max_restart)
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200367{
368 mbedtls_ecdsa_context ctx;
369 mbedtls_ecdsa_restart_ctx rs_ctx;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200370 int ret, cnt_restart;
371
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 mbedtls_ecdsa_init(&ctx);
373 mbedtls_ecdsa_restart_init(&rs_ctx);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200374
Gilles Peskine449bd832023-01-11 14:50:10 +0100375 TEST_ASSERT(mbedtls_ecp_group_load(&ctx.grp, id) == 0);
376 TEST_ASSERT(mbedtls_ecp_point_read_binary(&ctx.grp, &ctx.Q,
377 pk->x, pk->len) == 0);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200378
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 mbedtls_ecp_set_max_ops(max_ops);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200380
381 cnt_restart = 0;
382 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
384 hash->x, hash->len, sig->x, sig->len,
385 &rs_ctx);
386 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200387
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 TEST_ASSERT(ret == 0);
389 TEST_ASSERT(cnt_restart >= min_restart);
390 TEST_ASSERT(cnt_restart <= max_restart);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200391
392 /* try modifying r */
Ronald Cron9ed40732020-06-25 09:03:34 +0200393
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 TEST_ASSERT(sig->len > 10);
Ronald Cron9ed40732020-06-25 09:03:34 +0200395 sig->x[10]++;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200396 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
398 hash->x, hash->len, sig->x, sig->len,
399 &rs_ctx);
400 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
401 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_VERIFY_FAILED);
Ronald Cron9ed40732020-06-25 09:03:34 +0200402 sig->x[10]--;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200403
404 /* try modifying s */
Ronald Cron9ed40732020-06-25 09:03:34 +0200405 sig->x[sig->len - 1]++;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200406 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100407 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
408 hash->x, hash->len, sig->x, sig->len,
409 &rs_ctx);
410 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
411 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_VERIFY_FAILED);
Ronald Cron9ed40732020-06-25 09:03:34 +0200412 sig->x[sig->len - 1]--;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200413
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200414 /* Do we leak memory when aborting an operation?
415 * This test only makes sense when we actually restart */
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 if (min_restart > 0) {
417 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
418 hash->x, hash->len, sig->x, sig->len,
419 &rs_ctx);
420 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200421 }
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200422
423exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 mbedtls_ecdsa_free(&ctx);
425 mbedtls_ecdsa_restart_free(&rs_ctx);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200426}
427/* END_CASE */
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200428
429/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE:MBEDTLS_ECDSA_DETERMINISTIC */
Gilles Peskine449bd832023-01-11 14:50:10 +0100430void ecdsa_write_restart(int id, char *d_str, int md_alg,
431 data_t *hash, data_t *sig_check,
432 int max_ops, int min_restart, int max_restart)
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200433{
434 int ret, cnt_restart;
435 mbedtls_ecdsa_restart_ctx rs_ctx;
436 mbedtls_ecdsa_context ctx;
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200437 unsigned char sig[MBEDTLS_ECDSA_MAX_LEN];
Neil Armstrong5ea65172022-07-19 16:54:28 +0200438 size_t slen;
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200439
Manuel Pégourié-Gonnard91cc8bb2023-03-20 11:02:12 +0100440 MD_PSA_INIT();
441
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 mbedtls_ecdsa_restart_init(&rs_ctx);
443 mbedtls_ecdsa_init(&ctx);
444 memset(sig, 0, sizeof(sig));
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200445
Gilles Peskine449bd832023-01-11 14:50:10 +0100446 TEST_ASSERT(mbedtls_ecp_group_load(&ctx.grp, id) == 0);
447 TEST_ASSERT(mbedtls_test_read_mpi(&ctx.d, d_str) == 0);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200448
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 mbedtls_ecp_set_max_ops(max_ops);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200450
Gilles Peskine449bd832023-01-11 14:50:10 +0100451 slen = sizeof(sig);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200452 cnt_restart = 0;
453 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100454 ret = mbedtls_ecdsa_write_signature_restartable(&ctx,
455 md_alg,
456 hash->x,
457 hash->len,
458 sig,
459 sizeof(sig),
460 &slen,
461 mbedtls_test_rnd_std_rand,
462 NULL,
463 &rs_ctx);
464 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200465
Gilles Peskine449bd832023-01-11 14:50:10 +0100466 TEST_ASSERT(ret == 0);
467 TEST_ASSERT(slen == sig_check->len);
468 TEST_ASSERT(memcmp(sig, sig_check->x, slen) == 0);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200469
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 TEST_ASSERT(cnt_restart >= min_restart);
471 TEST_ASSERT(cnt_restart <= max_restart);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200472
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200473 /* Do we leak memory when aborting an operation?
474 * This test only makes sense when we actually restart */
Gilles Peskine449bd832023-01-11 14:50:10 +0100475 if (min_restart > 0) {
476 ret = mbedtls_ecdsa_write_signature_restartable(&ctx,
477 md_alg,
478 hash->x,
479 hash->len,
480 sig,
481 sizeof(sig),
482 &slen,
483 mbedtls_test_rnd_std_rand,
484 NULL,
485 &rs_ctx);
486 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200487 }
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200488
489exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100490 mbedtls_ecdsa_restart_free(&rs_ctx);
491 mbedtls_ecdsa_free(&ctx);
Manuel Pégourié-Gonnard91cc8bb2023-03-20 11:02:12 +0100492 MD_PSA_DONE();
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200493}
494/* END_CASE */
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100495
496/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100497void 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 +0100498{
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100499 mbedtls_ecdsa_context ctx;
500 mbedtls_mpi sig_r, sig_s;
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 mbedtls_ecdsa_init(&ctx);
503 mbedtls_mpi_init(&sig_r);
504 mbedtls_mpi_init(&sig_s);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100505
506 /* Prepare ECP group context */
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 TEST_EQUAL(mbedtls_ecp_group_load(&ctx.grp, grp_id), 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100508
509 /* Prepare public key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100510 TEST_EQUAL(mbedtls_test_read_mpi(&ctx.Q.X, x), 0);
511 TEST_EQUAL(mbedtls_test_read_mpi(&ctx.Q.Y, y), 0);
512 TEST_EQUAL(mbedtls_mpi_lset(&ctx.Q.Z, 1), 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100513
514 /* Prepare signature R & S */
Gilles Peskine449bd832023-01-11 14:50:10 +0100515 TEST_EQUAL(mbedtls_test_read_mpi(&sig_r, r), 0);
516 TEST_EQUAL(mbedtls_test_read_mpi(&sig_s, s), 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100517
518 /* Test whether public key has expected validity */
Gilles Peskine449bd832023-01-11 14:50:10 +0100519 TEST_EQUAL(mbedtls_ecp_check_pubkey(&ctx.grp, &ctx.Q),
520 expected == MBEDTLS_ERR_ECP_INVALID_KEY ? MBEDTLS_ERR_ECP_INVALID_KEY : 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100521
522 /* Verification */
Gilles Peskine449bd832023-01-11 14:50:10 +0100523 int result = mbedtls_ecdsa_verify(&ctx.grp, content->x, content->len, &ctx.Q, &sig_r, &sig_s);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100524
Gilles Peskine449bd832023-01-11 14:50:10 +0100525 TEST_EQUAL(result, expected);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100526exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100527 mbedtls_ecdsa_free(&ctx);
528 mbedtls_mpi_free(&sig_r);
529 mbedtls_mpi_free(&sig_s);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100530}
Dave Rodgman56cfb312022-08-10 12:21:23 +0100531/* END_CASE */