[MBEDTLS] Sync to v2.2.1. By Ismael Ferreras Morezuelas. CORE-10817
[reactos.git] / reactos / dll / 3rdparty / mbedtls / 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( *p - start < 3 )
64 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
65
66 // We assume we never have lengths larger than 65535 bytes
67 //
68 *--(*p) = len % 256;
69 *--(*p) = ( len / 256 ) % 256;
70 *--(*p) = 0x82;
71
72 return( 3 );
73 }
74
75 int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
76 {
77 if( *p - start < 1 )
78 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
79
80 *--(*p) = tag;
81
82 return( 1 );
83 }
84
85 int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
86 const unsigned char *buf, size_t size )
87 {
88 size_t len = 0;
89
90 if( *p < start || (size_t)( *p - start ) < size )
91 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
92
93 len = size;
94 (*p) -= len;
95 memcpy( *p, buf, len );
96
97 return( (int) len );
98 }
99
100 #if defined(MBEDTLS_BIGNUM_C)
101 int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X )
102 {
103 int ret;
104 size_t len = 0;
105
106 // Write the MPI
107 //
108 len = mbedtls_mpi_size( X );
109
110 if( *p < start || (size_t)( *p - start ) < len )
111 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
112
113 (*p) -= len;
114 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) );
115
116 // DER format assumes 2s complement for numbers, so the leftmost bit
117 // should be 0 for positive numbers and 1 for negative numbers.
118 //
119 if( X->s ==1 && **p & 0x80 )
120 {
121 if( *p - start < 1 )
122 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
123
124 *--(*p) = 0x00;
125 len += 1;
126 }
127
128 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
129 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
130
131 ret = (int) len;
132
133 cleanup:
134 return( ret );
135 }
136 #endif /* MBEDTLS_BIGNUM_C */
137
138 int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start )
139 {
140 int ret;
141 size_t len = 0;
142
143 // Write NULL
144 //
145 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) );
146 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) );
147
148 return( (int) len );
149 }
150
151 int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
152 const char *oid, size_t oid_len )
153 {
154 int ret;
155 size_t len = 0;
156
157 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
158 (const unsigned char *) oid, oid_len ) );
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_OID ) );
161
162 return( (int) len );
163 }
164
165 int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
166 const char *oid, size_t oid_len,
167 size_t par_len )
168 {
169 int ret;
170 size_t len = 0;
171
172 if( par_len == 0 )
173 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) );
174 else
175 len += par_len;
176
177 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
178
179 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
180 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
181 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
182
183 return( (int) len );
184 }
185
186 int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
187 {
188 int ret;
189 size_t len = 0;
190
191 if( *p - start < 1 )
192 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
193
194 *--(*p) = (boolean) ? 255 : 0;
195 len++;
196
197 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
198 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) );
199
200 return( (int) len );
201 }
202
203 int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
204 {
205 int ret;
206 size_t len = 0;
207
208 // TODO negative values and values larger than 128
209 // DER format assumes 2s complement for numbers, so the leftmost bit
210 // should be 0 for positive numbers and 1 for negative numbers.
211 //
212 if( *p - start < 1 )
213 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
214
215 len += 1;
216 *--(*p) = val;
217
218 if( val > 0 && **p & 0x80 )
219 {
220 if( *p - start < 1 )
221 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
222
223 *--(*p) = 0x00;
224 len += 1;
225 }
226
227 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
228 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
229
230 return( (int) len );
231 }
232
233 int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start,
234 const char *text, size_t text_len )
235 {
236 int ret;
237 size_t len = 0;
238
239 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
240 (const unsigned char *) text, text_len ) );
241
242 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
243 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) );
244
245 return( (int) len );
246 }
247
248 int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
249 const char *text, size_t text_len )
250 {
251 int ret;
252 size_t len = 0;
253
254 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
255 (const unsigned char *) text, text_len ) );
256
257 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
258 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) );
259
260 return( (int) len );
261 }
262
263 int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
264 const unsigned char *buf, size_t bits )
265 {
266 int ret;
267 size_t len = 0, size;
268
269 size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 );
270
271 // Calculate byte length
272 //
273 if( *p < start || (size_t)( *p - start ) < size + 1 )
274 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
275
276 len = size + 1;
277 (*p) -= size;
278 memcpy( *p, buf, size );
279
280 // Write unused bits
281 //
282 *--(*p) = (unsigned char) (size * 8 - bits);
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_BIT_STRING ) );
286
287 return( (int) len );
288 }
289
290 int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
291 const unsigned char *buf, size_t size )
292 {
293 int ret;
294 size_t len = 0;
295
296 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) );
297
298 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
299 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
300
301 return( (int) len );
302 }
303
304 mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head,
305 const char *oid, size_t oid_len,
306 const unsigned char *val,
307 size_t val_len )
308 {
309 mbedtls_asn1_named_data *cur;
310
311 if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
312 {
313 // Add new entry if not present yet based on OID
314 //
315 if( ( cur = mbedtls_calloc( 1, sizeof(mbedtls_asn1_named_data) ) ) == NULL )
316 return( NULL );
317
318 cur->oid.len = oid_len;
319 cur->oid.p = mbedtls_calloc( 1, oid_len );
320 if( cur->oid.p == NULL )
321 {
322 mbedtls_free( cur );
323 return( NULL );
324 }
325
326 memcpy( cur->oid.p, oid, oid_len );
327
328 cur->val.len = val_len;
329 cur->val.p = mbedtls_calloc( 1, val_len );
330 if( cur->val.p == NULL )
331 {
332 mbedtls_free( cur->oid.p );
333 mbedtls_free( cur );
334 return( NULL );
335 }
336
337 cur->next = *head;
338 *head = cur;
339 }
340 else if( cur->val.len < val_len )
341 {
342 /*
343 * Enlarge existing value buffer if needed
344 * Preserve old data until the allocation succeeded, to leave list in
345 * a consistent state in case allocation fails.
346 */
347 void *p = mbedtls_calloc( 1, val_len );
348 if( p == NULL )
349 return( NULL );
350
351 mbedtls_free( cur->val.p );
352 cur->val.p = p;
353 cur->val.len = val_len;
354 }
355
356 if( val != NULL )
357 memcpy( cur->val.p, val, val_len );
358
359 return( cur );
360 }
361 #endif /* MBEDTLS_ASN1_WRITE_C */