• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  X.509 certificate 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  * - certificates: RFC 5280, updated by RFC 6818
10  * - CSRs: PKCS#10 v1.7 aka RFC 2986
11  * - attributes: PKCS#9 v2.0 aka RFC 2985
12  */
13 
14 #include "common.h"
15 
16 #if defined(MBEDTLS_X509_CRT_WRITE_C)
17 
18 #include "mbedtls/x509_crt.h"
19 #include "mbedtls/asn1write.h"
20 #include "mbedtls/error.h"
21 #include "mbedtls/oid.h"
22 #include "mbedtls/platform_util.h"
23 #include "mbedtls/sha1.h"
24 
25 #include <string.h>
26 
27 #if defined(MBEDTLS_PEM_WRITE_C)
28 #include "mbedtls/pem.h"
29 #endif /* MBEDTLS_PEM_WRITE_C */
30 
mbedtls_x509write_crt_init(mbedtls_x509write_cert * ctx)31 void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx)
32 {
33     memset(ctx, 0, sizeof(mbedtls_x509write_cert));
34 
35     mbedtls_mpi_init(&ctx->serial);
36     ctx->version = MBEDTLS_X509_CRT_VERSION_3;
37 }
38 
mbedtls_x509write_crt_free(mbedtls_x509write_cert * ctx)39 void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx)
40 {
41     mbedtls_mpi_free(&ctx->serial);
42 
43     mbedtls_asn1_free_named_data_list(&ctx->subject);
44     mbedtls_asn1_free_named_data_list(&ctx->issuer);
45     mbedtls_asn1_free_named_data_list(&ctx->extensions);
46 
47     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_cert));
48 }
49 
mbedtls_x509write_crt_set_version(mbedtls_x509write_cert * ctx,int version)50 void mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx,
51                                        int version)
52 {
53     ctx->version = version;
54 }
55 
mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert * ctx,mbedtls_md_type_t md_alg)56 void mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert *ctx,
57                                       mbedtls_md_type_t md_alg)
58 {
59     ctx->md_alg = md_alg;
60 }
61 
mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert * ctx,mbedtls_pk_context * key)62 void mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert *ctx,
63                                            mbedtls_pk_context *key)
64 {
65     ctx->subject_key = key;
66 }
67 
mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert * ctx,mbedtls_pk_context * key)68 void mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert *ctx,
69                                           mbedtls_pk_context *key)
70 {
71     ctx->issuer_key = key;
72 }
73 
mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert * ctx,const char * subject_name)74 int mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert *ctx,
75                                            const char *subject_name)
76 {
77     return mbedtls_x509_string_to_names(&ctx->subject, subject_name);
78 }
79 
mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert * ctx,const char * issuer_name)80 int mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx,
81                                           const char *issuer_name)
82 {
83     return mbedtls_x509_string_to_names(&ctx->issuer, issuer_name);
84 }
85 
mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert * ctx,const mbedtls_mpi * serial)86 int mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx,
87                                      const mbedtls_mpi *serial)
88 {
89     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
90 
91     if (mbedtls_mpi_size(serial) > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) {
92         return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
93     }
94 
95     if ((ret = mbedtls_mpi_copy(&ctx->serial, serial)) != 0) {
96         return ret;
97     }
98 
99     return 0;
100 }
101 
mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert * ctx,const char * not_before,const char * not_after)102 int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx,
103                                        const char *not_before,
104                                        const char *not_after)
105 {
106     if (strlen(not_before) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
107         strlen(not_after)  != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1) {
108         return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
109     }
110     strncpy(ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN);
111     strncpy(ctx->not_after, not_after, MBEDTLS_X509_RFC5280_UTC_TIME_LEN);
112     ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
113     ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
114 
115     return 0;
116 }
117 
mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert * ctx,const char * oid,size_t oid_len,int critical,const unsigned char * val,size_t val_len)118 int mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx,
119                                         const char *oid, size_t oid_len,
120                                         int critical,
121                                         const unsigned char *val, size_t val_len)
122 {
123     return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len,
124                                       critical, val, val_len);
125 }
126 
mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert * ctx,int is_ca,int max_pathlen)127 int mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx,
128                                                 int is_ca, int max_pathlen)
129 {
130     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
131     unsigned char buf[9];
132     unsigned char *c = buf + sizeof(buf);
133     size_t len = 0;
134 
135     memset(buf, 0, sizeof(buf));
136 
137     if (is_ca && max_pathlen > 127) {
138         return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
139     }
140 
141     if (is_ca) {
142         if (max_pathlen >= 0) {
143             MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf,
144                                                              max_pathlen));
145         }
146         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(&c, buf, 1));
147     }
148 
149     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
150     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,
151                                                      MBEDTLS_ASN1_CONSTRUCTED |
152                                                      MBEDTLS_ASN1_SEQUENCE));
153 
154     return
155         mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
156                                             MBEDTLS_OID_SIZE(MBEDTLS_OID_BASIC_CONSTRAINTS),
157                                             is_ca, buf + sizeof(buf) - len, len);
158 }
159 
160 #if defined(MBEDTLS_SHA1_C)
mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert * ctx)161 int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx)
162 {
163     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
164     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
165     unsigned char *c = buf + sizeof(buf);
166     size_t len = 0;
167 
168     memset(buf, 0, sizeof(buf));
169     MBEDTLS_ASN1_CHK_ADD(len,
170                          mbedtls_pk_write_pubkey(&c, buf, ctx->subject_key));
171 
172     ret = mbedtls_sha1_ret(buf + sizeof(buf) - len, len,
173                            buf + sizeof(buf) - 20);
174     if (ret != 0) {
175         return ret;
176     }
177     c = buf + sizeof(buf) - 20;
178     len = 20;
179 
180     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
181     MBEDTLS_ASN1_CHK_ADD(len,
182                          mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_OCTET_STRING));
183 
184     return mbedtls_x509write_crt_set_extension(ctx,
185                                                MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
186                                                MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER),
187                                                0, buf + sizeof(buf) - len, len);
188 }
189 
mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert * ctx)190 int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx)
191 {
192     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
193     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
194     unsigned char *c = buf + sizeof(buf);
195     size_t len = 0;
196 
197     memset(buf, 0, sizeof(buf));
198     MBEDTLS_ASN1_CHK_ADD(len,
199                          mbedtls_pk_write_pubkey(&c, buf, ctx->issuer_key));
200 
201     ret = mbedtls_sha1_ret(buf + sizeof(buf) - len, len,
202                            buf + sizeof(buf) - 20);
203     if (ret != 0) {
204         return ret;
205     }
206     c = buf + sizeof(buf) - 20;
207     len = 20;
208 
209     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
210     MBEDTLS_ASN1_CHK_ADD(len,
211                          mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0));
212 
213     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
214     MBEDTLS_ASN1_CHK_ADD(len,
215                          mbedtls_asn1_write_tag(&c, buf,
216                                                 MBEDTLS_ASN1_CONSTRUCTED |
217                                                 MBEDTLS_ASN1_SEQUENCE));
218 
219     return mbedtls_x509write_crt_set_extension(
220         ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
221         MBEDTLS_OID_SIZE(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER),
222         0, buf + sizeof(buf) - len, len);
223 }
224 #endif /* MBEDTLS_SHA1_C */
225 
mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert * ctx,unsigned int key_usage)226 int mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx,
227                                         unsigned int key_usage)
228 {
229     unsigned char buf[5] = { 0 }, ku[2] = { 0 };
230     unsigned char *c;
231     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
232     const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
233                                       MBEDTLS_X509_KU_NON_REPUDIATION   |
234                                       MBEDTLS_X509_KU_KEY_ENCIPHERMENT  |
235                                       MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
236                                       MBEDTLS_X509_KU_KEY_AGREEMENT     |
237                                       MBEDTLS_X509_KU_KEY_CERT_SIGN     |
238                                       MBEDTLS_X509_KU_CRL_SIGN          |
239                                       MBEDTLS_X509_KU_ENCIPHER_ONLY     |
240                                       MBEDTLS_X509_KU_DECIPHER_ONLY;
241 
242     /* Check that nothing other than the allowed flags is set */
243     if ((key_usage & ~allowed_bits) != 0) {
244         return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
245     }
246 
247     c = buf + 5;
248     MBEDTLS_PUT_UINT16_LE(key_usage, ku, 0);
249     ret = mbedtls_asn1_write_named_bitstring(&c, buf, ku, 9);
250 
251     if (ret < 0) {
252         return ret;
253     } else if (ret < 3 || ret > 5) {
254         return MBEDTLS_ERR_X509_INVALID_FORMAT;
255     }
256 
257     ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_KEY_USAGE,
258                                               MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE),
259                                               1, c, (size_t) ret);
260     if (ret != 0) {
261         return ret;
262     }
263 
264     return 0;
265 }
266 
mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert * ctx,unsigned char ns_cert_type)267 int mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx,
268                                            unsigned char ns_cert_type)
269 {
270     unsigned char buf[4] = { 0 };
271     unsigned char *c;
272     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
273 
274     c = buf + 4;
275 
276     ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8);
277     if (ret < 3 || ret > 4) {
278         return ret;
279     }
280 
281     ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE,
282                                               MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE),
283                                               0, c, (size_t) ret);
284     if (ret != 0) {
285         return ret;
286     }
287 
288     return 0;
289 }
290 
x509_write_time(unsigned char ** p,unsigned char * start,const char * t,size_t size)291 static int x509_write_time(unsigned char **p, unsigned char *start,
292                            const char *t, size_t size)
293 {
294     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
295     size_t len = 0;
296 
297     /*
298      * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
299      */
300     if (t[0] < '2' || (t[0] == '2' && t[1] == '0' && t[2] < '5')) {
301         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
302                                                                 (const unsigned char *) t + 2,
303                                                                 size - 2));
304         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
305         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
306                                                          MBEDTLS_ASN1_UTC_TIME));
307     } else {
308         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
309                                                                 (const unsigned char *) t,
310                                                                 size));
311         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
312         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
313                                                          MBEDTLS_ASN1_GENERALIZED_TIME));
314     }
315 
316     return (int) len;
317 }
318 
mbedtls_x509write_crt_der(mbedtls_x509write_cert * ctx,unsigned char * buf,size_t size,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)319 int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx,
320                               unsigned char *buf, size_t size,
321                               int (*f_rng)(void *, unsigned char *, size_t),
322                               void *p_rng)
323 {
324     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
325     const char *sig_oid;
326     size_t sig_oid_len = 0;
327     unsigned char *c, *c2;
328     unsigned char hash[64];
329     unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
330     size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
331     size_t len = 0;
332     mbedtls_pk_type_t pk_alg;
333     int write_sig_null_par;
334 
335     /*
336      * Prepare data to be signed at the end of the target buffer
337      */
338     c = buf + size;
339 
340     /* Signature algorithm needed in TBS, and later for actual signature */
341 
342     /* There's no direct way of extracting a signature algorithm
343      * (represented as an element of mbedtls_pk_type_t) from a PK instance. */
344     if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_RSA)) {
345         pk_alg = MBEDTLS_PK_RSA;
346     } else if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_ECDSA)) {
347         pk_alg = MBEDTLS_PK_ECDSA;
348     } else {
349         return MBEDTLS_ERR_X509_INVALID_ALG;
350     }
351 
352     if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg,
353                                               &sig_oid, &sig_oid_len)) != 0) {
354         return ret;
355     }
356 
357     /*
358      *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
359      */
360 
361     /* Only for v3 */
362     if (ctx->version == MBEDTLS_X509_CRT_VERSION_3) {
363         MBEDTLS_ASN1_CHK_ADD(len,
364                              mbedtls_x509_write_extensions(&c,
365                                                            buf, ctx->extensions));
366         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
367         MBEDTLS_ASN1_CHK_ADD(len,
368                              mbedtls_asn1_write_tag(&c, buf,
369                                                     MBEDTLS_ASN1_CONSTRUCTED |
370                                                     MBEDTLS_ASN1_SEQUENCE));
371         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
372         MBEDTLS_ASN1_CHK_ADD(len,
373                              mbedtls_asn1_write_tag(&c, buf,
374                                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC |
375                                                     MBEDTLS_ASN1_CONSTRUCTED | 3));
376     }
377 
378     /*
379      *  SubjectPublicKeyInfo
380      */
381     MBEDTLS_ASN1_CHK_ADD(pub_len,
382                          mbedtls_pk_write_pubkey_der(ctx->subject_key,
383                                                      buf, c - buf));
384     c -= pub_len;
385     len += pub_len;
386 
387     /*
388      *  Subject  ::=  Name
389      */
390     MBEDTLS_ASN1_CHK_ADD(len,
391                          mbedtls_x509_write_names(&c, buf,
392                                                   ctx->subject));
393 
394     /*
395      *  Validity ::= SEQUENCE {
396      *       notBefore      Time,
397      *       notAfter       Time }
398      */
399     sub_len = 0;
400 
401     MBEDTLS_ASN1_CHK_ADD(sub_len,
402                          x509_write_time(&c, buf, ctx->not_after,
403                                          MBEDTLS_X509_RFC5280_UTC_TIME_LEN));
404 
405     MBEDTLS_ASN1_CHK_ADD(sub_len,
406                          x509_write_time(&c, buf, ctx->not_before,
407                                          MBEDTLS_X509_RFC5280_UTC_TIME_LEN));
408 
409     len += sub_len;
410     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, sub_len));
411     MBEDTLS_ASN1_CHK_ADD(len,
412                          mbedtls_asn1_write_tag(&c, buf,
413                                                 MBEDTLS_ASN1_CONSTRUCTED |
414                                                 MBEDTLS_ASN1_SEQUENCE));
415 
416     /*
417      *  Issuer  ::=  Name
418      */
419     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf,
420                                                        ctx->issuer));
421 
422     /*
423      *  Signature   ::=  AlgorithmIdentifier
424      */
425     if (pk_alg == MBEDTLS_PK_ECDSA) {
426         /*
427          * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature
428          * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and
429          * https://www.rfc-editor.org/rfc/rfc5758#section-3.
430          */
431         write_sig_null_par = 0;
432     } else {
433         write_sig_null_par = 1;
434     }
435     MBEDTLS_ASN1_CHK_ADD(len,
436                          mbedtls_asn1_write_algorithm_identifier_ext(&c, buf,
437                                                                      sig_oid, strlen(sig_oid),
438                                                                      0, write_sig_null_par));
439 
440     /*
441      *  Serial   ::=  INTEGER
442      */
443     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&c, buf,
444                                                      &ctx->serial));
445 
446     /*
447      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
448      */
449 
450     /* Can be omitted for v1 */
451     if (ctx->version != MBEDTLS_X509_CRT_VERSION_1) {
452         sub_len = 0;
453         MBEDTLS_ASN1_CHK_ADD(sub_len,
454                              mbedtls_asn1_write_int(&c, buf, ctx->version));
455         len += sub_len;
456         MBEDTLS_ASN1_CHK_ADD(len,
457                              mbedtls_asn1_write_len(&c, buf, sub_len));
458         MBEDTLS_ASN1_CHK_ADD(len,
459                              mbedtls_asn1_write_tag(&c, buf,
460                                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC |
461                                                     MBEDTLS_ASN1_CONSTRUCTED | 0));
462     }
463 
464     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
465     MBEDTLS_ASN1_CHK_ADD(len,
466                          mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
467                                                 MBEDTLS_ASN1_SEQUENCE));
468 
469     /*
470      * Make signature
471      */
472 
473     /* Compute hash of CRT. */
474     if ((ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c,
475                           len, hash)) != 0) {
476         return ret;
477     }
478 
479     if ((ret = mbedtls_pk_sign(ctx->issuer_key, ctx->md_alg,
480                                hash, 0, sig, &sig_len,
481                                f_rng, p_rng)) != 0) {
482         return ret;
483     }
484 
485     /* Move CRT to the front of the buffer to have space
486      * for the signature. */
487     memmove(buf, c, len);
488     c = buf + len;
489 
490     /* Add signature at the end of the buffer,
491      * making sure that it doesn't underflow
492      * into the CRT buffer. */
493     c2 = buf + size;
494     MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, mbedtls_x509_write_sig(&c2, c,
495                                                                  sig_oid, sig_oid_len,
496                                                                  sig, sig_len, pk_alg));
497 
498     /*
499      * Memory layout after this step:
500      *
501      * buf       c=buf+len                c2            buf+size
502      * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm]
503      */
504 
505     /* Move raw CRT to just before the signature. */
506     c = c2 - len;
507     memmove(c, buf, len);
508 
509     len += sig_and_oid_len;
510     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
511     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,
512                                                      MBEDTLS_ASN1_CONSTRUCTED |
513                                                      MBEDTLS_ASN1_SEQUENCE));
514 
515     return (int) len;
516 }
517 
518 #define PEM_BEGIN_CRT           "-----BEGIN CERTIFICATE-----\n"
519 #define PEM_END_CRT             "-----END CERTIFICATE-----\n"
520 
521 #if defined(MBEDTLS_PEM_WRITE_C)
mbedtls_x509write_crt_pem(mbedtls_x509write_cert * crt,unsigned char * buf,size_t size,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)522 int mbedtls_x509write_crt_pem(mbedtls_x509write_cert *crt,
523                               unsigned char *buf, size_t size,
524                               int (*f_rng)(void *, unsigned char *, size_t),
525                               void *p_rng)
526 {
527     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
528     size_t olen;
529 
530     if ((ret = mbedtls_x509write_crt_der(crt, buf, size,
531                                          f_rng, p_rng)) < 0) {
532         return ret;
533     }
534 
535     if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CRT, PEM_END_CRT,
536                                         buf + size - ret, ret,
537                                         buf, size, &olen)) != 0) {
538         return ret;
539     }
540 
541     return 0;
542 }
543 #endif /* MBEDTLS_PEM_WRITE_C */
544 
545 #endif /* MBEDTLS_X509_CRT_WRITE_C */
546