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