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