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 */>>>>>> |