blob: 87c5ef6b51bcaa9ef69ad608a4893ccd6afaa7e3 [file] [log] [blame]
Jaeden Ameroe54e6932018-08-06 16:19:58 +01001/*
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 Crypto (https://tls.mbed.org)
20 */
21
22#if !defined(MBEDCRYPTO_CONFIG_FILE)
23#include "mbedcrypto/config.h"
24#else
25#include MBEDCRYPTO_CONFIG_FILE
26#endif
27
28#if defined(MBEDCRYPTO_ASN1_WRITE_C)
29
30#include "mbedcrypto/asn1write.h"
31
32#include <string.h>
33
34#if defined(MBEDCRYPTO_PLATFORM_C)
35#include "mbedcrypto/platform.h"
36#else
37#include <stdlib.h>
38#define mbedcrypto_calloc calloc
39#define mbedcrypto_free free
40#endif
41
42int mbedcrypto_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( MBEDCRYPTO_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( MBEDCRYPTO_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( MBEDCRYPTO_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( MBEDCRYPTO_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( len <= 0xFFFFFFFF )
87 {
88 if( *p - start < 5 )
89 return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
90
91 *--(*p) = ( len ) & 0xFF;
92 *--(*p) = ( len >> 8 ) & 0xFF;
93 *--(*p) = ( len >> 16 ) & 0xFF;
94 *--(*p) = ( len >> 24 ) & 0xFF;
95 *--(*p) = 0x84;
96 return( 5 );
97 }
98
99 return( MBEDCRYPTO_ERR_ASN1_INVALID_LENGTH );
100}
101
102int mbedcrypto_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
103{
104 if( *p - start < 1 )
105 return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
106
107 *--(*p) = tag;
108
109 return( 1 );
110}
111
112int mbedcrypto_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
113 const unsigned char *buf, size_t size )
114{
115 size_t len = 0;
116
117 if( *p < start || (size_t)( *p - start ) < size )
118 return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
119
120 len = size;
121 (*p) -= len;
122 memcpy( *p, buf, len );
123
124 return( (int) len );
125}
126
127#if defined(MBEDCRYPTO_BIGNUM_C)
128int mbedcrypto_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedcrypto_mpi *X )
129{
130 int ret;
131 size_t len = 0;
132
133 // Write the MPI
134 //
135 len = mbedcrypto_mpi_size( X );
136
137 if( *p < start || (size_t)( *p - start ) < len )
138 return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
139
140 (*p) -= len;
141 MBEDCRYPTO_MPI_CHK( mbedcrypto_mpi_write_binary( X, *p, len ) );
142
143 // DER format assumes 2s complement for numbers, so the leftmost bit
144 // should be 0 for positive numbers and 1 for negative numbers.
145 //
146 if( X->s ==1 && **p & 0x80 )
147 {
148 if( *p - start < 1 )
149 return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
150
151 *--(*p) = 0x00;
152 len += 1;
153 }
154
155 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
156 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_INTEGER ) );
157
158 ret = (int) len;
159
160cleanup:
161 return( ret );
162}
163#endif /* MBEDCRYPTO_BIGNUM_C */
164
165int mbedcrypto_asn1_write_null( unsigned char **p, unsigned char *start )
166{
167 int ret;
168 size_t len = 0;
169
170 // Write NULL
171 //
172 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, 0) );
173 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_NULL ) );
174
175 return( (int) len );
176}
177
178int mbedcrypto_asn1_write_oid( unsigned char **p, unsigned char *start,
179 const char *oid, size_t oid_len )
180{
181 int ret;
182 size_t len = 0;
183
184 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_raw_buffer( p, start,
185 (const unsigned char *) oid, oid_len ) );
186 MBEDCRYPTO_ASN1_CHK_ADD( len , mbedcrypto_asn1_write_len( p, start, len ) );
187 MBEDCRYPTO_ASN1_CHK_ADD( len , mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_OID ) );
188
189 return( (int) len );
190}
191
192int mbedcrypto_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
193 const char *oid, size_t oid_len,
194 size_t par_len )
195{
196 int ret;
197 size_t len = 0;
198
199 if( par_len == 0 )
200 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_null( p, start ) );
201 else
202 len += par_len;
203
204 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_oid( p, start, oid, oid_len ) );
205
206 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
207 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start,
208 MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) );
209
210 return( (int) len );
211}
212
213int mbedcrypto_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
214{
215 int ret;
216 size_t len = 0;
217
218 if( *p - start < 1 )
219 return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
220
221 *--(*p) = (boolean) ? 255 : 0;
222 len++;
223
224 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
225 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_BOOLEAN ) );
226
227 return( (int) len );
228}
229
230int mbedcrypto_asn1_write_int( unsigned char **p, unsigned char *start, int val )
231{
232 int ret;
233 size_t len = 0;
234
235 if( *p - start < 1 )
236 return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
237
238 len += 1;
239 *--(*p) = val;
240
241 if( val > 0 && **p & 0x80 )
242 {
243 if( *p - start < 1 )
244 return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
245
246 *--(*p) = 0x00;
247 len += 1;
248 }
249
250 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
251 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_INTEGER ) );
252
253 return( (int) len );
254}
255
256int mbedcrypto_asn1_write_printable_string( unsigned char **p, unsigned char *start,
257 const char *text, size_t text_len )
258{
259 int ret;
260 size_t len = 0;
261
262 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_raw_buffer( p, start,
263 (const unsigned char *) text, text_len ) );
264
265 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
266 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_PRINTABLE_STRING ) );
267
268 return( (int) len );
269}
270
271int mbedcrypto_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
272 const char *text, size_t text_len )
273{
274 int ret;
275 size_t len = 0;
276
277 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_raw_buffer( p, start,
278 (const unsigned char *) text, text_len ) );
279
280 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
281 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_IA5_STRING ) );
282
283 return( (int) len );
284}
285
286int mbedcrypto_asn1_write_bitstring( unsigned char **p, unsigned char *start,
287 const unsigned char *buf, size_t bits )
288{
289 int ret;
290 size_t len = 0, size;
291
292 size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 );
293
294 // Calculate byte length
295 //
296 if( *p < start || (size_t)( *p - start ) < size + 1 )
297 return( MBEDCRYPTO_ERR_ASN1_BUF_TOO_SMALL );
298
299 len = size + 1;
300 (*p) -= size;
301 memcpy( *p, buf, size );
302
303 // Write unused bits
304 //
305 *--(*p) = (unsigned char) (size * 8 - bits);
306
307 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
308 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_BIT_STRING ) );
309
310 return( (int) len );
311}
312
313int mbedcrypto_asn1_write_octet_string( unsigned char **p, unsigned char *start,
314 const unsigned char *buf, size_t size )
315{
316 int ret;
317 size_t len = 0;
318
319 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_raw_buffer( p, start, buf, size ) );
320
321 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_len( p, start, len ) );
322 MBEDCRYPTO_ASN1_CHK_ADD( len, mbedcrypto_asn1_write_tag( p, start, MBEDCRYPTO_ASN1_OCTET_STRING ) );
323
324 return( (int) len );
325}
326
327mbedcrypto_asn1_named_data *mbedcrypto_asn1_store_named_data( mbedcrypto_asn1_named_data **head,
328 const char *oid, size_t oid_len,
329 const unsigned char *val,
330 size_t val_len )
331{
332 mbedcrypto_asn1_named_data *cur;
333
334 if( ( cur = mbedcrypto_asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
335 {
336 // Add new entry if not present yet based on OID
337 //
338 cur = (mbedcrypto_asn1_named_data*)mbedcrypto_calloc( 1,
339 sizeof(mbedcrypto_asn1_named_data) );
340 if( cur == NULL )
341 return( NULL );
342
343 cur->oid.len = oid_len;
344 cur->oid.p = mbedcrypto_calloc( 1, oid_len );
345 if( cur->oid.p == NULL )
346 {
347 mbedcrypto_free( cur );
348 return( NULL );
349 }
350
351 memcpy( cur->oid.p, oid, oid_len );
352
353 cur->val.len = val_len;
354 cur->val.p = mbedcrypto_calloc( 1, val_len );
355 if( cur->val.p == NULL )
356 {
357 mbedcrypto_free( cur->oid.p );
358 mbedcrypto_free( cur );
359 return( NULL );
360 }
361
362 cur->next = *head;
363 *head = cur;
364 }
365 else if( cur->val.len < val_len )
366 {
367 /*
368 * Enlarge existing value buffer if needed
369 * Preserve old data until the allocation succeeded, to leave list in
370 * a consistent state in case allocation fails.
371 */
372 void *p = mbedcrypto_calloc( 1, val_len );
373 if( p == NULL )
374 return( NULL );
375
376 mbedcrypto_free( cur->val.p );
377 cur->val.p = p;
378 cur->val.len = val_len;
379 }
380
381 if( val != NULL )
382 memcpy( cur->val.p, val, val_len );
383
384 return( cur );
385}
386#endif /* MBEDCRYPTO_ASN1_WRITE_C */