blob: d9ff80219d8ce67c724e3fd9d3a375bbbeec1922 [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"
Paul Bakker33b43f12013-08-20 11:48:36 +02003/* END_HEADER */
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +01004
Paul Bakker33b43f12013-08-20 11:48:36 +02005/* BEGIN_DEPENDENCIES
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02006 * depends_on:MBEDTLS_ECDSA_C
Paul Bakker33b43f12013-08-20 11:48:36 +02007 * END_DEPENDENCIES
8 */
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +01009
Paul Bakker33b43f12013-08-20 11:48:36 +020010/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010011void ecdsa_prim_zero(int id)
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010012{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020013 mbedtls_ecp_group grp;
14 mbedtls_ecp_point Q;
15 mbedtls_mpi d, r, s;
Ronald Cron351f0ee2020-06-10 12:12:18 +020016 mbedtls_test_rnd_pseudo_info rnd_info;
Manuel Pégourié-Gonnard88579842023-03-28 11:20:23 +020017 unsigned char buf[MBEDTLS_MD_MAX_SIZE];
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010018
Gilles Peskine449bd832023-01-11 14:50:10 +010019 mbedtls_ecp_group_init(&grp);
20 mbedtls_ecp_point_init(&Q);
21 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
22 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
23 memset(buf, 0, sizeof(buf));
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010024
Gilles Peskine449bd832023-01-11 14:50:10 +010025 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
26 TEST_ASSERT(mbedtls_ecp_gen_keypair(&grp, &d, &Q,
27 &mbedtls_test_rnd_pseudo_rand,
28 &rnd_info) == 0);
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010029
Gilles Peskine449bd832023-01-11 14:50:10 +010030 TEST_ASSERT(mbedtls_ecdsa_sign(&grp, &r, &s, &d, buf, sizeof(buf),
31 &mbedtls_test_rnd_pseudo_rand,
32 &rnd_info) == 0);
33 TEST_ASSERT(mbedtls_ecdsa_verify(&grp, buf, sizeof(buf), &Q, &r, &s) == 0);
TRodziewicz5feb6702021-04-06 19:55:17 +020034
TRodziewicz40de3c92021-04-07 19:16:18 +020035exit:
Gilles Peskine449bd832023-01-11 14:50:10 +010036 mbedtls_ecp_group_free(&grp);
37 mbedtls_ecp_point_free(&Q);
38 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
TRodziewicz40de3c92021-04-07 19:16:18 +020039}
40/* END_CASE */
41
42/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010043void ecdsa_prim_random(int id)
TRodziewicz40de3c92021-04-07 19:16:18 +020044{
45 mbedtls_ecp_group grp;
46 mbedtls_ecp_point Q;
47 mbedtls_mpi d, r, s;
48 mbedtls_test_rnd_pseudo_info rnd_info;
Manuel Pégourié-Gonnard88579842023-03-28 11:20:23 +020049 unsigned char buf[MBEDTLS_MD_MAX_SIZE];
TRodziewicz40de3c92021-04-07 19:16:18 +020050
Gilles Peskine449bd832023-01-11 14:50:10 +010051 mbedtls_ecp_group_init(&grp);
52 mbedtls_ecp_point_init(&Q);
53 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
54 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
55 memset(buf, 0, sizeof(buf));
TRodziewicz40de3c92021-04-07 19:16:18 +020056
57 /* prepare material for signature */
Gilles Peskine449bd832023-01-11 14:50:10 +010058 TEST_ASSERT(mbedtls_test_rnd_pseudo_rand(&rnd_info,
59 buf, sizeof(buf)) == 0);
60 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
61 TEST_ASSERT(mbedtls_ecp_gen_keypair(&grp, &d, &Q,
62 &mbedtls_test_rnd_pseudo_rand,
63 &rnd_info) == 0);
TRodziewicz40de3c92021-04-07 19:16:18 +020064
Gilles Peskine449bd832023-01-11 14:50:10 +010065 TEST_ASSERT(mbedtls_ecdsa_sign(&grp, &r, &s, &d, buf, sizeof(buf),
66 &mbedtls_test_rnd_pseudo_rand,
67 &rnd_info) == 0);
68 TEST_ASSERT(mbedtls_ecdsa_verify(&grp, buf, sizeof(buf), &Q, &r, &s) == 0);
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010069
Paul Bakkerbd51b262014-07-10 15:26:12 +020070exit:
Gilles Peskine449bd832023-01-11 14:50:10 +010071 mbedtls_ecp_group_free(&grp);
72 mbedtls_ecp_point_free(&Q);
73 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
Manuel Pégourié-Gonnardd1c71502013-01-26 19:09:07 +010074}
Paul Bakker33b43f12013-08-20 11:48:36 +020075/* END_CASE */
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010076
Paul Bakker33b43f12013-08-20 11:48:36 +020077/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010078void ecdsa_prim_test_vectors(int id, char *d_str, char *xQ_str,
79 char *yQ_str, data_t *rnd_buf,
80 data_t *hash, char *r_str, char *s_str,
81 int result)
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010082{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083 mbedtls_ecp_group grp;
84 mbedtls_ecp_point Q;
Manuel Pégourié-Gonnardec528932022-04-21 09:25:23 +020085 mbedtls_mpi d, r, s, r_check, s_check, zero;
Ronald Cron351f0ee2020-06-10 12:12:18 +020086 mbedtls_test_rnd_buf_info rnd_info;
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010087
Gilles Peskine449bd832023-01-11 14:50:10 +010088 mbedtls_ecp_group_init(&grp);
89 mbedtls_ecp_point_init(&Q);
90 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
91 mbedtls_mpi_init(&r_check); mbedtls_mpi_init(&s_check);
92 mbedtls_mpi_init(&zero);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +010093
Gilles Peskine449bd832023-01-11 14:50:10 +010094 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
95 TEST_ASSERT(mbedtls_ecp_point_read_string(&Q, 16, xQ_str, yQ_str) == 0);
96 TEST_ASSERT(mbedtls_test_read_mpi(&d, d_str) == 0);
97 TEST_ASSERT(mbedtls_test_read_mpi(&r_check, r_str) == 0);
98 TEST_ASSERT(mbedtls_test_read_mpi(&s_check, s_str) == 0);
Gilles Peskineecacc3c2021-03-24 00:48:57 +010099 rnd_info.fallback_f_rng = mbedtls_test_rnd_std_rand;
100 rnd_info.fallback_p_rng = NULL;
Azim Khand30ca132017-06-09 04:32:58 +0100101 rnd_info.buf = rnd_buf->x;
102 rnd_info.length = rnd_buf->len;
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100103
Azim Khand30ca132017-06-09 04:32:58 +0100104 /* Fix rnd_buf->x by shifting it left if necessary */
Gilles Peskine449bd832023-01-11 14:50:10 +0100105 if (grp.nbits % 8 != 0) {
106 unsigned char shift = 8 - (grp.nbits % 8);
Manuel Pégourié-Gonnardfae079e2014-01-06 11:00:07 +0100107 size_t i;
108
Gilles Peskine449bd832023-01-11 14:50:10 +0100109 for (i = 0; i < rnd_info.length - 1; i++) {
110 rnd_buf->x[i] = rnd_buf->x[i] << shift | rnd_buf->x[i+1] >> (8 - shift);
111 }
Manuel Pégourié-Gonnardfae079e2014-01-06 11:00:07 +0100112
Azim Khand30ca132017-06-09 04:32:58 +0100113 rnd_buf->x[rnd_info.length-1] <<= shift;
Manuel Pégourié-Gonnardfae079e2014-01-06 11:00:07 +0100114 }
115
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 TEST_ASSERT(mbedtls_ecdsa_sign(&grp, &r, &s, &d, hash->x, hash->len,
117 mbedtls_test_rnd_buffer_rand, &rnd_info) == result);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100118
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 if (result == 0) {
Manuel Pégourié-Gonnardec528932022-04-21 09:25:23 +0200120 /* Check we generated the expected values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100121 TEST_EQUAL(mbedtls_mpi_cmp_mpi(&r, &r_check), 0);
122 TEST_EQUAL(mbedtls_mpi_cmp_mpi(&s, &s_check), 0);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100123
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200124 /* Valid signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100125 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len,
126 &Q, &r_check, &s_check), 0);
Manuel Pégourié-Gonnardd0a66cc2018-06-13 09:53:21 +0200127
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200128 /* Invalid signature: wrong public key (G instead of Q) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len,
130 &grp.G, &r_check, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd0a66cc2018-06-13 09:53:21 +0200131
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200132 /* Invalid signatures: r or s or both one off */
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 TEST_EQUAL(mbedtls_mpi_sub_int(&r, &r_check, 1), 0);
134 TEST_EQUAL(mbedtls_mpi_add_int(&s, &s_check, 1), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200135
Gilles Peskine449bd832023-01-11 14:50:10 +0100136 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
137 &r, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
138 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
139 &r_check, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
140 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
141 &r, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200142
143 /* Invalid signatures: r, s or both (CVE-2022-21449) are zero */
Gilles Peskine449bd832023-01-11 14:50:10 +0100144 TEST_EQUAL(mbedtls_mpi_lset(&zero, 0), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200145
Gilles Peskine449bd832023-01-11 14:50:10 +0100146 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
147 &zero, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
148 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
149 &r_check, &zero), MBEDTLS_ERR_ECP_VERIFY_FAILED);
150 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
151 &zero, &zero), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200152
153 /* Invalid signatures: r, s or both are == N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100154 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
155 &grp.N, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
156 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
157 &r_check, &grp.N), MBEDTLS_ERR_ECP_VERIFY_FAILED);
158 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
159 &grp.N, &grp.N), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardec528932022-04-21 09:25:23 +0200160
161 /* Invalid signatures: r, s or both are negative */
Gilles Peskine449bd832023-01-11 14:50:10 +0100162 TEST_EQUAL(mbedtls_mpi_sub_mpi(&r, &r_check, &grp.N), 0);
163 TEST_EQUAL(mbedtls_mpi_sub_mpi(&s, &s_check, &grp.N), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200164
Gilles Peskine449bd832023-01-11 14:50:10 +0100165 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
166 &r, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
167 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
168 &r_check, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
169 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
170 &r, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200171
172 /* Invalid signatures: r or s or both are > N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100173 TEST_EQUAL(mbedtls_mpi_add_mpi(&r, &r_check, &grp.N), 0);
174 TEST_EQUAL(mbedtls_mpi_add_mpi(&s, &s_check, &grp.N), 0);
Manuel Pégourié-Gonnardd8d19de2022-04-20 10:34:22 +0200175
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
177 &r, &s_check), MBEDTLS_ERR_ECP_VERIFY_FAILED);
178 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
179 &r_check, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
180 TEST_EQUAL(mbedtls_ecdsa_verify(&grp, hash->x, hash->len, &Q,
181 &r, &s), MBEDTLS_ERR_ECP_VERIFY_FAILED);
Darryl Greenf5bcbed2017-11-17 17:09:31 +0000182 }
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100183
Paul Bakkerbd51b262014-07-10 15:26:12 +0200184exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100185 mbedtls_ecp_group_free(&grp);
186 mbedtls_ecp_point_free(&Q);
187 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
188 mbedtls_mpi_free(&r_check); mbedtls_mpi_free(&s_check);
189 mbedtls_mpi_free(&zero);
Manuel Pégourié-Gonnard602a8972013-01-27 08:10:28 +0100190}
Paul Bakker33b43f12013-08-20 11:48:36 +0200191/* END_CASE */
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_DETERMINISTIC */
Gilles Peskine449bd832023-01-11 14:50:10 +0100194void ecdsa_det_test_vectors(int id, char *d_str, int md_alg, data_t *hash,
195 char *r_str, char *s_str)
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100196{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 mbedtls_ecp_group grp;
198 mbedtls_mpi d, r, s, r_check, s_check;
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 mbedtls_ecp_group_init(&grp);
200 mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
201 mbedtls_mpi_init(&r_check); mbedtls_mpi_init(&s_check);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100202
Gilles Peskine8369b4a2024-11-04 18:21:57 +0100203 MD_PSA_INIT();
204
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
206 TEST_ASSERT(mbedtls_test_read_mpi(&d, d_str) == 0);
207 TEST_ASSERT(mbedtls_test_read_mpi(&r_check, r_str) == 0);
208 TEST_ASSERT(mbedtls_test_read_mpi(&s_check, s_str) == 0);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100209
Janos Follath651eac82019-01-04 15:51:24 +0000210 TEST_ASSERT(
Gilles Peskine449bd832023-01-11 14:50:10 +0100211 mbedtls_ecdsa_sign_det_ext(&grp, &r, &s, &d,
212 hash->x, hash->len, md_alg,
213 mbedtls_test_rnd_std_rand,
214 NULL)
215 == 0);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100216
Gilles Peskine449bd832023-01-11 14:50:10 +0100217 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&r, &r_check) == 0);
218 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&s, &s_check) == 0);
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100219
Paul Bakkerbd51b262014-07-10 15:26:12 +0200220exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100221 mbedtls_ecp_group_free(&grp);
222 mbedtls_mpi_free(&d); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s);
223 mbedtls_mpi_free(&r_check); mbedtls_mpi_free(&s_check);
Manuel Pégourié-Gonnardebef58d2023-03-16 12:48:24 +0100224 MD_PSA_DONE();
Manuel Pégourié-Gonnard4daaef72014-01-06 14:25:56 +0100225}
226/* END_CASE */
227
Manuel Pégourié-Gonnardebef58d2023-03-16 12:48:24 +0100228/* BEGIN_CASE depends_on:MBEDTLS_MD_CAN_SHA256 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100229void ecdsa_write_read_zero(int id)
TRodziewicz40de3c92021-04-07 19:16:18 +0200230{
231 mbedtls_ecdsa_context ctx;
232 mbedtls_test_rnd_pseudo_info rnd_info;
233 unsigned char hash[32];
234 unsigned char sig[200];
235 size_t sig_len, i;
236
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 mbedtls_ecdsa_init(&ctx);
238 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
239 memset(hash, 0, sizeof(hash));
240 memset(sig, 0x2a, sizeof(sig));
TRodziewicz40de3c92021-04-07 19:16:18 +0200241
Gilles Peskine8369b4a2024-11-04 18:21:57 +0100242 MD_PSA_INIT();
243
TRodziewicz40de3c92021-04-07 19:16:18 +0200244 /* generate signing key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100245 TEST_ASSERT(mbedtls_ecdsa_genkey(&ctx, id,
246 &mbedtls_test_rnd_pseudo_rand,
247 &rnd_info) == 0);
TRodziewicz40de3c92021-04-07 19:16:18 +0200248
249 /* generate and write signature, then read and verify it */
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 TEST_ASSERT(mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256,
251 hash, sizeof(hash),
252 sig, sizeof(sig), &sig_len,
253 &mbedtls_test_rnd_pseudo_rand,
254 &rnd_info) == 0);
255 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
256 sig, sig_len) == 0);
TRodziewicz40de3c92021-04-07 19:16:18 +0200257
258 /* check we didn't write past the announced length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100259 for (i = sig_len; i < sizeof(sig); i++) {
260 TEST_ASSERT(sig[i] == 0x2a);
261 }
TRodziewicz40de3c92021-04-07 19:16:18 +0200262
263 /* try verification with invalid length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
265 sig, sig_len - 1) != 0);
266 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
267 sig, sig_len + 1) != 0);
TRodziewicz40de3c92021-04-07 19:16:18 +0200268
269 /* try invalid sequence tag */
270 sig[0]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
272 sig, sig_len) != 0);
TRodziewicz40de3c92021-04-07 19:16:18 +0200273 sig[0]--;
274
275 /* try modifying r */
276 sig[10]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100277 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
278 sig, sig_len) == MBEDTLS_ERR_ECP_VERIFY_FAILED);
TRodziewicz40de3c92021-04-07 19:16:18 +0200279 sig[10]--;
280
281 /* try modifying s */
282 sig[sig_len - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
284 sig, sig_len) == MBEDTLS_ERR_ECP_VERIFY_FAILED);
TRodziewicz40de3c92021-04-07 19:16:18 +0200285 sig[sig_len - 1]--;
286
287exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100288 mbedtls_ecdsa_free(&ctx);
Manuel Pégourié-Gonnard91cc8bb2023-03-20 11:02:12 +0100289 MD_PSA_DONE();
TRodziewicz40de3c92021-04-07 19:16:18 +0200290}
291/* END_CASE */
292
Manuel Pégourié-Gonnardebef58d2023-03-16 12:48:24 +0100293/* BEGIN_CASE depends_on:MBEDTLS_MD_CAN_SHA256 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100294void ecdsa_write_read_random(int id)
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200295{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296 mbedtls_ecdsa_context ctx;
Ronald Cron351f0ee2020-06-10 12:12:18 +0200297 mbedtls_test_rnd_pseudo_info rnd_info;
Manuel Pégourié-Gonnarddfdcac92015-03-31 11:41:42 +0200298 unsigned char hash[32];
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200299 unsigned char sig[200];
300 size_t sig_len, i;
301
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 mbedtls_ecdsa_init(&ctx);
303 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
304 memset(hash, 0, sizeof(hash));
305 memset(sig, 0x2a, sizeof(sig));
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200306
Gilles Peskine8369b4a2024-11-04 18:21:57 +0100307 MD_PSA_INIT();
308
TRodziewicz40de3c92021-04-07 19:16:18 +0200309 /* prepare material for signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 TEST_ASSERT(mbedtls_test_rnd_pseudo_rand(&rnd_info,
311 hash, sizeof(hash)) == 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200312
TRodziewicz40de3c92021-04-07 19:16:18 +0200313 /* generate signing key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 TEST_ASSERT(mbedtls_ecdsa_genkey(&ctx, id,
315 &mbedtls_test_rnd_pseudo_rand,
316 &rnd_info) == 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200317
TRodziewicz40de3c92021-04-07 19:16:18 +0200318 /* generate and write signature, then read and verify it */
Gilles Peskine449bd832023-01-11 14:50:10 +0100319 TEST_ASSERT(mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256,
320 hash, sizeof(hash),
321 sig, sizeof(sig), &sig_len,
322 &mbedtls_test_rnd_pseudo_rand,
323 &rnd_info) == 0);
324 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
325 sig, sig_len) == 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200326
TRodziewicz40de3c92021-04-07 19:16:18 +0200327 /* check we didn't write past the announced length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 for (i = sig_len; i < sizeof(sig); i++) {
329 TEST_ASSERT(sig[i] == 0x2a);
330 }
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200331
TRodziewicz40de3c92021-04-07 19:16:18 +0200332 /* try verification with invalid length */
Gilles Peskine449bd832023-01-11 14:50:10 +0100333 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
334 sig, sig_len - 1) != 0);
335 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
336 sig, sig_len + 1) != 0);
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200337
TRodziewicz40de3c92021-04-07 19:16:18 +0200338 /* try invalid sequence tag */
339 sig[0]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
341 sig, sig_len) != 0);
TRodziewicz40de3c92021-04-07 19:16:18 +0200342 sig[0]--;
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200343
TRodziewicz40de3c92021-04-07 19:16:18 +0200344 /* try modifying r */
345 sig[10]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
347 sig, sig_len) == MBEDTLS_ERR_ECP_VERIFY_FAILED);
TRodziewicz40de3c92021-04-07 19:16:18 +0200348 sig[10]--;
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200349
TRodziewicz40de3c92021-04-07 19:16:18 +0200350 /* try modifying s */
351 sig[sig_len - 1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 TEST_ASSERT(mbedtls_ecdsa_read_signature(&ctx, hash, sizeof(hash),
353 sig, sig_len) == MBEDTLS_ERR_ECP_VERIFY_FAILED);
TRodziewicz40de3c92021-04-07 19:16:18 +0200354 sig[sig_len - 1]--;
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200355
Paul Bakkerbd51b262014-07-10 15:26:12 +0200356exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100357 mbedtls_ecdsa_free(&ctx);
Manuel Pégourié-Gonnard91cc8bb2023-03-20 11:02:12 +0100358 MD_PSA_DONE();
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +0200359}
360/* END_CASE */
Manuel Pégourié-Gonnard937340b2014-01-06 10:27:16 +0100361
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200362/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100363void ecdsa_read_restart(int id, data_t *pk, data_t *hash, data_t *sig,
364 int max_ops, int min_restart, int max_restart)
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200365{
366 mbedtls_ecdsa_context ctx;
367 mbedtls_ecdsa_restart_ctx rs_ctx;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200368 int ret, cnt_restart;
369
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 mbedtls_ecdsa_init(&ctx);
371 mbedtls_ecdsa_restart_init(&rs_ctx);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200372
Gilles Peskine449bd832023-01-11 14:50:10 +0100373 TEST_ASSERT(mbedtls_ecp_group_load(&ctx.grp, id) == 0);
374 TEST_ASSERT(mbedtls_ecp_point_read_binary(&ctx.grp, &ctx.Q,
375 pk->x, pk->len) == 0);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200376
Gilles Peskine449bd832023-01-11 14:50:10 +0100377 mbedtls_ecp_set_max_ops(max_ops);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200378
379 cnt_restart = 0;
380 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100381 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
382 hash->x, hash->len, sig->x, sig->len,
383 &rs_ctx);
384 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200385
Gilles Peskine449bd832023-01-11 14:50:10 +0100386 TEST_ASSERT(ret == 0);
387 TEST_ASSERT(cnt_restart >= min_restart);
388 TEST_ASSERT(cnt_restart <= max_restart);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200389
390 /* try modifying r */
Ronald Cron9ed40732020-06-25 09:03:34 +0200391
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 TEST_ASSERT(sig->len > 10);
Ronald Cron9ed40732020-06-25 09:03:34 +0200393 sig->x[10]++;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200394 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100395 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
396 hash->x, hash->len, sig->x, sig->len,
397 &rs_ctx);
398 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
399 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_VERIFY_FAILED);
Ronald Cron9ed40732020-06-25 09:03:34 +0200400 sig->x[10]--;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200401
402 /* try modifying s */
Ronald Cron9ed40732020-06-25 09:03:34 +0200403 sig->x[sig->len - 1]++;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200404 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
406 hash->x, hash->len, sig->x, sig->len,
407 &rs_ctx);
408 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
409 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_VERIFY_FAILED);
Ronald Cron9ed40732020-06-25 09:03:34 +0200410 sig->x[sig->len - 1]--;
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200411
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200412 /* Do we leak memory when aborting an operation?
413 * This test only makes sense when we actually restart */
Gilles Peskine449bd832023-01-11 14:50:10 +0100414 if (min_restart > 0) {
415 ret = mbedtls_ecdsa_read_signature_restartable(&ctx,
416 hash->x, hash->len, sig->x, sig->len,
417 &rs_ctx);
418 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200419 }
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200420
421exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100422 mbedtls_ecdsa_free(&ctx);
423 mbedtls_ecdsa_restart_free(&rs_ctx);
Manuel Pégourié-Gonnard722e5152017-04-21 11:04:47 +0200424}
425/* END_CASE */
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200426
427/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE:MBEDTLS_ECDSA_DETERMINISTIC */
Gilles Peskine449bd832023-01-11 14:50:10 +0100428void ecdsa_write_restart(int id, char *d_str, int md_alg,
429 data_t *hash, data_t *sig_check,
430 int max_ops, int min_restart, int max_restart)
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200431{
432 int ret, cnt_restart;
433 mbedtls_ecdsa_restart_ctx rs_ctx;
434 mbedtls_ecdsa_context ctx;
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200435 unsigned char sig[MBEDTLS_ECDSA_MAX_LEN];
Neil Armstrong5ea65172022-07-19 16:54:28 +0200436 size_t slen;
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200437
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 mbedtls_ecdsa_restart_init(&rs_ctx);
439 mbedtls_ecdsa_init(&ctx);
440 memset(sig, 0, sizeof(sig));
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200441
Gilles Peskine8369b4a2024-11-04 18:21:57 +0100442 MD_PSA_INIT();
443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 TEST_ASSERT(mbedtls_ecp_group_load(&ctx.grp, id) == 0);
445 TEST_ASSERT(mbedtls_test_read_mpi(&ctx.d, d_str) == 0);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200446
Gilles Peskine449bd832023-01-11 14:50:10 +0100447 mbedtls_ecp_set_max_ops(max_ops);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200448
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 slen = sizeof(sig);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200450 cnt_restart = 0;
451 do {
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 ret = mbedtls_ecdsa_write_signature_restartable(&ctx,
453 md_alg,
454 hash->x,
455 hash->len,
456 sig,
457 sizeof(sig),
458 &slen,
459 mbedtls_test_rnd_std_rand,
460 NULL,
461 &rs_ctx);
462 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200463
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 TEST_ASSERT(ret == 0);
465 TEST_ASSERT(slen == sig_check->len);
466 TEST_ASSERT(memcmp(sig, sig_check->x, slen) == 0);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200467
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 TEST_ASSERT(cnt_restart >= min_restart);
469 TEST_ASSERT(cnt_restart <= max_restart);
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200470
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200471 /* Do we leak memory when aborting an operation?
472 * This test only makes sense when we actually restart */
Gilles Peskine449bd832023-01-11 14:50:10 +0100473 if (min_restart > 0) {
474 ret = mbedtls_ecdsa_write_signature_restartable(&ctx,
475 md_alg,
476 hash->x,
477 hash->len,
478 sig,
479 sizeof(sig),
480 &slen,
481 mbedtls_test_rnd_std_rand,
482 NULL,
483 &rs_ctx);
484 TEST_ASSERT(ret == MBEDTLS_ERR_ECP_IN_PROGRESS);
Manuel Pégourié-Gonnard46ba7f32017-08-28 12:20:39 +0200485 }
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200486
487exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100488 mbedtls_ecdsa_restart_free(&rs_ctx);
489 mbedtls_ecdsa_free(&ctx);
Manuel Pégourié-Gonnard91cc8bb2023-03-20 11:02:12 +0100490 MD_PSA_DONE();
Manuel Pégourié-Gonnardeb402f32017-04-25 10:57:30 +0200491}
492/* END_CASE */
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100493
494/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100495void 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 +0100496{
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100497 mbedtls_ecdsa_context ctx;
498 mbedtls_mpi sig_r, sig_s;
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100499
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 mbedtls_ecdsa_init(&ctx);
501 mbedtls_mpi_init(&sig_r);
502 mbedtls_mpi_init(&sig_s);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100503
504 /* Prepare ECP group context */
Gilles Peskine449bd832023-01-11 14:50:10 +0100505 TEST_EQUAL(mbedtls_ecp_group_load(&ctx.grp, grp_id), 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100506
507 /* Prepare public key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100508 TEST_EQUAL(mbedtls_test_read_mpi(&ctx.Q.X, x), 0);
509 TEST_EQUAL(mbedtls_test_read_mpi(&ctx.Q.Y, y), 0);
510 TEST_EQUAL(mbedtls_mpi_lset(&ctx.Q.Z, 1), 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100511
512 /* Prepare signature R & S */
Gilles Peskine449bd832023-01-11 14:50:10 +0100513 TEST_EQUAL(mbedtls_test_read_mpi(&sig_r, r), 0);
514 TEST_EQUAL(mbedtls_test_read_mpi(&sig_s, s), 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100515
516 /* Test whether public key has expected validity */
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 TEST_EQUAL(mbedtls_ecp_check_pubkey(&ctx.grp, &ctx.Q),
518 expected == MBEDTLS_ERR_ECP_INVALID_KEY ? MBEDTLS_ERR_ECP_INVALID_KEY : 0);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100519
520 /* Verification */
Gilles Peskine449bd832023-01-11 14:50:10 +0100521 int result = mbedtls_ecdsa_verify(&ctx.grp, content->x, content->len, &ctx.Q, &sig_r, &sig_s);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100522
Gilles Peskine449bd832023-01-11 14:50:10 +0100523 TEST_EQUAL(result, expected);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100524exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100525 mbedtls_ecdsa_free(&ctx);
526 mbedtls_mpi_free(&sig_r);
527 mbedtls_mpi_free(&sig_s);
Dave Rodgman1fdb8e82022-08-10 11:32:07 +0100528}
Dave Rodgman56cfb312022-08-10 12:21:23 +0100529/* END_CASE */