xref: /third_party/mbedtls/library/x509_csr.c (revision a8e1175b)
1/*
2 *  X.509 Certificate Signing Request (CSR) parsing
3 *
4 *  Copyright The Mbed TLS Contributors
5 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 */
7/*
8 *  The ITU-T X.509 standard defines a certificate format for PKI.
9 *
10 *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
11 *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
12 *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
13 *
14 *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
15 *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
16 */
17
18#include "common.h"
19
20#if defined(MBEDTLS_X509_CSR_PARSE_C)
21
22#include "mbedtls/x509_csr.h"
23#include "x509_internal.h"
24#include "mbedtls/error.h"
25#include "mbedtls/oid.h"
26#include "mbedtls/platform_util.h"
27
28#include <string.h>
29
30#if defined(MBEDTLS_PEM_PARSE_C)
31#include "mbedtls/pem.h"
32#endif
33
34#include "mbedtls/platform.h"
35
36#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
37#include <stdio.h>
38#endif
39
40/*
41 *  Version  ::=  INTEGER  {  v1(0)  }
42 */
43static int x509_csr_get_version(unsigned char **p,
44                                const unsigned char *end,
45                                int *ver)
46{
47    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
48
49    if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {
50        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
51            *ver = 0;
52            return 0;
53        }
54
55        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);
56    }
57
58    return 0;
59}
60
61/*
62 * Parse CSR extension requests in DER format
63 */
64static int x509_csr_parse_extensions(mbedtls_x509_csr *csr,
65                                     unsigned char **p, const unsigned char *end,
66                                     mbedtls_x509_csr_ext_cb_t cb,
67                                     void *p_ctx)
68{
69    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
70    size_t len;
71    unsigned char *end_ext_data, *end_ext_octet;
72
73    while (*p < end) {
74        mbedtls_x509_buf extn_oid = { 0, 0, NULL };
75        int is_critical = 0; /* DEFAULT FALSE */
76        int ext_type = 0;
77
78        /* Read sequence tag */
79        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
80                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
81            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
82        }
83
84        end_ext_data = *p + len;
85
86        /* Get extension ID */
87        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len,
88                                        MBEDTLS_ASN1_OID)) != 0) {
89            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
90        }
91
92        extn_oid.tag = MBEDTLS_ASN1_OID;
93        extn_oid.p = *p;
94        *p += extn_oid.len;
95
96        /* Get optional critical */
97        if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 &&
98            (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
99            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
100        }
101
102        /* Data should be octet string type */
103        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
104                                        MBEDTLS_ASN1_OCTET_STRING)) != 0) {
105            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
106        }
107
108        end_ext_octet = *p + len;
109
110        if (end_ext_octet != end_ext_data) {
111            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
112                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
113        }
114
115        /*
116         * Detect supported extensions and skip unsupported extensions
117         */
118        ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
119
120        if (ret != 0) {
121            /* Give the callback (if any) a chance to handle the extension */
122            if (cb != NULL) {
123                ret = cb(p_ctx, csr, &extn_oid, is_critical, *p, end_ext_octet);
124                if (ret != 0 && is_critical) {
125                    return ret;
126                }
127                *p = end_ext_octet;
128                continue;
129            }
130
131            /* No parser found, skip extension */
132            *p = end_ext_octet;
133
134            if (is_critical) {
135                /* Data is marked as critical: fail */
136                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
137                                         MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
138            }
139            continue;
140        }
141
142        /* Forbid repeated extensions */
143        if ((csr->ext_types & ext_type) != 0) {
144            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
145                                     MBEDTLS_ERR_ASN1_INVALID_DATA);
146        }
147
148        csr->ext_types |= ext_type;
149
150        switch (ext_type) {
151            case MBEDTLS_X509_EXT_KEY_USAGE:
152                /* Parse key usage */
153                if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data,
154                                                      &csr->key_usage)) != 0) {
155                    return ret;
156                }
157                break;
158
159            case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
160                /* Parse subject alt name */
161                if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data,
162                                                             &csr->subject_alt_names)) != 0) {
163                    return ret;
164                }
165                break;
166
167            case MBEDTLS_X509_EXT_NS_CERT_TYPE:
168                /* Parse netscape certificate type */
169                if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data,
170                                                         &csr->ns_cert_type)) != 0) {
171                    return ret;
172                }
173                break;
174            default:
175                /*
176                 * If this is a non-critical extension, which the oid layer
177                 * supports, but there isn't an x509 parser for it,
178                 * skip the extension.
179                 */
180                if (is_critical) {
181                    return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
182                } else {
183                    *p = end_ext_octet;
184                }
185        }
186    }
187
188    if (*p != end) {
189        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
190                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
191    }
192
193    return 0;
194}
195
196/*
197 * Parse CSR attributes in DER format
198 */
199static int x509_csr_parse_attributes(mbedtls_x509_csr *csr,
200                                     const unsigned char *start, const unsigned char *end,
201                                     mbedtls_x509_csr_ext_cb_t cb,
202                                     void *p_ctx)
203{
204    int ret;
205    size_t len;
206    unsigned char *end_attr_data;
207    unsigned char **p = (unsigned char **) &start;
208
209    while (*p < end) {
210        mbedtls_x509_buf attr_oid = { 0, 0, NULL };
211
212        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
213                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
214            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
215        }
216        end_attr_data = *p + len;
217
218        /* Get attribute ID */
219        if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len,
220                                        MBEDTLS_ASN1_OID)) != 0) {
221            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
222        }
223
224        attr_oid.tag = MBEDTLS_ASN1_OID;
225        attr_oid.p = *p;
226        *p += attr_oid.len;
227
228        /* Check that this is an extension-request attribute */
229        if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) {
230            if ((ret = mbedtls_asn1_get_tag(p, end, &len,
231                                            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
232                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
233            }
234
235            if ((ret = mbedtls_asn1_get_tag(p, end, &len,
236                                            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
237                0) {
238                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
239            }
240
241            if ((ret = x509_csr_parse_extensions(csr, p, *p + len, cb, p_ctx)) != 0) {
242                return ret;
243            }
244
245            if (*p != end_attr_data) {
246                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
247                                         MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
248            }
249        }
250
251        *p = end_attr_data;
252    }
253
254    if (*p != end) {
255        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
256                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
257    }
258
259    return 0;
260}
261
262/*
263 * Parse a CSR in DER format
264 */
265static int mbedtls_x509_csr_parse_der_internal(mbedtls_x509_csr *csr,
266                                               const unsigned char *buf, size_t buflen,
267                                               mbedtls_x509_csr_ext_cb_t cb,
268                                               void *p_ctx)
269{
270    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
271    size_t len;
272    unsigned char *p, *end;
273    mbedtls_x509_buf sig_params;
274
275    memset(&sig_params, 0, sizeof(mbedtls_x509_buf));
276
277    /*
278     * Check for valid input
279     */
280    if (csr == NULL || buf == NULL || buflen == 0) {
281        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
282    }
283
284    mbedtls_x509_csr_init(csr);
285
286    /*
287     * first copy the raw DER data
288     */
289    p = mbedtls_calloc(1, len = buflen);
290
291    if (p == NULL) {
292        return MBEDTLS_ERR_X509_ALLOC_FAILED;
293    }
294
295    memcpy(p, buf, buflen);
296
297    csr->raw.p = p;
298    csr->raw.len = len;
299    end = p + len;
300
301    /*
302     *  CertificationRequest ::= SEQUENCE {
303     *       certificationRequestInfo CertificationRequestInfo,
304     *       signatureAlgorithm AlgorithmIdentifier,
305     *       signature          BIT STRING
306     *  }
307     */
308    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
309                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
310        mbedtls_x509_csr_free(csr);
311        return MBEDTLS_ERR_X509_INVALID_FORMAT;
312    }
313
314    if (len != (size_t) (end - p)) {
315        mbedtls_x509_csr_free(csr);
316        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
317                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
318    }
319
320    /*
321     *  CertificationRequestInfo ::= SEQUENCE {
322     */
323    csr->cri.p = p;
324
325    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
326                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
327        mbedtls_x509_csr_free(csr);
328        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
329    }
330
331    end = p + len;
332    csr->cri.len = (size_t) (end - csr->cri.p);
333
334    /*
335     *  Version  ::=  INTEGER {  v1(0) }
336     */
337    if ((ret = x509_csr_get_version(&p, end, &csr->version)) != 0) {
338        mbedtls_x509_csr_free(csr);
339        return ret;
340    }
341
342    if (csr->version != 0) {
343        mbedtls_x509_csr_free(csr);
344        return MBEDTLS_ERR_X509_UNKNOWN_VERSION;
345    }
346
347    csr->version++;
348
349    /*
350     *  subject               Name
351     */
352    csr->subject_raw.p = p;
353
354    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
355                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
356        mbedtls_x509_csr_free(csr);
357        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
358    }
359
360    if ((ret = mbedtls_x509_get_name(&p, p + len, &csr->subject)) != 0) {
361        mbedtls_x509_csr_free(csr);
362        return ret;
363    }
364
365    csr->subject_raw.len = (size_t) (p - csr->subject_raw.p);
366
367    /*
368     *  subjectPKInfo SubjectPublicKeyInfo
369     */
370    if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &csr->pk)) != 0) {
371        mbedtls_x509_csr_free(csr);
372        return ret;
373    }
374
375    /*
376     *  attributes    [0] Attributes
377     *
378     *  The list of possible attributes is open-ended, though RFC 2985
379     *  (PKCS#9) defines a few in section 5.4. We currently don't support any,
380     *  so we just ignore them. This is a safe thing to do as the worst thing
381     *  that could happen is that we issue a certificate that does not match
382     *  the requester's expectations - this cannot cause a violation of our
383     *  signature policies.
384     */
385    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
386                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
387        0) {
388        mbedtls_x509_csr_free(csr);
389        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
390    }
391
392    if ((ret = x509_csr_parse_attributes(csr, p, p + len, cb, p_ctx)) != 0) {
393        mbedtls_x509_csr_free(csr);
394        return ret;
395    }
396
397    p += len;
398
399    end = csr->raw.p + csr->raw.len;
400
401    /*
402     *  signatureAlgorithm   AlgorithmIdentifier,
403     *  signature            BIT STRING
404     */
405    if ((ret = mbedtls_x509_get_alg(&p, end, &csr->sig_oid, &sig_params)) != 0) {
406        mbedtls_x509_csr_free(csr);
407        return ret;
408    }
409
410    if ((ret = mbedtls_x509_get_sig_alg(&csr->sig_oid, &sig_params,
411                                        &csr->sig_md, &csr->sig_pk,
412                                        &csr->sig_opts)) != 0) {
413        mbedtls_x509_csr_free(csr);
414        return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG;
415    }
416
417    if ((ret = mbedtls_x509_get_sig(&p, end, &csr->sig)) != 0) {
418        mbedtls_x509_csr_free(csr);
419        return ret;
420    }
421
422    if (p != end) {
423        mbedtls_x509_csr_free(csr);
424        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
425                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
426    }
427
428    return 0;
429}
430
431/*
432 * Parse a CSR in DER format
433 */
434int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
435                               const unsigned char *buf, size_t buflen)
436{
437    return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, NULL, NULL);
438}
439
440/*
441 * Parse a CSR in DER format with callback for unknown extensions
442 */
443int mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr,
444                                           const unsigned char *buf, size_t buflen,
445                                           mbedtls_x509_csr_ext_cb_t cb,
446                                           void *p_ctx)
447{
448    return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, cb, p_ctx);
449}
450
451/*
452 * Parse a CSR, allowing for PEM or raw DER encoding
453 */
454int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen)
455{
456#if defined(MBEDTLS_PEM_PARSE_C)
457    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
458    size_t use_len;
459    mbedtls_pem_context pem;
460#endif
461
462    /*
463     * Check for valid input
464     */
465    if (csr == NULL || buf == NULL || buflen == 0) {
466        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
467    }
468
469#if defined(MBEDTLS_PEM_PARSE_C)
470    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
471    if (buf[buflen - 1] == '\0') {
472        mbedtls_pem_init(&pem);
473        ret = mbedtls_pem_read_buffer(&pem,
474                                      "-----BEGIN CERTIFICATE REQUEST-----",
475                                      "-----END CERTIFICATE REQUEST-----",
476                                      buf, NULL, 0, &use_len);
477        if (ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
478            ret = mbedtls_pem_read_buffer(&pem,
479                                          "-----BEGIN NEW CERTIFICATE REQUEST-----",
480                                          "-----END NEW CERTIFICATE REQUEST-----",
481                                          buf, NULL, 0, &use_len);
482        }
483
484        if (ret == 0) {
485            /*
486             * Was PEM encoded, parse the result
487             */
488            ret = mbedtls_x509_csr_parse_der(csr, pem.buf, pem.buflen);
489        }
490
491        mbedtls_pem_free(&pem);
492        if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
493            return ret;
494        }
495    }
496#endif /* MBEDTLS_PEM_PARSE_C */
497    return mbedtls_x509_csr_parse_der(csr, buf, buflen);
498}
499
500#if defined(MBEDTLS_FS_IO)
501/*
502 * Load a CSR into the structure
503 */
504int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path)
505{
506    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
507    size_t n;
508    unsigned char *buf;
509
510    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
511        return ret;
512    }
513
514    ret = mbedtls_x509_csr_parse(csr, buf, n);
515
516    mbedtls_zeroize_and_free(buf, n);
517
518    return ret;
519}
520#endif /* MBEDTLS_FS_IO */
521
522#if !defined(MBEDTLS_X509_REMOVE_INFO)
523#define BEFORE_COLON    14
524#define BC              "14"
525/*
526 * Return an informational string about the CSR.
527 */
528int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix,
529                          const mbedtls_x509_csr *csr)
530{
531    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
532    size_t n;
533    char *p;
534    char key_size_str[BEFORE_COLON];
535
536    p = buf;
537    n = size;
538
539    ret = mbedtls_snprintf(p, n, "%sCSR version   : %d",
540                           prefix, csr->version);
541    MBEDTLS_X509_SAFE_SNPRINTF;
542
543    ret = mbedtls_snprintf(p, n, "\n%ssubject name  : ", prefix);
544    MBEDTLS_X509_SAFE_SNPRINTF;
545    ret = mbedtls_x509_dn_gets(p, n, &csr->subject);
546    MBEDTLS_X509_SAFE_SNPRINTF;
547
548    ret = mbedtls_snprintf(p, n, "\n%ssigned using  : ", prefix);
549    MBEDTLS_X509_SAFE_SNPRINTF;
550
551    ret = mbedtls_x509_sig_alg_gets(p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
552                                    csr->sig_opts);
553    MBEDTLS_X509_SAFE_SNPRINTF;
554
555    if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON,
556                                            mbedtls_pk_get_name(&csr->pk))) != 0) {
557        return ret;
558    }
559
560    ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
561                           (int) mbedtls_pk_get_bitlen(&csr->pk));
562    MBEDTLS_X509_SAFE_SNPRINTF;
563
564    /*
565     * Optional extensions
566     */
567
568    if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
569        ret = mbedtls_snprintf(p, n, "\n%ssubject alt name  :", prefix);
570        MBEDTLS_X509_SAFE_SNPRINTF;
571
572        if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n,
573                                                      &csr->subject_alt_names,
574                                                      prefix)) != 0) {
575            return ret;
576        }
577    }
578
579    if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) {
580        ret = mbedtls_snprintf(p, n, "\n%scert. type        : ", prefix);
581        MBEDTLS_X509_SAFE_SNPRINTF;
582
583        if ((ret = mbedtls_x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) {
584            return ret;
585        }
586    }
587
588    if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) {
589        ret = mbedtls_snprintf(p, n, "\n%skey usage         : ", prefix);
590        MBEDTLS_X509_SAFE_SNPRINTF;
591
592        if ((ret = mbedtls_x509_info_key_usage(&p, &n, csr->key_usage)) != 0) {
593            return ret;
594        }
595    }
596
597    if (csr->ext_types != 0) {
598        ret = mbedtls_snprintf(p, n, "\n");
599        MBEDTLS_X509_SAFE_SNPRINTF;
600    }
601
602    return (int) (size - n);
603}
604#endif /* MBEDTLS_X509_REMOVE_INFO */
605
606/*
607 * Initialize a CSR
608 */
609void mbedtls_x509_csr_init(mbedtls_x509_csr *csr)
610{
611    memset(csr, 0, sizeof(mbedtls_x509_csr));
612}
613
614/*
615 * Unallocate all CSR data
616 */
617void mbedtls_x509_csr_free(mbedtls_x509_csr *csr)
618{
619    if (csr == NULL) {
620        return;
621    }
622
623    mbedtls_pk_free(&csr->pk);
624
625#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
626    mbedtls_free(csr->sig_opts);
627#endif
628
629    mbedtls_asn1_free_named_data_list_shallow(csr->subject.next);
630    mbedtls_asn1_sequence_free(csr->subject_alt_names.next);
631
632    if (csr->raw.p != NULL) {
633        mbedtls_zeroize_and_free(csr->raw.p, csr->raw.len);
634    }
635
636    mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr));
637}
638
639#endif /* MBEDTLS_X509_CSR_PARSE_C */
640