blob: c81501c4d5e052bf012802728a54454ea10bf3be [file] [log] [blame]
Raef Coles8ff6df52021-07-21 12:42:15 +01001/* BEGIN_HEADER */
Raef Coles7dce69a2022-08-24 14:07:06 +01002#include "lmots.h"
3#include "mbedtls/lms.h"
4
Raef Coles9c9027b2022-09-02 18:26:31 +01005#if defined(MBEDTLS_TEST_HOOKS)
Gilles Peskine449bd832023-01-11 14:50:10 +01006int check_lmots_private_key_for_leak(unsigned char *sig)
Raef Coles9c9027b2022-09-02 18:26:31 +01007{
8 size_t idx;
9
Gilles Peskine449bd832023-01-11 14:50:10 +010010 for (idx = MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(MBEDTLS_LMOTS_SHA256_N32_W8);
Raef Coles9c9027b2022-09-02 18:26:31 +010011 idx < MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8);
Gilles Peskine449bd832023-01-11 14:50:10 +010012 idx++) {
13 TEST_EQUAL(sig[idx], 0x7E);
Raef Coles9c9027b2022-09-02 18:26:31 +010014 }
15
Gilles Peskine449bd832023-01-11 14:50:10 +010016 return 0;
Raef Coles781f7be2022-10-13 09:23:11 +010017
18exit:
Gilles Peskine449bd832023-01-11 14:50:10 +010019 return -1;
Raef Coles9c9027b2022-09-02 18:26:31 +010020}
21#endif /* defined(MBEDTLS_TEST_HOOKS) */
22
Raef Coles8ff6df52021-07-21 12:42:15 +010023/* END_HEADER */
24
25/* BEGIN_DEPENDENCIES
Raef Coles1b43a742022-10-13 09:44:27 +010026 * depends_on:MBEDTLS_LMS_C
Raef Coles8ff6df52021-07-21 12:42:15 +010027 * END_DEPENDENCIES
28 */
29
Raef Coles5127e852022-10-07 10:35:56 +010030/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */
Gilles Peskine449bd832023-01-11 14:50:10 +010031void lmots_sign_verify_test(data_t *msg, data_t *key_id, int leaf_id,
32 data_t *seed)
Raef Coles8ff6df52021-07-21 12:42:15 +010033{
Raef Coles01c71a12022-08-31 15:55:00 +010034 mbedtls_lmots_public_t pub_ctx;
35 mbedtls_lmots_private_t priv_ctx;
Raef Colese9479a02022-09-01 16:06:35 +010036 unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)];
Raef Coles8ff6df52021-07-21 12:42:15 +010037
Gilles Peskine449bd832023-01-11 14:50:10 +010038 mbedtls_lmots_public_init(&pub_ctx);
39 mbedtls_lmots_private_init(&priv_ctx);
Valerio Setti84733902024-06-27 08:05:09 +020040 USE_PSA_INIT();
Raef Coles8ff6df52021-07-21 12:42:15 +010041
Gilles Peskine449bd832023-01-11 14:50:10 +010042 TEST_EQUAL(mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8,
43 key_id->x, leaf_id, seed->x, seed->len), 0);
44 TEST_EQUAL(mbedtls_lmots_calculate_public_key(&pub_ctx, &priv_ctx), 0);
45 TEST_EQUAL(mbedtls_lmots_sign(&priv_ctx, &mbedtls_test_rnd_std_rand, NULL,
46 msg->x, msg->len, sig, sizeof(sig), NULL), 0);
47 TEST_EQUAL(mbedtls_lmots_verify(&pub_ctx, msg->x, msg->len, sig, sizeof(sig)), 0);
Raef Coles8ff6df52021-07-21 12:42:15 +010048
49exit:
Gilles Peskine449bd832023-01-11 14:50:10 +010050 mbedtls_lmots_public_free(&pub_ctx);
51 mbedtls_lmots_private_free(&priv_ctx);
Valerio Setti84733902024-06-27 08:05:09 +020052 USE_PSA_DONE();
Raef Coles8ff6df52021-07-21 12:42:15 +010053}
54/* END_CASE */
55
Raef Coles5127e852022-10-07 10:35:56 +010056/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */
Gilles Peskine449bd832023-01-11 14:50:10 +010057void lmots_sign_verify_null_msg_test(data_t *key_id, int leaf_id, data_t *seed)
Raef Coles9c9027b2022-09-02 18:26:31 +010058{
59 mbedtls_lmots_public_t pub_ctx;
60 mbedtls_lmots_private_t priv_ctx;
61 unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)];
62
Gilles Peskine449bd832023-01-11 14:50:10 +010063 mbedtls_lmots_public_init(&pub_ctx);
64 mbedtls_lmots_private_init(&priv_ctx);
Valerio Setti84733902024-06-27 08:05:09 +020065 USE_PSA_INIT();
Raef Coles9c9027b2022-09-02 18:26:31 +010066
Gilles Peskine449bd832023-01-11 14:50:10 +010067 TEST_EQUAL(mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8,
68 key_id->x, leaf_id, seed->x, seed->len), 0);
69 TEST_EQUAL(mbedtls_lmots_calculate_public_key(&pub_ctx, &priv_ctx), 0);
70 TEST_EQUAL(mbedtls_lmots_sign(&priv_ctx, &mbedtls_test_rnd_std_rand, NULL,
71 NULL, 0, sig, sizeof(sig), NULL), 0);
72 TEST_EQUAL(mbedtls_lmots_verify(&pub_ctx, NULL, 0, sig, sizeof(sig)), 0);
Raef Coles9c9027b2022-09-02 18:26:31 +010073
74exit:
Gilles Peskine449bd832023-01-11 14:50:10 +010075 mbedtls_lmots_public_free(&pub_ctx);
76 mbedtls_lmots_private_free(&priv_ctx);
Valerio Setti84733902024-06-27 08:05:09 +020077 USE_PSA_DONE();
Raef Coles9c9027b2022-09-02 18:26:31 +010078}
79/* END_CASE */
80
81/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +010082void lmots_verify_test(data_t *msg, data_t *sig, data_t *pub_key,
83 int expected_rc)
Raef Coles8ff6df52021-07-21 12:42:15 +010084{
Raef Coles01c71a12022-08-31 15:55:00 +010085 mbedtls_lmots_public_t ctx;
Raef Coles0dc604e2022-10-10 17:35:26 +010086 unsigned int size;
87 unsigned char *tmp_sig = NULL;
Raef Coles8ff6df52021-07-21 12:42:15 +010088
Gilles Peskine449bd832023-01-11 14:50:10 +010089 mbedtls_lmots_public_init(&ctx);
Valerio Setti84733902024-06-27 08:05:09 +020090 USE_PSA_INIT();
Raef Coles8ff6df52021-07-21 12:42:15 +010091
Gilles Peskine449bd832023-01-11 14:50:10 +010092 TEST_EQUAL(mbedtls_lmots_import_public_key(&ctx, pub_key->x, pub_key->len), 0);
Raef Coles8ff6df52021-07-21 12:42:15 +010093
Gilles Peskine449bd832023-01-11 14:50:10 +010094 TEST_EQUAL(mbedtls_lmots_verify(&ctx, msg->x, msg->len, sig->x, sig->len), expected_rc);
Raef Coles0dc604e2022-10-10 17:35:26 +010095
96 /* Test negative cases if the input data is valid */
Gilles Peskine449bd832023-01-11 14:50:10 +010097 if (expected_rc == 0) {
98 if (msg->len >= 1) {
Raef Coles8b55ba62022-10-12 09:28:26 +010099 /* Altering first message byte must cause verification failure */
100 msg->x[0] ^= 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100101 TEST_EQUAL(mbedtls_lmots_verify(&ctx, msg->x, msg->len, sig->x, sig->len),
Raef Coles8b55ba62022-10-12 09:28:26 +0100102 MBEDTLS_ERR_LMS_VERIFY_FAILED);
103 msg->x[0] ^= 1;
Raef Coles0dc604e2022-10-10 17:35:26 +0100104
Raef Coles8b55ba62022-10-12 09:28:26 +0100105 /* Altering last message byte must cause verification failure */
106 msg->x[msg->len - 1] ^= 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100107 TEST_EQUAL(mbedtls_lmots_verify(&ctx, msg->x, msg->len, sig->x, sig->len),
Raef Coles8b55ba62022-10-12 09:28:26 +0100108 MBEDTLS_ERR_LMS_VERIFY_FAILED);
109 msg->x[msg->len - 1] ^= 1;
110 }
Raef Coles0dc604e2022-10-10 17:35:26 +0100111
112 /* Altering first signature byte must cause verification failure */
113 sig->x[0] ^= 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 TEST_EQUAL(mbedtls_lmots_verify(&ctx, msg->x, msg->len, sig->x, sig->len),
Raef Coles0dc604e2022-10-10 17:35:26 +0100115 MBEDTLS_ERR_LMS_VERIFY_FAILED);
116 sig->x[0] ^= 1;
117
Raef Coles0dc604e2022-10-10 17:35:26 +0100118 /* Altering last signature byte must cause verification failure */
119 sig->x[sig->len - 1] ^= 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100120 TEST_EQUAL(mbedtls_lmots_verify(&ctx, msg->x, msg->len, sig->x, sig->len),
Raef Coles0dc604e2022-10-10 17:35:26 +0100121 MBEDTLS_ERR_LMS_VERIFY_FAILED);
122 sig->x[sig->len - 1] ^= 1;
123
124 /* Signatures of all sizes must not verify, whether shorter or longer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100125 for (size = 0; size < sig->len; size++) {
126 if (size == sig->len) {
Raef Coles0dc604e2022-10-10 17:35:26 +0100127 continue;
Gilles Peskine449bd832023-01-11 14:50:10 +0100128 }
Raef Coles0dc604e2022-10-10 17:35:26 +0100129
Tom Cosgrove05b2a872023-07-21 11:31:13 +0100130 TEST_CALLOC(tmp_sig, size);
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 if (tmp_sig != NULL) {
132 memcpy(tmp_sig, sig->x, MIN(size, sig->len));
133 }
Raef Coles0dc604e2022-10-10 17:35:26 +0100134
Gilles Peskine449bd832023-01-11 14:50:10 +0100135 TEST_EQUAL(mbedtls_lmots_verify(&ctx, msg->x, msg->len, tmp_sig, size),
Raef Coles0dc604e2022-10-10 17:35:26 +0100136 MBEDTLS_ERR_LMS_VERIFY_FAILED);
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 mbedtls_free(tmp_sig);
Raef Coles0dc604e2022-10-10 17:35:26 +0100138 tmp_sig = NULL;
139 }
140 }
Raef Coles8ff6df52021-07-21 12:42:15 +0100141
142exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100143 mbedtls_free(tmp_sig);
144 mbedtls_lmots_public_free(&ctx);
Valerio Setti84733902024-06-27 08:05:09 +0200145 USE_PSA_DONE();
Raef Coles8ff6df52021-07-21 12:42:15 +0100146}
147/* END_CASE */
148
Raef Coles370cc432022-10-07 16:07:33 +0100149/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100150void lmots_import_export_test(data_t *pub_key, int expected_import_rc)
Raef Coles8ff6df52021-07-21 12:42:15 +0100151{
Raef Coles01c71a12022-08-31 15:55:00 +0100152 mbedtls_lmots_public_t ctx;
Raef Coles66edf6a2022-10-12 09:36:58 +0100153 unsigned char *exported_pub_key = NULL;
154 size_t exported_pub_key_buf_size;
155 size_t exported_pub_key_size;
Raef Coles8ff6df52021-07-21 12:42:15 +0100156
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 mbedtls_lmots_public_init(&ctx);
Valerio Setti84733902024-06-27 08:05:09 +0200158 USE_PSA_INIT();
159
Gilles Peskine449bd832023-01-11 14:50:10 +0100160 TEST_EQUAL(mbedtls_lmots_import_public_key(&ctx, pub_key->x, pub_key->len),
161 expected_import_rc);
Raef Coles8ff6df52021-07-21 12:42:15 +0100162
Gilles Peskine449bd832023-01-11 14:50:10 +0100163 if (expected_import_rc == 0) {
Raef Coles66edf6a2022-10-12 09:36:58 +0100164 exported_pub_key_buf_size = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8);
Tom Cosgrove05b2a872023-07-21 11:31:13 +0100165 TEST_CALLOC(exported_pub_key, exported_pub_key_buf_size);
Raef Coles66edf6a2022-10-12 09:36:58 +0100166
Gilles Peskine449bd832023-01-11 14:50:10 +0100167 TEST_EQUAL(mbedtls_lmots_export_public_key(&ctx, exported_pub_key,
Raef Coles66edf6a2022-10-12 09:36:58 +0100168 exported_pub_key_buf_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100169 &exported_pub_key_size), 0);
Raef Coles66edf6a2022-10-12 09:36:58 +0100170
Gilles Peskine449bd832023-01-11 14:50:10 +0100171 TEST_EQUAL(exported_pub_key_size,
172 MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8));
Tom Cosgrovee4e9e7d2023-07-21 11:40:20 +0100173 TEST_MEMORY_COMPARE(pub_key->x, pub_key->len,
Tom Cosgrove0540fe72023-07-27 14:17:27 +0100174 exported_pub_key, exported_pub_key_size);
Raef Coles66edf6a2022-10-12 09:36:58 +0100175 mbedtls_free(exported_pub_key);
176 exported_pub_key = NULL;
177
178 /* Export into too-small buffer should fail */
179 exported_pub_key_buf_size = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) - 1;
Tom Cosgrove05b2a872023-07-21 11:31:13 +0100180 TEST_CALLOC(exported_pub_key, exported_pub_key_buf_size);
Gilles Peskine449bd832023-01-11 14:50:10 +0100181 TEST_EQUAL(mbedtls_lmots_export_public_key(&ctx, exported_pub_key,
182 exported_pub_key_buf_size, NULL),
183 MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL);
Raef Coles66edf6a2022-10-12 09:36:58 +0100184 mbedtls_free(exported_pub_key);
185 exported_pub_key = NULL;
Raef Coles6b2c5732022-10-13 09:41:39 +0100186
187 /* Export into too-large buffer should succeed */
188 exported_pub_key_buf_size = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) + 1;
Tom Cosgrove05b2a872023-07-21 11:31:13 +0100189 TEST_CALLOC(exported_pub_key, exported_pub_key_buf_size);
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 TEST_EQUAL(mbedtls_lmots_export_public_key(&ctx, exported_pub_key,
Raef Coles6d7d94a2022-10-13 17:55:46 +0100191 exported_pub_key_buf_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100192 &exported_pub_key_size),
193 0);
Tom Cosgrovee4e9e7d2023-07-21 11:40:20 +0100194 TEST_MEMORY_COMPARE(pub_key->x, pub_key->len,
Tom Cosgrove0540fe72023-07-27 14:17:27 +0100195 exported_pub_key, exported_pub_key_size);
Raef Coles6b2c5732022-10-13 09:41:39 +0100196 mbedtls_free(exported_pub_key);
197 exported_pub_key = NULL;
Raef Coles66edf6a2022-10-12 09:36:58 +0100198 }
Raef Coles8ff6df52021-07-21 12:42:15 +0100199
200exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 mbedtls_lmots_public_free(&ctx);
202 mbedtls_free(exported_pub_key);
Valerio Setti84733902024-06-27 08:05:09 +0200203 USE_PSA_DONE();
Raef Coles8ff6df52021-07-21 12:42:15 +0100204}
205/* END_CASE */
206
Raef Coles5127e852022-10-07 10:35:56 +0100207/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100208void lmots_reuse_test(data_t *msg, data_t *key_id, int leaf_id, data_t *seed)
Raef Coles8ff6df52021-07-21 12:42:15 +0100209{
Raef Coles01c71a12022-08-31 15:55:00 +0100210 mbedtls_lmots_private_t ctx;
Raef Colese9479a02022-09-01 16:06:35 +0100211 unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)];
Raef Coles8ff6df52021-07-21 12:42:15 +0100212
Gilles Peskine449bd832023-01-11 14:50:10 +0100213 mbedtls_lmots_private_init(&ctx);
Valerio Setti84733902024-06-27 08:05:09 +0200214 USE_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100215 TEST_EQUAL(mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8,
216 key_id->x, leaf_id, seed->x,
217 seed->len), 0);
218 TEST_EQUAL(mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL,
219 msg->x, msg->len, sig, sizeof(sig), NULL), 0);
Raef Coles8ff6df52021-07-21 12:42:15 +0100220
221 /* Running another sign operation should fail, since the key should now have
222 * been erased.
223 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100224 TEST_EQUAL(mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL,
225 msg->x, msg->len, sig, sizeof(sig), NULL),
226 MBEDTLS_ERR_LMS_BAD_INPUT_DATA);
Raef Coles8ff6df52021-07-21 12:42:15 +0100227
228exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 mbedtls_lmots_private_free(&ctx);
Valerio Setti84733902024-06-27 08:05:09 +0200230 USE_PSA_DONE();
Raef Coles8ff6df52021-07-21 12:42:15 +0100231}
232/* END_CASE */
Raef Coles9c9027b2022-09-02 18:26:31 +0100233
Raef Coles59eb0d02022-10-12 15:19:17 +0100234/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:MBEDTLS_LMS_PRIVATE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100235void lmots_signature_leak_test(data_t *msg, data_t *key_id, int leaf_id,
236 data_t *seed)
Raef Coles9c9027b2022-09-02 18:26:31 +0100237{
238 mbedtls_lmots_private_t ctx;
239 unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)];
240
241 mbedtls_lmots_sign_private_key_invalidated_hook = &check_lmots_private_key_for_leak;
242
243 /* Fill with recognisable pattern */
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 memset(sig, 0x7E, sizeof(sig));
Raef Coles9c9027b2022-09-02 18:26:31 +0100245
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 mbedtls_lmots_private_init(&ctx);
Valerio Setti84733902024-06-27 08:05:09 +0200247 USE_PSA_INIT();
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 TEST_EQUAL(mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8,
249 key_id->x, leaf_id, seed->x,
250 seed->len), 0);
251 TEST_EQUAL(mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL,
252 msg->x, msg->len, sig, sizeof(sig), NULL), 0);
Raef Coles9c9027b2022-09-02 18:26:31 +0100253
254exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100255 mbedtls_lmots_private_free(&ctx);
Raef Coles9c9027b2022-09-02 18:26:31 +0100256 mbedtls_lmots_sign_private_key_invalidated_hook = NULL;
Valerio Setti84733902024-06-27 08:05:09 +0200257 USE_PSA_DONE();
Raef Coles9c9027b2022-09-02 18:26:31 +0100258}
259/* END_CASE */