1 /*
2  *  X.509 Certificate Signing Request writing
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  *
7  *  This file is provided under the Apache License 2.0, or the
8  *  GNU General Public License v2.0 or later.
9  *
10  *  **********
11  *  Apache License 2.0:
12  *
13  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
14  *  not use this file except in compliance with the License.
15  *  You may obtain a copy of the License at
16  *
17  *  http://www.apache.org/licenses/LICENSE-2.0
18  *
19  *  Unless required by applicable law or agreed to in writing, software
20  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the License for the specific language governing permissions and
23  *  limitations under the License.
24  *
25  *  **********
26  *
27  *  **********
28  *  GNU General Public License v2.0 or later:
29  *
30  *  This program is free software; you can redistribute it and/or modify
31  *  it under the terms of the GNU General Public License as published by
32  *  the Free Software Foundation; either version 2 of the License, or
33  *  (at your option) any later version.
34  *
35  *  This program is distributed in the hope that it will be useful,
36  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
37  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  *  GNU General Public License for more details.
39  *
40  *  You should have received a copy of the GNU General Public License along
41  *  with this program; if not, write to the Free Software Foundation, Inc.,
42  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43  *
44  *  **********
45  */
46 /*
47  * References:
48  * - CSRs: PKCS#10 v1.7 aka RFC 2986
49  * - attributes: PKCS#9 v2.0 aka RFC 2985
50  */
51 
52 #if !defined(MBEDTLS_CONFIG_FILE)
53 #include "mbedtls/config.h"
54 #else
55 #include MBEDTLS_CONFIG_FILE
56 #endif
57 
58 #if defined(MBEDTLS_X509_CSR_WRITE_C)
59 
60 #include "mbedtls/x509_csr.h"
61 #include "mbedtls/oid.h"
62 #include "mbedtls/asn1write.h"
63 #include "mbedtls/platform_util.h"
64 
65 #include <string.h>
66 #include <stdlib.h>
67 
68 #if defined(MBEDTLS_PEM_WRITE_C)
69 #include "mbedtls/pem.h"
70 #endif
71 
72 /*
73  * For the currently used signature algorithms the buffer to store any signature
74  * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
75  */
76 #if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
77 #define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
78 #else
79 #define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
80 #endif
81 
82 #if defined(MBEDTLS_PLATFORM_C)
83 #include "mbedtls/platform.h"
84 #else
85 #include <stdlib.h>
86 #define mbedtls_calloc    calloc
87 #define mbedtls_free      free
88 #endif
89 
90 void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )
91 {
92     memset( ctx, 0, sizeof( mbedtls_x509write_csr ) );
93 }
94 
95 void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx )
96 {
97     mbedtls_asn1_free_named_data_list( &ctx->subject );
98     mbedtls_asn1_free_named_data_list( &ctx->extensions );
99 
100     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) );
101 }
102 
103 void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg )
104 {
105     ctx->md_alg = md_alg;
106 }
107 
108 void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key )
109 {
110     ctx->key = key;
111 }
112 
113 int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx,
114                                     const char *subject_name )
115 {
116     return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
117 }
118 
119 int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx,
120                                  const char *oid, size_t oid_len,
121                                  const unsigned char *val, size_t val_len )
122 {
123     return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
124                                0, val, val_len );
125 }
126 
127 static size_t csr_get_unused_bits_for_named_bitstring( unsigned char bitstring,
128                                                        size_t bit_offset )
129 {
130     size_t unused_bits;
131 
132      /* Count the unused bits removing trailing 0s */
133     for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ )
134         if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 )
135             break;
136 
137      return( unused_bits );
138 }
139 
140 int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage )
141 {
142     unsigned char buf[4];
143     unsigned char *c;
144     size_t unused_bits;
145     int ret;
146 
147     c = buf + 4;
148 
149     unused_bits = csr_get_unused_bits_for_named_bitstring( key_usage, 0 );
150     ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 8 - unused_bits );
151 
152     if( ret < 0 )
153         return( ret );
154     else if( ret < 3 || ret > 4 )
155         return( MBEDTLS_ERR_X509_INVALID_FORMAT );
156 
157     ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
158                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
159                                        c, (size_t)ret );
160     if( ret != 0 )
161         return( ret );
162 
163     return( 0 );
164 }
165 
166 int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx,
167                                     unsigned char ns_cert_type )
168 {
169     unsigned char buf[4];
170     unsigned char *c;
171     size_t unused_bits;
172     int ret;
173 
174     c = buf + 4;
175 
176     unused_bits = csr_get_unused_bits_for_named_bitstring( ns_cert_type, 0 );
177     ret = mbedtls_asn1_write_bitstring( &c,
178                                         buf,
179                                         &ns_cert_type,
180                                         8 - unused_bits );
181 
182     if( ret < 0 )
183         return( ret );
184     else if( ret < 3 || ret > 4 )
185         return( ret );
186 
187     ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
188                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
189                                        c, (size_t)ret );
190     if( ret != 0 )
191         return( ret );
192 
193     return( 0 );
194 }
195 
196 static int x509write_csr_der_internal( mbedtls_x509write_csr *ctx,
197                                  unsigned char *buf,
198                                  size_t size,
199                                  unsigned char *sig,
200                                  int (*f_rng)(void *, unsigned char *, size_t),
201                                  void *p_rng )
202 {
203     int ret;
204     const char *sig_oid;
205     size_t sig_oid_len = 0;
206     unsigned char *c, *c2;
207     unsigned char hash[64];
208     size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
209     size_t len = 0;
210     mbedtls_pk_type_t pk_alg;
211 
212     /* Write the CSR backwards starting from the end of buf */
213     c = buf + size;
214 
215     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, buf,
216                                                            ctx->extensions ) );
217 
218     if( len )
219     {
220         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
221         MBEDTLS_ASN1_CHK_ADD( len,
222             mbedtls_asn1_write_tag(
223                 &c, buf,
224                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
225 
226         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
227         MBEDTLS_ASN1_CHK_ADD( len,
228             mbedtls_asn1_write_tag(
229                 &c, buf,
230                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) );
231 
232         MBEDTLS_ASN1_CHK_ADD( len,
233             mbedtls_asn1_write_oid(
234                 &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
235                 MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) );
236 
237         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
238         MBEDTLS_ASN1_CHK_ADD( len,
239             mbedtls_asn1_write_tag(
240                 &c, buf,
241                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
242     }
243 
244     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
245     MBEDTLS_ASN1_CHK_ADD( len,
246         mbedtls_asn1_write_tag(
247             &c, buf,
248             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) );
249 
250     MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key,
251                                                               buf, c - buf ) );
252     c -= pub_len;
253     len += pub_len;
254 
255     /*
256      *  Subject  ::=  Name
257      */
258     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf,
259                                                          ctx->subject ) );
260 
261     /*
262      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
263      */
264     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );
265 
266     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
267     MBEDTLS_ASN1_CHK_ADD( len,
268         mbedtls_asn1_write_tag(
269             &c, buf,
270             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
271 
272     /*
273      * Sign the written CSR data into the sig buffer
274      * Note: hash errors can happen only after an internal error
275      */
276     ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
277     if( ret != 0 )
278         return( ret );
279 
280     if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
281                                  f_rng, p_rng ) ) != 0 )
282     {
283         return( ret );
284     }
285 
286     if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) )
287         pk_alg = MBEDTLS_PK_RSA;
288     else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) )
289         pk_alg = MBEDTLS_PK_ECDSA;
290     else
291         return( MBEDTLS_ERR_X509_INVALID_ALG );
292 
293     if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
294                                               &sig_oid, &sig_oid_len ) ) != 0 )
295     {
296         return( ret );
297     }
298 
299     /*
300      * Move the written CSR data to the start of buf to create space for
301      * writing the signature into buf.
302      */
303     memmove( buf, c, len );
304 
305     /*
306      * Write sig and its OID into buf backwards from the end of buf.
307      * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len
308      * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed.
309      */
310     c2 = buf + size;
311     MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len,
312         mbedtls_x509_write_sig( &c2, buf + len, sig_oid, sig_oid_len,
313                                 sig, sig_len ) );
314 
315     /*
316      * Compact the space between the CSR data and signature by moving the
317      * CSR data to the start of the signature.
318      */
319     c2 -= len;
320     memmove( c2, buf, len );
321 
322     /* ASN encode the total size and tag the CSR data with it. */
323     len += sig_and_oid_len;
324     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
325     MBEDTLS_ASN1_CHK_ADD( len,
326         mbedtls_asn1_write_tag(
327             &c2, buf,
328             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
329 
330     /* Zero the unused bytes at the start of buf */
331     memset( buf, 0, c2 - buf);
332 
333     return( (int) len );
334 }
335 
336 int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf,
337                                size_t size,
338                                int (*f_rng)(void *, unsigned char *, size_t),
339                                void *p_rng )
340 {
341     int ret;
342     unsigned char *sig;
343 
344     if( ( sig = mbedtls_calloc( 1, SIGNATURE_MAX_SIZE ) ) == NULL )
345     {
346         return( MBEDTLS_ERR_X509_ALLOC_FAILED );
347     }
348 
349     ret = x509write_csr_der_internal( ctx, buf, size, sig, f_rng, p_rng );
350 
351     mbedtls_free( sig );
352 
353     return( ret );
354 }
355 
356 #define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
357 #define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
358 
359 #if defined(MBEDTLS_PEM_WRITE_C)
360 int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
361                        int (*f_rng)(void *, unsigned char *, size_t),
362                        void *p_rng )
363 {
364     int ret;
365     unsigned char output_buf[4096];
366     size_t olen = 0;
367 
368     if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf),
369                                    f_rng, p_rng ) ) < 0 )
370     {
371         return( ret );
372     }
373 
374     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
375                                   output_buf + sizeof(output_buf) - ret,
376                                   ret, buf, size, &olen ) ) != 0 )
377     {
378         return( ret );
379     }
380 
381     return( 0 );
382 }
383 #endif /* MBEDTLS_PEM_WRITE_C */
384 
385 #endif /* MBEDTLS_X509_CSR_WRITE_C */
386