• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  X.509 Certificate Signing Request writing
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0
6  *
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8  *  not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  */
19 /*
20  * References:
21  * - CSRs: PKCS#10 v1.7 aka RFC 2986
22  * - attributes: PKCS#9 v2.0 aka RFC 2985
23  */
24 
25 #include "common.h"
26 
27 #if defined(MBEDTLS_X509_CSR_WRITE_C)
28 
29 #include "mbedtls/x509.h"
30 #include "mbedtls/x509_csr.h"
31 #include "mbedtls/asn1write.h"
32 #include "mbedtls/error.h"
33 #include "mbedtls/oid.h"
34 #include "mbedtls/platform_util.h"
35 
36 #if defined(MBEDTLS_USE_PSA_CRYPTO)
37 #include "psa/crypto.h"
38 #include "mbedtls/psa_util.h"
39 #endif /* MBEDTLS_USE_PSA_CRYPTO */
40 #include "hash_info.h"
41 
42 #include <string.h>
43 #include <stdlib.h>
44 
45 #if defined(MBEDTLS_PEM_WRITE_C)
46 #include "mbedtls/pem.h"
47 #endif
48 
49 #include "mbedtls/platform.h"
50 
mbedtls_x509write_csr_init(mbedtls_x509write_csr * ctx)51 void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx)
52 {
53     memset(ctx, 0, sizeof(mbedtls_x509write_csr));
54 }
55 
mbedtls_x509write_csr_free(mbedtls_x509write_csr * ctx)56 void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx)
57 {
58     mbedtls_asn1_free_named_data_list(&ctx->subject);
59     mbedtls_asn1_free_named_data_list(&ctx->extensions);
60 
61     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr));
62 }
63 
mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr * ctx,mbedtls_md_type_t md_alg)64 void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg)
65 {
66     ctx->md_alg = md_alg;
67 }
68 
mbedtls_x509write_csr_set_key(mbedtls_x509write_csr * ctx,mbedtls_pk_context * key)69 void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key)
70 {
71     ctx->key = key;
72 }
73 
mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr * ctx,const char * subject_name)74 int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx,
75                                            const char *subject_name)
76 {
77     return mbedtls_x509_string_to_names(&ctx->subject, subject_name);
78 }
79 
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)80 int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx,
81                                         const char *oid, size_t oid_len,
82                                         int critical,
83                                         const unsigned char *val, size_t val_len)
84 {
85     return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len,
86                                       critical, val, val_len);
87 }
88 
mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr * ctx,const mbedtls_x509_san_list * san_list)89 int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx,
90                                                        const mbedtls_x509_san_list *san_list)
91 {
92     int ret = 0;
93     const mbedtls_x509_san_list *cur;
94     unsigned char *buf;
95     unsigned char *p;
96     size_t len;
97     size_t buflen = 0;
98 
99     /* Determine the maximum size of the SubjectAltName list */
100     for (cur = san_list; cur != NULL; cur = cur->next) {
101         /* Calculate size of the required buffer */
102         switch (cur->node.type) {
103             case MBEDTLS_X509_SAN_DNS_NAME:
104             case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
105             case MBEDTLS_X509_SAN_IP_ADDRESS:
106                 /* length of value for each name entry,
107                  * maximum 4 bytes for the length field,
108                  * 1 byte for the tag/type.
109                  */
110                 buflen += cur->node.san.unstructured_name.len + 4 + 1;
111                 break;
112 
113             default:
114                 /* Not supported - skip. */
115                 break;
116         }
117     }
118 
119     /* Add the extra length field and tag */
120     buflen += 4 + 1;
121 
122     /* Allocate buffer */
123     buf = mbedtls_calloc(1, buflen);
124     if (buf == NULL) {
125         return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
126     }
127 
128     mbedtls_platform_zeroize(buf, buflen);
129     p = buf + buflen;
130 
131     /* Write ASN.1-based structure */
132     cur = san_list;
133     len = 0;
134     while (cur != NULL) {
135         switch (cur->node.type) {
136             case MBEDTLS_X509_SAN_DNS_NAME:
137             case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
138             case MBEDTLS_X509_SAN_IP_ADDRESS:
139             {
140                 const unsigned char *unstructured_name =
141                     (const unsigned char *) cur->node.san.unstructured_name.p;
142                 size_t unstructured_name_len = cur->node.san.unstructured_name.len;
143 
144                 MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,
145                                              mbedtls_asn1_write_raw_buffer(
146                                                  &p, buf,
147                                                  unstructured_name, unstructured_name_len));
148                 MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(
149                                                  &p, buf, unstructured_name_len));
150                 MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,
151                                              mbedtls_asn1_write_tag(
152                                                  &p, buf,
153                                                  MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type));
154             }
155             break;
156             default:
157                 /* Skip unsupported names. */
158                 break;
159         }
160         cur = cur->next;
161     }
162 
163     MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
164     MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,
165                                  mbedtls_asn1_write_tag(&p, buf,
166                                                         MBEDTLS_ASN1_CONSTRUCTED |
167                                                         MBEDTLS_ASN1_SEQUENCE));
168 
169     ret = mbedtls_x509write_csr_set_extension(
170         ctx,
171         MBEDTLS_OID_SUBJECT_ALT_NAME,
172         MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME),
173         0,
174         buf + buflen - len,
175         len);
176 
177     /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list
178      * was incorrectly calculated and memory is corrupted. */
179     if (p < buf) {
180         ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
181     }
182 
183 cleanup:
184     mbedtls_free(buf);
185     return ret;
186 }
187 
mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr * ctx,unsigned char key_usage)188 int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage)
189 {
190     unsigned char buf[4] = { 0 };
191     unsigned char *c;
192     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
193 
194     c = buf + 4;
195 
196     ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8);
197     if (ret < 3 || ret > 4) {
198         return ret;
199     }
200 
201     ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE,
202                                               MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE),
203                                               0, c, (size_t) ret);
204     if (ret != 0) {
205         return ret;
206     }
207 
208     return 0;
209 }
210 
mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr * ctx,unsigned char ns_cert_type)211 int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx,
212                                            unsigned char ns_cert_type)
213 {
214     unsigned char buf[4] = { 0 };
215     unsigned char *c;
216     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
217 
218     c = buf + 4;
219 
220     ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8);
221     if (ret < 3 || ret > 4) {
222         return ret;
223     }
224 
225     ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE,
226                                               MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE),
227                                               0, c, (size_t) ret);
228     if (ret != 0) {
229         return ret;
230     }
231 
232     return 0;
233 }
234 
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)235 static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
236                                       unsigned char *buf,
237                                       size_t size,
238                                       unsigned char *sig, size_t sig_size,
239                                       int (*f_rng)(void *, unsigned char *, size_t),
240                                       void *p_rng)
241 {
242     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
243     const char *sig_oid;
244     size_t sig_oid_len = 0;
245     unsigned char *c, *c2;
246     unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
247     size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
248     size_t len = 0;
249     mbedtls_pk_type_t pk_alg;
250 #if defined(MBEDTLS_USE_PSA_CRYPTO)
251     size_t hash_len;
252     psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(ctx->md_alg);
253 #endif /* MBEDTLS_USE_PSA_CRYPTO */
254 
255     /* Write the CSR backwards starting from the end of buf */
256     c = buf + size;
257 
258     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf,
259                                                             ctx->extensions));
260 
261     if (len) {
262         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
263         MBEDTLS_ASN1_CHK_ADD(len,
264                              mbedtls_asn1_write_tag(
265                                  &c, buf,
266                                  MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
267 
268         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
269         MBEDTLS_ASN1_CHK_ADD(len,
270                              mbedtls_asn1_write_tag(
271                                  &c, buf,
272                                  MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET));
273 
274         MBEDTLS_ASN1_CHK_ADD(len,
275                              mbedtls_asn1_write_oid(
276                                  &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
277                                  MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ)));
278 
279         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
280         MBEDTLS_ASN1_CHK_ADD(len,
281                              mbedtls_asn1_write_tag(
282                                  &c, buf,
283                                  MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
284     }
285 
286     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
287     MBEDTLS_ASN1_CHK_ADD(len,
288                          mbedtls_asn1_write_tag(
289                              &c, buf,
290                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC));
291 
292     MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key,
293                                                               buf, c - buf));
294     c -= pub_len;
295     len += pub_len;
296 
297     /*
298      *  Subject  ::=  Name
299      */
300     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf,
301                                                        ctx->subject));
302 
303     /*
304      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
305      */
306     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0));
307 
308     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
309     MBEDTLS_ASN1_CHK_ADD(len,
310                          mbedtls_asn1_write_tag(
311                              &c, buf,
312                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
313 
314     /*
315      * Sign the written CSR data into the sig buffer
316      * Note: hash errors can happen only after an internal error
317      */
318 #if defined(MBEDTLS_USE_PSA_CRYPTO)
319     if (psa_hash_compute(hash_alg,
320                          c,
321                          len,
322                          hash,
323                          sizeof(hash),
324                          &hash_len) != PSA_SUCCESS) {
325         return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
326     }
327 #else /* MBEDTLS_USE_PSA_CRYPTO */
328     ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash);
329     if (ret != 0) {
330         return ret;
331     }
332 #endif
333     if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0,
334                                sig, sig_size, &sig_len,
335                                f_rng, p_rng)) != 0) {
336         return ret;
337     }
338 
339     if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) {
340         pk_alg = MBEDTLS_PK_RSA;
341     } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) {
342         pk_alg = MBEDTLS_PK_ECDSA;
343     } else {
344         return MBEDTLS_ERR_X509_INVALID_ALG;
345     }
346 
347     if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg,
348                                               &sig_oid, &sig_oid_len)) != 0) {
349         return ret;
350     }
351 
352     /*
353      * Move the written CSR data to the start of buf to create space for
354      * writing the signature into buf.
355      */
356     memmove(buf, c, len);
357 
358     /*
359      * Write sig and its OID into buf backwards from the end of buf.
360      * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len
361      * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed.
362      */
363     c2 = buf + size;
364     MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len,
365                          mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len,
366                                                 sig, sig_len));
367 
368     /*
369      * Compact the space between the CSR data and signature by moving the
370      * CSR data to the start of the signature.
371      */
372     c2 -= len;
373     memmove(c2, buf, len);
374 
375     /* ASN encode the total size and tag the CSR data with it. */
376     len += sig_and_oid_len;
377     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len));
378     MBEDTLS_ASN1_CHK_ADD(len,
379                          mbedtls_asn1_write_tag(
380                              &c2, buf,
381                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
382 
383     /* Zero the unused bytes at the start of buf */
384     memset(buf, 0, c2 - buf);
385 
386     return (int) len;
387 }
388 
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)389 int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf,
390                               size_t size,
391                               int (*f_rng)(void *, unsigned char *, size_t),
392                               void *p_rng)
393 {
394     int ret;
395     unsigned char *sig;
396 
397     if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) {
398         return MBEDTLS_ERR_X509_ALLOC_FAILED;
399     }
400 
401     ret = x509write_csr_der_internal(ctx, buf, size,
402                                      sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE,
403                                      f_rng, p_rng);
404 
405     mbedtls_free(sig);
406 
407     return ret;
408 }
409 
410 #define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
411 #define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
412 
413 #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)414 int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
415                               int (*f_rng)(void *, unsigned char *, size_t),
416                               void *p_rng)
417 {
418     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
419     size_t olen = 0;
420 
421     if ((ret = mbedtls_x509write_csr_der(ctx, buf, size,
422                                          f_rng, p_rng)) < 0) {
423         return ret;
424     }
425 
426     if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR,
427                                         buf + size - ret,
428                                         ret, buf, size, &olen)) != 0) {
429         return ret;
430     }
431 
432     return 0;
433 }
434 #endif /* MBEDTLS_PEM_WRITE_C */
435 
436 #endif /* MBEDTLS_X509_CSR_WRITE_C */
437