Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8774 rgimad 1
/*
2
 *  X.509 Certificate Signing Request writing
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
 * References:
25
 * - CSRs: PKCS#10 v1.7 aka RFC 2986
26
 * - attributes: PKCS#9 v2.0 aka RFC 2985
27
 */
28
 
29
#if !defined(MBEDTLS_CONFIG_FILE)
30
#include "mbedtls/config.h"
31
#else
32
#include MBEDTLS_CONFIG_FILE
33
#endif
34
 
35
#if defined(MBEDTLS_X509_CSR_WRITE_C)
36
 
37
#include "mbedtls/x509_csr.h"
38
#include "mbedtls/oid.h"
39
#include "mbedtls/asn1write.h"
40
#include "mbedtls/platform_util.h"
41
 
42
#include 
43
#include 
44
 
45
#if defined(MBEDTLS_PEM_WRITE_C)
46
#include "mbedtls/pem.h"
47
#endif
48
 
49
/*
50
 * For the currently used signature algorithms the buffer to store any signature
51
 * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
52
 */
53
#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
54
#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
55
#else
56
#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
57
#endif
58
 
59
void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )
60
{
61
    memset( ctx, 0, sizeof( mbedtls_x509write_csr ) );
62
}
63
 
64
void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx )
65
{
66
    mbedtls_asn1_free_named_data_list( &ctx->subject );
67
    mbedtls_asn1_free_named_data_list( &ctx->extensions );
68
 
69
    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) );
70
}
71
 
72
void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg )
73
{
74
    ctx->md_alg = md_alg;
75
}
76
 
77
void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key )
78
{
79
    ctx->key = key;
80
}
81
 
82
int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx,
83
                                    const char *subject_name )
84
{
85
    return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
86
}
87
 
88
int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx,
89
                                 const char *oid, size_t oid_len,
90
                                 const unsigned char *val, size_t val_len )
91
{
92
    return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
93
                               0, val, val_len );
94
}
95
 
96
static size_t csr_get_unused_bits_for_named_bitstring( unsigned char bitstring,
97
                                                       size_t bit_offset )
98
{
99
    size_t unused_bits;
100
 
101
     /* Count the unused bits removing trailing 0s */
102
    for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ )
103
        if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 )
104
            break;
105
 
106
     return( unused_bits );
107
}
108
 
109
int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage )
110
{
111
    unsigned char buf[4];
112
    unsigned char *c;
113
    size_t unused_bits;
114
    int ret;
115
 
116
    c = buf + 4;
117
 
118
    unused_bits = csr_get_unused_bits_for_named_bitstring( key_usage, 0 );
119
    ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 8 - unused_bits );
120
 
121
    if( ret < 0 )
122
        return( ret );
123
    else if( ret < 3 || ret > 4 )
124
        return( MBEDTLS_ERR_X509_INVALID_FORMAT );
125
 
126
    ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
127
                                       MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
128
                                       c, (size_t)ret );
129
    if( ret != 0 )
130
        return( ret );
131
 
132
    return( 0 );
133
}
134
 
135
int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx,
136
                                    unsigned char ns_cert_type )
137
{
138
    unsigned char buf[4];
139
    unsigned char *c;
140
    size_t unused_bits;
141
    int ret;
142
 
143
    c = buf + 4;
144
 
145
    unused_bits = csr_get_unused_bits_for_named_bitstring( ns_cert_type, 0 );
146
    ret = mbedtls_asn1_write_bitstring( &c,
147
                                        buf,
148
                                        &ns_cert_type,
149
                                        8 - unused_bits );
150
 
151
    if( ret < 0 )
152
        return( ret );
153
    else if( ret < 3 || ret > 4 )
154
        return( ret );
155
 
156
    ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
157
                                       MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
158
                                       c, (size_t)ret );
159
    if( ret != 0 )
160
        return( ret );
161
 
162
    return( 0 );
163
}
164
 
165
int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
166
                       int (*f_rng)(void *, unsigned char *, size_t),
167
                       void *p_rng )
168
{
169
    int ret;
170
    const char *sig_oid;
171
    size_t sig_oid_len = 0;
172
    unsigned char *c, *c2;
173
    unsigned char hash[64];
174
    unsigned char sig[SIGNATURE_MAX_SIZE];
175
    unsigned char tmp_buf[2048];
176
    size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
177
    size_t len = 0;
178
    mbedtls_pk_type_t pk_alg;
179
 
180
    /*
181
     * Prepare data to be signed in tmp_buf
182
     */
183
    c = tmp_buf + sizeof( tmp_buf );
184
 
185
    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
186
 
187
    if( len )
188
    {
189
        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
190
        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
191
                                                        MBEDTLS_ASN1_SEQUENCE ) );
192
 
193
        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
194
        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
195
                                                        MBEDTLS_ASN1_SET ) );
196
 
197
        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
198
                                          MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) );
199
 
200
        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
201
        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
202
                                                        MBEDTLS_ASN1_SEQUENCE ) );
203
    }
204
 
205
    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
206
    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
207
                                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC ) );
208
 
209
    MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key,
210
                                                tmp_buf, c - tmp_buf ) );
211
    c -= pub_len;
212
    len += pub_len;
213
 
214
    /*
215
     *  Subject  ::=  Name
216
     */
217
    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) );
218
 
219
    /*
220
     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
221
     */
222
    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) );
223
 
224
    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
225
    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
226
                                                    MBEDTLS_ASN1_SEQUENCE ) );
227
 
228
    /*
229
     * Prepare signature
230
     */
231
    ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
232
    if( ret != 0 )
233
        return( ret );
234
 
235
    if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
236
                                 f_rng, p_rng ) ) != 0 )
237
    {
238
        return( ret );
239
    }
240
 
241
    if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) )
242
        pk_alg = MBEDTLS_PK_RSA;
243
    else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) )
244
        pk_alg = MBEDTLS_PK_ECDSA;
245
    else
246
        return( MBEDTLS_ERR_X509_INVALID_ALG );
247
 
248
    if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
249
                                                &sig_oid, &sig_oid_len ) ) != 0 )
250
    {
251
        return( ret );
252
    }
253
 
254
    /*
255
     * Write data to output buffer
256
     */
257
    c2 = buf + size;
258
    MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
259
                                        sig_oid, sig_oid_len, sig, sig_len ) );
260
 
261
    if( len > (size_t)( c2 - buf ) )
262
        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
263
 
264
    c2 -= len;
265
    memcpy( c2, c, len );
266
 
267
    len += sig_and_oid_len;
268
    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
269
    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED |
270
                                                 MBEDTLS_ASN1_SEQUENCE ) );
271
 
272
    return( (int) len );
273
}
274
 
275
#define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
276
#define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
277
 
278
#if defined(MBEDTLS_PEM_WRITE_C)
279
int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
280
                       int (*f_rng)(void *, unsigned char *, size_t),
281
                       void *p_rng )
282
{
283
    int ret;
284
    unsigned char output_buf[4096];
285
    size_t olen = 0;
286
 
287
    if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf),
288
                                   f_rng, p_rng ) ) < 0 )
289
    {
290
        return( ret );
291
    }
292
 
293
    if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
294
                                  output_buf + sizeof(output_buf) - ret,
295
                                  ret, buf, size, &olen ) ) != 0 )
296
    {
297
        return( ret );
298
    }
299
 
300
    return( 0 );
301
}
302
#endif /* MBEDTLS_PEM_WRITE_C */
303
 
304
#endif /* MBEDTLS_X509_CSR_WRITE_C */