Branch data Line data Source code
1 : : /*
2 : : * ASN.1 buffer writing functionality
3 : : *
4 : : * Copyright The Mbed TLS Contributors
5 : : * SPDX-License-Identifier: Apache-2.0
6 : : *
7 : : * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 : : * not use this file except in compliance with the License.
9 : : * You may obtain a copy of the License at
10 : : *
11 : : * http://www.apache.org/licenses/LICENSE-2.0
12 : : *
13 : : * Unless required by applicable law or agreed to in writing, software
14 : : * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 : : * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : : * See the License for the specific language governing permissions and
17 : : * limitations under the License.
18 : : */
19 : :
20 : : #include "common.h"
21 : :
22 : : #if defined(MBEDTLS_ASN1_WRITE_C)
23 : :
24 : : #include "mbedtls/asn1write.h"
25 : : #include "mbedtls/error.h"
26 : :
27 : : #include <string.h>
28 : :
29 : : #if defined(MBEDTLS_PLATFORM_C)
30 : : #include "mbedtls/platform.h"
31 : : #else
32 : : #include <stdlib.h>
33 : : #define mbedtls_calloc calloc
34 : : #define mbedtls_free free
35 : : #endif
36 : :
37 : 0 : int mbedtls_asn1_write_len( unsigned char **p, const unsigned char *start, size_t len )
38 : : {
39 [ # # ]: 0 : if( len < 0x80 )
40 : : {
41 [ # # ]: 0 : if( *p - start < 1 )
42 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
43 : :
44 : 0 : *--(*p) = (unsigned char) len;
45 : 0 : return( 1 );
46 : : }
47 : :
48 [ # # ]: 0 : if( len <= 0xFF )
49 : : {
50 [ # # ]: 0 : if( *p - start < 2 )
51 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
52 : :
53 : 0 : *--(*p) = (unsigned char) len;
54 : 0 : *--(*p) = 0x81;
55 : 0 : return( 2 );
56 : : }
57 : :
58 [ # # ]: 0 : if( len <= 0xFFFF )
59 : : {
60 [ # # ]: 0 : if( *p - start < 3 )
61 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
62 : :
63 : 0 : *--(*p) = MBEDTLS_BYTE_0( len );
64 : 0 : *--(*p) = MBEDTLS_BYTE_1( len );
65 : 0 : *--(*p) = 0x82;
66 : 0 : return( 3 );
67 : : }
68 : :
69 [ # # ]: 0 : if( len <= 0xFFFFFF )
70 : : {
71 [ # # ]: 0 : if( *p - start < 4 )
72 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
73 : :
74 : 0 : *--(*p) = MBEDTLS_BYTE_0( len );
75 : 0 : *--(*p) = MBEDTLS_BYTE_1( len );
76 : 0 : *--(*p) = MBEDTLS_BYTE_2( len );
77 : 0 : *--(*p) = 0x83;
78 : 0 : return( 4 );
79 : : }
80 : :
81 : : #if SIZE_MAX > 0xFFFFFFFF
82 : : if( len <= 0xFFFFFFFF )
83 : : #endif
84 : : {
85 [ # # ]: 0 : if( *p - start < 5 )
86 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
87 : :
88 : 0 : *--(*p) = MBEDTLS_BYTE_0( len );
89 : 0 : *--(*p) = MBEDTLS_BYTE_1( len );
90 : 0 : *--(*p) = MBEDTLS_BYTE_2( len );
91 : 0 : *--(*p) = MBEDTLS_BYTE_3( len );
92 : 0 : *--(*p) = 0x84;
93 : 0 : return( 5 );
94 : : }
95 : :
96 : : #if SIZE_MAX > 0xFFFFFFFF
97 : : return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
98 : : #endif
99 : : }
100 : :
101 : 0 : int mbedtls_asn1_write_tag( unsigned char **p, const unsigned char *start, unsigned char tag )
102 : : {
103 [ # # ]: 0 : if( *p - start < 1 )
104 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
105 : :
106 : 0 : *--(*p) = tag;
107 : :
108 : 0 : return( 1 );
109 : : }
110 : :
111 : 0 : int mbedtls_asn1_write_raw_buffer( unsigned char **p, const unsigned char *start,
112 : : const unsigned char *buf, size_t size )
113 : : {
114 : 0 : size_t len = 0;
115 : :
116 [ # # # # ]: 0 : if( *p < start || (size_t)( *p - start ) < size )
117 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
118 : :
119 : 0 : len = size;
120 : 0 : (*p) -= len;
121 : 0 : memcpy( *p, buf, len );
122 : :
123 : 0 : return( (int) len );
124 : : }
125 : :
126 : : #if defined(MBEDTLS_BIGNUM_C)
127 : 0 : int mbedtls_asn1_write_mpi( unsigned char **p, const unsigned char *start, const mbedtls_mpi *X )
128 : : {
129 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
130 : 0 : size_t len = 0;
131 : :
132 : : // Write the MPI
133 : : //
134 : 0 : len = mbedtls_mpi_size( X );
135 : :
136 [ # # # # ]: 0 : if( *p < start || (size_t)( *p - start ) < len )
137 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
138 : :
139 : 0 : (*p) -= len;
140 [ # # ]: 0 : MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) );
141 : :
142 : : // DER format assumes 2s complement for numbers, so the leftmost bit
143 : : // should be 0 for positive numbers and 1 for negative numbers.
144 : : //
145 [ # # # # ]: 0 : if( X->s ==1 && **p & 0x80 )
146 : : {
147 [ # # ]: 0 : if( *p - start < 1 )
148 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
149 : :
150 : 0 : *--(*p) = 0x00;
151 : 0 : len += 1;
152 : : }
153 : :
154 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
155 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
156 : :
157 : 0 : ret = (int) len;
158 : :
159 : : cleanup:
160 : : return( ret );
161 : : }
162 : : #endif /* MBEDTLS_BIGNUM_C */
163 : :
164 : 0 : int mbedtls_asn1_write_null( unsigned char **p, const unsigned char *start )
165 : : {
166 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
167 : 0 : size_t len = 0;
168 : :
169 : : // Write NULL
170 : : //
171 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) );
172 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) );
173 : :
174 : 0 : return( (int) len );
175 : : }
176 : :
177 : 0 : int mbedtls_asn1_write_oid( unsigned char **p, const unsigned char *start,
178 : : const char *oid, size_t oid_len )
179 : : {
180 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
181 : 0 : size_t len = 0;
182 : :
183 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
184 : : (const unsigned char *) oid, oid_len ) );
185 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) );
186 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );
187 : :
188 : 0 : return( (int) len );
189 : : }
190 : :
191 : 0 : int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, const unsigned char *start,
192 : : const char *oid, size_t oid_len,
193 : : size_t par_len )
194 : : {
195 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
196 : 0 : size_t len = 0;
197 : :
198 [ # # ]: 0 : if( par_len == 0 )
199 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) );
200 : : else
201 : : len += par_len;
202 : :
203 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
204 : :
205 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
206 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
207 : : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
208 : :
209 : 0 : return( (int) len );
210 : : }
211 : :
212 : 0 : int mbedtls_asn1_write_bool( unsigned char **p, const unsigned char *start, int boolean )
213 : : {
214 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
215 : 0 : size_t len = 0;
216 : :
217 [ # # ]: 0 : if( *p - start < 1 )
218 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
219 : :
220 [ # # ]: 0 : *--(*p) = (boolean) ? 255 : 0;
221 : 0 : len++;
222 : :
223 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
224 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) );
225 : :
226 : 0 : return( (int) len );
227 : : }
228 : :
229 : 0 : static int asn1_write_tagged_int( unsigned char **p, const unsigned char *start, int val, int tag )
230 : : {
231 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
232 : 0 : size_t len = 0;
233 : :
234 : 0 : do
235 : : {
236 [ # # ]: 0 : if( *p - start < 1 )
237 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
238 : 0 : len += 1;
239 : 0 : *--(*p) = val & 0xff;
240 : 0 : val >>= 8;
241 : : }
242 [ # # ]: 0 : while( val > 0 );
243 : :
244 [ # # ]: 0 : if( **p & 0x80 )
245 : : {
246 [ # # ]: 0 : if( *p - start < 1 )
247 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
248 : 0 : *--(*p) = 0x00;
249 : 0 : len += 1;
250 : : }
251 : :
252 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
253 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
254 : :
255 : 0 : return( (int) len );
256 : : }
257 : :
258 : 0 : int mbedtls_asn1_write_int( unsigned char **p, const unsigned char *start, int val )
259 : : {
260 : 0 : return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) );
261 : : }
262 : :
263 : 0 : int mbedtls_asn1_write_enum( unsigned char **p, const unsigned char *start, int val )
264 : : {
265 : 0 : return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) );
266 : : }
267 : :
268 : 0 : int mbedtls_asn1_write_tagged_string( unsigned char **p, const unsigned char *start, int tag,
269 : : const char *text, size_t text_len )
270 : : {
271 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
272 : 0 : size_t len = 0;
273 : :
274 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
275 : : (const unsigned char *) text, text_len ) );
276 : :
277 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
278 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
279 : :
280 : 0 : return( (int) len );
281 : : }
282 : :
283 : 0 : int mbedtls_asn1_write_utf8_string( unsigned char **p, const unsigned char *start,
284 : : const char *text, size_t text_len )
285 : : {
286 : 0 : return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) );
287 : : }
288 : :
289 : 0 : int mbedtls_asn1_write_printable_string( unsigned char **p, const unsigned char *start,
290 : : const char *text, size_t text_len )
291 : : {
292 : 0 : return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) );
293 : : }
294 : :
295 : 0 : int mbedtls_asn1_write_ia5_string( unsigned char **p, const unsigned char *start,
296 : : const char *text, size_t text_len )
297 : : {
298 : 0 : return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) );
299 : : }
300 : :
301 : 0 : int mbedtls_asn1_write_named_bitstring( unsigned char **p,
302 : : const unsigned char *start,
303 : : const unsigned char *buf,
304 : : size_t bits )
305 : : {
306 : 0 : size_t unused_bits, byte_len;
307 : 0 : const unsigned char *cur_byte;
308 : 0 : unsigned char cur_byte_shifted;
309 : 0 : unsigned char bit;
310 : :
311 : 0 : byte_len = ( bits + 7 ) / 8;
312 : 0 : unused_bits = ( byte_len * 8 ) - bits;
313 : :
314 : : /*
315 : : * Named bitstrings require that trailing 0s are excluded in the encoding
316 : : * of the bitstring. Trailing 0s are considered part of the 'unused' bits
317 : : * when encoding this value in the first content octet
318 : : */
319 [ # # ]: 0 : if( bits != 0 )
320 : : {
321 : 0 : cur_byte = buf + byte_len - 1;
322 : 0 : cur_byte_shifted = *cur_byte >> unused_bits;
323 : :
324 : 0 : for( ; ; )
325 : : {
326 : 0 : bit = cur_byte_shifted & 0x1;
327 : 0 : cur_byte_shifted >>= 1;
328 : :
329 [ # # ]: 0 : if( bit != 0 )
330 : : break;
331 : :
332 : 0 : bits--;
333 [ # # ]: 0 : if( bits == 0 )
334 : : break;
335 : :
336 [ # # ]: 0 : if( bits % 8 == 0 )
337 : 0 : cur_byte_shifted = *--cur_byte;
338 : : }
339 : : }
340 : :
341 : 0 : return( mbedtls_asn1_write_bitstring( p, start, buf, bits ) );
342 : : }
343 : :
344 : 0 : int mbedtls_asn1_write_bitstring( unsigned char **p, const unsigned char *start,
345 : : const unsigned char *buf, size_t bits )
346 : : {
347 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
348 : 0 : size_t len = 0;
349 : 0 : size_t unused_bits, byte_len;
350 : :
351 : 0 : byte_len = ( bits + 7 ) / 8;
352 : 0 : unused_bits = ( byte_len * 8 ) - bits;
353 : :
354 [ # # # # ]: 0 : if( *p < start || (size_t)( *p - start ) < byte_len + 1 )
355 : : return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
356 : :
357 : 0 : len = byte_len + 1;
358 : :
359 : : /* Write the bitstring. Ensure the unused bits are zeroed */
360 [ # # ]: 0 : if( byte_len > 0 )
361 : : {
362 : 0 : byte_len--;
363 : 0 : *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 );
364 : 0 : ( *p ) -= byte_len;
365 : 0 : memcpy( *p, buf, byte_len );
366 : : }
367 : :
368 : : /* Write unused bits */
369 : 0 : *--( *p ) = (unsigned char)unused_bits;
370 : :
371 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
372 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
373 : :
374 : 0 : return( (int) len );
375 : : }
376 : :
377 : 0 : int mbedtls_asn1_write_octet_string( unsigned char **p, const unsigned char *start,
378 : : const unsigned char *buf, size_t size )
379 : : {
380 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
381 : 0 : size_t len = 0;
382 : :
383 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) );
384 : :
385 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
386 [ # # ]: 0 : MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
387 : :
388 : 0 : return( (int) len );
389 : : }
390 : :
391 : :
392 : : /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
393 : : * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
394 : 0 : static mbedtls_asn1_named_data *asn1_find_named_data(
395 : : mbedtls_asn1_named_data *list,
396 : : const char *oid, size_t len )
397 : : {
398 [ # # ]: 0 : while( list != NULL )
399 : : {
400 [ # # ]: 0 : if( list->oid.len == len &&
401 [ # # ]: 0 : memcmp( list->oid.p, oid, len ) == 0 )
402 : : {
403 : : break;
404 : : }
405 : :
406 : 0 : list = list->next;
407 : : }
408 : :
409 : 0 : return( list );
410 : : }
411 : :
412 : 0 : mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
413 : : mbedtls_asn1_named_data **head,
414 : : const char *oid, size_t oid_len,
415 : : const unsigned char *val,
416 : : size_t val_len )
417 : : {
418 : 0 : mbedtls_asn1_named_data *cur;
419 : :
420 [ # # ]: 0 : if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
421 : : {
422 : : // Add new entry if not present yet based on OID
423 : : //
424 : 0 : cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1,
425 : : sizeof(mbedtls_asn1_named_data) );
426 [ # # ]: 0 : if( cur == NULL )
427 : : return( NULL );
428 : :
429 : 0 : cur->oid.len = oid_len;
430 : 0 : cur->oid.p = mbedtls_calloc( 1, oid_len );
431 [ # # ]: 0 : if( cur->oid.p == NULL )
432 : : {
433 : 0 : mbedtls_free( cur );
434 : 0 : return( NULL );
435 : : }
436 : :
437 [ # # ]: 0 : memcpy( cur->oid.p, oid, oid_len );
438 : :
439 : 0 : cur->val.len = val_len;
440 [ # # ]: 0 : if( val_len != 0 )
441 : : {
442 : 0 : cur->val.p = mbedtls_calloc( 1, val_len );
443 [ # # ]: 0 : if( cur->val.p == NULL )
444 : : {
445 : 0 : mbedtls_free( cur->oid.p );
446 : 0 : mbedtls_free( cur );
447 : 0 : return( NULL );
448 : : }
449 : : }
450 : :
451 : 0 : cur->next = *head;
452 : 0 : *head = cur;
453 : : }
454 [ # # ]: 0 : else if( val_len == 0 )
455 : : {
456 : 0 : mbedtls_free( cur->val.p );
457 : 0 : cur->val.p = NULL;
458 : : }
459 [ # # ]: 0 : else if( cur->val.len != val_len )
460 : : {
461 : : /*
462 : : * Enlarge existing value buffer if needed
463 : : * Preserve old data until the allocation succeeded, to leave list in
464 : : * a consistent state in case allocation fails.
465 : : */
466 : 0 : void *p = mbedtls_calloc( 1, val_len );
467 [ # # ]: 0 : if( p == NULL )
468 : : return( NULL );
469 : :
470 : 0 : mbedtls_free( cur->val.p );
471 : 0 : cur->val.p = p;
472 : 0 : cur->val.len = val_len;
473 : : }
474 : :
475 [ # # ]: 0 : if( val != NULL )
476 : 0 : memcpy( cur->val.p, val, val_len );
477 : :
478 : : return( cur );
479 : : }
480 : : #endif /* MBEDTLS_ASN1_WRITE_C */
|