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 /*
8  * References:
9  * - CSRs: PKCS#10 v1.7 aka RFC 2986
10  * - attributes: PKCS#9 v2.0 aka RFC 2985
11  */
12 
13 #include "common.h"
14 
15 #if defined(MBEDTLS_X509_CSR_WRITE_C)
16 
17 #include "x509_internal.h"
18 #include "mbedtls/x509_csr.h"
19 #include "mbedtls/asn1write.h"
20 #include "mbedtls/error.h"
21 #include "mbedtls/oid.h"
22 #include "mbedtls/platform_util.h"
23 
24 #if defined(MBEDTLS_USE_PSA_CRYPTO)
25 #include "psa/crypto.h"
26 #include "psa_util_internal.h"
27 #include "mbedtls/psa_util.h"
28 #endif /* MBEDTLS_USE_PSA_CRYPTO */
29 
30 #include <string.h>
31 #include <stdlib.h>
32 
33 #if defined(MBEDTLS_PEM_WRITE_C)
34 #include "mbedtls/pem.h"
35 #endif
36 
37 #include "mbedtls/platform.h"
38 
mbedtls_x509write_csr_init(mbedtls_x509write_csr * ctx)39 void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx)
40 {
41     memset(ctx, 0, sizeof(mbedtls_x509write_csr));
42 }
43 
mbedtls_x509write_csr_free(mbedtls_x509write_csr * ctx)44 void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx)
45 {
46     if (ctx == NULL) {
47         return;
48     }
49 
50     mbedtls_asn1_free_named_data_list(&ctx->subject);
51     mbedtls_asn1_free_named_data_list(&ctx->extensions);
52 
53     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr));
54 }
55 
mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr * ctx,mbedtls_md_type_t md_alg)56 void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg)
57 {
58     ctx->md_alg = md_alg;
59 }
60 
mbedtls_x509write_csr_set_key(mbedtls_x509write_csr * ctx,mbedtls_pk_context * key)61 void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key)
62 {
63     ctx->key = key;
64 }
65 
mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr * ctx,const char * subject_name)66 int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx,
67                                            const char *subject_name)
68 {
69     return mbedtls_x509_string_to_names(&ctx->subject, subject_name);
70 }
71 
mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr * ctx,const char * oid,size_t oid_len,int critical,const unsigned char * val,size_t val_len)72 int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx,
73                                         const char *oid, size_t oid_len,
74                                         int critical,
75                                         const unsigned char *val, size_t val_len)
76 {
77     return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len,
78                                       critical, val, val_len);
79 }
80 
mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr * ctx,const mbedtls_x509_san_list * san_list)81 int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx,
82                                                        const mbedtls_x509_san_list *san_list)
83 {
84     return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list);
85 }
86 
mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr * ctx,unsigned char key_usage)87 int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage)
88 {
89     unsigned char buf[4] = { 0 };
90     unsigned char *c;
91     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
92 
93     c = buf + 4;
94 
95     ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8);
96     if (ret < 3 || ret > 4) {
97         return ret;
98     }
99 
100     ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE,
101                                               MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE),
102                                               0, c, (size_t) ret);
103     if (ret != 0) {
104         return ret;
105     }
106 
107     return 0;
108 }
109 
mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr * ctx,unsigned char ns_cert_type)110 int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx,
111                                            unsigned char ns_cert_type)
112 {
113     unsigned char buf[4] = { 0 };
114     unsigned char *c;
115     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
116 
117     c = buf + 4;
118 
119     ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8);
120     if (ret < 3 || ret > 4) {
121         return ret;
122     }
123 
124     ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE,
125                                               MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE),
126                                               0, c, (size_t) ret);
127     if (ret != 0) {
128         return ret;
129     }
130 
131     return 0;
132 }
133 
x509write_csr_der_internal(mbedtls_x509write_csr * ctx,unsigned char * buf,size_t size,unsigned char * sig,size_t sig_size,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)134 static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
135                                       unsigned char *buf,
136                                       size_t size,
137                                       unsigned char *sig, size_t sig_size,
138                                       int (*f_rng)(void *, unsigned char *, size_t),
139                                       void *p_rng)
140 {
141     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
142     const char *sig_oid;
143     size_t sig_oid_len = 0;
144     unsigned char *c, *c2;
145     unsigned char hash[MBEDTLS_MD_MAX_SIZE];
146     size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
147     size_t len = 0;
148     mbedtls_pk_type_t pk_alg;
149 #if defined(MBEDTLS_USE_PSA_CRYPTO)
150     size_t hash_len;
151     psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ctx->md_alg);
152 #endif /* MBEDTLS_USE_PSA_CRYPTO */
153 
154     /* Write the CSR backwards starting from the end of buf */
155     c = buf + size;
156 
157     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf,
158                                                             ctx->extensions));
159 
160     if (len) {
161         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
162         MBEDTLS_ASN1_CHK_ADD(len,
163                              mbedtls_asn1_write_tag(
164                                  &c, buf,
165                                  MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
166 
167         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
168         MBEDTLS_ASN1_CHK_ADD(len,
169                              mbedtls_asn1_write_tag(
170                                  &c, buf,
171                                  MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET));
172 
173         MBEDTLS_ASN1_CHK_ADD(len,
174                              mbedtls_asn1_write_oid(
175                                  &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
176                                  MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ)));
177 
178         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
179         MBEDTLS_ASN1_CHK_ADD(len,
180                              mbedtls_asn1_write_tag(
181                                  &c, buf,
182                                  MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
183     }
184 
185     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
186     MBEDTLS_ASN1_CHK_ADD(len,
187                          mbedtls_asn1_write_tag(
188                              &c, buf,
189                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC));
190 
191     MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key,
192                                                               buf, (size_t) (c - buf)));
193     c -= pub_len;
194     len += pub_len;
195 
196     /*
197      *  Subject  ::=  Name
198      */
199     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf,
200                                                        ctx->subject));
201 
202     /*
203      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
204      */
205     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0));
206 
207     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
208     MBEDTLS_ASN1_CHK_ADD(len,
209                          mbedtls_asn1_write_tag(
210                              &c, buf,
211                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
212 
213     /*
214      * Sign the written CSR data into the sig buffer
215      * Note: hash errors can happen only after an internal error
216      */
217 #if defined(MBEDTLS_USE_PSA_CRYPTO)
218     if (psa_hash_compute(hash_alg,
219                          c,
220                          len,
221                          hash,
222                          sizeof(hash),
223                          &hash_len) != PSA_SUCCESS) {
224         return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
225     }
226 #else /* MBEDTLS_USE_PSA_CRYPTO */
227     ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash);
228     if (ret != 0) {
229         return ret;
230     }
231 #endif
232     if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0,
233                                sig, sig_size, &sig_len,
234                                f_rng, p_rng)) != 0) {
235         return ret;
236     }
237 
238     if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) {
239         pk_alg = MBEDTLS_PK_RSA;
240     } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) {
241         pk_alg = MBEDTLS_PK_ECDSA;
242     } else {
243         return MBEDTLS_ERR_X509_INVALID_ALG;
244     }
245 
246     if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg,
247                                               &sig_oid, &sig_oid_len)) != 0) {
248         return ret;
249     }
250 
251     /*
252      * Move the written CSR data to the start of buf to create space for
253      * writing the signature into buf.
254      */
255     memmove(buf, c, len);
256 
257     /*
258      * Write sig and its OID into buf backwards from the end of buf.
259      * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len
260      * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed.
261      */
262     c2 = buf + size;
263     MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len,
264                          mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len,
265                                                 sig, sig_len, pk_alg));
266 
267     /*
268      * Compact the space between the CSR data and signature by moving the
269      * CSR data to the start of the signature.
270      */
271     c2 -= len;
272     memmove(c2, buf, len);
273 
274     /* ASN encode the total size and tag the CSR data with it. */
275     len += sig_and_oid_len;
276     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len));
277     MBEDTLS_ASN1_CHK_ADD(len,
278                          mbedtls_asn1_write_tag(
279                              &c2, buf,
280                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
281 
282     /* Zero the unused bytes at the start of buf */
283     memset(buf, 0, (size_t) (c2 - buf));
284 
285     return (int) len;
286 }
287 
mbedtls_x509write_csr_der(mbedtls_x509write_csr * ctx,unsigned char * buf,size_t size,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)288 int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf,
289                               size_t size,
290                               int (*f_rng)(void *, unsigned char *, size_t),
291                               void *p_rng)
292 {
293     int ret;
294     unsigned char *sig;
295 
296     if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) {
297         return MBEDTLS_ERR_X509_ALLOC_FAILED;
298     }
299 
300     ret = x509write_csr_der_internal(ctx, buf, size,
301                                      sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE,
302                                      f_rng, p_rng);
303 
304     mbedtls_free(sig);
305 
306     return ret;
307 }
308 
309 #define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
310 #define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
311 
312 #if defined(MBEDTLS_PEM_WRITE_C)
mbedtls_x509write_csr_pem(mbedtls_x509write_csr * ctx,unsigned char * buf,size_t size,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)313 int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
314                               int (*f_rng)(void *, unsigned char *, size_t),
315                               void *p_rng)
316 {
317     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
318     size_t olen = 0;
319 
320     if ((ret = mbedtls_x509write_csr_der(ctx, buf, size,
321                                          f_rng, p_rng)) < 0) {
322         return ret;
323     }
324 
325     if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR,
326                                         buf + size - ret,
327                                         ret, buf, size, &olen)) != 0) {
328         return ret;
329     }
330 
331     return 0;
332 }
333 #endif /* MBEDTLS_PEM_WRITE_C */
334 
335 #endif /* MBEDTLS_X509_CSR_WRITE_C */
336