Manuel Pégourié-Gonnard | 36178ff | 2014-05-29 14:26:03 +0200 | [diff] [blame] | 1 | /* BEGIN_HEADER */ |
Manuel Pégourié-Gonnard | 7f80997 | 2015-03-09 17:05:11 +0000 | [diff] [blame] | 2 | #include "mbedtls/asn1write.h" |
Manuel Pégourié-Gonnard | 36178ff | 2014-05-29 14:26:03 +0200 | [diff] [blame] | 3 | |
| 4 | #define GUARD_LEN 4 |
| 5 | #define GUARD_VAL 0x2a |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 6 | |
| 7 | typedef struct |
| 8 | { |
| 9 | unsigned char *output; |
| 10 | unsigned char *start; |
| 11 | unsigned char *end; |
| 12 | unsigned char *p; |
| 13 | size_t size; |
| 14 | } generic_write_data_t; |
| 15 | |
| 16 | int generic_write_start_step( generic_write_data_t *data ) |
| 17 | { |
Chris Jones | 9634bb1 | 2021-01-20 15:56:42 +0000 | [diff] [blame] | 18 | mbedtls_test_set_step( data->size ); |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 19 | mbedtls_free( data->output ); |
| 20 | data->output = NULL; |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 21 | ASSERT_ALLOC( data->output, data->size == 0 ? 1 : data->size ); |
| 22 | data->end = data->output + data->size; |
| 23 | data->p = data->end; |
| 24 | data->start = data->end - data->size; |
| 25 | return( 1 ); |
| 26 | exit: |
| 27 | return( 0 ); |
| 28 | } |
| 29 | |
| 30 | int generic_write_finish_step( generic_write_data_t *data, |
| 31 | const data_t *expected, int ret ) |
| 32 | { |
| 33 | int ok = 0; |
| 34 | |
| 35 | if( data->size < expected->len ) |
| 36 | { |
| 37 | TEST_EQUAL( ret, MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); |
| 38 | } |
| 39 | else |
| 40 | { |
| 41 | TEST_EQUAL( ret, data->end - data->p ); |
| 42 | TEST_ASSERT( data->p >= data->start ); |
| 43 | TEST_ASSERT( data->p <= data->end ); |
| 44 | ASSERT_COMPARE( data->p, (size_t)( data->end - data->p ), |
| 45 | expected->x, expected->len ); |
| 46 | } |
| 47 | ok = 1; |
| 48 | |
| 49 | exit: |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 50 | return( ok ); |
| 51 | } |
| 52 | |
Manuel Pégourié-Gonnard | 36178ff | 2014-05-29 14:26:03 +0200 | [diff] [blame] | 53 | /* END_HEADER */ |
| 54 | |
| 55 | /* BEGIN_DEPENDENCIES |
Manuel Pégourié-Gonnard | 2cf5a7c | 2015-04-08 12:49:31 +0200 | [diff] [blame] | 56 | * depends_on:MBEDTLS_ASN1_WRITE_C |
Manuel Pégourié-Gonnard | 36178ff | 2014-05-29 14:26:03 +0200 | [diff] [blame] | 57 | * END_DEPENDENCIES |
| 58 | */ |
| 59 | |
| 60 | /* BEGIN_CASE */ |
Gilles Peskine | 9311cf5 | 2019-03-01 20:05:05 +0100 | [diff] [blame] | 61 | void mbedtls_asn1_write_null( data_t *expected ) |
| 62 | { |
| 63 | generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 }; |
| 64 | int ret; |
| 65 | |
Gilles Peskine | 2c2730a | 2022-06-10 20:15:44 +0200 | [diff] [blame] | 66 | for( data.size = 0; data.size <= expected->len + 1; data.size++ ) |
Gilles Peskine | 9311cf5 | 2019-03-01 20:05:05 +0100 | [diff] [blame] | 67 | { |
| 68 | if( ! generic_write_start_step( &data ) ) |
| 69 | goto exit; |
| 70 | ret = mbedtls_asn1_write_null( &data.p, data.start ); |
| 71 | if( ! generic_write_finish_step( &data, expected, ret ) ) |
| 72 | goto exit; |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 73 | /* There's no parsing function for NULL. */ |
Gilles Peskine | 9311cf5 | 2019-03-01 20:05:05 +0100 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | exit: |
| 77 | mbedtls_free( data.output ); |
| 78 | } |
| 79 | /* END_CASE */ |
| 80 | |
| 81 | /* BEGIN_CASE */ |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 82 | void mbedtls_asn1_write_bool( int val, data_t *expected ) |
| 83 | { |
| 84 | generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 }; |
| 85 | int ret; |
| 86 | |
Gilles Peskine | 2c2730a | 2022-06-10 20:15:44 +0200 | [diff] [blame] | 87 | for( data.size = 0; data.size <= expected->len + 1; data.size++ ) |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 88 | { |
| 89 | if( ! generic_write_start_step( &data ) ) |
| 90 | goto exit; |
| 91 | ret = mbedtls_asn1_write_bool( &data.p, data.start, val ); |
| 92 | if( ! generic_write_finish_step( &data, expected, ret ) ) |
| 93 | goto exit; |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 94 | #if defined(MBEDTLS_ASN1_PARSE_C) |
| 95 | if( ret >= 0 ) |
| 96 | { |
| 97 | int read = 0xdeadbeef; |
| 98 | TEST_EQUAL( mbedtls_asn1_get_bool( &data.p, data.end, &read ), 0 ); |
| 99 | TEST_EQUAL( val, read ); |
| 100 | } |
| 101 | #endif /* MBEDTLS_ASN1_PARSE_C */ |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 102 | } |
| 103 | |
| 104 | exit: |
| 105 | mbedtls_free( data.output ); |
| 106 | } |
| 107 | /* END_CASE */ |
| 108 | |
| 109 | /* BEGIN_CASE */ |
| 110 | void mbedtls_asn1_write_int( int val, data_t *expected ) |
| 111 | { |
| 112 | generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 }; |
| 113 | int ret; |
| 114 | |
Gilles Peskine | 2c2730a | 2022-06-10 20:15:44 +0200 | [diff] [blame] | 115 | for( data.size = 0; data.size <= expected->len + 1; data.size++ ) |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 116 | { |
| 117 | if( ! generic_write_start_step( &data ) ) |
| 118 | goto exit; |
| 119 | ret = mbedtls_asn1_write_int( &data.p, data.start, val ); |
| 120 | if( ! generic_write_finish_step( &data, expected, ret ) ) |
| 121 | goto exit; |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 122 | #if defined(MBEDTLS_ASN1_PARSE_C) |
| 123 | if( ret >= 0 ) |
| 124 | { |
| 125 | int read = 0xdeadbeef; |
| 126 | TEST_EQUAL( mbedtls_asn1_get_int( &data.p, data.end, &read ), 0 ); |
| 127 | TEST_EQUAL( val, read ); |
| 128 | } |
| 129 | #endif /* MBEDTLS_ASN1_PARSE_C */ |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 130 | } |
| 131 | |
| 132 | exit: |
| 133 | mbedtls_free( data.output ); |
| 134 | } |
| 135 | /* END_CASE */ |
| 136 | |
Mykhailo Sopiha | 6af7bf9 | 2019-10-31 15:55:16 +0200 | [diff] [blame] | 137 | |
| 138 | /* BEGIN_CASE */ |
| 139 | void mbedtls_asn1_write_enum( int val, data_t *expected ) |
| 140 | { |
| 141 | generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 }; |
| 142 | int ret; |
| 143 | |
Gilles Peskine | 2c2730a | 2022-06-10 20:15:44 +0200 | [diff] [blame] | 144 | for( data.size = 0; data.size <= expected->len + 1; data.size++ ) |
Mykhailo Sopiha | 6af7bf9 | 2019-10-31 15:55:16 +0200 | [diff] [blame] | 145 | { |
| 146 | if( ! generic_write_start_step( &data ) ) |
| 147 | goto exit; |
| 148 | ret = mbedtls_asn1_write_enum( &data.p, data.start, val ); |
| 149 | if( ! generic_write_finish_step( &data, expected, ret ) ) |
| 150 | goto exit; |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 151 | #if defined(MBEDTLS_ASN1_PARSE_C) |
| 152 | if( ret >= 0 ) |
| 153 | { |
| 154 | int read = 0xdeadbeef; |
| 155 | TEST_EQUAL( mbedtls_asn1_get_enum( &data.p, data.end, &read ), 0 ); |
| 156 | TEST_EQUAL( val, read ); |
| 157 | } |
| 158 | #endif /* MBEDTLS_ASN1_PARSE_C */ |
Mykhailo Sopiha | 6af7bf9 | 2019-10-31 15:55:16 +0200 | [diff] [blame] | 159 | } |
| 160 | |
| 161 | exit: |
| 162 | mbedtls_free( data.output ); |
| 163 | } |
| 164 | /* END_CASE */ |
| 165 | |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 166 | /* BEGIN_CASE depends_on:MBEDTLS_BIGNUM_C */ |
| 167 | void mbedtls_asn1_write_mpi( data_t *val, data_t *expected ) |
| 168 | { |
| 169 | generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 }; |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 170 | mbedtls_mpi mpi, read; |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 171 | int ret; |
| 172 | |
| 173 | mbedtls_mpi_init( &mpi ); |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 174 | mbedtls_mpi_init( &read ); |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 175 | TEST_ASSERT( mbedtls_mpi_read_binary( &mpi, val->x, val->len ) == 0 ); |
| 176 | |
Gilles Peskine | 2c2730a | 2022-06-10 20:15:44 +0200 | [diff] [blame] | 177 | for( data.size = 0; data.size <= expected->len + 1; data.size++ ) |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 178 | { |
| 179 | if( ! generic_write_start_step( &data ) ) |
| 180 | goto exit; |
| 181 | ret = mbedtls_asn1_write_mpi( &data.p, data.start, &mpi ); |
| 182 | if( ! generic_write_finish_step( &data, expected, ret ) ) |
| 183 | goto exit; |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 184 | #if defined(MBEDTLS_ASN1_PARSE_C) |
| 185 | if( ret >= 0 ) |
| 186 | { |
| 187 | TEST_EQUAL( mbedtls_asn1_get_mpi( &data.p, data.end, &read ), 0 ); |
| 188 | TEST_EQUAL( 0, mbedtls_mpi_cmp_mpi( &mpi, &read ) ); |
| 189 | } |
| 190 | #endif /* MBEDTLS_ASN1_PARSE_C */ |
| 191 | /* Skip some intermediate lengths, they're boring. */ |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 192 | if( expected->len > 10 && data.size == 8 ) |
| 193 | data.size = expected->len - 2; |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 194 | } |
| 195 | |
| 196 | exit: |
| 197 | mbedtls_mpi_free( &mpi ); |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 198 | mbedtls_mpi_free( &read ); |
Gilles Peskine | 3a032c3 | 2019-03-01 18:13:36 +0100 | [diff] [blame] | 199 | mbedtls_free( data.output ); |
| 200 | } |
| 201 | /* END_CASE */ |
| 202 | |
| 203 | /* BEGIN_CASE */ |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 204 | void mbedtls_asn1_write_string( int tag, data_t *content, data_t *expected ) |
Manuel Pégourié-Gonnard | 36178ff | 2014-05-29 14:26:03 +0200 | [diff] [blame] | 205 | { |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 206 | generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 }; |
Manuel Pégourié-Gonnard | 36178ff | 2014-05-29 14:26:03 +0200 | [diff] [blame] | 207 | int ret; |
Manuel Pégourié-Gonnard | 36178ff | 2014-05-29 14:26:03 +0200 | [diff] [blame] | 208 | |
Gilles Peskine | 2c2730a | 2022-06-10 20:15:44 +0200 | [diff] [blame] | 209 | for( data.size = 0; data.size <= expected->len + 1; data.size++ ) |
Manuel Pégourié-Gonnard | 36178ff | 2014-05-29 14:26:03 +0200 | [diff] [blame] | 210 | { |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 211 | if( ! generic_write_start_step( &data ) ) |
| 212 | goto exit; |
| 213 | switch( tag ) |
| 214 | { |
| 215 | case MBEDTLS_ASN1_OCTET_STRING: |
| 216 | ret = mbedtls_asn1_write_octet_string( |
| 217 | &data.p, data.start, content->x, content->len ); |
| 218 | break; |
Gilles Peskine | 9311cf5 | 2019-03-01 20:05:05 +0100 | [diff] [blame] | 219 | case MBEDTLS_ASN1_OID: |
| 220 | ret = mbedtls_asn1_write_oid( |
| 221 | &data.p, data.start, |
| 222 | (const char *) content->x, content->len ); |
| 223 | break; |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 224 | case MBEDTLS_ASN1_UTF8_STRING: |
| 225 | ret = mbedtls_asn1_write_utf8_string( |
| 226 | &data.p, data.start, |
| 227 | (const char *) content->x, content->len ); |
| 228 | break; |
| 229 | case MBEDTLS_ASN1_PRINTABLE_STRING: |
| 230 | ret = mbedtls_asn1_write_printable_string( |
| 231 | &data.p, data.start, |
| 232 | (const char *) content->x, content->len ); |
| 233 | break; |
| 234 | case MBEDTLS_ASN1_IA5_STRING: |
| 235 | ret = mbedtls_asn1_write_ia5_string( |
| 236 | &data.p, data.start, |
| 237 | (const char *) content->x, content->len ); |
| 238 | break; |
| 239 | default: |
| 240 | ret = mbedtls_asn1_write_tagged_string( |
| 241 | &data.p, data.start, tag, |
| 242 | (const char *) content->x, content->len ); |
| 243 | } |
| 244 | if( ! generic_write_finish_step( &data, expected, ret ) ) |
| 245 | goto exit; |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 246 | /* There's no parsing function for octet or character strings. */ |
| 247 | /* Skip some intermediate lengths, they're boring. */ |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 248 | if( expected->len > 10 && data.size == 8 ) |
| 249 | data.size = expected->len - 2; |
Manuel Pégourié-Gonnard | 36178ff | 2014-05-29 14:26:03 +0200 | [diff] [blame] | 250 | } |
| 251 | |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 252 | exit: |
| 253 | mbedtls_free( data.output ); |
Manuel Pégourié-Gonnard | c22bb49 | 2014-05-29 17:16:45 +0200 | [diff] [blame] | 254 | } |
| 255 | /* END_CASE */ |
Paul Bakker | e325db9 | 2016-07-14 10:27:36 +0100 | [diff] [blame] | 256 | |
Gilles Peskine | 9311cf5 | 2019-03-01 20:05:05 +0100 | [diff] [blame] | 257 | /* BEGIN_CASE */ |
| 258 | void mbedtls_asn1_write_algorithm_identifier( data_t *oid, |
| 259 | int par_len, |
| 260 | data_t *expected ) |
| 261 | { |
| 262 | generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 }; |
| 263 | int ret; |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 264 | #if defined(MBEDTLS_ASN1_PARSE_C) |
| 265 | unsigned char *buf_complete = NULL; |
| 266 | #endif /* MBEDTLS_ASN1_PARSE_C */ |
Gilles Peskine | 9311cf5 | 2019-03-01 20:05:05 +0100 | [diff] [blame] | 267 | |
Gilles Peskine | 2c2730a | 2022-06-10 20:15:44 +0200 | [diff] [blame] | 268 | for( data.size = 0; data.size <= expected->len + 1; data.size++ ) |
Gilles Peskine | 9311cf5 | 2019-03-01 20:05:05 +0100 | [diff] [blame] | 269 | { |
| 270 | if( ! generic_write_start_step( &data ) ) |
| 271 | goto exit; |
| 272 | ret = mbedtls_asn1_write_algorithm_identifier( |
| 273 | &data.p, data.start, |
| 274 | (const char *) oid->x, oid->len, par_len ); |
| 275 | /* If params_len != 0, mbedtls_asn1_write_algorithm_identifier() |
| 276 | * assumes that the parameters are already present in the buffer |
| 277 | * and returns a length that accounts for this, but our test |
| 278 | * data omits the parameters. */ |
| 279 | if( ret >= 0 ) |
| 280 | ret -= par_len; |
| 281 | if( ! generic_write_finish_step( &data, expected, ret ) ) |
| 282 | goto exit; |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 283 | |
| 284 | #if defined(MBEDTLS_ASN1_PARSE_C) |
| 285 | /* Only do a parse-back test if the parameters aren't too large for |
| 286 | * a small-heap environment. The boundary is somewhat arbitrary. */ |
| 287 | if( ret >= 0 && par_len <= 1234 ) |
| 288 | { |
| 289 | mbedtls_asn1_buf alg = {0, 0, NULL}; |
| 290 | mbedtls_asn1_buf params = {0, 0, NULL}; |
| 291 | /* The writing function doesn't write the parameters unless |
| 292 | * they're null: it only takes their length as input. But the |
| 293 | * parsing function requires the parameters to be present. |
| 294 | * Thus make up parameters. */ |
| 295 | size_t data_len = data.end - data.p; |
| 296 | size_t len_complete = data_len + par_len; |
| 297 | unsigned char expected_params_tag; |
| 298 | size_t expected_params_len; |
| 299 | ASSERT_ALLOC( buf_complete, len_complete ); |
| 300 | unsigned char *end_complete = buf_complete + len_complete; |
| 301 | memcpy( buf_complete, data.p, data_len ); |
| 302 | if( par_len == 0 ) |
| 303 | { |
| 304 | /* mbedtls_asn1_write_algorithm_identifier() wrote a NULL */ |
| 305 | expected_params_tag = 0x05; |
| 306 | expected_params_len = 0; |
| 307 | } |
| 308 | else if( par_len >= 2 && par_len < 2 + 128 ) |
| 309 | { |
| 310 | /* Write an OCTET STRING with a short length encoding */ |
| 311 | expected_params_tag = buf_complete[data_len] = 0x04; |
| 312 | expected_params_len = par_len - 2; |
| 313 | buf_complete[data_len + 1] = (unsigned char) expected_params_len; |
| 314 | } |
| 315 | else if( par_len >= 4 + 128 && par_len < 3 + 256 * 256 ) |
| 316 | { |
| 317 | /* Write an OCTET STRING with a two-byte length encoding */ |
| 318 | expected_params_tag = buf_complete[data_len] = 0x04; |
| 319 | expected_params_len = par_len - 4; |
| 320 | buf_complete[data_len + 1] = 0x82; |
| 321 | buf_complete[data_len + 2] = (unsigned char) ( expected_params_len >> 8 ); |
| 322 | buf_complete[data_len + 3] = (unsigned char) ( expected_params_len ); |
| 323 | } |
| 324 | else |
| 325 | { |
| 326 | TEST_ASSERT( ! "Bad test data: invalid length of ASN.1 element" ); |
| 327 | } |
| 328 | unsigned char *p = buf_complete; |
| 329 | TEST_EQUAL( mbedtls_asn1_get_alg( &p, end_complete, |
| 330 | &alg, ¶ms ), 0 ); |
| 331 | TEST_EQUAL( alg.tag, MBEDTLS_ASN1_OID ); |
| 332 | ASSERT_COMPARE( alg.p, alg.len, oid->x, oid->len ); |
| 333 | TEST_EQUAL( params.tag, expected_params_tag ); |
| 334 | TEST_EQUAL( params.len, expected_params_len ); |
| 335 | mbedtls_free( buf_complete ); |
| 336 | buf_complete = NULL; |
| 337 | } |
| 338 | #endif /* MBEDTLS_ASN1_PARSE_C */ |
Gilles Peskine | 9311cf5 | 2019-03-01 20:05:05 +0100 | [diff] [blame] | 339 | } |
| 340 | |
| 341 | exit: |
| 342 | mbedtls_free( data.output ); |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 343 | #if defined(MBEDTLS_ASN1_PARSE_C) |
| 344 | mbedtls_free( buf_complete ); |
| 345 | #endif /* MBEDTLS_ASN1_PARSE_C */ |
Gilles Peskine | 9311cf5 | 2019-03-01 20:05:05 +0100 | [diff] [blame] | 346 | } |
| 347 | /* END_CASE */ |
| 348 | |
Gilles Peskine | 91d8d02 | 2019-03-01 19:34:24 +0100 | [diff] [blame] | 349 | /* BEGIN_CASE depends_on:MBEDTLS_ASN1_PARSE_C */ |
Azim Khan | 5fcca46 | 2018-06-29 11:05:32 +0100 | [diff] [blame] | 350 | void mbedtls_asn1_write_len( int len, data_t * asn1, int buf_len, |
Azim Khan | d30ca13 | 2017-06-09 04:32:58 +0100 | [diff] [blame] | 351 | int result ) |
Paul Bakker | e325db9 | 2016-07-14 10:27:36 +0100 | [diff] [blame] | 352 | { |
| 353 | int ret; |
| 354 | unsigned char buf[150]; |
Paul Bakker | e325db9 | 2016-07-14 10:27:36 +0100 | [diff] [blame] | 355 | unsigned char *p; |
Azim Khan | 9079170 | 2017-05-30 00:57:11 +0100 | [diff] [blame] | 356 | size_t i; |
| 357 | size_t read_len; |
Paul Bakker | e325db9 | 2016-07-14 10:27:36 +0100 | [diff] [blame] | 358 | |
| 359 | memset( buf, GUARD_VAL, sizeof( buf ) ); |
Paul Bakker | e325db9 | 2016-07-14 10:27:36 +0100 | [diff] [blame] | 360 | |
Paul Bakker | 58bfb83 | 2016-07-14 11:02:31 +0100 | [diff] [blame] | 361 | p = buf + GUARD_LEN + buf_len; |
Paul Bakker | e325db9 | 2016-07-14 10:27:36 +0100 | [diff] [blame] | 362 | |
| 363 | ret = mbedtls_asn1_write_len( &p, buf + GUARD_LEN, (size_t) len ); |
| 364 | |
| 365 | TEST_ASSERT( ret == result ); |
| 366 | |
| 367 | /* Check for buffer overwrite on both sides */ |
| 368 | for( i = 0; i < GUARD_LEN; i++ ) |
| 369 | { |
| 370 | TEST_ASSERT( buf[i] == GUARD_VAL ); |
Paul Bakker | 58bfb83 | 2016-07-14 11:02:31 +0100 | [diff] [blame] | 371 | TEST_ASSERT( buf[GUARD_LEN + buf_len + i] == GUARD_VAL ); |
Paul Bakker | e325db9 | 2016-07-14 10:27:36 +0100 | [diff] [blame] | 372 | } |
| 373 | |
| 374 | if( result >= 0 ) |
| 375 | { |
Azim Khan | d30ca13 | 2017-06-09 04:32:58 +0100 | [diff] [blame] | 376 | TEST_ASSERT( p + asn1->len == buf + GUARD_LEN + buf_len ); |
Paul Bakker | e325db9 | 2016-07-14 10:27:36 +0100 | [diff] [blame] | 377 | |
Azim Khan | d30ca13 | 2017-06-09 04:32:58 +0100 | [diff] [blame] | 378 | TEST_ASSERT( memcmp( p, asn1->x, asn1->len ) == 0 ); |
Paul Bakker | 5e8b77c | 2016-07-14 11:14:54 +0100 | [diff] [blame] | 379 | |
| 380 | /* Read back with mbedtls_asn1_get_len() to check */ |
| 381 | ret = mbedtls_asn1_get_len( &p, buf + GUARD_LEN + buf_len, &read_len ); |
| 382 | |
| 383 | if( len == 0 ) |
| 384 | { |
| 385 | TEST_ASSERT( ret == 0 ); |
| 386 | } |
| 387 | else |
| 388 | { |
| 389 | /* Return will be MBEDTLS_ERR_ASN1_OUT_OF_DATA because the rest of |
| 390 | * the buffer is missing |
| 391 | */ |
| 392 | TEST_ASSERT( ret == MBEDTLS_ERR_ASN1_OUT_OF_DATA ); |
| 393 | } |
| 394 | TEST_ASSERT( read_len == (size_t) len ); |
| 395 | TEST_ASSERT( p == buf + GUARD_LEN + buf_len ); |
Paul Bakker | e325db9 | 2016-07-14 10:27:36 +0100 | [diff] [blame] | 396 | } |
| 397 | } |
| 398 | /* END_CASE */ |
Andres Amaya Garcia | 5d26163 | 2018-09-26 10:51:16 +0100 | [diff] [blame] | 399 | |
| 400 | /* BEGIN_CASE */ |
| 401 | void test_asn1_write_bitstrings( data_t *bitstring, int bits, |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 402 | data_t *expected, int is_named ) |
Andres Amaya Garcia | 5d26163 | 2018-09-26 10:51:16 +0100 | [diff] [blame] | 403 | { |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 404 | generic_write_data_t data = { NULL, NULL, NULL, NULL, 0 }; |
Andres Amaya Garcia | 5d26163 | 2018-09-26 10:51:16 +0100 | [diff] [blame] | 405 | int ret; |
Mateusz Starzyk | 4e300d0 | 2021-01-27 15:37:12 +0100 | [diff] [blame] | 406 | int ( *func )( unsigned char **p, const unsigned char *start, |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 407 | const unsigned char *buf, size_t bits ) = |
| 408 | ( is_named ? mbedtls_asn1_write_named_bitstring : |
| 409 | mbedtls_asn1_write_bitstring ); |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 410 | #if defined(MBEDTLS_ASN1_PARSE_C) |
| 411 | unsigned char *masked_bitstring = NULL; |
| 412 | #endif /* MBEDTLS_ASN1_PARSE_C */ |
| 413 | |
| 414 | /* The API expects `bitstring->x` to contain `bits` bits. */ |
| 415 | size_t byte_length = ( bits + 7 ) / 8; |
| 416 | TEST_ASSERT( bitstring->len >= byte_length ); |
| 417 | |
| 418 | #if defined(MBEDTLS_ASN1_PARSE_C) |
| 419 | ASSERT_ALLOC( masked_bitstring, byte_length ); |
| 420 | memcpy( masked_bitstring, bitstring->x, byte_length ); |
| 421 | if( bits % 8 != 0 ) |
| 422 | masked_bitstring[byte_length - 1] &= ~( 0xff >> ( bits % 8 ) ); |
| 423 | size_t value_bits = bits; |
| 424 | if( is_named ) |
| 425 | { |
| 426 | /* In a named bit string, all trailing 0 bits are removed. */ |
| 427 | while( byte_length > 0 && masked_bitstring[byte_length - 1] == 0 ) |
| 428 | --byte_length; |
| 429 | value_bits = 8 * byte_length; |
| 430 | if( byte_length > 0 ) |
| 431 | { |
| 432 | unsigned char last_byte = masked_bitstring[byte_length - 1]; |
| 433 | for( unsigned b = 1; b < 0xff && ( last_byte & b ) == 0; b <<= 1 ) |
| 434 | --value_bits; |
| 435 | } |
| 436 | } |
| 437 | #endif /* MBEDTLS_ASN1_PARSE_C */ |
Andres Amaya Garcia | 5d26163 | 2018-09-26 10:51:16 +0100 | [diff] [blame] | 438 | |
Gilles Peskine | 2c2730a | 2022-06-10 20:15:44 +0200 | [diff] [blame] | 439 | for( data.size = 0; data.size <= expected->len + 1; data.size++ ) |
Andres Amaya Garcia | 5d26163 | 2018-09-26 10:51:16 +0100 | [diff] [blame] | 440 | { |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 441 | if( ! generic_write_start_step( &data ) ) |
| 442 | goto exit; |
| 443 | ret = ( *func )( &data.p, data.start, bitstring->x, bits ); |
| 444 | if( ! generic_write_finish_step( &data, expected, ret ) ) |
| 445 | goto exit; |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 446 | #if defined(MBEDTLS_ASN1_PARSE_C) |
| 447 | if( ret >= 0 ) |
| 448 | { |
| 449 | mbedtls_asn1_bitstring read = {0, 0, NULL}; |
| 450 | TEST_EQUAL( mbedtls_asn1_get_bitstring( &data.p, data.end, |
| 451 | &read ), 0 ); |
| 452 | ASSERT_COMPARE( read.p, read.len, |
| 453 | masked_bitstring, byte_length ); |
| 454 | TEST_EQUAL( read.unused_bits, 8 * byte_length - value_bits ); |
| 455 | } |
| 456 | #endif /* MBEDTLS_ASN1_PARSE_C */ |
Andres Amaya Garcia | 5d26163 | 2018-09-26 10:51:16 +0100 | [diff] [blame] | 457 | } |
| 458 | |
Gilles Peskine | 3f37dca | 2019-03-01 19:30:20 +0100 | [diff] [blame] | 459 | exit: |
| 460 | mbedtls_free( data.output ); |
Gilles Peskine | 6194053 | 2022-06-15 21:17:25 +0200 | [diff] [blame^] | 461 | #if defined(MBEDTLS_ASN1_PARSE_C) |
| 462 | mbedtls_free( masked_bitstring ); |
| 463 | #endif /* MBEDTLS_ASN1_PARSE_C */ |
Andres Amaya Garcia | 5d26163 | 2018-09-26 10:51:16 +0100 | [diff] [blame] | 464 | } |
| 465 | /* END_CASE */ |
Gilles Peskine | a902303 | 2019-03-01 23:26:05 +0100 | [diff] [blame] | 466 | |
| 467 | /* BEGIN_CASE */ |
| 468 | void store_named_data_find( data_t *oid0, data_t *oid1, |
| 469 | data_t *oid2, data_t *oid3, |
| 470 | data_t *needle, int from, int position ) |
| 471 | { |
| 472 | data_t *oid[4] = {oid0, oid1, oid2, oid3}; |
| 473 | mbedtls_asn1_named_data nd[] ={ |
| 474 | { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 }, |
| 475 | { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 }, |
| 476 | { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 }, |
| 477 | { {0x06, 0, NULL}, {0, 0, NULL}, NULL, 0 }, |
| 478 | }; |
| 479 | mbedtls_asn1_named_data *pointers[ARRAY_LENGTH( nd ) + 1]; |
| 480 | size_t i; |
| 481 | mbedtls_asn1_named_data *head = NULL; |
| 482 | mbedtls_asn1_named_data *found = NULL; |
| 483 | |
| 484 | for( i = 0; i < ARRAY_LENGTH( nd ); i++ ) |
| 485 | pointers[i] = &nd[i]; |
| 486 | pointers[ARRAY_LENGTH( nd )] = NULL; |
| 487 | for( i = 0; i < ARRAY_LENGTH( nd ); i++ ) |
| 488 | { |
| 489 | ASSERT_ALLOC( nd[i].oid.p, oid[i]->len ); |
| 490 | memcpy( nd[i].oid.p, oid[i]->x, oid[i]->len ); |
| 491 | nd[i].oid.len = oid[i]->len; |
| 492 | nd[i].next = pointers[i+1]; |
| 493 | } |
| 494 | |
| 495 | head = pointers[from]; |
| 496 | found = mbedtls_asn1_store_named_data( &head, |
| 497 | (const char *) needle->x, |
| 498 | needle->len, |
| 499 | NULL, 0 ); |
| 500 | |
| 501 | /* In any case, the existing list structure must be unchanged. */ |
| 502 | for( i = 0; i < ARRAY_LENGTH( nd ); i++ ) |
| 503 | TEST_ASSERT( nd[i].next == pointers[i+1] ); |
| 504 | |
| 505 | if( position >= 0 ) |
| 506 | { |
| 507 | /* position should have been found and modified. */ |
| 508 | TEST_ASSERT( head == pointers[from] ); |
| 509 | TEST_ASSERT( found == pointers[position] ); |
| 510 | } |
| 511 | else |
| 512 | { |
| 513 | /* A new entry should have been created. */ |
| 514 | TEST_ASSERT( found == head ); |
| 515 | TEST_ASSERT( head->next == pointers[from] ); |
| 516 | for( i = 0; i < ARRAY_LENGTH( nd ); i++ ) |
| 517 | TEST_ASSERT( found != &nd[i] ); |
| 518 | } |
| 519 | |
| 520 | exit: |
| 521 | if( found != NULL && found == head && found != pointers[from] ) |
| 522 | { |
| 523 | mbedtls_free( found->oid.p ); |
| 524 | mbedtls_free( found ); |
| 525 | } |
| 526 | for( i = 0; i < ARRAY_LENGTH( nd ); i++ ) |
| 527 | mbedtls_free( nd[i].oid.p ); |
| 528 | } |
| 529 | /* END_CASE */ |
| 530 | |
| 531 | /* BEGIN_CASE */ |
| 532 | void store_named_data_val_found( int old_len, int new_len ) |
| 533 | { |
| 534 | mbedtls_asn1_named_data nd = |
| 535 | { {0x06, 3, (unsigned char *) "OID"}, {0, 0, NULL}, NULL, 0 }; |
| 536 | mbedtls_asn1_named_data *head = &nd; |
| 537 | mbedtls_asn1_named_data *found = NULL; |
| 538 | unsigned char *old_val = NULL; |
| 539 | unsigned char *new_val = (unsigned char *) "new value"; |
| 540 | |
| 541 | if( old_len != 0 ) |
| 542 | { |
| 543 | ASSERT_ALLOC( nd.val.p, (size_t) old_len ); |
| 544 | old_val = nd.val.p; |
| 545 | nd.val.len = old_len; |
| 546 | memset( old_val, 'x', old_len ); |
| 547 | } |
| 548 | if( new_len <= 0 ) |
| 549 | { |
| 550 | new_len = - new_len; |
| 551 | new_val = NULL; |
| 552 | } |
| 553 | |
| 554 | found = mbedtls_asn1_store_named_data( &head, "OID", 3, |
| 555 | new_val, new_len ); |
| 556 | TEST_ASSERT( head == &nd ); |
| 557 | TEST_ASSERT( found == head ); |
| 558 | |
| 559 | if( new_val != NULL) |
| 560 | ASSERT_COMPARE( found->val.p, found->val.len, |
| 561 | new_val, (size_t) new_len ); |
| 562 | if( new_len == 0) |
| 563 | TEST_ASSERT( found->val.p == NULL ); |
| 564 | else if( new_len == old_len ) |
| 565 | TEST_ASSERT( found->val.p == old_val ); |
| 566 | else |
| 567 | TEST_ASSERT( found->val.p != old_val ); |
| 568 | |
| 569 | exit: |
| 570 | mbedtls_free( nd.val.p ); |
| 571 | } |
| 572 | /* END_CASE */ |
| 573 | |
| 574 | /* BEGIN_CASE */ |
Werner Lewis | e59a531 | 2022-05-04 09:44:50 +0100 | [diff] [blame] | 575 | void store_named_data_val_new( int new_len, int set_new_val ) |
Gilles Peskine | a902303 | 2019-03-01 23:26:05 +0100 | [diff] [blame] | 576 | { |
| 577 | mbedtls_asn1_named_data *head = NULL; |
| 578 | mbedtls_asn1_named_data *found = NULL; |
| 579 | const unsigned char *oid = (unsigned char *) "OID"; |
| 580 | size_t oid_len = strlen( (const char *) oid ); |
| 581 | const unsigned char *new_val = (unsigned char *) "new value"; |
| 582 | |
Werner Lewis | e59a531 | 2022-05-04 09:44:50 +0100 | [diff] [blame] | 583 | if( set_new_val == 0 ) |
Gilles Peskine | a902303 | 2019-03-01 23:26:05 +0100 | [diff] [blame] | 584 | new_val = NULL; |
Gilles Peskine | a902303 | 2019-03-01 23:26:05 +0100 | [diff] [blame] | 585 | |
| 586 | found = mbedtls_asn1_store_named_data( &head, |
| 587 | (const char *) oid, oid_len, |
| 588 | new_val, (size_t) new_len ); |
| 589 | TEST_ASSERT( found != NULL ); |
| 590 | TEST_ASSERT( found == head ); |
| 591 | TEST_ASSERT( found->oid.p != oid ); |
| 592 | ASSERT_COMPARE( found->oid.p, found->oid.len, oid, oid_len ); |
| 593 | if( new_len == 0 ) |
| 594 | TEST_ASSERT( found->val.p == NULL ); |
| 595 | else if( new_val == NULL ) |
| 596 | TEST_ASSERT( found->val.p != NULL ); |
| 597 | else |
| 598 | { |
| 599 | TEST_ASSERT( found->val.p != new_val ); |
| 600 | ASSERT_COMPARE( found->val.p, found->val.len, |
| 601 | new_val, (size_t) new_len ); |
| 602 | } |
| 603 | |
| 604 | exit: |
| 605 | if( found != NULL ) |
| 606 | { |
| 607 | mbedtls_free( found->oid.p ); |
| 608 | mbedtls_free( found->val.p ); |
| 609 | } |
| 610 | mbedtls_free( found ); |
| 611 | } |
| 612 | /* END_CASE */ |