1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * X.509 common functions for parsing and verification 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_USE_C) 21a8e1175bSopenharmony_ci 22a8e1175bSopenharmony_ci#include "x509_internal.h" 23a8e1175bSopenharmony_ci#include "mbedtls/asn1.h" 24a8e1175bSopenharmony_ci#include "mbedtls/error.h" 25a8e1175bSopenharmony_ci#include "mbedtls/oid.h" 26a8e1175bSopenharmony_ci 27a8e1175bSopenharmony_ci#include <stdio.h> 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/asn1write.h" 35a8e1175bSopenharmony_ci 36a8e1175bSopenharmony_ci#include "mbedtls/platform.h" 37a8e1175bSopenharmony_ci 38a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME) 39a8e1175bSopenharmony_ci#include "mbedtls/platform_time.h" 40a8e1175bSopenharmony_ci#endif 41a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME_DATE) 42a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h" 43a8e1175bSopenharmony_ci#include <time.h> 44a8e1175bSopenharmony_ci#endif 45a8e1175bSopenharmony_ci 46a8e1175bSopenharmony_ci#define CHECK(code) \ 47a8e1175bSopenharmony_ci do { \ 48a8e1175bSopenharmony_ci if ((ret = (code)) != 0) { \ 49a8e1175bSopenharmony_ci return ret; \ 50a8e1175bSopenharmony_ci } \ 51a8e1175bSopenharmony_ci } while (0) 52a8e1175bSopenharmony_ci 53a8e1175bSopenharmony_ci#define CHECK_RANGE(min, max, val) \ 54a8e1175bSopenharmony_ci do { \ 55a8e1175bSopenharmony_ci if ((val) < (min) || (val) > (max)) { \ 56a8e1175bSopenharmony_ci return ret; \ 57a8e1175bSopenharmony_ci } \ 58a8e1175bSopenharmony_ci } while (0) 59a8e1175bSopenharmony_ci 60a8e1175bSopenharmony_ci/* 61a8e1175bSopenharmony_ci * CertificateSerialNumber ::= INTEGER 62a8e1175bSopenharmony_ci */ 63a8e1175bSopenharmony_ciint mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end, 64a8e1175bSopenharmony_ci mbedtls_x509_buf *serial) 65a8e1175bSopenharmony_ci{ 66a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 67a8e1175bSopenharmony_ci 68a8e1175bSopenharmony_ci if ((end - *p) < 1) { 69a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, 70a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_OUT_OF_DATA); 71a8e1175bSopenharmony_ci } 72a8e1175bSopenharmony_ci 73a8e1175bSopenharmony_ci if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) && 74a8e1175bSopenharmony_ci **p != MBEDTLS_ASN1_INTEGER) { 75a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, 76a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 77a8e1175bSopenharmony_ci } 78a8e1175bSopenharmony_ci 79a8e1175bSopenharmony_ci serial->tag = *(*p)++; 80a8e1175bSopenharmony_ci 81a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) { 82a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret); 83a8e1175bSopenharmony_ci } 84a8e1175bSopenharmony_ci 85a8e1175bSopenharmony_ci serial->p = *p; 86a8e1175bSopenharmony_ci *p += serial->len; 87a8e1175bSopenharmony_ci 88a8e1175bSopenharmony_ci return 0; 89a8e1175bSopenharmony_ci} 90a8e1175bSopenharmony_ci 91a8e1175bSopenharmony_ci/* Get an algorithm identifier without parameters (eg for signatures) 92a8e1175bSopenharmony_ci * 93a8e1175bSopenharmony_ci * AlgorithmIdentifier ::= SEQUENCE { 94a8e1175bSopenharmony_ci * algorithm OBJECT IDENTIFIER, 95a8e1175bSopenharmony_ci * parameters ANY DEFINED BY algorithm OPTIONAL } 96a8e1175bSopenharmony_ci */ 97a8e1175bSopenharmony_ciint mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end, 98a8e1175bSopenharmony_ci mbedtls_x509_buf *alg) 99a8e1175bSopenharmony_ci{ 100a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 101a8e1175bSopenharmony_ci 102a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) { 103a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 104a8e1175bSopenharmony_ci } 105a8e1175bSopenharmony_ci 106a8e1175bSopenharmony_ci return 0; 107a8e1175bSopenharmony_ci} 108a8e1175bSopenharmony_ci 109a8e1175bSopenharmony_ci/* 110a8e1175bSopenharmony_ci * Parse an algorithm identifier with (optional) parameters 111a8e1175bSopenharmony_ci */ 112a8e1175bSopenharmony_ciint mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, 113a8e1175bSopenharmony_ci mbedtls_x509_buf *alg, mbedtls_x509_buf *params) 114a8e1175bSopenharmony_ci{ 115a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 116a8e1175bSopenharmony_ci 117a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) { 118a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 119a8e1175bSopenharmony_ci } 120a8e1175bSopenharmony_ci 121a8e1175bSopenharmony_ci return 0; 122a8e1175bSopenharmony_ci} 123a8e1175bSopenharmony_ci 124a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 125a8e1175bSopenharmony_ci/* 126a8e1175bSopenharmony_ci * Convert md type to string 127a8e1175bSopenharmony_ci */ 128a8e1175bSopenharmony_ci#if !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 129a8e1175bSopenharmony_ci 130a8e1175bSopenharmony_cistatic inline const char *md_type_to_string(mbedtls_md_type_t md_alg) 131a8e1175bSopenharmony_ci{ 132a8e1175bSopenharmony_ci switch (md_alg) { 133a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_MD5) 134a8e1175bSopenharmony_ci case MBEDTLS_MD_MD5: 135a8e1175bSopenharmony_ci return "MD5"; 136a8e1175bSopenharmony_ci#endif 137a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA1) 138a8e1175bSopenharmony_ci case MBEDTLS_MD_SHA1: 139a8e1175bSopenharmony_ci return "SHA1"; 140a8e1175bSopenharmony_ci#endif 141a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA224) 142a8e1175bSopenharmony_ci case MBEDTLS_MD_SHA224: 143a8e1175bSopenharmony_ci return "SHA224"; 144a8e1175bSopenharmony_ci#endif 145a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA256) 146a8e1175bSopenharmony_ci case MBEDTLS_MD_SHA256: 147a8e1175bSopenharmony_ci return "SHA256"; 148a8e1175bSopenharmony_ci#endif 149a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA384) 150a8e1175bSopenharmony_ci case MBEDTLS_MD_SHA384: 151a8e1175bSopenharmony_ci return "SHA384"; 152a8e1175bSopenharmony_ci#endif 153a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA512) 154a8e1175bSopenharmony_ci case MBEDTLS_MD_SHA512: 155a8e1175bSopenharmony_ci return "SHA512"; 156a8e1175bSopenharmony_ci#endif 157a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_RIPEMD160) 158a8e1175bSopenharmony_ci case MBEDTLS_MD_RIPEMD160: 159a8e1175bSopenharmony_ci return "RIPEMD160"; 160a8e1175bSopenharmony_ci#endif 161a8e1175bSopenharmony_ci case MBEDTLS_MD_NONE: 162a8e1175bSopenharmony_ci return NULL; 163a8e1175bSopenharmony_ci default: 164a8e1175bSopenharmony_ci return NULL; 165a8e1175bSopenharmony_ci } 166a8e1175bSopenharmony_ci} 167a8e1175bSopenharmony_ci 168a8e1175bSopenharmony_ci#endif /* !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) */ 169a8e1175bSopenharmony_ci/* 170a8e1175bSopenharmony_ci * HashAlgorithm ::= AlgorithmIdentifier 171a8e1175bSopenharmony_ci * 172a8e1175bSopenharmony_ci * AlgorithmIdentifier ::= SEQUENCE { 173a8e1175bSopenharmony_ci * algorithm OBJECT IDENTIFIER, 174a8e1175bSopenharmony_ci * parameters ANY DEFINED BY algorithm OPTIONAL } 175a8e1175bSopenharmony_ci * 176a8e1175bSopenharmony_ci * For HashAlgorithm, parameters MUST be NULL or absent. 177a8e1175bSopenharmony_ci */ 178a8e1175bSopenharmony_cistatic int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg) 179a8e1175bSopenharmony_ci{ 180a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 181a8e1175bSopenharmony_ci unsigned char *p; 182a8e1175bSopenharmony_ci const unsigned char *end; 183a8e1175bSopenharmony_ci mbedtls_x509_buf md_oid; 184a8e1175bSopenharmony_ci size_t len; 185a8e1175bSopenharmony_ci 186a8e1175bSopenharmony_ci /* Make sure we got a SEQUENCE and setup bounds */ 187a8e1175bSopenharmony_ci if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { 188a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 189a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 190a8e1175bSopenharmony_ci } 191a8e1175bSopenharmony_ci 192a8e1175bSopenharmony_ci p = alg->p; 193a8e1175bSopenharmony_ci end = p + alg->len; 194a8e1175bSopenharmony_ci 195a8e1175bSopenharmony_ci if (p >= end) { 196a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 197a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_OUT_OF_DATA); 198a8e1175bSopenharmony_ci } 199a8e1175bSopenharmony_ci 200a8e1175bSopenharmony_ci /* Parse md_oid */ 201a8e1175bSopenharmony_ci md_oid.tag = *p; 202a8e1175bSopenharmony_ci 203a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) { 204a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 205a8e1175bSopenharmony_ci } 206a8e1175bSopenharmony_ci 207a8e1175bSopenharmony_ci md_oid.p = p; 208a8e1175bSopenharmony_ci p += md_oid.len; 209a8e1175bSopenharmony_ci 210a8e1175bSopenharmony_ci /* Get md_alg from md_oid */ 211a8e1175bSopenharmony_ci if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) { 212a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 213a8e1175bSopenharmony_ci } 214a8e1175bSopenharmony_ci 215a8e1175bSopenharmony_ci /* Make sure params is absent of NULL */ 216a8e1175bSopenharmony_ci if (p == end) { 217a8e1175bSopenharmony_ci return 0; 218a8e1175bSopenharmony_ci } 219a8e1175bSopenharmony_ci 220a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) { 221a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 222a8e1175bSopenharmony_ci } 223a8e1175bSopenharmony_ci 224a8e1175bSopenharmony_ci if (p != end) { 225a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 226a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 227a8e1175bSopenharmony_ci } 228a8e1175bSopenharmony_ci 229a8e1175bSopenharmony_ci return 0; 230a8e1175bSopenharmony_ci} 231a8e1175bSopenharmony_ci 232a8e1175bSopenharmony_ci/* 233a8e1175bSopenharmony_ci * RSASSA-PSS-params ::= SEQUENCE { 234a8e1175bSopenharmony_ci * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, 235a8e1175bSopenharmony_ci * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, 236a8e1175bSopenharmony_ci * saltLength [2] INTEGER DEFAULT 20, 237a8e1175bSopenharmony_ci * trailerField [3] INTEGER DEFAULT 1 } 238a8e1175bSopenharmony_ci * -- Note that the tags in this Sequence are explicit. 239a8e1175bSopenharmony_ci * 240a8e1175bSopenharmony_ci * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value 241a8e1175bSopenharmony_ci * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other 242a8e1175bSopenharmony_ci * option. Enforce this at parsing time. 243a8e1175bSopenharmony_ci */ 244a8e1175bSopenharmony_ciint mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params, 245a8e1175bSopenharmony_ci mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, 246a8e1175bSopenharmony_ci int *salt_len) 247a8e1175bSopenharmony_ci{ 248a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 249a8e1175bSopenharmony_ci unsigned char *p; 250a8e1175bSopenharmony_ci const unsigned char *end, *end2; 251a8e1175bSopenharmony_ci size_t len; 252a8e1175bSopenharmony_ci mbedtls_x509_buf alg_id, alg_params; 253a8e1175bSopenharmony_ci 254a8e1175bSopenharmony_ci /* First set everything to defaults */ 255a8e1175bSopenharmony_ci *md_alg = MBEDTLS_MD_SHA1; 256a8e1175bSopenharmony_ci *mgf_md = MBEDTLS_MD_SHA1; 257a8e1175bSopenharmony_ci *salt_len = 20; 258a8e1175bSopenharmony_ci 259a8e1175bSopenharmony_ci /* Make sure params is a SEQUENCE and setup bounds */ 260a8e1175bSopenharmony_ci if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { 261a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 262a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 263a8e1175bSopenharmony_ci } 264a8e1175bSopenharmony_ci 265a8e1175bSopenharmony_ci p = (unsigned char *) params->p; 266a8e1175bSopenharmony_ci end = p + params->len; 267a8e1175bSopenharmony_ci 268a8e1175bSopenharmony_ci if (p == end) { 269a8e1175bSopenharmony_ci return 0; 270a8e1175bSopenharmony_ci } 271a8e1175bSopenharmony_ci 272a8e1175bSopenharmony_ci /* 273a8e1175bSopenharmony_ci * HashAlgorithm 274a8e1175bSopenharmony_ci */ 275a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 276a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 277a8e1175bSopenharmony_ci 0)) == 0) { 278a8e1175bSopenharmony_ci end2 = p + len; 279a8e1175bSopenharmony_ci 280a8e1175bSopenharmony_ci /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ 281a8e1175bSopenharmony_ci if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) { 282a8e1175bSopenharmony_ci return ret; 283a8e1175bSopenharmony_ci } 284a8e1175bSopenharmony_ci 285a8e1175bSopenharmony_ci if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) { 286a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 287a8e1175bSopenharmony_ci } 288a8e1175bSopenharmony_ci 289a8e1175bSopenharmony_ci if (p != end2) { 290a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 291a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 292a8e1175bSopenharmony_ci } 293a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 294a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 295a8e1175bSopenharmony_ci } 296a8e1175bSopenharmony_ci 297a8e1175bSopenharmony_ci if (p == end) { 298a8e1175bSopenharmony_ci return 0; 299a8e1175bSopenharmony_ci } 300a8e1175bSopenharmony_ci 301a8e1175bSopenharmony_ci /* 302a8e1175bSopenharmony_ci * MaskGenAlgorithm 303a8e1175bSopenharmony_ci */ 304a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 305a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 306a8e1175bSopenharmony_ci 1)) == 0) { 307a8e1175bSopenharmony_ci end2 = p + len; 308a8e1175bSopenharmony_ci 309a8e1175bSopenharmony_ci /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ 310a8e1175bSopenharmony_ci if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) { 311a8e1175bSopenharmony_ci return ret; 312a8e1175bSopenharmony_ci } 313a8e1175bSopenharmony_ci 314a8e1175bSopenharmony_ci /* Only MFG1 is recognised for now */ 315a8e1175bSopenharmony_ci if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) { 316a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE, 317a8e1175bSopenharmony_ci MBEDTLS_ERR_OID_NOT_FOUND); 318a8e1175bSopenharmony_ci } 319a8e1175bSopenharmony_ci 320a8e1175bSopenharmony_ci /* Parse HashAlgorithm */ 321a8e1175bSopenharmony_ci if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) { 322a8e1175bSopenharmony_ci return ret; 323a8e1175bSopenharmony_ci } 324a8e1175bSopenharmony_ci 325a8e1175bSopenharmony_ci if (p != end2) { 326a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 327a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 328a8e1175bSopenharmony_ci } 329a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 330a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 331a8e1175bSopenharmony_ci } 332a8e1175bSopenharmony_ci 333a8e1175bSopenharmony_ci if (p == end) { 334a8e1175bSopenharmony_ci return 0; 335a8e1175bSopenharmony_ci } 336a8e1175bSopenharmony_ci 337a8e1175bSopenharmony_ci /* 338a8e1175bSopenharmony_ci * salt_len 339a8e1175bSopenharmony_ci */ 340a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 341a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 342a8e1175bSopenharmony_ci 2)) == 0) { 343a8e1175bSopenharmony_ci end2 = p + len; 344a8e1175bSopenharmony_ci 345a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) { 346a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 347a8e1175bSopenharmony_ci } 348a8e1175bSopenharmony_ci 349a8e1175bSopenharmony_ci if (p != end2) { 350a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 351a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 352a8e1175bSopenharmony_ci } 353a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 354a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 355a8e1175bSopenharmony_ci } 356a8e1175bSopenharmony_ci 357a8e1175bSopenharmony_ci if (p == end) { 358a8e1175bSopenharmony_ci return 0; 359a8e1175bSopenharmony_ci } 360a8e1175bSopenharmony_ci 361a8e1175bSopenharmony_ci /* 362a8e1175bSopenharmony_ci * trailer_field (if present, must be 1) 363a8e1175bSopenharmony_ci */ 364a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 365a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 366a8e1175bSopenharmony_ci 3)) == 0) { 367a8e1175bSopenharmony_ci int trailer_field; 368a8e1175bSopenharmony_ci 369a8e1175bSopenharmony_ci end2 = p + len; 370a8e1175bSopenharmony_ci 371a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) { 372a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 373a8e1175bSopenharmony_ci } 374a8e1175bSopenharmony_ci 375a8e1175bSopenharmony_ci if (p != end2) { 376a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 377a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 378a8e1175bSopenharmony_ci } 379a8e1175bSopenharmony_ci 380a8e1175bSopenharmony_ci if (trailer_field != 1) { 381a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_ALG; 382a8e1175bSopenharmony_ci } 383a8e1175bSopenharmony_ci } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 384a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); 385a8e1175bSopenharmony_ci } 386a8e1175bSopenharmony_ci 387a8e1175bSopenharmony_ci if (p != end) { 388a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, 389a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 390a8e1175bSopenharmony_ci } 391a8e1175bSopenharmony_ci 392a8e1175bSopenharmony_ci return 0; 393a8e1175bSopenharmony_ci} 394a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 395a8e1175bSopenharmony_ci 396a8e1175bSopenharmony_ci/* 397a8e1175bSopenharmony_ci * AttributeTypeAndValue ::= SEQUENCE { 398a8e1175bSopenharmony_ci * type AttributeType, 399a8e1175bSopenharmony_ci * value AttributeValue } 400a8e1175bSopenharmony_ci * 401a8e1175bSopenharmony_ci * AttributeType ::= OBJECT IDENTIFIER 402a8e1175bSopenharmony_ci * 403a8e1175bSopenharmony_ci * AttributeValue ::= ANY DEFINED BY AttributeType 404a8e1175bSopenharmony_ci */ 405a8e1175bSopenharmony_cistatic int x509_get_attr_type_value(unsigned char **p, 406a8e1175bSopenharmony_ci const unsigned char *end, 407a8e1175bSopenharmony_ci mbedtls_x509_name *cur) 408a8e1175bSopenharmony_ci{ 409a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 410a8e1175bSopenharmony_ci size_t len; 411a8e1175bSopenharmony_ci mbedtls_x509_buf *oid; 412a8e1175bSopenharmony_ci mbedtls_x509_buf *val; 413a8e1175bSopenharmony_ci 414a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(p, end, &len, 415a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 416a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); 417a8e1175bSopenharmony_ci } 418a8e1175bSopenharmony_ci 419a8e1175bSopenharmony_ci end = *p + len; 420a8e1175bSopenharmony_ci 421a8e1175bSopenharmony_ci if ((end - *p) < 1) { 422a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, 423a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_OUT_OF_DATA); 424a8e1175bSopenharmony_ci } 425a8e1175bSopenharmony_ci 426a8e1175bSopenharmony_ci oid = &cur->oid; 427a8e1175bSopenharmony_ci oid->tag = **p; 428a8e1175bSopenharmony_ci 429a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) { 430a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); 431a8e1175bSopenharmony_ci } 432a8e1175bSopenharmony_ci 433a8e1175bSopenharmony_ci oid->p = *p; 434a8e1175bSopenharmony_ci *p += oid->len; 435a8e1175bSopenharmony_ci 436a8e1175bSopenharmony_ci if ((end - *p) < 1) { 437a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, 438a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_OUT_OF_DATA); 439a8e1175bSopenharmony_ci } 440a8e1175bSopenharmony_ci 441a8e1175bSopenharmony_ci if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && 442a8e1175bSopenharmony_ci **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && 443a8e1175bSopenharmony_ci **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && 444a8e1175bSopenharmony_ci **p != MBEDTLS_ASN1_BIT_STRING) { 445a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, 446a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 447a8e1175bSopenharmony_ci } 448a8e1175bSopenharmony_ci 449a8e1175bSopenharmony_ci val = &cur->val; 450a8e1175bSopenharmony_ci val->tag = *(*p)++; 451a8e1175bSopenharmony_ci 452a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) { 453a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); 454a8e1175bSopenharmony_ci } 455a8e1175bSopenharmony_ci 456a8e1175bSopenharmony_ci val->p = *p; 457a8e1175bSopenharmony_ci *p += val->len; 458a8e1175bSopenharmony_ci 459a8e1175bSopenharmony_ci if (*p != end) { 460a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, 461a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 462a8e1175bSopenharmony_ci } 463a8e1175bSopenharmony_ci 464a8e1175bSopenharmony_ci cur->next = NULL; 465a8e1175bSopenharmony_ci 466a8e1175bSopenharmony_ci return 0; 467a8e1175bSopenharmony_ci} 468a8e1175bSopenharmony_ci 469a8e1175bSopenharmony_ci/* 470a8e1175bSopenharmony_ci * Name ::= CHOICE { -- only one possibility for now -- 471a8e1175bSopenharmony_ci * rdnSequence RDNSequence } 472a8e1175bSopenharmony_ci * 473a8e1175bSopenharmony_ci * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 474a8e1175bSopenharmony_ci * 475a8e1175bSopenharmony_ci * RelativeDistinguishedName ::= 476a8e1175bSopenharmony_ci * SET OF AttributeTypeAndValue 477a8e1175bSopenharmony_ci * 478a8e1175bSopenharmony_ci * AttributeTypeAndValue ::= SEQUENCE { 479a8e1175bSopenharmony_ci * type AttributeType, 480a8e1175bSopenharmony_ci * value AttributeValue } 481a8e1175bSopenharmony_ci * 482a8e1175bSopenharmony_ci * AttributeType ::= OBJECT IDENTIFIER 483a8e1175bSopenharmony_ci * 484a8e1175bSopenharmony_ci * AttributeValue ::= ANY DEFINED BY AttributeType 485a8e1175bSopenharmony_ci * 486a8e1175bSopenharmony_ci * The data structure is optimized for the common case where each RDN has only 487a8e1175bSopenharmony_ci * one element, which is represented as a list of AttributeTypeAndValue. 488a8e1175bSopenharmony_ci * For the general case we still use a flat list, but we mark elements of the 489a8e1175bSopenharmony_ci * same set so that they are "merged" together in the functions that consume 490a8e1175bSopenharmony_ci * this list, eg mbedtls_x509_dn_gets(). 491a8e1175bSopenharmony_ci * 492a8e1175bSopenharmony_ci * On success, this function may allocate a linked list starting at cur->next 493a8e1175bSopenharmony_ci * that must later be free'd by the caller using mbedtls_free(). In error 494a8e1175bSopenharmony_ci * cases, this function frees all allocated memory internally and the caller 495a8e1175bSopenharmony_ci * has no freeing responsibilities. 496a8e1175bSopenharmony_ci */ 497a8e1175bSopenharmony_ciint mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, 498a8e1175bSopenharmony_ci mbedtls_x509_name *cur) 499a8e1175bSopenharmony_ci{ 500a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 501a8e1175bSopenharmony_ci size_t set_len; 502a8e1175bSopenharmony_ci const unsigned char *end_set; 503a8e1175bSopenharmony_ci mbedtls_x509_name *head = cur; 504a8e1175bSopenharmony_ci 505a8e1175bSopenharmony_ci /* don't use recursion, we'd risk stack overflow if not optimized */ 506a8e1175bSopenharmony_ci while (1) { 507a8e1175bSopenharmony_ci /* 508a8e1175bSopenharmony_ci * parse SET 509a8e1175bSopenharmony_ci */ 510a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(p, end, &set_len, 511a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) { 512a8e1175bSopenharmony_ci ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); 513a8e1175bSopenharmony_ci goto error; 514a8e1175bSopenharmony_ci } 515a8e1175bSopenharmony_ci 516a8e1175bSopenharmony_ci end_set = *p + set_len; 517a8e1175bSopenharmony_ci 518a8e1175bSopenharmony_ci while (1) { 519a8e1175bSopenharmony_ci if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) { 520a8e1175bSopenharmony_ci goto error; 521a8e1175bSopenharmony_ci } 522a8e1175bSopenharmony_ci 523a8e1175bSopenharmony_ci if (*p == end_set) { 524a8e1175bSopenharmony_ci break; 525a8e1175bSopenharmony_ci } 526a8e1175bSopenharmony_ci 527a8e1175bSopenharmony_ci /* Mark this item as being no the only one in a set */ 528a8e1175bSopenharmony_ci cur->next_merged = 1; 529a8e1175bSopenharmony_ci 530a8e1175bSopenharmony_ci cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name)); 531a8e1175bSopenharmony_ci 532a8e1175bSopenharmony_ci if (cur->next == NULL) { 533a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_X509_ALLOC_FAILED; 534a8e1175bSopenharmony_ci goto error; 535a8e1175bSopenharmony_ci } 536a8e1175bSopenharmony_ci 537a8e1175bSopenharmony_ci cur = cur->next; 538a8e1175bSopenharmony_ci } 539a8e1175bSopenharmony_ci 540a8e1175bSopenharmony_ci /* 541a8e1175bSopenharmony_ci * continue until end of SEQUENCE is reached 542a8e1175bSopenharmony_ci */ 543a8e1175bSopenharmony_ci if (*p == end) { 544a8e1175bSopenharmony_ci return 0; 545a8e1175bSopenharmony_ci } 546a8e1175bSopenharmony_ci 547a8e1175bSopenharmony_ci cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name)); 548a8e1175bSopenharmony_ci 549a8e1175bSopenharmony_ci if (cur->next == NULL) { 550a8e1175bSopenharmony_ci ret = MBEDTLS_ERR_X509_ALLOC_FAILED; 551a8e1175bSopenharmony_ci goto error; 552a8e1175bSopenharmony_ci } 553a8e1175bSopenharmony_ci 554a8e1175bSopenharmony_ci cur = cur->next; 555a8e1175bSopenharmony_ci } 556a8e1175bSopenharmony_ci 557a8e1175bSopenharmony_cierror: 558a8e1175bSopenharmony_ci /* Skip the first element as we did not allocate it */ 559a8e1175bSopenharmony_ci mbedtls_asn1_free_named_data_list_shallow(head->next); 560a8e1175bSopenharmony_ci head->next = NULL; 561a8e1175bSopenharmony_ci 562a8e1175bSopenharmony_ci return ret; 563a8e1175bSopenharmony_ci} 564a8e1175bSopenharmony_ci 565a8e1175bSopenharmony_cistatic int x509_date_is_valid(const mbedtls_x509_time *t) 566a8e1175bSopenharmony_ci{ 567a8e1175bSopenharmony_ci unsigned int month_days; 568a8e1175bSopenharmony_ci unsigned int year; 569a8e1175bSopenharmony_ci switch (t->mon) { 570a8e1175bSopenharmony_ci case 1: case 3: case 5: case 7: case 8: case 10: case 12: 571a8e1175bSopenharmony_ci month_days = 31; 572a8e1175bSopenharmony_ci break; 573a8e1175bSopenharmony_ci case 4: case 6: case 9: case 11: 574a8e1175bSopenharmony_ci month_days = 30; 575a8e1175bSopenharmony_ci break; 576a8e1175bSopenharmony_ci case 2: 577a8e1175bSopenharmony_ci year = (unsigned int) t->year; 578a8e1175bSopenharmony_ci month_days = ((year & 3) || (!(year % 100) 579a8e1175bSopenharmony_ci && (year % 400))) 580a8e1175bSopenharmony_ci ? 28 : 29; 581a8e1175bSopenharmony_ci break; 582a8e1175bSopenharmony_ci default: 583a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_DATE; 584a8e1175bSopenharmony_ci } 585a8e1175bSopenharmony_ci 586a8e1175bSopenharmony_ci if ((unsigned int) (t->day - 1) >= month_days || /* (1 - days in month) */ 587a8e1175bSopenharmony_ci /* (unsigned int) (t->mon - 1) >= 12 || */ /* (1 - 12) checked above */ 588a8e1175bSopenharmony_ci (unsigned int) t->year > 9999 || /* (0 - 9999) */ 589a8e1175bSopenharmony_ci (unsigned int) t->hour > 23 || /* (0 - 23) */ 590a8e1175bSopenharmony_ci (unsigned int) t->min > 59 || /* (0 - 59) */ 591a8e1175bSopenharmony_ci (unsigned int) t->sec > 59) { /* (0 - 59) */ 592a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_DATE; 593a8e1175bSopenharmony_ci } 594a8e1175bSopenharmony_ci 595a8e1175bSopenharmony_ci return 0; 596a8e1175bSopenharmony_ci} 597a8e1175bSopenharmony_ci 598a8e1175bSopenharmony_cistatic int x509_parse2_int(const unsigned char *p) 599a8e1175bSopenharmony_ci{ 600a8e1175bSopenharmony_ci uint32_t d1 = p[0] - '0'; 601a8e1175bSopenharmony_ci uint32_t d2 = p[1] - '0'; 602a8e1175bSopenharmony_ci return (d1 < 10 && d2 < 10) ? (int) (d1 * 10 + d2) : -1; 603a8e1175bSopenharmony_ci} 604a8e1175bSopenharmony_ci 605a8e1175bSopenharmony_ci/* 606a8e1175bSopenharmony_ci * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) 607a8e1175bSopenharmony_ci * field. 608a8e1175bSopenharmony_ci */ 609a8e1175bSopenharmony_cistatic int x509_parse_time(const unsigned char *p, mbedtls_x509_time *tm, 610a8e1175bSopenharmony_ci size_t yearlen) 611a8e1175bSopenharmony_ci{ 612a8e1175bSopenharmony_ci int x; 613a8e1175bSopenharmony_ci 614a8e1175bSopenharmony_ci /* 615a8e1175bSopenharmony_ci * Parse year, month, day, hour, minute, second 616a8e1175bSopenharmony_ci */ 617a8e1175bSopenharmony_ci tm->year = x509_parse2_int(p); 618a8e1175bSopenharmony_ci if (tm->year < 0) { 619a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_DATE; 620a8e1175bSopenharmony_ci } 621a8e1175bSopenharmony_ci 622a8e1175bSopenharmony_ci if (4 == yearlen) { 623a8e1175bSopenharmony_ci x = tm->year * 100; 624a8e1175bSopenharmony_ci p += 2; 625a8e1175bSopenharmony_ci tm->year = x509_parse2_int(p); 626a8e1175bSopenharmony_ci if (tm->year < 0) { 627a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_DATE; 628a8e1175bSopenharmony_ci } 629a8e1175bSopenharmony_ci } else { 630a8e1175bSopenharmony_ci x = (tm->year < 50) ? 2000 : 1900; 631a8e1175bSopenharmony_ci } 632a8e1175bSopenharmony_ci tm->year += x; 633a8e1175bSopenharmony_ci 634a8e1175bSopenharmony_ci tm->mon = x509_parse2_int(p + 2); 635a8e1175bSopenharmony_ci tm->day = x509_parse2_int(p + 4); 636a8e1175bSopenharmony_ci tm->hour = x509_parse2_int(p + 6); 637a8e1175bSopenharmony_ci tm->min = x509_parse2_int(p + 8); 638a8e1175bSopenharmony_ci tm->sec = x509_parse2_int(p + 10); 639a8e1175bSopenharmony_ci 640a8e1175bSopenharmony_ci return x509_date_is_valid(tm); 641a8e1175bSopenharmony_ci} 642a8e1175bSopenharmony_ci 643a8e1175bSopenharmony_ci/* 644a8e1175bSopenharmony_ci * Time ::= CHOICE { 645a8e1175bSopenharmony_ci * utcTime UTCTime, 646a8e1175bSopenharmony_ci * generalTime GeneralizedTime } 647a8e1175bSopenharmony_ci */ 648a8e1175bSopenharmony_ciint mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, 649a8e1175bSopenharmony_ci mbedtls_x509_time *tm) 650a8e1175bSopenharmony_ci{ 651a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 652a8e1175bSopenharmony_ci size_t len, year_len; 653a8e1175bSopenharmony_ci unsigned char tag; 654a8e1175bSopenharmony_ci 655a8e1175bSopenharmony_ci if ((end - *p) < 1) { 656a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, 657a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_OUT_OF_DATA); 658a8e1175bSopenharmony_ci } 659a8e1175bSopenharmony_ci 660a8e1175bSopenharmony_ci tag = **p; 661a8e1175bSopenharmony_ci 662a8e1175bSopenharmony_ci if (tag == MBEDTLS_ASN1_UTC_TIME) { 663a8e1175bSopenharmony_ci year_len = 2; 664a8e1175bSopenharmony_ci } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) { 665a8e1175bSopenharmony_ci year_len = 4; 666a8e1175bSopenharmony_ci } else { 667a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, 668a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 669a8e1175bSopenharmony_ci } 670a8e1175bSopenharmony_ci 671a8e1175bSopenharmony_ci (*p)++; 672a8e1175bSopenharmony_ci ret = mbedtls_asn1_get_len(p, end, &len); 673a8e1175bSopenharmony_ci 674a8e1175bSopenharmony_ci if (ret != 0) { 675a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret); 676a8e1175bSopenharmony_ci } 677a8e1175bSopenharmony_ci 678a8e1175bSopenharmony_ci /* len is 12 or 14 depending on year_len, plus optional trailing 'Z' */ 679a8e1175bSopenharmony_ci if (len != year_len + 10 && 680a8e1175bSopenharmony_ci !(len == year_len + 11 && (*p)[(len - 1)] == 'Z')) { 681a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_DATE; 682a8e1175bSopenharmony_ci } 683a8e1175bSopenharmony_ci 684a8e1175bSopenharmony_ci (*p) += len; 685a8e1175bSopenharmony_ci return x509_parse_time(*p - len, tm, year_len); 686a8e1175bSopenharmony_ci} 687a8e1175bSopenharmony_ci 688a8e1175bSopenharmony_ciint mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig) 689a8e1175bSopenharmony_ci{ 690a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 691a8e1175bSopenharmony_ci size_t len; 692a8e1175bSopenharmony_ci int tag_type; 693a8e1175bSopenharmony_ci 694a8e1175bSopenharmony_ci if ((end - *p) < 1) { 695a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, 696a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_OUT_OF_DATA); 697a8e1175bSopenharmony_ci } 698a8e1175bSopenharmony_ci 699a8e1175bSopenharmony_ci tag_type = **p; 700a8e1175bSopenharmony_ci 701a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) { 702a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret); 703a8e1175bSopenharmony_ci } 704a8e1175bSopenharmony_ci 705a8e1175bSopenharmony_ci sig->tag = tag_type; 706a8e1175bSopenharmony_ci sig->len = len; 707a8e1175bSopenharmony_ci sig->p = *p; 708a8e1175bSopenharmony_ci 709a8e1175bSopenharmony_ci *p += len; 710a8e1175bSopenharmony_ci 711a8e1175bSopenharmony_ci return 0; 712a8e1175bSopenharmony_ci} 713a8e1175bSopenharmony_ci 714a8e1175bSopenharmony_ci/* 715a8e1175bSopenharmony_ci * Get signature algorithm from alg OID and optional parameters 716a8e1175bSopenharmony_ci */ 717a8e1175bSopenharmony_ciint mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, 718a8e1175bSopenharmony_ci mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, 719a8e1175bSopenharmony_ci void **sig_opts) 720a8e1175bSopenharmony_ci{ 721a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 722a8e1175bSopenharmony_ci 723a8e1175bSopenharmony_ci if (*sig_opts != NULL) { 724a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 725a8e1175bSopenharmony_ci } 726a8e1175bSopenharmony_ci 727a8e1175bSopenharmony_ci if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) { 728a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret); 729a8e1175bSopenharmony_ci } 730a8e1175bSopenharmony_ci 731a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 732a8e1175bSopenharmony_ci if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) { 733a8e1175bSopenharmony_ci mbedtls_pk_rsassa_pss_options *pss_opts; 734a8e1175bSopenharmony_ci 735a8e1175bSopenharmony_ci pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options)); 736a8e1175bSopenharmony_ci if (pss_opts == NULL) { 737a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_ALLOC_FAILED; 738a8e1175bSopenharmony_ci } 739a8e1175bSopenharmony_ci 740a8e1175bSopenharmony_ci ret = mbedtls_x509_get_rsassa_pss_params(sig_params, 741a8e1175bSopenharmony_ci md_alg, 742a8e1175bSopenharmony_ci &pss_opts->mgf1_hash_id, 743a8e1175bSopenharmony_ci &pss_opts->expected_salt_len); 744a8e1175bSopenharmony_ci if (ret != 0) { 745a8e1175bSopenharmony_ci mbedtls_free(pss_opts); 746a8e1175bSopenharmony_ci return ret; 747a8e1175bSopenharmony_ci } 748a8e1175bSopenharmony_ci 749a8e1175bSopenharmony_ci *sig_opts = (void *) pss_opts; 750a8e1175bSopenharmony_ci } else 751a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 752a8e1175bSopenharmony_ci { 753a8e1175bSopenharmony_ci /* Make sure parameters are absent or NULL */ 754a8e1175bSopenharmony_ci if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) || 755a8e1175bSopenharmony_ci sig_params->len != 0) { 756a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_ALG; 757a8e1175bSopenharmony_ci } 758a8e1175bSopenharmony_ci } 759a8e1175bSopenharmony_ci 760a8e1175bSopenharmony_ci return 0; 761a8e1175bSopenharmony_ci} 762a8e1175bSopenharmony_ci 763a8e1175bSopenharmony_ci/* 764a8e1175bSopenharmony_ci * X.509 Extensions (No parsing of extensions, pointer should 765a8e1175bSopenharmony_ci * be either manually updated or extensions should be parsed!) 766a8e1175bSopenharmony_ci */ 767a8e1175bSopenharmony_ciint mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, 768a8e1175bSopenharmony_ci mbedtls_x509_buf *ext, int tag) 769a8e1175bSopenharmony_ci{ 770a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 771a8e1175bSopenharmony_ci size_t len; 772a8e1175bSopenharmony_ci 773a8e1175bSopenharmony_ci /* Extension structure use EXPLICIT tagging. That is, the actual 774a8e1175bSopenharmony_ci * `Extensions` structure is wrapped by a tag-length pair using 775a8e1175bSopenharmony_ci * the respective context-specific tag. */ 776a8e1175bSopenharmony_ci ret = mbedtls_asn1_get_tag(p, end, &ext->len, 777a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag); 778a8e1175bSopenharmony_ci if (ret != 0) { 779a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 780a8e1175bSopenharmony_ci } 781a8e1175bSopenharmony_ci 782a8e1175bSopenharmony_ci ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag; 783a8e1175bSopenharmony_ci ext->p = *p; 784a8e1175bSopenharmony_ci end = *p + ext->len; 785a8e1175bSopenharmony_ci 786a8e1175bSopenharmony_ci /* 787a8e1175bSopenharmony_ci * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 788a8e1175bSopenharmony_ci */ 789a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(p, end, &len, 790a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 791a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 792a8e1175bSopenharmony_ci } 793a8e1175bSopenharmony_ci 794a8e1175bSopenharmony_ci if (end != *p + len) { 795a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 796a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 797a8e1175bSopenharmony_ci } 798a8e1175bSopenharmony_ci 799a8e1175bSopenharmony_ci return 0; 800a8e1175bSopenharmony_ci} 801a8e1175bSopenharmony_ci 802a8e1175bSopenharmony_cistatic char nibble_to_hex_digit(int i) 803a8e1175bSopenharmony_ci{ 804a8e1175bSopenharmony_ci return (i < 10) ? (i + '0') : (i - 10 + 'A'); 805a8e1175bSopenharmony_ci} 806a8e1175bSopenharmony_ci 807a8e1175bSopenharmony_ci/* 808a8e1175bSopenharmony_ci * Store the name in printable form into buf; no more 809a8e1175bSopenharmony_ci * than size characters will be written 810a8e1175bSopenharmony_ci */ 811a8e1175bSopenharmony_ciint mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn) 812a8e1175bSopenharmony_ci{ 813a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 814a8e1175bSopenharmony_ci size_t i, j, n, asn1_len_size, asn1_tag_size, asn1_tag_len_buf_start; 815a8e1175bSopenharmony_ci /* 6 is enough as our asn1 write functions only write one byte for the tag and at most five bytes for the length*/ 816a8e1175bSopenharmony_ci unsigned char asn1_tag_len_buf[6]; 817a8e1175bSopenharmony_ci unsigned char *asn1_len_p; 818a8e1175bSopenharmony_ci unsigned char c, merge = 0; 819a8e1175bSopenharmony_ci const mbedtls_x509_name *name; 820a8e1175bSopenharmony_ci const char *short_name = NULL; 821a8e1175bSopenharmony_ci char lowbits, highbits; 822a8e1175bSopenharmony_ci char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; 823a8e1175bSopenharmony_ci int print_hexstring; 824a8e1175bSopenharmony_ci 825a8e1175bSopenharmony_ci memset(s, 0, sizeof(s)); 826a8e1175bSopenharmony_ci 827a8e1175bSopenharmony_ci name = dn; 828a8e1175bSopenharmony_ci p = buf; 829a8e1175bSopenharmony_ci n = size; 830a8e1175bSopenharmony_ci 831a8e1175bSopenharmony_ci while (name != NULL) { 832a8e1175bSopenharmony_ci if (!name->oid.p) { 833a8e1175bSopenharmony_ci name = name->next; 834a8e1175bSopenharmony_ci continue; 835a8e1175bSopenharmony_ci } 836a8e1175bSopenharmony_ci 837a8e1175bSopenharmony_ci if (name != dn) { 838a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, merge ? " + " : ", "); 839a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 840a8e1175bSopenharmony_ci } 841a8e1175bSopenharmony_ci 842a8e1175bSopenharmony_ci print_hexstring = (name->val.tag != MBEDTLS_ASN1_UTF8_STRING) && 843a8e1175bSopenharmony_ci (name->val.tag != MBEDTLS_ASN1_PRINTABLE_STRING) && 844a8e1175bSopenharmony_ci (name->val.tag != MBEDTLS_ASN1_IA5_STRING); 845a8e1175bSopenharmony_ci 846a8e1175bSopenharmony_ci if ((ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name)) == 0) { 847a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "%s=", short_name); 848a8e1175bSopenharmony_ci } else { 849a8e1175bSopenharmony_ci if ((ret = mbedtls_oid_get_numeric_string(p, n, &name->oid)) > 0) { 850a8e1175bSopenharmony_ci n -= ret; 851a8e1175bSopenharmony_ci p += ret; 852a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "="); 853a8e1175bSopenharmony_ci print_hexstring = 1; 854a8e1175bSopenharmony_ci } else if (ret == MBEDTLS_ERR_OID_BUF_TOO_SMALL) { 855a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 856a8e1175bSopenharmony_ci } else { 857a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "\?\?="); 858a8e1175bSopenharmony_ci } 859a8e1175bSopenharmony_ci } 860a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 861a8e1175bSopenharmony_ci 862a8e1175bSopenharmony_ci if (print_hexstring) { 863a8e1175bSopenharmony_ci s[0] = '#'; 864a8e1175bSopenharmony_ci 865a8e1175bSopenharmony_ci asn1_len_p = asn1_tag_len_buf + sizeof(asn1_tag_len_buf); 866a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_write_len(&asn1_len_p, asn1_tag_len_buf, name->val.len)) < 0) { 867a8e1175bSopenharmony_ci return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 868a8e1175bSopenharmony_ci } 869a8e1175bSopenharmony_ci asn1_len_size = ret; 870a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_write_tag(&asn1_len_p, asn1_tag_len_buf, name->val.tag)) < 0) { 871a8e1175bSopenharmony_ci return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 872a8e1175bSopenharmony_ci } 873a8e1175bSopenharmony_ci asn1_tag_size = ret; 874a8e1175bSopenharmony_ci asn1_tag_len_buf_start = sizeof(asn1_tag_len_buf) - asn1_len_size - asn1_tag_size; 875a8e1175bSopenharmony_ci for (i = 0, j = 1; i < asn1_len_size + asn1_tag_size; i++) { 876a8e1175bSopenharmony_ci if (j + 1 >= sizeof(s) - 1) { 877a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 878a8e1175bSopenharmony_ci } 879a8e1175bSopenharmony_ci c = asn1_tag_len_buf[asn1_tag_len_buf_start+i]; 880a8e1175bSopenharmony_ci lowbits = (c & 0x0F); 881a8e1175bSopenharmony_ci highbits = c >> 4; 882a8e1175bSopenharmony_ci s[j++] = nibble_to_hex_digit(highbits); 883a8e1175bSopenharmony_ci s[j++] = nibble_to_hex_digit(lowbits); 884a8e1175bSopenharmony_ci } 885a8e1175bSopenharmony_ci for (i = 0; i < name->val.len; i++) { 886a8e1175bSopenharmony_ci if (j + 1 >= sizeof(s) - 1) { 887a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 888a8e1175bSopenharmony_ci } 889a8e1175bSopenharmony_ci c = name->val.p[i]; 890a8e1175bSopenharmony_ci lowbits = (c & 0x0F); 891a8e1175bSopenharmony_ci highbits = c >> 4; 892a8e1175bSopenharmony_ci s[j++] = nibble_to_hex_digit(highbits); 893a8e1175bSopenharmony_ci s[j++] = nibble_to_hex_digit(lowbits); 894a8e1175bSopenharmony_ci } 895a8e1175bSopenharmony_ci } else { 896a8e1175bSopenharmony_ci for (i = 0, j = 0; i < name->val.len; i++, j++) { 897a8e1175bSopenharmony_ci if (j >= sizeof(s) - 1) { 898a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 899a8e1175bSopenharmony_ci } 900a8e1175bSopenharmony_ci 901a8e1175bSopenharmony_ci c = name->val.p[i]; 902a8e1175bSopenharmony_ci // Special characters requiring escaping, RFC 4514 Section 2.4 903a8e1175bSopenharmony_ci if (c == '\0') { 904a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_NAME; 905a8e1175bSopenharmony_ci } else { 906a8e1175bSopenharmony_ci if (strchr(",=+<>;\"\\", c) || 907a8e1175bSopenharmony_ci ((i == 0) && strchr("# ", c)) || 908a8e1175bSopenharmony_ci ((i == name->val.len-1) && (c == ' '))) { 909a8e1175bSopenharmony_ci if (j + 1 >= sizeof(s) - 1) { 910a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 911a8e1175bSopenharmony_ci } 912a8e1175bSopenharmony_ci s[j++] = '\\'; 913a8e1175bSopenharmony_ci } 914a8e1175bSopenharmony_ci } 915a8e1175bSopenharmony_ci if (c < 32 || c >= 127) { 916a8e1175bSopenharmony_ci if (j + 3 >= sizeof(s) - 1) { 917a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 918a8e1175bSopenharmony_ci } 919a8e1175bSopenharmony_ci s[j++] = '\\'; 920a8e1175bSopenharmony_ci lowbits = (c & 0x0F); 921a8e1175bSopenharmony_ci highbits = c >> 4; 922a8e1175bSopenharmony_ci s[j++] = nibble_to_hex_digit(highbits); 923a8e1175bSopenharmony_ci s[j] = nibble_to_hex_digit(lowbits); 924a8e1175bSopenharmony_ci } else { 925a8e1175bSopenharmony_ci s[j] = c; 926a8e1175bSopenharmony_ci } 927a8e1175bSopenharmony_ci } 928a8e1175bSopenharmony_ci } 929a8e1175bSopenharmony_ci s[j] = '\0'; 930a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "%s", s); 931a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 932a8e1175bSopenharmony_ci 933a8e1175bSopenharmony_ci merge = name->next_merged; 934a8e1175bSopenharmony_ci name = name->next; 935a8e1175bSopenharmony_ci } 936a8e1175bSopenharmony_ci 937a8e1175bSopenharmony_ci return (int) (size - n); 938a8e1175bSopenharmony_ci} 939a8e1175bSopenharmony_ci 940a8e1175bSopenharmony_ci/* 941a8e1175bSopenharmony_ci * Store the serial in printable form into buf; no more 942a8e1175bSopenharmony_ci * than size characters will be written 943a8e1175bSopenharmony_ci */ 944a8e1175bSopenharmony_ciint mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial) 945a8e1175bSopenharmony_ci{ 946a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 947a8e1175bSopenharmony_ci size_t i, n, nr; 948a8e1175bSopenharmony_ci char *p; 949a8e1175bSopenharmony_ci 950a8e1175bSopenharmony_ci p = buf; 951a8e1175bSopenharmony_ci n = size; 952a8e1175bSopenharmony_ci 953a8e1175bSopenharmony_ci nr = (serial->len <= 32) 954a8e1175bSopenharmony_ci ? serial->len : 28; 955a8e1175bSopenharmony_ci 956a8e1175bSopenharmony_ci for (i = 0; i < nr; i++) { 957a8e1175bSopenharmony_ci if (i == 0 && nr > 1 && serial->p[i] == 0x0) { 958a8e1175bSopenharmony_ci continue; 959a8e1175bSopenharmony_ci } 960a8e1175bSopenharmony_ci 961a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "%02X%s", 962a8e1175bSopenharmony_ci serial->p[i], (i < nr - 1) ? ":" : ""); 963a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 964a8e1175bSopenharmony_ci } 965a8e1175bSopenharmony_ci 966a8e1175bSopenharmony_ci if (nr != serial->len) { 967a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "...."); 968a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 969a8e1175bSopenharmony_ci } 970a8e1175bSopenharmony_ci 971a8e1175bSopenharmony_ci return (int) (size - n); 972a8e1175bSopenharmony_ci} 973a8e1175bSopenharmony_ci 974a8e1175bSopenharmony_ci#if !defined(MBEDTLS_X509_REMOVE_INFO) 975a8e1175bSopenharmony_ci/* 976a8e1175bSopenharmony_ci * Helper for writing signature algorithms 977a8e1175bSopenharmony_ci */ 978a8e1175bSopenharmony_ciint mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid, 979a8e1175bSopenharmony_ci mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, 980a8e1175bSopenharmony_ci const void *sig_opts) 981a8e1175bSopenharmony_ci{ 982a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 983a8e1175bSopenharmony_ci char *p = buf; 984a8e1175bSopenharmony_ci size_t n = size; 985a8e1175bSopenharmony_ci const char *desc = NULL; 986a8e1175bSopenharmony_ci 987a8e1175bSopenharmony_ci ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc); 988a8e1175bSopenharmony_ci if (ret != 0) { 989a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "???"); 990a8e1175bSopenharmony_ci } else { 991a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "%s", desc); 992a8e1175bSopenharmony_ci } 993a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 994a8e1175bSopenharmony_ci 995a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 996a8e1175bSopenharmony_ci if (pk_alg == MBEDTLS_PK_RSASSA_PSS) { 997a8e1175bSopenharmony_ci const mbedtls_pk_rsassa_pss_options *pss_opts; 998a8e1175bSopenharmony_ci 999a8e1175bSopenharmony_ci pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; 1000a8e1175bSopenharmony_ci 1001a8e1175bSopenharmony_ci const char *name = md_type_to_string(md_alg); 1002a8e1175bSopenharmony_ci const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id); 1003a8e1175bSopenharmony_ci 1004a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)", 1005a8e1175bSopenharmony_ci name ? name : "???", 1006a8e1175bSopenharmony_ci mgf_name ? mgf_name : "???", 1007a8e1175bSopenharmony_ci (unsigned int) pss_opts->expected_salt_len); 1008a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1009a8e1175bSopenharmony_ci } 1010a8e1175bSopenharmony_ci#else 1011a8e1175bSopenharmony_ci ((void) pk_alg); 1012a8e1175bSopenharmony_ci ((void) md_alg); 1013a8e1175bSopenharmony_ci ((void) sig_opts); 1014a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 1015a8e1175bSopenharmony_ci 1016a8e1175bSopenharmony_ci return (int) (size - n); 1017a8e1175bSopenharmony_ci} 1018a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_REMOVE_INFO */ 1019a8e1175bSopenharmony_ci 1020a8e1175bSopenharmony_ci/* 1021a8e1175bSopenharmony_ci * Helper for writing "RSA key size", "EC key size", etc 1022a8e1175bSopenharmony_ci */ 1023a8e1175bSopenharmony_ciint mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name) 1024a8e1175bSopenharmony_ci{ 1025a8e1175bSopenharmony_ci char *p = buf; 1026a8e1175bSopenharmony_ci size_t n = buf_size; 1027a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1028a8e1175bSopenharmony_ci 1029a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "%s key size", name); 1030a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1031a8e1175bSopenharmony_ci 1032a8e1175bSopenharmony_ci return 0; 1033a8e1175bSopenharmony_ci} 1034a8e1175bSopenharmony_ci 1035a8e1175bSopenharmony_ciint mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, 1036a8e1175bSopenharmony_ci const mbedtls_x509_time *t2) 1037a8e1175bSopenharmony_ci{ 1038a8e1175bSopenharmony_ci int x; 1039a8e1175bSopenharmony_ci 1040a8e1175bSopenharmony_ci x = (((t1->year << 9) | (t1->mon << 5) | (t1->day)) - 1041a8e1175bSopenharmony_ci ((t2->year << 9) | (t2->mon << 5) | (t2->day))); 1042a8e1175bSopenharmony_ci if (x != 0) { 1043a8e1175bSopenharmony_ci return x; 1044a8e1175bSopenharmony_ci } 1045a8e1175bSopenharmony_ci 1046a8e1175bSopenharmony_ci x = (((t1->hour << 12) | (t1->min << 6) | (t1->sec)) - 1047a8e1175bSopenharmony_ci ((t2->hour << 12) | (t2->min << 6) | (t2->sec))); 1048a8e1175bSopenharmony_ci return x; 1049a8e1175bSopenharmony_ci} 1050a8e1175bSopenharmony_ci 1051a8e1175bSopenharmony_ci#if defined(MBEDTLS_HAVE_TIME_DATE) 1052a8e1175bSopenharmony_ciint mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now) 1053a8e1175bSopenharmony_ci{ 1054a8e1175bSopenharmony_ci struct tm tm; 1055a8e1175bSopenharmony_ci 1056a8e1175bSopenharmony_ci if (mbedtls_platform_gmtime_r(&tt, &tm) == NULL) { 1057a8e1175bSopenharmony_ci return -1; 1058a8e1175bSopenharmony_ci } 1059a8e1175bSopenharmony_ci 1060a8e1175bSopenharmony_ci now->year = tm.tm_year + 1900; 1061a8e1175bSopenharmony_ci now->mon = tm.tm_mon + 1; 1062a8e1175bSopenharmony_ci now->day = tm.tm_mday; 1063a8e1175bSopenharmony_ci now->hour = tm.tm_hour; 1064a8e1175bSopenharmony_ci now->min = tm.tm_min; 1065a8e1175bSopenharmony_ci now->sec = tm.tm_sec; 1066a8e1175bSopenharmony_ci return 0; 1067a8e1175bSopenharmony_ci} 1068a8e1175bSopenharmony_ci 1069a8e1175bSopenharmony_cistatic int x509_get_current_time(mbedtls_x509_time *now) 1070a8e1175bSopenharmony_ci{ 1071a8e1175bSopenharmony_ci return mbedtls_x509_time_gmtime(mbedtls_time(NULL), now); 1072a8e1175bSopenharmony_ci} 1073a8e1175bSopenharmony_ci 1074a8e1175bSopenharmony_ciint mbedtls_x509_time_is_past(const mbedtls_x509_time *to) 1075a8e1175bSopenharmony_ci{ 1076a8e1175bSopenharmony_ci mbedtls_x509_time now; 1077a8e1175bSopenharmony_ci 1078a8e1175bSopenharmony_ci if (x509_get_current_time(&now) != 0) { 1079a8e1175bSopenharmony_ci return 1; 1080a8e1175bSopenharmony_ci } 1081a8e1175bSopenharmony_ci 1082a8e1175bSopenharmony_ci return mbedtls_x509_time_cmp(to, &now) < 0; 1083a8e1175bSopenharmony_ci} 1084a8e1175bSopenharmony_ci 1085a8e1175bSopenharmony_ciint mbedtls_x509_time_is_future(const mbedtls_x509_time *from) 1086a8e1175bSopenharmony_ci{ 1087a8e1175bSopenharmony_ci mbedtls_x509_time now; 1088a8e1175bSopenharmony_ci 1089a8e1175bSopenharmony_ci if (x509_get_current_time(&now) != 0) { 1090a8e1175bSopenharmony_ci return 1; 1091a8e1175bSopenharmony_ci } 1092a8e1175bSopenharmony_ci 1093a8e1175bSopenharmony_ci return mbedtls_x509_time_cmp(from, &now) > 0; 1094a8e1175bSopenharmony_ci} 1095a8e1175bSopenharmony_ci 1096a8e1175bSopenharmony_ci#else /* MBEDTLS_HAVE_TIME_DATE */ 1097a8e1175bSopenharmony_ci 1098a8e1175bSopenharmony_ciint mbedtls_x509_time_is_past(const mbedtls_x509_time *to) 1099a8e1175bSopenharmony_ci{ 1100a8e1175bSopenharmony_ci ((void) to); 1101a8e1175bSopenharmony_ci return 0; 1102a8e1175bSopenharmony_ci} 1103a8e1175bSopenharmony_ci 1104a8e1175bSopenharmony_ciint mbedtls_x509_time_is_future(const mbedtls_x509_time *from) 1105a8e1175bSopenharmony_ci{ 1106a8e1175bSopenharmony_ci ((void) from); 1107a8e1175bSopenharmony_ci return 0; 1108a8e1175bSopenharmony_ci} 1109a8e1175bSopenharmony_ci#endif /* MBEDTLS_HAVE_TIME_DATE */ 1110a8e1175bSopenharmony_ci 1111a8e1175bSopenharmony_ci/* Common functions for parsing CRT and CSR. */ 1112a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C) 1113a8e1175bSopenharmony_ci/* 1114a8e1175bSopenharmony_ci * OtherName ::= SEQUENCE { 1115a8e1175bSopenharmony_ci * type-id OBJECT IDENTIFIER, 1116a8e1175bSopenharmony_ci * value [0] EXPLICIT ANY DEFINED BY type-id } 1117a8e1175bSopenharmony_ci * 1118a8e1175bSopenharmony_ci * HardwareModuleName ::= SEQUENCE { 1119a8e1175bSopenharmony_ci * hwType OBJECT IDENTIFIER, 1120a8e1175bSopenharmony_ci * hwSerialNum OCTET STRING } 1121a8e1175bSopenharmony_ci * 1122a8e1175bSopenharmony_ci * NOTE: we currently only parse and use otherName of type HwModuleName, 1123a8e1175bSopenharmony_ci * as defined in RFC 4108. 1124a8e1175bSopenharmony_ci */ 1125a8e1175bSopenharmony_cistatic int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, 1126a8e1175bSopenharmony_ci mbedtls_x509_san_other_name *other_name) 1127a8e1175bSopenharmony_ci{ 1128a8e1175bSopenharmony_ci int ret = 0; 1129a8e1175bSopenharmony_ci size_t len; 1130a8e1175bSopenharmony_ci unsigned char *p = subject_alt_name->p; 1131a8e1175bSopenharmony_ci const unsigned char *end = p + subject_alt_name->len; 1132a8e1175bSopenharmony_ci mbedtls_x509_buf cur_oid; 1133a8e1175bSopenharmony_ci 1134a8e1175bSopenharmony_ci if ((subject_alt_name->tag & 1135a8e1175bSopenharmony_ci (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) != 1136a8e1175bSopenharmony_ci (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) { 1137a8e1175bSopenharmony_ci /* 1138a8e1175bSopenharmony_ci * The given subject alternative name is not of type "othername". 1139a8e1175bSopenharmony_ci */ 1140a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 1141a8e1175bSopenharmony_ci } 1142a8e1175bSopenharmony_ci 1143a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 1144a8e1175bSopenharmony_ci MBEDTLS_ASN1_OID)) != 0) { 1145a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1146a8e1175bSopenharmony_ci } 1147a8e1175bSopenharmony_ci 1148a8e1175bSopenharmony_ci cur_oid.tag = MBEDTLS_ASN1_OID; 1149a8e1175bSopenharmony_ci cur_oid.p = p; 1150a8e1175bSopenharmony_ci cur_oid.len = len; 1151a8e1175bSopenharmony_ci 1152a8e1175bSopenharmony_ci /* 1153a8e1175bSopenharmony_ci * Only HwModuleName is currently supported. 1154a8e1175bSopenharmony_ci */ 1155a8e1175bSopenharmony_ci if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) { 1156a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; 1157a8e1175bSopenharmony_ci } 1158a8e1175bSopenharmony_ci other_name->type_id = cur_oid; 1159a8e1175bSopenharmony_ci 1160a8e1175bSopenharmony_ci p += len; 1161a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 1162a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 1163a8e1175bSopenharmony_ci 0) { 1164a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1165a8e1175bSopenharmony_ci } 1166a8e1175bSopenharmony_ci 1167a8e1175bSopenharmony_ci if (end != p + len) { 1168a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1169a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 1170a8e1175bSopenharmony_ci } 1171a8e1175bSopenharmony_ci 1172a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 1173a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 1174a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1175a8e1175bSopenharmony_ci } 1176a8e1175bSopenharmony_ci 1177a8e1175bSopenharmony_ci if (end != p + len) { 1178a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1179a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 1180a8e1175bSopenharmony_ci } 1181a8e1175bSopenharmony_ci 1182a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { 1183a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1184a8e1175bSopenharmony_ci } 1185a8e1175bSopenharmony_ci 1186a8e1175bSopenharmony_ci other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID; 1187a8e1175bSopenharmony_ci other_name->value.hardware_module_name.oid.p = p; 1188a8e1175bSopenharmony_ci other_name->value.hardware_module_name.oid.len = len; 1189a8e1175bSopenharmony_ci 1190a8e1175bSopenharmony_ci p += len; 1191a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(&p, end, &len, 1192a8e1175bSopenharmony_ci MBEDTLS_ASN1_OCTET_STRING)) != 0) { 1193a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1194a8e1175bSopenharmony_ci } 1195a8e1175bSopenharmony_ci 1196a8e1175bSopenharmony_ci other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING; 1197a8e1175bSopenharmony_ci other_name->value.hardware_module_name.val.p = p; 1198a8e1175bSopenharmony_ci other_name->value.hardware_module_name.val.len = len; 1199a8e1175bSopenharmony_ci p += len; 1200a8e1175bSopenharmony_ci if (p != end) { 1201a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1202a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 1203a8e1175bSopenharmony_ci } 1204a8e1175bSopenharmony_ci return 0; 1205a8e1175bSopenharmony_ci} 1206a8e1175bSopenharmony_ci 1207a8e1175bSopenharmony_ci/* Check mbedtls_x509_get_subject_alt_name for detailed description. 1208a8e1175bSopenharmony_ci * 1209a8e1175bSopenharmony_ci * In some cases while parsing subject alternative names the sequence tag is optional 1210a8e1175bSopenharmony_ci * (e.g. CertSerialNumber). This function is designed to handle such case. 1211a8e1175bSopenharmony_ci */ 1212a8e1175bSopenharmony_ciint mbedtls_x509_get_subject_alt_name_ext(unsigned char **p, 1213a8e1175bSopenharmony_ci const unsigned char *end, 1214a8e1175bSopenharmony_ci mbedtls_x509_sequence *subject_alt_name) 1215a8e1175bSopenharmony_ci{ 1216a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1217a8e1175bSopenharmony_ci size_t tag_len; 1218a8e1175bSopenharmony_ci mbedtls_asn1_sequence *cur = subject_alt_name; 1219a8e1175bSopenharmony_ci 1220a8e1175bSopenharmony_ci while (*p < end) { 1221a8e1175bSopenharmony_ci mbedtls_x509_subject_alternative_name tmp_san_name; 1222a8e1175bSopenharmony_ci mbedtls_x509_buf tmp_san_buf; 1223a8e1175bSopenharmony_ci memset(&tmp_san_name, 0, sizeof(tmp_san_name)); 1224a8e1175bSopenharmony_ci 1225a8e1175bSopenharmony_ci tmp_san_buf.tag = **p; 1226a8e1175bSopenharmony_ci (*p)++; 1227a8e1175bSopenharmony_ci 1228a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) { 1229a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1230a8e1175bSopenharmony_ci } 1231a8e1175bSopenharmony_ci 1232a8e1175bSopenharmony_ci tmp_san_buf.p = *p; 1233a8e1175bSopenharmony_ci tmp_san_buf.len = tag_len; 1234a8e1175bSopenharmony_ci 1235a8e1175bSopenharmony_ci if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) != 1236a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONTEXT_SPECIFIC) { 1237a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1238a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 1239a8e1175bSopenharmony_ci } 1240a8e1175bSopenharmony_ci 1241a8e1175bSopenharmony_ci /* 1242a8e1175bSopenharmony_ci * Check that the SAN is structured correctly by parsing it. 1243a8e1175bSopenharmony_ci * The SAN structure is discarded afterwards. 1244a8e1175bSopenharmony_ci */ 1245a8e1175bSopenharmony_ci ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &tmp_san_name); 1246a8e1175bSopenharmony_ci /* 1247a8e1175bSopenharmony_ci * In case the extension is malformed, return an error, 1248a8e1175bSopenharmony_ci * and clear the allocated sequences. 1249a8e1175bSopenharmony_ci */ 1250a8e1175bSopenharmony_ci if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { 1251a8e1175bSopenharmony_ci mbedtls_asn1_sequence_free(subject_alt_name->next); 1252a8e1175bSopenharmony_ci subject_alt_name->next = NULL; 1253a8e1175bSopenharmony_ci return ret; 1254a8e1175bSopenharmony_ci } 1255a8e1175bSopenharmony_ci 1256a8e1175bSopenharmony_ci mbedtls_x509_free_subject_alt_name(&tmp_san_name); 1257a8e1175bSopenharmony_ci /* Allocate and assign next pointer */ 1258a8e1175bSopenharmony_ci if (cur->buf.p != NULL) { 1259a8e1175bSopenharmony_ci if (cur->next != NULL) { 1260a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; 1261a8e1175bSopenharmony_ci } 1262a8e1175bSopenharmony_ci 1263a8e1175bSopenharmony_ci cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); 1264a8e1175bSopenharmony_ci 1265a8e1175bSopenharmony_ci if (cur->next == NULL) { 1266a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1267a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_ALLOC_FAILED); 1268a8e1175bSopenharmony_ci } 1269a8e1175bSopenharmony_ci 1270a8e1175bSopenharmony_ci cur = cur->next; 1271a8e1175bSopenharmony_ci } 1272a8e1175bSopenharmony_ci 1273a8e1175bSopenharmony_ci cur->buf = tmp_san_buf; 1274a8e1175bSopenharmony_ci *p += tmp_san_buf.len; 1275a8e1175bSopenharmony_ci } 1276a8e1175bSopenharmony_ci 1277a8e1175bSopenharmony_ci /* Set final sequence entry's next pointer to NULL */ 1278a8e1175bSopenharmony_ci cur->next = NULL; 1279a8e1175bSopenharmony_ci 1280a8e1175bSopenharmony_ci if (*p != end) { 1281a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1282a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 1283a8e1175bSopenharmony_ci } 1284a8e1175bSopenharmony_ci 1285a8e1175bSopenharmony_ci return 0; 1286a8e1175bSopenharmony_ci} 1287a8e1175bSopenharmony_ci 1288a8e1175bSopenharmony_ci/* 1289a8e1175bSopenharmony_ci * SubjectAltName ::= GeneralNames 1290a8e1175bSopenharmony_ci * 1291a8e1175bSopenharmony_ci * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName 1292a8e1175bSopenharmony_ci * 1293a8e1175bSopenharmony_ci * GeneralName ::= CHOICE { 1294a8e1175bSopenharmony_ci * otherName [0] OtherName, 1295a8e1175bSopenharmony_ci * rfc822Name [1] IA5String, 1296a8e1175bSopenharmony_ci * dNSName [2] IA5String, 1297a8e1175bSopenharmony_ci * x400Address [3] ORAddress, 1298a8e1175bSopenharmony_ci * directoryName [4] Name, 1299a8e1175bSopenharmony_ci * ediPartyName [5] EDIPartyName, 1300a8e1175bSopenharmony_ci * uniformResourceIdentifier [6] IA5String, 1301a8e1175bSopenharmony_ci * iPAddress [7] OCTET STRING, 1302a8e1175bSopenharmony_ci * registeredID [8] OBJECT IDENTIFIER } 1303a8e1175bSopenharmony_ci * 1304a8e1175bSopenharmony_ci * OtherName ::= SEQUENCE { 1305a8e1175bSopenharmony_ci * type-id OBJECT IDENTIFIER, 1306a8e1175bSopenharmony_ci * value [0] EXPLICIT ANY DEFINED BY type-id } 1307a8e1175bSopenharmony_ci * 1308a8e1175bSopenharmony_ci * EDIPartyName ::= SEQUENCE { 1309a8e1175bSopenharmony_ci * nameAssigner [0] DirectoryString OPTIONAL, 1310a8e1175bSopenharmony_ci * partyName [1] DirectoryString } 1311a8e1175bSopenharmony_ci * 1312a8e1175bSopenharmony_ci * We list all types, but use the following GeneralName types from RFC 5280: 1313a8e1175bSopenharmony_ci * "dnsName", "uniformResourceIdentifier" and "hardware_module_name" 1314a8e1175bSopenharmony_ci * of type "otherName", as defined in RFC 4108. 1315a8e1175bSopenharmony_ci */ 1316a8e1175bSopenharmony_ciint mbedtls_x509_get_subject_alt_name(unsigned char **p, 1317a8e1175bSopenharmony_ci const unsigned char *end, 1318a8e1175bSopenharmony_ci mbedtls_x509_sequence *subject_alt_name) 1319a8e1175bSopenharmony_ci{ 1320a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1321a8e1175bSopenharmony_ci size_t len; 1322a8e1175bSopenharmony_ci 1323a8e1175bSopenharmony_ci /* Get main sequence tag */ 1324a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_tag(p, end, &len, 1325a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { 1326a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1327a8e1175bSopenharmony_ci } 1328a8e1175bSopenharmony_ci 1329a8e1175bSopenharmony_ci if (*p + len != end) { 1330a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1331a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 1332a8e1175bSopenharmony_ci } 1333a8e1175bSopenharmony_ci 1334a8e1175bSopenharmony_ci return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name); 1335a8e1175bSopenharmony_ci} 1336a8e1175bSopenharmony_ci 1337a8e1175bSopenharmony_ciint mbedtls_x509_get_ns_cert_type(unsigned char **p, 1338a8e1175bSopenharmony_ci const unsigned char *end, 1339a8e1175bSopenharmony_ci unsigned char *ns_cert_type) 1340a8e1175bSopenharmony_ci{ 1341a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1342a8e1175bSopenharmony_ci mbedtls_x509_bitstring bs = { 0, 0, NULL }; 1343a8e1175bSopenharmony_ci 1344a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { 1345a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1346a8e1175bSopenharmony_ci } 1347a8e1175bSopenharmony_ci 1348a8e1175bSopenharmony_ci /* A bitstring with no flags set is still technically valid, as it will mean 1349a8e1175bSopenharmony_ci that the certificate has no designated purpose at the time of creation. */ 1350a8e1175bSopenharmony_ci if (bs.len == 0) { 1351a8e1175bSopenharmony_ci *ns_cert_type = 0; 1352a8e1175bSopenharmony_ci return 0; 1353a8e1175bSopenharmony_ci } 1354a8e1175bSopenharmony_ci 1355a8e1175bSopenharmony_ci if (bs.len != 1) { 1356a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, 1357a8e1175bSopenharmony_ci MBEDTLS_ERR_ASN1_INVALID_LENGTH); 1358a8e1175bSopenharmony_ci } 1359a8e1175bSopenharmony_ci 1360a8e1175bSopenharmony_ci /* Get actual bitstring */ 1361a8e1175bSopenharmony_ci *ns_cert_type = *bs.p; 1362a8e1175bSopenharmony_ci return 0; 1363a8e1175bSopenharmony_ci} 1364a8e1175bSopenharmony_ci 1365a8e1175bSopenharmony_ciint mbedtls_x509_get_key_usage(unsigned char **p, 1366a8e1175bSopenharmony_ci const unsigned char *end, 1367a8e1175bSopenharmony_ci unsigned int *key_usage) 1368a8e1175bSopenharmony_ci{ 1369a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1370a8e1175bSopenharmony_ci size_t i; 1371a8e1175bSopenharmony_ci mbedtls_x509_bitstring bs = { 0, 0, NULL }; 1372a8e1175bSopenharmony_ci 1373a8e1175bSopenharmony_ci if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { 1374a8e1175bSopenharmony_ci return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); 1375a8e1175bSopenharmony_ci } 1376a8e1175bSopenharmony_ci 1377a8e1175bSopenharmony_ci /* A bitstring with no flags set is still technically valid, as it will mean 1378a8e1175bSopenharmony_ci that the certificate has no designated purpose at the time of creation. */ 1379a8e1175bSopenharmony_ci if (bs.len == 0) { 1380a8e1175bSopenharmony_ci *key_usage = 0; 1381a8e1175bSopenharmony_ci return 0; 1382a8e1175bSopenharmony_ci } 1383a8e1175bSopenharmony_ci 1384a8e1175bSopenharmony_ci /* Get actual bitstring */ 1385a8e1175bSopenharmony_ci *key_usage = 0; 1386a8e1175bSopenharmony_ci for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) { 1387a8e1175bSopenharmony_ci *key_usage |= (unsigned int) bs.p[i] << (8*i); 1388a8e1175bSopenharmony_ci } 1389a8e1175bSopenharmony_ci 1390a8e1175bSopenharmony_ci return 0; 1391a8e1175bSopenharmony_ci} 1392a8e1175bSopenharmony_ci 1393a8e1175bSopenharmony_ciint mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf, 1394a8e1175bSopenharmony_ci mbedtls_x509_subject_alternative_name *san) 1395a8e1175bSopenharmony_ci{ 1396a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1397a8e1175bSopenharmony_ci switch (san_buf->tag & 1398a8e1175bSopenharmony_ci (MBEDTLS_ASN1_TAG_CLASS_MASK | 1399a8e1175bSopenharmony_ci MBEDTLS_ASN1_TAG_VALUE_MASK)) { 1400a8e1175bSopenharmony_ci /* 1401a8e1175bSopenharmony_ci * otherName 1402a8e1175bSopenharmony_ci */ 1403a8e1175bSopenharmony_ci case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME): 1404a8e1175bSopenharmony_ci { 1405a8e1175bSopenharmony_ci mbedtls_x509_san_other_name other_name; 1406a8e1175bSopenharmony_ci 1407a8e1175bSopenharmony_ci ret = x509_get_other_name(san_buf, &other_name); 1408a8e1175bSopenharmony_ci if (ret != 0) { 1409a8e1175bSopenharmony_ci return ret; 1410a8e1175bSopenharmony_ci } 1411a8e1175bSopenharmony_ci 1412a8e1175bSopenharmony_ci memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1413a8e1175bSopenharmony_ci san->type = MBEDTLS_X509_SAN_OTHER_NAME; 1414a8e1175bSopenharmony_ci memcpy(&san->san.other_name, 1415a8e1175bSopenharmony_ci &other_name, sizeof(other_name)); 1416a8e1175bSopenharmony_ci 1417a8e1175bSopenharmony_ci } 1418a8e1175bSopenharmony_ci break; 1419a8e1175bSopenharmony_ci /* 1420a8e1175bSopenharmony_ci * uniformResourceIdentifier 1421a8e1175bSopenharmony_ci */ 1422a8e1175bSopenharmony_ci case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER): 1423a8e1175bSopenharmony_ci { 1424a8e1175bSopenharmony_ci memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1425a8e1175bSopenharmony_ci san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER; 1426a8e1175bSopenharmony_ci 1427a8e1175bSopenharmony_ci memcpy(&san->san.unstructured_name, 1428a8e1175bSopenharmony_ci san_buf, sizeof(*san_buf)); 1429a8e1175bSopenharmony_ci 1430a8e1175bSopenharmony_ci } 1431a8e1175bSopenharmony_ci break; 1432a8e1175bSopenharmony_ci /* 1433a8e1175bSopenharmony_ci * dNSName 1434a8e1175bSopenharmony_ci */ 1435a8e1175bSopenharmony_ci case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME): 1436a8e1175bSopenharmony_ci { 1437a8e1175bSopenharmony_ci memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1438a8e1175bSopenharmony_ci san->type = MBEDTLS_X509_SAN_DNS_NAME; 1439a8e1175bSopenharmony_ci 1440a8e1175bSopenharmony_ci memcpy(&san->san.unstructured_name, 1441a8e1175bSopenharmony_ci san_buf, sizeof(*san_buf)); 1442a8e1175bSopenharmony_ci } 1443a8e1175bSopenharmony_ci break; 1444a8e1175bSopenharmony_ci /* 1445a8e1175bSopenharmony_ci * IP address 1446a8e1175bSopenharmony_ci */ 1447a8e1175bSopenharmony_ci case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS): 1448a8e1175bSopenharmony_ci { 1449a8e1175bSopenharmony_ci memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1450a8e1175bSopenharmony_ci san->type = MBEDTLS_X509_SAN_IP_ADDRESS; 1451a8e1175bSopenharmony_ci // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported 1452a8e1175bSopenharmony_ci if (san_buf->len == 4 || san_buf->len == 16) { 1453a8e1175bSopenharmony_ci memcpy(&san->san.unstructured_name, 1454a8e1175bSopenharmony_ci san_buf, sizeof(*san_buf)); 1455a8e1175bSopenharmony_ci } else { 1456a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 1457a8e1175bSopenharmony_ci } 1458a8e1175bSopenharmony_ci } 1459a8e1175bSopenharmony_ci break; 1460a8e1175bSopenharmony_ci /* 1461a8e1175bSopenharmony_ci * rfc822Name 1462a8e1175bSopenharmony_ci */ 1463a8e1175bSopenharmony_ci case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME): 1464a8e1175bSopenharmony_ci { 1465a8e1175bSopenharmony_ci memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1466a8e1175bSopenharmony_ci san->type = MBEDTLS_X509_SAN_RFC822_NAME; 1467a8e1175bSopenharmony_ci memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); 1468a8e1175bSopenharmony_ci } 1469a8e1175bSopenharmony_ci break; 1470a8e1175bSopenharmony_ci /* 1471a8e1175bSopenharmony_ci * directoryName 1472a8e1175bSopenharmony_ci */ 1473a8e1175bSopenharmony_ci case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DIRECTORY_NAME): 1474a8e1175bSopenharmony_ci { 1475a8e1175bSopenharmony_ci size_t name_len; 1476a8e1175bSopenharmony_ci unsigned char *p = san_buf->p; 1477a8e1175bSopenharmony_ci memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); 1478a8e1175bSopenharmony_ci san->type = MBEDTLS_X509_SAN_DIRECTORY_NAME; 1479a8e1175bSopenharmony_ci 1480a8e1175bSopenharmony_ci ret = mbedtls_asn1_get_tag(&p, p + san_buf->len, &name_len, 1481a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); 1482a8e1175bSopenharmony_ci 1483a8e1175bSopenharmony_ci if (ret != 0) { 1484a8e1175bSopenharmony_ci return ret; 1485a8e1175bSopenharmony_ci } 1486a8e1175bSopenharmony_ci 1487a8e1175bSopenharmony_ci if ((ret = mbedtls_x509_get_name(&p, p + name_len, 1488a8e1175bSopenharmony_ci &san->san.directory_name)) != 0) { 1489a8e1175bSopenharmony_ci return ret; 1490a8e1175bSopenharmony_ci } 1491a8e1175bSopenharmony_ci } 1492a8e1175bSopenharmony_ci break; 1493a8e1175bSopenharmony_ci /* 1494a8e1175bSopenharmony_ci * Type not supported 1495a8e1175bSopenharmony_ci */ 1496a8e1175bSopenharmony_ci default: 1497a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; 1498a8e1175bSopenharmony_ci } 1499a8e1175bSopenharmony_ci return 0; 1500a8e1175bSopenharmony_ci} 1501a8e1175bSopenharmony_ci 1502a8e1175bSopenharmony_civoid mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san) 1503a8e1175bSopenharmony_ci{ 1504a8e1175bSopenharmony_ci if (san->type == MBEDTLS_X509_SAN_DIRECTORY_NAME) { 1505a8e1175bSopenharmony_ci mbedtls_asn1_free_named_data_list_shallow(san->san.directory_name.next); 1506a8e1175bSopenharmony_ci } 1507a8e1175bSopenharmony_ci} 1508a8e1175bSopenharmony_ci 1509a8e1175bSopenharmony_ci#if !defined(MBEDTLS_X509_REMOVE_INFO) 1510a8e1175bSopenharmony_ciint mbedtls_x509_info_subject_alt_name(char **buf, size_t *size, 1511a8e1175bSopenharmony_ci const mbedtls_x509_sequence 1512a8e1175bSopenharmony_ci *subject_alt_name, 1513a8e1175bSopenharmony_ci const char *prefix) 1514a8e1175bSopenharmony_ci{ 1515a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1516a8e1175bSopenharmony_ci size_t i; 1517a8e1175bSopenharmony_ci size_t n = *size; 1518a8e1175bSopenharmony_ci char *p = *buf; 1519a8e1175bSopenharmony_ci const mbedtls_x509_sequence *cur = subject_alt_name; 1520a8e1175bSopenharmony_ci mbedtls_x509_subject_alternative_name san; 1521a8e1175bSopenharmony_ci int parse_ret; 1522a8e1175bSopenharmony_ci 1523a8e1175bSopenharmony_ci while (cur != NULL) { 1524a8e1175bSopenharmony_ci memset(&san, 0, sizeof(san)); 1525a8e1175bSopenharmony_ci parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san); 1526a8e1175bSopenharmony_ci if (parse_ret != 0) { 1527a8e1175bSopenharmony_ci if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { 1528a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix); 1529a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1530a8e1175bSopenharmony_ci } else { 1531a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "\n%s <malformed>", prefix); 1532a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1533a8e1175bSopenharmony_ci } 1534a8e1175bSopenharmony_ci cur = cur->next; 1535a8e1175bSopenharmony_ci continue; 1536a8e1175bSopenharmony_ci } 1537a8e1175bSopenharmony_ci 1538a8e1175bSopenharmony_ci switch (san.type) { 1539a8e1175bSopenharmony_ci /* 1540a8e1175bSopenharmony_ci * otherName 1541a8e1175bSopenharmony_ci */ 1542a8e1175bSopenharmony_ci case MBEDTLS_X509_SAN_OTHER_NAME: 1543a8e1175bSopenharmony_ci { 1544a8e1175bSopenharmony_ci mbedtls_x509_san_other_name *other_name = &san.san.other_name; 1545a8e1175bSopenharmony_ci 1546a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "\n%s otherName :", prefix); 1547a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1548a8e1175bSopenharmony_ci 1549a8e1175bSopenharmony_ci if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, 1550a8e1175bSopenharmony_ci &other_name->type_id) == 0) { 1551a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "\n%s hardware module name :", prefix); 1552a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1553a8e1175bSopenharmony_ci ret = 1554a8e1175bSopenharmony_ci mbedtls_snprintf(p, n, "\n%s hardware type : ", prefix); 1555a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1556a8e1175bSopenharmony_ci 1557a8e1175bSopenharmony_ci ret = mbedtls_oid_get_numeric_string(p, 1558a8e1175bSopenharmony_ci n, 1559a8e1175bSopenharmony_ci &other_name->value.hardware_module_name.oid); 1560a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1561a8e1175bSopenharmony_ci 1562a8e1175bSopenharmony_ci ret = 1563a8e1175bSopenharmony_ci mbedtls_snprintf(p, n, "\n%s hardware serial number : ", prefix); 1564a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1565a8e1175bSopenharmony_ci 1566a8e1175bSopenharmony_ci for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) { 1567a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, 1568a8e1175bSopenharmony_ci n, 1569a8e1175bSopenharmony_ci "%02X", 1570a8e1175bSopenharmony_ci other_name->value.hardware_module_name.val.p[i]); 1571a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1572a8e1175bSopenharmony_ci } 1573a8e1175bSopenharmony_ci }/* MBEDTLS_OID_ON_HW_MODULE_NAME */ 1574a8e1175bSopenharmony_ci } 1575a8e1175bSopenharmony_ci break; 1576a8e1175bSopenharmony_ci /* 1577a8e1175bSopenharmony_ci * uniformResourceIdentifier 1578a8e1175bSopenharmony_ci */ 1579a8e1175bSopenharmony_ci case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: 1580a8e1175bSopenharmony_ci { 1581a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "\n%s uniformResourceIdentifier : ", prefix); 1582a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1583a8e1175bSopenharmony_ci if (san.san.unstructured_name.len >= n) { 1584a8e1175bSopenharmony_ci if (n > 0) { 1585a8e1175bSopenharmony_ci *p = '\0'; 1586a8e1175bSopenharmony_ci } 1587a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 1588a8e1175bSopenharmony_ci } 1589a8e1175bSopenharmony_ci 1590a8e1175bSopenharmony_ci memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); 1591a8e1175bSopenharmony_ci p += san.san.unstructured_name.len; 1592a8e1175bSopenharmony_ci n -= san.san.unstructured_name.len; 1593a8e1175bSopenharmony_ci } 1594a8e1175bSopenharmony_ci break; 1595a8e1175bSopenharmony_ci /* 1596a8e1175bSopenharmony_ci * dNSName 1597a8e1175bSopenharmony_ci * RFC822 Name 1598a8e1175bSopenharmony_ci */ 1599a8e1175bSopenharmony_ci case MBEDTLS_X509_SAN_DNS_NAME: 1600a8e1175bSopenharmony_ci case MBEDTLS_X509_SAN_RFC822_NAME: 1601a8e1175bSopenharmony_ci { 1602a8e1175bSopenharmony_ci const char *dns_name = "dNSName"; 1603a8e1175bSopenharmony_ci const char *rfc822_name = "rfc822Name"; 1604a8e1175bSopenharmony_ci 1605a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, 1606a8e1175bSopenharmony_ci "\n%s %s : ", 1607a8e1175bSopenharmony_ci prefix, 1608a8e1175bSopenharmony_ci san.type == 1609a8e1175bSopenharmony_ci MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name); 1610a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1611a8e1175bSopenharmony_ci if (san.san.unstructured_name.len >= n) { 1612a8e1175bSopenharmony_ci if (n > 0) { 1613a8e1175bSopenharmony_ci *p = '\0'; 1614a8e1175bSopenharmony_ci } 1615a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 1616a8e1175bSopenharmony_ci } 1617a8e1175bSopenharmony_ci 1618a8e1175bSopenharmony_ci memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); 1619a8e1175bSopenharmony_ci p += san.san.unstructured_name.len; 1620a8e1175bSopenharmony_ci n -= san.san.unstructured_name.len; 1621a8e1175bSopenharmony_ci } 1622a8e1175bSopenharmony_ci break; 1623a8e1175bSopenharmony_ci /* 1624a8e1175bSopenharmony_ci * iPAddress 1625a8e1175bSopenharmony_ci */ 1626a8e1175bSopenharmony_ci case MBEDTLS_X509_SAN_IP_ADDRESS: 1627a8e1175bSopenharmony_ci { 1628a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "\n%s %s : ", 1629a8e1175bSopenharmony_ci prefix, "iPAddress"); 1630a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1631a8e1175bSopenharmony_ci if (san.san.unstructured_name.len >= n) { 1632a8e1175bSopenharmony_ci if (n > 0) { 1633a8e1175bSopenharmony_ci *p = '\0'; 1634a8e1175bSopenharmony_ci } 1635a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 1636a8e1175bSopenharmony_ci } 1637a8e1175bSopenharmony_ci 1638a8e1175bSopenharmony_ci unsigned char *ip = san.san.unstructured_name.p; 1639a8e1175bSopenharmony_ci // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported 1640a8e1175bSopenharmony_ci if (san.san.unstructured_name.len == 4) { 1641a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); 1642a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1643a8e1175bSopenharmony_ci } else if (san.san.unstructured_name.len == 16) { 1644a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, 1645a8e1175bSopenharmony_ci "%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X", 1646a8e1175bSopenharmony_ci ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], 1647a8e1175bSopenharmony_ci ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], 1648a8e1175bSopenharmony_ci ip[14], ip[15]); 1649a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1650a8e1175bSopenharmony_ci } else { 1651a8e1175bSopenharmony_ci if (n > 0) { 1652a8e1175bSopenharmony_ci *p = '\0'; 1653a8e1175bSopenharmony_ci } 1654a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 1655a8e1175bSopenharmony_ci } 1656a8e1175bSopenharmony_ci } 1657a8e1175bSopenharmony_ci break; 1658a8e1175bSopenharmony_ci /* 1659a8e1175bSopenharmony_ci * directoryName 1660a8e1175bSopenharmony_ci */ 1661a8e1175bSopenharmony_ci case MBEDTLS_X509_SAN_DIRECTORY_NAME: 1662a8e1175bSopenharmony_ci { 1663a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "\n%s directoryName : ", prefix); 1664a8e1175bSopenharmony_ci if (ret < 0 || (size_t) ret >= n) { 1665a8e1175bSopenharmony_ci mbedtls_x509_free_subject_alt_name(&san); 1666a8e1175bSopenharmony_ci } 1667a8e1175bSopenharmony_ci 1668a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1669a8e1175bSopenharmony_ci ret = mbedtls_x509_dn_gets(p, n, &san.san.directory_name); 1670a8e1175bSopenharmony_ci 1671a8e1175bSopenharmony_ci if (ret < 0) { 1672a8e1175bSopenharmony_ci mbedtls_x509_free_subject_alt_name(&san); 1673a8e1175bSopenharmony_ci if (n > 0) { 1674a8e1175bSopenharmony_ci *p = '\0'; 1675a8e1175bSopenharmony_ci } 1676a8e1175bSopenharmony_ci return ret; 1677a8e1175bSopenharmony_ci } 1678a8e1175bSopenharmony_ci 1679a8e1175bSopenharmony_ci p += ret; 1680a8e1175bSopenharmony_ci n -= ret; 1681a8e1175bSopenharmony_ci } 1682a8e1175bSopenharmony_ci break; 1683a8e1175bSopenharmony_ci /* 1684a8e1175bSopenharmony_ci * Type not supported, skip item. 1685a8e1175bSopenharmony_ci */ 1686a8e1175bSopenharmony_ci default: 1687a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix); 1688a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; 1689a8e1175bSopenharmony_ci break; 1690a8e1175bSopenharmony_ci } 1691a8e1175bSopenharmony_ci 1692a8e1175bSopenharmony_ci /* So far memory is freed only in the case of directoryName 1693a8e1175bSopenharmony_ci * parsing succeeding, as mbedtls_x509_get_name allocates memory. */ 1694a8e1175bSopenharmony_ci mbedtls_x509_free_subject_alt_name(&san); 1695a8e1175bSopenharmony_ci cur = cur->next; 1696a8e1175bSopenharmony_ci } 1697a8e1175bSopenharmony_ci 1698a8e1175bSopenharmony_ci *p = '\0'; 1699a8e1175bSopenharmony_ci 1700a8e1175bSopenharmony_ci *size = n; 1701a8e1175bSopenharmony_ci *buf = p; 1702a8e1175bSopenharmony_ci 1703a8e1175bSopenharmony_ci return 0; 1704a8e1175bSopenharmony_ci} 1705a8e1175bSopenharmony_ci 1706a8e1175bSopenharmony_ci#define PRINT_ITEM(i) \ 1707a8e1175bSopenharmony_ci do { \ 1708a8e1175bSopenharmony_ci ret = mbedtls_snprintf(p, n, "%s" i, sep); \ 1709a8e1175bSopenharmony_ci MBEDTLS_X509_SAFE_SNPRINTF; \ 1710a8e1175bSopenharmony_ci sep = ", "; \ 1711a8e1175bSopenharmony_ci } while (0) 1712a8e1175bSopenharmony_ci 1713a8e1175bSopenharmony_ci#define CERT_TYPE(type, name) \ 1714a8e1175bSopenharmony_ci do { \ 1715a8e1175bSopenharmony_ci if (ns_cert_type & (type)) { \ 1716a8e1175bSopenharmony_ci PRINT_ITEM(name); \ 1717a8e1175bSopenharmony_ci } \ 1718a8e1175bSopenharmony_ci } while (0) 1719a8e1175bSopenharmony_ci 1720a8e1175bSopenharmony_ciint mbedtls_x509_info_cert_type(char **buf, size_t *size, 1721a8e1175bSopenharmony_ci unsigned char ns_cert_type) 1722a8e1175bSopenharmony_ci{ 1723a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1724a8e1175bSopenharmony_ci size_t n = *size; 1725a8e1175bSopenharmony_ci char *p = *buf; 1726a8e1175bSopenharmony_ci const char *sep = ""; 1727a8e1175bSopenharmony_ci 1728a8e1175bSopenharmony_ci CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client"); 1729a8e1175bSopenharmony_ci CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server"); 1730a8e1175bSopenharmony_ci CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email"); 1731a8e1175bSopenharmony_ci CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing"); 1732a8e1175bSopenharmony_ci CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved"); 1733a8e1175bSopenharmony_ci CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA"); 1734a8e1175bSopenharmony_ci CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA"); 1735a8e1175bSopenharmony_ci CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA"); 1736a8e1175bSopenharmony_ci 1737a8e1175bSopenharmony_ci *size = n; 1738a8e1175bSopenharmony_ci *buf = p; 1739a8e1175bSopenharmony_ci 1740a8e1175bSopenharmony_ci return 0; 1741a8e1175bSopenharmony_ci} 1742a8e1175bSopenharmony_ci 1743a8e1175bSopenharmony_ci#define KEY_USAGE(code, name) \ 1744a8e1175bSopenharmony_ci do { \ 1745a8e1175bSopenharmony_ci if ((key_usage) & (code)) { \ 1746a8e1175bSopenharmony_ci PRINT_ITEM(name); \ 1747a8e1175bSopenharmony_ci } \ 1748a8e1175bSopenharmony_ci } while (0) 1749a8e1175bSopenharmony_ci 1750a8e1175bSopenharmony_ciint mbedtls_x509_info_key_usage(char **buf, size_t *size, 1751a8e1175bSopenharmony_ci unsigned int key_usage) 1752a8e1175bSopenharmony_ci{ 1753a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1754a8e1175bSopenharmony_ci size_t n = *size; 1755a8e1175bSopenharmony_ci char *p = *buf; 1756a8e1175bSopenharmony_ci const char *sep = ""; 1757a8e1175bSopenharmony_ci 1758a8e1175bSopenharmony_ci KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature"); 1759a8e1175bSopenharmony_ci KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation"); 1760a8e1175bSopenharmony_ci KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment"); 1761a8e1175bSopenharmony_ci KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment"); 1762a8e1175bSopenharmony_ci KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement"); 1763a8e1175bSopenharmony_ci KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign"); 1764a8e1175bSopenharmony_ci KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign"); 1765a8e1175bSopenharmony_ci KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only"); 1766a8e1175bSopenharmony_ci KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only"); 1767a8e1175bSopenharmony_ci 1768a8e1175bSopenharmony_ci *size = n; 1769a8e1175bSopenharmony_ci *buf = p; 1770a8e1175bSopenharmony_ci 1771a8e1175bSopenharmony_ci return 0; 1772a8e1175bSopenharmony_ci} 1773a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_REMOVE_INFO */ 1774a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */ 1775a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_USE_C */ 1776