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