Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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