1/* BEGIN_HEADER */ 2#include "lmots.h" 3#include "mbedtls/lms.h" 4 5#if defined(MBEDTLS_TEST_HOOKS) 6int check_lmots_private_key_for_leak(unsigned char * sig) 7{ 8 size_t idx; 9 10 for( idx = MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(MBEDTLS_LMOTS_SHA256_N32_W8); 11 idx < MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8); 12 idx++ ) 13 { 14 TEST_EQUAL( sig[idx], 0x7E ); 15 } 16 17 return( 0 ); 18 19exit: 20 return( -1 ); 21} 22#endif /* defined(MBEDTLS_TEST_HOOKS) */ 23 24/* END_HEADER */ 25 26/* BEGIN_DEPENDENCIES 27 * depends_on:MBEDTLS_LMS_C 28 * END_DEPENDENCIES 29 */ 30 31/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ 32void lmots_sign_verify_test ( data_t *msg, data_t *key_id, int leaf_id, 33 data_t *seed ) 34{ 35 mbedtls_lmots_public_t pub_ctx; 36 mbedtls_lmots_private_t priv_ctx; 37 unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; 38 39 mbedtls_lmots_public_init( &pub_ctx ); 40 mbedtls_lmots_private_init( &priv_ctx ); 41 42 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 ); 48 49exit: 50 mbedtls_lmots_public_free( &pub_ctx ); 51 mbedtls_lmots_private_free( &priv_ctx ); 52} 53/* END_CASE */ 54 55/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ 56void lmots_sign_verify_null_msg_test ( data_t *key_id, int leaf_id, data_t *seed ) 57{ 58 mbedtls_lmots_public_t pub_ctx; 59 mbedtls_lmots_private_t priv_ctx; 60 unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; 61 62 mbedtls_lmots_public_init( &pub_ctx ); 63 mbedtls_lmots_private_init( &priv_ctx ); 64 65 TEST_EQUAL( mbedtls_lmots_generate_private_key(&priv_ctx, MBEDTLS_LMOTS_SHA256_N32_W8, 66 key_id->x, leaf_id, seed->x, seed->len ), 0 ); 67 TEST_EQUAL( mbedtls_lmots_calculate_public_key(&pub_ctx, &priv_ctx), 0 ); 68 TEST_EQUAL( mbedtls_lmots_sign(&priv_ctx, &mbedtls_test_rnd_std_rand, NULL, 69 NULL, 0, sig, sizeof(sig), NULL ), 0 ); 70 TEST_EQUAL( mbedtls_lmots_verify(&pub_ctx, NULL, 0, sig, sizeof(sig)), 0 ); 71 72exit: 73 mbedtls_lmots_public_free( &pub_ctx ); 74 mbedtls_lmots_private_free( &priv_ctx ); 75} 76/* END_CASE */ 77 78/* BEGIN_CASE */ 79void lmots_verify_test ( data_t *msg, data_t *sig, data_t *pub_key, 80 int expected_rc ) 81{ 82 mbedtls_lmots_public_t ctx; 83 unsigned int size; 84 unsigned char *tmp_sig = NULL; 85 86 mbedtls_lmots_public_init( &ctx ); 87 88 TEST_EQUAL(mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ), 0); 89 90 TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), expected_rc); 91 92 /* Test negative cases if the input data is valid */ 93 if( expected_rc == 0 ) 94 { 95 if( msg->len >= 1 ) 96 { 97 /* Altering first message byte must cause verification failure */ 98 msg->x[0] ^= 1; 99 TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), 100 MBEDTLS_ERR_LMS_VERIFY_FAILED); 101 msg->x[0] ^= 1; 102 103 /* Altering last message byte must cause verification failure */ 104 msg->x[msg->len - 1] ^= 1; 105 TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), 106 MBEDTLS_ERR_LMS_VERIFY_FAILED); 107 msg->x[msg->len - 1] ^= 1; 108 } 109 110 /* Altering first signature byte must cause verification failure */ 111 sig->x[0] ^= 1; 112 TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), 113 MBEDTLS_ERR_LMS_VERIFY_FAILED); 114 sig->x[0] ^= 1; 115 116 /* Altering last signature byte must cause verification failure */ 117 sig->x[sig->len - 1] ^= 1; 118 TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, sig->x, sig->len ), 119 MBEDTLS_ERR_LMS_VERIFY_FAILED); 120 sig->x[sig->len - 1] ^= 1; 121 122 /* Signatures of all sizes must not verify, whether shorter or longer */ 123 for( size = 0; size < sig->len; size++ ) { 124 if( size == sig->len ) 125 continue; 126 127 ASSERT_ALLOC( tmp_sig, size ); 128 if( tmp_sig != NULL ) 129 memcpy( tmp_sig, sig->x, MIN(size, sig->len) ); 130 131 TEST_EQUAL(mbedtls_lmots_verify( &ctx, msg->x, msg->len, tmp_sig, size ), 132 MBEDTLS_ERR_LMS_VERIFY_FAILED); 133 mbedtls_free( tmp_sig ); 134 tmp_sig = NULL; 135 } 136 } 137 138exit: 139 mbedtls_free( tmp_sig ); 140 mbedtls_lmots_public_free( &ctx ); 141} 142/* END_CASE */ 143 144/* BEGIN_CASE */ 145void lmots_import_export_test ( data_t * pub_key, int expected_import_rc ) 146{ 147 mbedtls_lmots_public_t ctx; 148 unsigned char *exported_pub_key = NULL; 149 size_t exported_pub_key_buf_size; 150 size_t exported_pub_key_size; 151 152 mbedtls_lmots_public_init( &ctx ); 153 TEST_EQUAL( mbedtls_lmots_import_public_key( &ctx, pub_key->x, pub_key->len ), 154 expected_import_rc ); 155 156 if( expected_import_rc == 0 ) 157 { 158 exported_pub_key_buf_size = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8); 159 ASSERT_ALLOC( exported_pub_key, exported_pub_key_buf_size ); 160 161 TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, 162 exported_pub_key_buf_size, 163 &exported_pub_key_size ), 0 ); 164 165 TEST_EQUAL( exported_pub_key_size, 166 MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) ); 167 ASSERT_COMPARE( pub_key->x, pub_key->len, 168 exported_pub_key, exported_pub_key_size ); 169 mbedtls_free(exported_pub_key); 170 exported_pub_key = NULL; 171 172 /* Export into too-small buffer should fail */ 173 exported_pub_key_buf_size = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) - 1; 174 ASSERT_ALLOC( exported_pub_key, exported_pub_key_buf_size); 175 TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, 176 exported_pub_key_buf_size, NULL ), 177 MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL ); 178 mbedtls_free(exported_pub_key); 179 exported_pub_key = NULL; 180 181 /* Export into too-large buffer should succeed */ 182 exported_pub_key_buf_size = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(MBEDTLS_LMOTS_SHA256_N32_W8) + 1; 183 ASSERT_ALLOC( exported_pub_key, exported_pub_key_buf_size); 184 TEST_EQUAL( mbedtls_lmots_export_public_key( &ctx, exported_pub_key, 185 exported_pub_key_buf_size, 186 &exported_pub_key_size ), 187 0 ); 188 ASSERT_COMPARE( pub_key->x, pub_key->len, 189 exported_pub_key, exported_pub_key_size ); 190 mbedtls_free(exported_pub_key); 191 exported_pub_key = NULL; 192 } 193 194exit: 195 mbedtls_lmots_public_free( &ctx ); 196 mbedtls_free( exported_pub_key ); 197} 198/* END_CASE */ 199 200/* BEGIN_CASE depends_on:MBEDTLS_LMS_PRIVATE */ 201void lmots_reuse_test ( data_t *msg, data_t *key_id, int leaf_id, data_t *seed ) 202{ 203 mbedtls_lmots_private_t ctx; 204 unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; 205 206 mbedtls_lmots_private_init( &ctx ); 207 TEST_EQUAL( mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8, 208 key_id->x, leaf_id, seed->x, 209 seed->len ), 0 ); 210 TEST_EQUAL( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, 211 msg->x, msg->len, sig, sizeof( sig ), NULL ), 0 ); 212 213 /* Running another sign operation should fail, since the key should now have 214 * been erased. 215 */ 216 TEST_EQUAL( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, 217 msg->x, msg->len, sig, sizeof( sig ), NULL ), MBEDTLS_ERR_LMS_BAD_INPUT_DATA ); 218 219exit: 220 mbedtls_lmots_private_free( &ctx ); 221} 222/* END_CASE */ 223 224/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:MBEDTLS_LMS_PRIVATE */ 225void lmots_signature_leak_test ( data_t *msg, data_t *key_id, int leaf_id, 226 data_t *seed ) 227{ 228 mbedtls_lmots_private_t ctx; 229 unsigned char sig[MBEDTLS_LMOTS_SIG_LEN(MBEDTLS_LMOTS_SHA256_N32_W8)]; 230 231 mbedtls_lmots_sign_private_key_invalidated_hook = &check_lmots_private_key_for_leak; 232 233 /* Fill with recognisable pattern */ 234 memset( sig, 0x7E, sizeof( sig ) ); 235 236 mbedtls_lmots_private_init( &ctx ); 237 TEST_EQUAL( mbedtls_lmots_generate_private_key(&ctx, MBEDTLS_LMOTS_SHA256_N32_W8, 238 key_id->x, leaf_id, seed->x, 239 seed->len ), 0 ); 240 TEST_EQUAL( mbedtls_lmots_sign(&ctx, mbedtls_test_rnd_std_rand, NULL, 241 msg->x, msg->len, sig, sizeof( sig ), NULL ), 0 ); 242 243exit: 244 mbedtls_lmots_private_free( &ctx ); 245 mbedtls_lmots_sign_private_key_invalidated_hook = NULL; 246} 247/* END_CASE */ 248