1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * X.509 base functions for creating certificates / CSRs 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#include "common.h" 9a8e1175bSopenharmony_ci 10a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_CREATE_C) 11a8e1175bSopenharmony_ci 12a8e1175bSopenharmony_ci#include "x509_internal.h" 13a8e1175bSopenharmony_ci#include "mbedtls/asn1write.h" 14a8e1175bSopenharmony_ci#include "mbedtls/error.h" 15a8e1175bSopenharmony_ci#include "mbedtls/oid.h" 16a8e1175bSopenharmony_ci 17a8e1175bSopenharmony_ci#include <string.h> 18a8e1175bSopenharmony_ci 19a8e1175bSopenharmony_ci#include "mbedtls/platform.h" 20a8e1175bSopenharmony_ci 21a8e1175bSopenharmony_ci#include "mbedtls/asn1.h" 22a8e1175bSopenharmony_ci 23a8e1175bSopenharmony_ci/* Structure linking OIDs for X.509 DN AttributeTypes to their 24a8e1175bSopenharmony_ci * string representations and default string encodings used by Mbed TLS. */ 25a8e1175bSopenharmony_citypedef struct { 26a8e1175bSopenharmony_ci const char *name; /* String representation of AttributeType, e.g. 27a8e1175bSopenharmony_ci * "CN" or "emailAddress". */ 28a8e1175bSopenharmony_ci size_t name_len; /* Length of 'name', without trailing 0 byte. */ 29a8e1175bSopenharmony_ci const char *oid; /* String representation of OID of AttributeType, 30a8e1175bSopenharmony_ci * as per RFC 5280, Appendix A.1. encoded as per 31a8e1175bSopenharmony_ci * X.690 */ 32a8e1175bSopenharmony_ci int default_tag; /* The default character encoding used for the 33a8e1175bSopenharmony_ci * given attribute type, e.g. 34a8e1175bSopenharmony_ci * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ 35a8e1175bSopenharmony_ci} x509_attr_descriptor_t; 36a8e1175bSopenharmony_ci 37a8e1175bSopenharmony_ci#define ADD_STRLEN(s) s, sizeof(s) - 1 38a8e1175bSopenharmony_ci 39a8e1175bSopenharmony_ci/* X.509 DN attributes from RFC 5280, Appendix A.1. */ 40a8e1175bSopenharmony_cistatic const x509_attr_descriptor_t x509_attrs[] = 41a8e1175bSopenharmony_ci{ 42a8e1175bSopenharmony_ci { ADD_STRLEN("CN"), 43a8e1175bSopenharmony_ci MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, 44a8e1175bSopenharmony_ci { ADD_STRLEN("commonName"), 45a8e1175bSopenharmony_ci MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, 46a8e1175bSopenharmony_ci { ADD_STRLEN("C"), 47a8e1175bSopenharmony_ci MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, 48a8e1175bSopenharmony_ci { ADD_STRLEN("countryName"), 49a8e1175bSopenharmony_ci MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, 50a8e1175bSopenharmony_ci { ADD_STRLEN("O"), 51a8e1175bSopenharmony_ci MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, 52a8e1175bSopenharmony_ci { ADD_STRLEN("organizationName"), 53a8e1175bSopenharmony_ci MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, 54a8e1175bSopenharmony_ci { ADD_STRLEN("L"), 55a8e1175bSopenharmony_ci MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, 56a8e1175bSopenharmony_ci { ADD_STRLEN("locality"), 57a8e1175bSopenharmony_ci MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, 58a8e1175bSopenharmony_ci { ADD_STRLEN("R"), 59a8e1175bSopenharmony_ci MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, 60a8e1175bSopenharmony_ci { ADD_STRLEN("OU"), 61a8e1175bSopenharmony_ci MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, 62a8e1175bSopenharmony_ci { ADD_STRLEN("organizationalUnitName"), 63a8e1175bSopenharmony_ci MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, 64a8e1175bSopenharmony_ci { ADD_STRLEN("ST"), 65a8e1175bSopenharmony_ci MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, 66a8e1175bSopenharmony_ci { ADD_STRLEN("stateOrProvinceName"), 67a8e1175bSopenharmony_ci MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, 68a8e1175bSopenharmony_ci { ADD_STRLEN("emailAddress"), 69a8e1175bSopenharmony_ci MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, 70a8e1175bSopenharmony_ci { ADD_STRLEN("serialNumber"), 71a8e1175bSopenharmony_ci MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING }, 72a8e1175bSopenharmony_ci { ADD_STRLEN("postalAddress"), 73a8e1175bSopenharmony_ci MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING }, 74a8e1175bSopenharmony_ci { ADD_STRLEN("postalCode"), 75a8e1175bSopenharmony_ci MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING }, 76a8e1175bSopenharmony_ci { ADD_STRLEN("dnQualifier"), 77a8e1175bSopenharmony_ci MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING }, 78a8e1175bSopenharmony_ci { ADD_STRLEN("title"), 79a8e1175bSopenharmony_ci MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING }, 80a8e1175bSopenharmony_ci { ADD_STRLEN("surName"), 81a8e1175bSopenharmony_ci MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, 82a8e1175bSopenharmony_ci { ADD_STRLEN("SN"), 83a8e1175bSopenharmony_ci MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, 84a8e1175bSopenharmony_ci { ADD_STRLEN("givenName"), 85a8e1175bSopenharmony_ci MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, 86a8e1175bSopenharmony_ci { ADD_STRLEN("GN"), 87a8e1175bSopenharmony_ci MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, 88a8e1175bSopenharmony_ci { ADD_STRLEN("initials"), 89a8e1175bSopenharmony_ci MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING }, 90a8e1175bSopenharmony_ci { ADD_STRLEN("pseudonym"), 91a8e1175bSopenharmony_ci MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING }, 92a8e1175bSopenharmony_ci { ADD_STRLEN("generationQualifier"), 93a8e1175bSopenharmony_ci MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING }, 94a8e1175bSopenharmony_ci { ADD_STRLEN("domainComponent"), 95a8e1175bSopenharmony_ci MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, 96a8e1175bSopenharmony_ci { ADD_STRLEN("DC"), 97a8e1175bSopenharmony_ci MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, 98a8e1175bSopenharmony_ci { NULL, 0, NULL, MBEDTLS_ASN1_NULL } 99a8e1175bSopenharmony_ci}; 100a8e1175bSopenharmony_ci 101a8e1175bSopenharmony_cistatic const x509_attr_descriptor_t *x509_attr_descr_from_name(const char *name, size_t name_len) 102a8e1175bSopenharmony_ci{ 103a8e1175bSopenharmony_ci const x509_attr_descriptor_t *cur; 104a8e1175bSopenharmony_ci 105a8e1175bSopenharmony_ci for (cur = x509_attrs; cur->name != NULL; cur++) { 106a8e1175bSopenharmony_ci if (cur->name_len == name_len && 107a8e1175bSopenharmony_ci strncmp(cur->name, name, name_len) == 0) { 108a8e1175bSopenharmony_ci break; 109a8e1175bSopenharmony_ci } 110a8e1175bSopenharmony_ci } 111a8e1175bSopenharmony_ci 112a8e1175bSopenharmony_ci if (cur->name == NULL) { 113a8e1175bSopenharmony_ci return NULL; 114a8e1175bSopenharmony_ci } 115a8e1175bSopenharmony_ci 116a8e1175bSopenharmony_ci return cur; 117a8e1175bSopenharmony_ci} 118a8e1175bSopenharmony_ci 119a8e1175bSopenharmony_cistatic int hex_to_int(char c) 120a8e1175bSopenharmony_ci{ 121a8e1175bSopenharmony_ci return ('0' <= c && c <= '9') ? (c - '0') : 122a8e1175bSopenharmony_ci ('a' <= c && c <= 'f') ? (c - 'a' + 10) : 123a8e1175bSopenharmony_ci ('A' <= c && c <= 'F') ? (c - 'A' + 10) : -1; 124a8e1175bSopenharmony_ci} 125a8e1175bSopenharmony_ci 126a8e1175bSopenharmony_cistatic int hexpair_to_int(const char *hexpair) 127a8e1175bSopenharmony_ci{ 128a8e1175bSopenharmony_ci int n1 = hex_to_int(*hexpair); 129a8e1175bSopenharmony_ci int n2 = hex_to_int(*(hexpair + 1)); 130a8e1175bSopenharmony_ci 131a8e1175bSopenharmony_ci if (n1 != -1 && n2 != -1) { 132a8e1175bSopenharmony_ci return (n1 << 4) | n2; 133a8e1175bSopenharmony_ci } else { 134a8e1175bSopenharmony_ci return -1; 135a8e1175bSopenharmony_ci } 136a8e1175bSopenharmony_ci} 137a8e1175bSopenharmony_ci 138a8e1175bSopenharmony_cistatic int parse_attribute_value_string(const char *s, 139a8e1175bSopenharmony_ci int len, 140a8e1175bSopenharmony_ci unsigned char *data, 141a8e1175bSopenharmony_ci size_t *data_len) 142a8e1175bSopenharmony_ci{ 143a8e1175bSopenharmony_ci const char *c; 144a8e1175bSopenharmony_ci const char *end = s + len; 145a8e1175bSopenharmony_ci unsigned char *d = data; 146a8e1175bSopenharmony_ci int n; 147a8e1175bSopenharmony_ci 148a8e1175bSopenharmony_ci for (c = s; c < end; c++) { 149a8e1175bSopenharmony_ci if (*c == '\\') { 150a8e1175bSopenharmony_ci c++; 151a8e1175bSopenharmony_ci 152a8e1175bSopenharmony_ci /* Check for valid escaped characters as per RFC 4514 Section 3 */ 153a8e1175bSopenharmony_ci if (c + 1 < end && (n = hexpair_to_int(c)) != -1) { 154a8e1175bSopenharmony_ci if (n == 0) { 155a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_NAME; 156a8e1175bSopenharmony_ci } 157a8e1175bSopenharmony_ci *(d++) = n; 158a8e1175bSopenharmony_ci c++; 159a8e1175bSopenharmony_ci } else if (c < end && strchr(" ,=+<>#;\"\\", *c)) { 160a8e1175bSopenharmony_ci *(d++) = *c; 161a8e1175bSopenharmony_ci } else { 162a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_NAME; 163a8e1175bSopenharmony_ci } 164a8e1175bSopenharmony_ci } else { 165a8e1175bSopenharmony_ci *(d++) = *c; 166a8e1175bSopenharmony_ci } 167a8e1175bSopenharmony_ci 168a8e1175bSopenharmony_ci if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) { 169a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_NAME; 170a8e1175bSopenharmony_ci } 171a8e1175bSopenharmony_ci } 172a8e1175bSopenharmony_ci *data_len = (size_t) (d - data); 173a8e1175bSopenharmony_ci return 0; 174a8e1175bSopenharmony_ci} 175a8e1175bSopenharmony_ci 176a8e1175bSopenharmony_ci/** Parse a hexstring containing a DER-encoded string. 177a8e1175bSopenharmony_ci * 178a8e1175bSopenharmony_ci * \param s A string of \p len bytes hexadecimal digits. 179a8e1175bSopenharmony_ci * \param len Number of bytes to read from \p s. 180a8e1175bSopenharmony_ci * \param data Output buffer of size \p data_size. 181a8e1175bSopenharmony_ci * On success, it contains the payload that's DER-encoded 182a8e1175bSopenharmony_ci * in the input (content without the tag and length). 183a8e1175bSopenharmony_ci * If the DER tag is a string tag, the payload is guaranteed 184a8e1175bSopenharmony_ci * not to contain null bytes. 185a8e1175bSopenharmony_ci * \param data_size Length of the \p data buffer. 186a8e1175bSopenharmony_ci * \param data_len On success, the length of the parsed string. 187a8e1175bSopenharmony_ci * It is guaranteed to be less than 188a8e1175bSopenharmony_ci * #MBEDTLS_X509_MAX_DN_NAME_SIZE. 189a8e1175bSopenharmony_ci * \param tag The ASN.1 tag that the payload in \p data is encoded in. 190a8e1175bSopenharmony_ci * 191a8e1175bSopenharmony_ci * \retval 0 on success. 192a8e1175bSopenharmony_ci * \retval #MBEDTLS_ERR_X509_INVALID_NAME if \p s does not contain 193a8e1175bSopenharmony_ci * a valid hexstring, 194a8e1175bSopenharmony_ci * or if the decoded hexstring is not valid DER, 195a8e1175bSopenharmony_ci * or if the payload does not fit in \p data, 196a8e1175bSopenharmony_ci * or if the payload is more than 197a8e1175bSopenharmony_ci * #MBEDTLS_X509_MAX_DN_NAME_SIZE bytes, 198a8e1175bSopenharmony_ci * of if \p *tag is an ASN.1 string tag and the payload 199a8e1175bSopenharmony_ci * contains a null byte. 200a8e1175bSopenharmony_ci * \retval #MBEDTLS_ERR_X509_ALLOC_FAILED on low memory. 201a8e1175bSopenharmony_ci */ 202a8e1175bSopenharmony_cistatic int parse_attribute_value_hex_der_encoded(const char *s, 203a8e1175bSopenharmony_ci size_t len, 204a8e1175bSopenharmony_ci unsigned char *data, 205a8e1175bSopenharmony_ci size_t data_size, 206a8e1175bSopenharmony_ci size_t *data_len, 207a8e1175bSopenharmony_ci int *tag) 208a8e1175bSopenharmony_ci{ 209a8e1175bSopenharmony_ci /* Step 1: preliminary length checks. */ 210a8e1175bSopenharmony_ci /* Each byte is encoded by exactly two hexadecimal digits. */ 211a8e1175bSopenharmony_ci if (len % 2 != 0) { 212a8e1175bSopenharmony_ci /* Odd number of hex digits */ 213a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_NAME; 214a8e1175bSopenharmony_ci } 215a8e1175bSopenharmony_ci size_t const der_length = len / 2; 216a8e1175bSopenharmony_ci if (der_length > MBEDTLS_X509_MAX_DN_NAME_SIZE + 4) { 217a8e1175bSopenharmony_ci /* The payload would be more than MBEDTLS_X509_MAX_DN_NAME_SIZE 218a8e1175bSopenharmony_ci * (after subtracting the ASN.1 tag and length). Reject this early 219a8e1175bSopenharmony_ci * to avoid allocating a large intermediate buffer. */ 220a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_NAME; 221a8e1175bSopenharmony_ci } 222a8e1175bSopenharmony_ci if (der_length < 1) { 223a8e1175bSopenharmony_ci /* Avoid empty-buffer shenanigans. A valid DER encoding is never 224a8e1175bSopenharmony_ci * empty. */ 225a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_NAME; 226a8e1175bSopenharmony_ci } 227a8e1175bSopenharmony_ci 228a8e1175bSopenharmony_ci /* Step 2: Decode the hex string into an intermediate buffer. */ 229a8e1175bSopenharmony_ci unsigned char *der = mbedtls_calloc(1, der_length); 230a8e1175bSopenharmony_ci if (der == NULL) { 231a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_ALLOC_FAILED; 232a8e1175bSopenharmony_ci } 233a8e1175bSopenharmony_ci /* Beyond this point, der needs to be freed on exit. */ 234a8e1175bSopenharmony_ci for (size_t i = 0; i < der_length; i++) { 235a8e1175bSopenharmony_ci int c = hexpair_to_int(s + 2 * i); 236a8e1175bSopenharmony_ci if (c < 0) { 237a8e1175bSopenharmony_ci goto error; 238a8e1175bSopenharmony_ci } 239a8e1175bSopenharmony_ci der[i] = c; 240a8e1175bSopenharmony_ci } 241a8e1175bSopenharmony_ci 242a8e1175bSopenharmony_ci /* Step 3: decode the DER. */ 243a8e1175bSopenharmony_ci /* We've checked that der_length >= 1 above. */ 244a8e1175bSopenharmony_ci *tag = der[0]; 245a8e1175bSopenharmony_ci { 246a8e1175bSopenharmony_ci unsigned char *p = der + 1; 247a8e1175bSopenharmony_ci if (mbedtls_asn1_get_len(&p, der + der_length, data_len) != 0) { 248a8e1175bSopenharmony_ci goto error; 249a8e1175bSopenharmony_ci } 250a8e1175bSopenharmony_ci /* Now p points to the first byte of the payload inside der, 251a8e1175bSopenharmony_ci * and *data_len is the length of the payload. */ 252a8e1175bSopenharmony_ci 253a8e1175bSopenharmony_ci /* Step 4: payload validation */ 254a8e1175bSopenharmony_ci if (*data_len > MBEDTLS_X509_MAX_DN_NAME_SIZE) { 255a8e1175bSopenharmony_ci goto error; 256a8e1175bSopenharmony_ci } 257a8e1175bSopenharmony_ci /* Strings must not contain null bytes. */ 258a8e1175bSopenharmony_ci if (MBEDTLS_ASN1_IS_STRING_TAG(*tag)) { 259a8e1175bSopenharmony_ci for (size_t i = 0; i < *data_len; i++) { 260a8e1175bSopenharmony_ci if (p[i] == 0) { 261a8e1175bSopenharmony_ci goto error; 262a8e1175bSopenharmony_ci } 263a8e1175bSopenharmony_ci } 264a8e1175bSopenharmony_ci } 265a8e1175bSopenharmony_ci 266a8e1175bSopenharmony_ci /* Step 5: output the payload. */ 267a8e1175bSopenharmony_ci if (*data_len > data_size) { 268a8e1175bSopenharmony_ci goto error; 269a8e1175bSopenharmony_ci } 270a8e1175bSopenharmony_ci memcpy(data, p, *data_len); 271a8e1175bSopenharmony_ci } 272a8e1175bSopenharmony_ci mbedtls_free(der); 273a8e1175bSopenharmony_ci 274a8e1175bSopenharmony_ci return 0; 275a8e1175bSopenharmony_ci 276a8e1175bSopenharmony_cierror: 277a8e1175bSopenharmony_ci mbedtls_free(der); 278a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_NAME; 279a8e1175bSopenharmony_ci} 280a8e1175bSopenharmony_ci 281a8e1175bSopenharmony_ciint mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name) 282a8e1175bSopenharmony_ci{ 283a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_X509_INVALID_NAME; 284a8e1175bSopenharmony_ci int parse_ret = 0; 285a8e1175bSopenharmony_ci const char *s = name, *c = s; 286a8e1175bSopenharmony_ci const char *end = s + strlen(s); 287a8e1175bSopenharmony_ci mbedtls_asn1_buf oid = { .p = NULL, .len = 0, .tag = MBEDTLS_ASN1_NULL }; 288a8e1175bSopenharmony_ci const x509_attr_descriptor_t *attr_descr = NULL; 289a8e1175bSopenharmony_ci int in_attr_type = 1; 290a8e1175bSopenharmony_ci int tag; 291a8e1175bSopenharmony_ci int numericoid = 0; 292a8e1175bSopenharmony_ci unsigned char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; 293a8e1175bSopenharmony_ci size_t data_len = 0; 294a8e1175bSopenharmony_ci 295a8e1175bSopenharmony_ci /* Clear existing chain if present */ 296a8e1175bSopenharmony_ci mbedtls_asn1_free_named_data_list(head); 297a8e1175bSopenharmony_ci 298a8e1175bSopenharmony_ci while (c <= end) { 299a8e1175bSopenharmony_ci if (in_attr_type && *c == '=') { 300a8e1175bSopenharmony_ci if ((attr_descr = x509_attr_descr_from_name(s, (size_t) (c - s))) == NULL) { 301a8e1175bSopenharmony_ci if ((mbedtls_oid_from_numeric_string(&oid, s, (size_t) (c - s))) != 0) { 302a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_NAME; 303a8e1175bSopenharmony_ci } else { 304a8e1175bSopenharmony_ci numericoid = 1; 305a8e1175bSopenharmony_ci } 306a8e1175bSopenharmony_ci } else { 307a8e1175bSopenharmony_ci oid.len = strlen(attr_descr->oid); 308a8e1175bSopenharmony_ci oid.p = mbedtls_calloc(1, oid.len); 309a8e1175bSopenharmony_ci memcpy(oid.p, attr_descr->oid, oid.len); 310a8e1175bSopenharmony_ci numericoid = 0; 311a8e1175bSopenharmony_ci } 312a8e1175bSopenharmony_ci 313a8e1175bSopenharmony_ci s = c + 1; 314a8e1175bSopenharmony_ci in_attr_type = 0; 315a8e1175bSopenharmony_ci } 316a8e1175bSopenharmony_ci 317a8e1175bSopenharmony_ci if (!in_attr_type && ((*c == ',' && *(c-1) != '\\') || c == end)) { 318a8e1175bSopenharmony_ci if (s == c) { 319a8e1175bSopenharmony_ci mbedtls_free(oid.p); 320a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_NAME; 321a8e1175bSopenharmony_ci } else if (*s == '#') { 322a8e1175bSopenharmony_ci /* We know that c >= s (loop invariant) and c != s (in this 323a8e1175bSopenharmony_ci * else branch), hence c - s - 1 >= 0. */ 324a8e1175bSopenharmony_ci parse_ret = parse_attribute_value_hex_der_encoded( 325a8e1175bSopenharmony_ci s + 1, (size_t) (c - s) - 1, 326a8e1175bSopenharmony_ci data, sizeof(data), &data_len, &tag); 327a8e1175bSopenharmony_ci if (parse_ret != 0) { 328a8e1175bSopenharmony_ci mbedtls_free(oid.p); 329a8e1175bSopenharmony_ci return parse_ret; 330a8e1175bSopenharmony_ci } 331a8e1175bSopenharmony_ci } else { 332a8e1175bSopenharmony_ci if (numericoid) { 333a8e1175bSopenharmony_ci mbedtls_free(oid.p); 334a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_NAME; 335a8e1175bSopenharmony_ci } else { 336a8e1175bSopenharmony_ci if ((parse_ret = 337a8e1175bSopenharmony_ci parse_attribute_value_string(s, (int) (c - s), data, 338a8e1175bSopenharmony_ci &data_len)) != 0) { 339a8e1175bSopenharmony_ci mbedtls_free(oid.p); 340a8e1175bSopenharmony_ci return parse_ret; 341a8e1175bSopenharmony_ci } 342a8e1175bSopenharmony_ci tag = attr_descr->default_tag; 343a8e1175bSopenharmony_ci } 344a8e1175bSopenharmony_ci } 345a8e1175bSopenharmony_ci 346a8e1175bSopenharmony_ci mbedtls_asn1_named_data *cur = 347a8e1175bSopenharmony_ci mbedtls_asn1_store_named_data(head, (char *) oid.p, oid.len, 348a8e1175bSopenharmony_ci (unsigned char *) data, 349a8e1175bSopenharmony_ci data_len); 350a8e1175bSopenharmony_ci mbedtls_free(oid.p); 351a8e1175bSopenharmony_ci oid.p = NULL; 352a8e1175bSopenharmony_ci if (cur == NULL) { 353a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_ALLOC_FAILED; 354a8e1175bSopenharmony_ci } 355a8e1175bSopenharmony_ci 356a8e1175bSopenharmony_ci // set tagType 357a8e1175bSopenharmony_ci cur->val.tag = tag; 358a8e1175bSopenharmony_ci 359a8e1175bSopenharmony_ci while (c < end && *(c + 1) == ' ') { 360a8e1175bSopenharmony_ci c++; 361a8e1175bSopenharmony_ci } 362a8e1175bSopenharmony_ci 363a8e1175bSopenharmony_ci s = c + 1; 364a8e1175bSopenharmony_ci in_attr_type = 1; 365a8e1175bSopenharmony_ci 366a8e1175bSopenharmony_ci /* Successfully parsed one name, update ret to success */ 367a8e1175bSopenharmony_ci ret = 0; 368a8e1175bSopenharmony_ci } 369a8e1175bSopenharmony_ci c++; 370a8e1175bSopenharmony_ci } 371a8e1175bSopenharmony_ci if (oid.p != NULL) { 372a8e1175bSopenharmony_ci mbedtls_free(oid.p); 373a8e1175bSopenharmony_ci } 374a8e1175bSopenharmony_ci return ret; 375a8e1175bSopenharmony_ci} 376a8e1175bSopenharmony_ci 377a8e1175bSopenharmony_ci/* The first byte of the value in the mbedtls_asn1_named_data structure is reserved 378a8e1175bSopenharmony_ci * to store the critical boolean for us 379a8e1175bSopenharmony_ci */ 380a8e1175bSopenharmony_ciint mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, 381a8e1175bSopenharmony_ci int critical, const unsigned char *val, size_t val_len) 382a8e1175bSopenharmony_ci{ 383a8e1175bSopenharmony_ci mbedtls_asn1_named_data *cur; 384a8e1175bSopenharmony_ci 385a8e1175bSopenharmony_ci if (val_len > (SIZE_MAX - 1)) { 386a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 387a8e1175bSopenharmony_ci } 388a8e1175bSopenharmony_ci 389a8e1175bSopenharmony_ci if ((cur = mbedtls_asn1_store_named_data(head, oid, oid_len, 390a8e1175bSopenharmony_ci NULL, val_len + 1)) == NULL) { 391a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_ALLOC_FAILED; 392a8e1175bSopenharmony_ci } 393a8e1175bSopenharmony_ci 394a8e1175bSopenharmony_ci cur->val.p[0] = critical; 395a8e1175bSopenharmony_ci memcpy(cur->val.p + 1, val, val_len); 396a8e1175bSopenharmony_ci 397a8e1175bSopenharmony_ci return 0; 398a8e1175bSopenharmony_ci} 399a8e1175bSopenharmony_ci 400a8e1175bSopenharmony_ci/* 401a8e1175bSopenharmony_ci * RelativeDistinguishedName ::= 402a8e1175bSopenharmony_ci * SET OF AttributeTypeAndValue 403a8e1175bSopenharmony_ci * 404a8e1175bSopenharmony_ci * AttributeTypeAndValue ::= SEQUENCE { 405a8e1175bSopenharmony_ci * type AttributeType, 406a8e1175bSopenharmony_ci * value AttributeValue } 407a8e1175bSopenharmony_ci * 408a8e1175bSopenharmony_ci * AttributeType ::= OBJECT IDENTIFIER 409a8e1175bSopenharmony_ci * 410a8e1175bSopenharmony_ci * AttributeValue ::= ANY DEFINED BY AttributeType 411a8e1175bSopenharmony_ci */ 412a8e1175bSopenharmony_cistatic int x509_write_name(unsigned char **p, 413a8e1175bSopenharmony_ci unsigned char *start, 414a8e1175bSopenharmony_ci mbedtls_asn1_named_data *cur_name) 415a8e1175bSopenharmony_ci{ 416a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 417a8e1175bSopenharmony_ci size_t len = 0; 418a8e1175bSopenharmony_ci const char *oid = (const char *) cur_name->oid.p; 419a8e1175bSopenharmony_ci size_t oid_len = cur_name->oid.len; 420a8e1175bSopenharmony_ci const unsigned char *name = cur_name->val.p; 421a8e1175bSopenharmony_ci size_t name_len = cur_name->val.len; 422a8e1175bSopenharmony_ci 423a8e1175bSopenharmony_ci // Write correct string tag and value 424a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tagged_string(p, start, 425a8e1175bSopenharmony_ci cur_name->val.tag, 426a8e1175bSopenharmony_ci (const char *) name, 427a8e1175bSopenharmony_ci name_len)); 428a8e1175bSopenharmony_ci // Write OID 429a8e1175bSopenharmony_ci // 430a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, 431a8e1175bSopenharmony_ci oid_len)); 432a8e1175bSopenharmony_ci 433a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 434a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, 435a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | 436a8e1175bSopenharmony_ci MBEDTLS_ASN1_SEQUENCE)); 437a8e1175bSopenharmony_ci 438a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 439a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, 440a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | 441a8e1175bSopenharmony_ci MBEDTLS_ASN1_SET)); 442a8e1175bSopenharmony_ci 443a8e1175bSopenharmony_ci return (int) len; 444a8e1175bSopenharmony_ci} 445a8e1175bSopenharmony_ci 446a8e1175bSopenharmony_ciint mbedtls_x509_write_names(unsigned char **p, unsigned char *start, 447a8e1175bSopenharmony_ci mbedtls_asn1_named_data *first) 448a8e1175bSopenharmony_ci{ 449a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 450a8e1175bSopenharmony_ci size_t len = 0; 451a8e1175bSopenharmony_ci mbedtls_asn1_named_data *cur = first; 452a8e1175bSopenharmony_ci 453a8e1175bSopenharmony_ci while (cur != NULL) { 454a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, x509_write_name(p, start, cur)); 455a8e1175bSopenharmony_ci cur = cur->next; 456a8e1175bSopenharmony_ci } 457a8e1175bSopenharmony_ci 458a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 459a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | 460a8e1175bSopenharmony_ci MBEDTLS_ASN1_SEQUENCE)); 461a8e1175bSopenharmony_ci 462a8e1175bSopenharmony_ci return (int) len; 463a8e1175bSopenharmony_ci} 464a8e1175bSopenharmony_ci 465a8e1175bSopenharmony_ciint mbedtls_x509_write_sig(unsigned char **p, unsigned char *start, 466a8e1175bSopenharmony_ci const char *oid, size_t oid_len, 467a8e1175bSopenharmony_ci unsigned char *sig, size_t size, 468a8e1175bSopenharmony_ci mbedtls_pk_type_t pk_alg) 469a8e1175bSopenharmony_ci{ 470a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 471a8e1175bSopenharmony_ci int write_null_par; 472a8e1175bSopenharmony_ci size_t len = 0; 473a8e1175bSopenharmony_ci 474a8e1175bSopenharmony_ci if (*p < start || (size_t) (*p - start) < size) { 475a8e1175bSopenharmony_ci return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 476a8e1175bSopenharmony_ci } 477a8e1175bSopenharmony_ci 478a8e1175bSopenharmony_ci len = size; 479a8e1175bSopenharmony_ci (*p) -= len; 480a8e1175bSopenharmony_ci memcpy(*p, sig, len); 481a8e1175bSopenharmony_ci 482a8e1175bSopenharmony_ci if (*p - start < 1) { 483a8e1175bSopenharmony_ci return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 484a8e1175bSopenharmony_ci } 485a8e1175bSopenharmony_ci 486a8e1175bSopenharmony_ci *--(*p) = 0; 487a8e1175bSopenharmony_ci len += 1; 488a8e1175bSopenharmony_ci 489a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 490a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING)); 491a8e1175bSopenharmony_ci 492a8e1175bSopenharmony_ci // Write OID 493a8e1175bSopenharmony_ci // 494a8e1175bSopenharmony_ci if (pk_alg == MBEDTLS_PK_ECDSA) { 495a8e1175bSopenharmony_ci /* 496a8e1175bSopenharmony_ci * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature 497a8e1175bSopenharmony_ci * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and 498a8e1175bSopenharmony_ci * https://www.rfc-editor.org/rfc/rfc5758#section-3. 499a8e1175bSopenharmony_ci */ 500a8e1175bSopenharmony_ci write_null_par = 0; 501a8e1175bSopenharmony_ci } else { 502a8e1175bSopenharmony_ci write_null_par = 1; 503a8e1175bSopenharmony_ci } 504a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 505a8e1175bSopenharmony_ci mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, 506a8e1175bSopenharmony_ci 0, write_null_par)); 507a8e1175bSopenharmony_ci 508a8e1175bSopenharmony_ci return (int) len; 509a8e1175bSopenharmony_ci} 510a8e1175bSopenharmony_ci 511a8e1175bSopenharmony_cistatic int x509_write_extension(unsigned char **p, unsigned char *start, 512a8e1175bSopenharmony_ci mbedtls_asn1_named_data *ext) 513a8e1175bSopenharmony_ci{ 514a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 515a8e1175bSopenharmony_ci size_t len = 0; 516a8e1175bSopenharmony_ci 517a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, ext->val.p + 1, 518a8e1175bSopenharmony_ci ext->val.len - 1)); 519a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, ext->val.len - 1)); 520a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING)); 521a8e1175bSopenharmony_ci 522a8e1175bSopenharmony_ci if (ext->val.p[0] != 0) { 523a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(p, start, 1)); 524a8e1175bSopenharmony_ci } 525a8e1175bSopenharmony_ci 526a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, ext->oid.p, 527a8e1175bSopenharmony_ci ext->oid.len)); 528a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, ext->oid.len)); 529a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID)); 530a8e1175bSopenharmony_ci 531a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 532a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | 533a8e1175bSopenharmony_ci MBEDTLS_ASN1_SEQUENCE)); 534a8e1175bSopenharmony_ci 535a8e1175bSopenharmony_ci return (int) len; 536a8e1175bSopenharmony_ci} 537a8e1175bSopenharmony_ci 538a8e1175bSopenharmony_ci/* 539a8e1175bSopenharmony_ci * Extension ::= SEQUENCE { 540a8e1175bSopenharmony_ci * extnID OBJECT IDENTIFIER, 541a8e1175bSopenharmony_ci * critical BOOLEAN DEFAULT FALSE, 542a8e1175bSopenharmony_ci * extnValue OCTET STRING 543a8e1175bSopenharmony_ci * -- contains the DER encoding of an ASN.1 value 544a8e1175bSopenharmony_ci * -- corresponding to the extension type identified 545a8e1175bSopenharmony_ci * -- by extnID 546a8e1175bSopenharmony_ci * } 547a8e1175bSopenharmony_ci */ 548a8e1175bSopenharmony_ciint mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start, 549a8e1175bSopenharmony_ci mbedtls_asn1_named_data *first) 550a8e1175bSopenharmony_ci{ 551a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 552a8e1175bSopenharmony_ci size_t len = 0; 553a8e1175bSopenharmony_ci mbedtls_asn1_named_data *cur_ext = first; 554a8e1175bSopenharmony_ci 555a8e1175bSopenharmony_ci while (cur_ext != NULL) { 556a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, x509_write_extension(p, start, cur_ext)); 557a8e1175bSopenharmony_ci cur_ext = cur_ext->next; 558a8e1175bSopenharmony_ci } 559a8e1175bSopenharmony_ci 560a8e1175bSopenharmony_ci return (int) len; 561a8e1175bSopenharmony_ci} 562a8e1175bSopenharmony_ci 563a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_CREATE_C */ 564