1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * X.509 certificate writing 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 * References: 9a8e1175bSopenharmony_ci * - certificates: RFC 5280, updated by RFC 6818 10a8e1175bSopenharmony_ci * - CSRs: PKCS#10 v1.7 aka RFC 2986 11a8e1175bSopenharmony_ci * - attributes: PKCS#9 v2.0 aka RFC 2985 12a8e1175bSopenharmony_ci */ 13a8e1175bSopenharmony_ci 14a8e1175bSopenharmony_ci#include "common.h" 15a8e1175bSopenharmony_ci 16a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_CRT_WRITE_C) 17a8e1175bSopenharmony_ci 18a8e1175bSopenharmony_ci#include "mbedtls/x509_crt.h" 19a8e1175bSopenharmony_ci#include "x509_internal.h" 20a8e1175bSopenharmony_ci#include "mbedtls/asn1write.h" 21a8e1175bSopenharmony_ci#include "mbedtls/error.h" 22a8e1175bSopenharmony_ci#include "mbedtls/oid.h" 23a8e1175bSopenharmony_ci#include "mbedtls/platform.h" 24a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h" 25a8e1175bSopenharmony_ci#include "mbedtls/md.h" 26a8e1175bSopenharmony_ci 27a8e1175bSopenharmony_ci#include <string.h> 28a8e1175bSopenharmony_ci#include <stdint.h> 29a8e1175bSopenharmony_ci 30a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_WRITE_C) 31a8e1175bSopenharmony_ci#include "mbedtls/pem.h" 32a8e1175bSopenharmony_ci#endif /* MBEDTLS_PEM_WRITE_C */ 33a8e1175bSopenharmony_ci 34a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO) 35a8e1175bSopenharmony_ci#include "psa/crypto.h" 36a8e1175bSopenharmony_ci#include "psa_util_internal.h" 37a8e1175bSopenharmony_ci#include "mbedtls/psa_util.h" 38a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */ 39a8e1175bSopenharmony_ci 40a8e1175bSopenharmony_civoid mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx) 41a8e1175bSopenharmony_ci{ 42a8e1175bSopenharmony_ci memset(ctx, 0, sizeof(mbedtls_x509write_cert)); 43a8e1175bSopenharmony_ci 44a8e1175bSopenharmony_ci ctx->version = MBEDTLS_X509_CRT_VERSION_3; 45a8e1175bSopenharmony_ci} 46a8e1175bSopenharmony_ci 47a8e1175bSopenharmony_civoid mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx) 48a8e1175bSopenharmony_ci{ 49a8e1175bSopenharmony_ci mbedtls_asn1_free_named_data_list(&ctx->subject); 50a8e1175bSopenharmony_ci mbedtls_asn1_free_named_data_list(&ctx->issuer); 51a8e1175bSopenharmony_ci mbedtls_asn1_free_named_data_list(&ctx->extensions); 52a8e1175bSopenharmony_ci 53a8e1175bSopenharmony_ci mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_cert)); 54a8e1175bSopenharmony_ci} 55a8e1175bSopenharmony_ci 56a8e1175bSopenharmony_civoid mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx, 57a8e1175bSopenharmony_ci int version) 58a8e1175bSopenharmony_ci{ 59a8e1175bSopenharmony_ci ctx->version = version; 60a8e1175bSopenharmony_ci} 61a8e1175bSopenharmony_ci 62a8e1175bSopenharmony_civoid mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert *ctx, 63a8e1175bSopenharmony_ci mbedtls_md_type_t md_alg) 64a8e1175bSopenharmony_ci{ 65a8e1175bSopenharmony_ci ctx->md_alg = md_alg; 66a8e1175bSopenharmony_ci} 67a8e1175bSopenharmony_ci 68a8e1175bSopenharmony_civoid mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert *ctx, 69a8e1175bSopenharmony_ci mbedtls_pk_context *key) 70a8e1175bSopenharmony_ci{ 71a8e1175bSopenharmony_ci ctx->subject_key = key; 72a8e1175bSopenharmony_ci} 73a8e1175bSopenharmony_ci 74a8e1175bSopenharmony_civoid mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert *ctx, 75a8e1175bSopenharmony_ci mbedtls_pk_context *key) 76a8e1175bSopenharmony_ci{ 77a8e1175bSopenharmony_ci ctx->issuer_key = key; 78a8e1175bSopenharmony_ci} 79a8e1175bSopenharmony_ci 80a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert *ctx, 81a8e1175bSopenharmony_ci const char *subject_name) 82a8e1175bSopenharmony_ci{ 83a8e1175bSopenharmony_ci return mbedtls_x509_string_to_names(&ctx->subject, subject_name); 84a8e1175bSopenharmony_ci} 85a8e1175bSopenharmony_ci 86a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx, 87a8e1175bSopenharmony_ci const char *issuer_name) 88a8e1175bSopenharmony_ci{ 89a8e1175bSopenharmony_ci return mbedtls_x509_string_to_names(&ctx->issuer, issuer_name); 90a8e1175bSopenharmony_ci} 91a8e1175bSopenharmony_ci 92a8e1175bSopenharmony_ci#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) 93a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx, 94a8e1175bSopenharmony_ci const mbedtls_mpi *serial) 95a8e1175bSopenharmony_ci{ 96a8e1175bSopenharmony_ci int ret; 97a8e1175bSopenharmony_ci size_t tmp_len; 98a8e1175bSopenharmony_ci 99a8e1175bSopenharmony_ci /* Ensure that the MPI value fits into the buffer */ 100a8e1175bSopenharmony_ci tmp_len = mbedtls_mpi_size(serial); 101a8e1175bSopenharmony_ci if (tmp_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) { 102a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 103a8e1175bSopenharmony_ci } 104a8e1175bSopenharmony_ci 105a8e1175bSopenharmony_ci ctx->serial_len = tmp_len; 106a8e1175bSopenharmony_ci 107a8e1175bSopenharmony_ci ret = mbedtls_mpi_write_binary(serial, ctx->serial, tmp_len); 108a8e1175bSopenharmony_ci if (ret < 0) { 109a8e1175bSopenharmony_ci return ret; 110a8e1175bSopenharmony_ci } 111a8e1175bSopenharmony_ci 112a8e1175bSopenharmony_ci return 0; 113a8e1175bSopenharmony_ci} 114a8e1175bSopenharmony_ci#endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED 115a8e1175bSopenharmony_ci 116a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx, 117a8e1175bSopenharmony_ci unsigned char *serial, size_t serial_len) 118a8e1175bSopenharmony_ci{ 119a8e1175bSopenharmony_ci if (serial_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) { 120a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 121a8e1175bSopenharmony_ci } 122a8e1175bSopenharmony_ci 123a8e1175bSopenharmony_ci ctx->serial_len = serial_len; 124a8e1175bSopenharmony_ci memcpy(ctx->serial, serial, serial_len); 125a8e1175bSopenharmony_ci 126a8e1175bSopenharmony_ci return 0; 127a8e1175bSopenharmony_ci} 128a8e1175bSopenharmony_ci 129a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx, 130a8e1175bSopenharmony_ci const char *not_before, 131a8e1175bSopenharmony_ci const char *not_after) 132a8e1175bSopenharmony_ci{ 133a8e1175bSopenharmony_ci if (strlen(not_before) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || 134a8e1175bSopenharmony_ci strlen(not_after) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1) { 135a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 136a8e1175bSopenharmony_ci } 137a8e1175bSopenharmony_ci strncpy(ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN); 138a8e1175bSopenharmony_ci strncpy(ctx->not_after, not_after, MBEDTLS_X509_RFC5280_UTC_TIME_LEN); 139a8e1175bSopenharmony_ci ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; 140a8e1175bSopenharmony_ci ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; 141a8e1175bSopenharmony_ci 142a8e1175bSopenharmony_ci return 0; 143a8e1175bSopenharmony_ci} 144a8e1175bSopenharmony_ci 145a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx, 146a8e1175bSopenharmony_ci const mbedtls_x509_san_list *san_list) 147a8e1175bSopenharmony_ci{ 148a8e1175bSopenharmony_ci return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list); 149a8e1175bSopenharmony_ci} 150a8e1175bSopenharmony_ci 151a8e1175bSopenharmony_ci 152a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx, 153a8e1175bSopenharmony_ci const char *oid, size_t oid_len, 154a8e1175bSopenharmony_ci int critical, 155a8e1175bSopenharmony_ci const unsigned char *val, size_t val_len) 156a8e1175bSopenharmony_ci{ 157a8e1175bSopenharmony_ci return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, 158a8e1175bSopenharmony_ci critical, val, val_len); 159a8e1175bSopenharmony_ci} 160a8e1175bSopenharmony_ci 161a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx, 162a8e1175bSopenharmony_ci int is_ca, int max_pathlen) 163a8e1175bSopenharmony_ci{ 164a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 165a8e1175bSopenharmony_ci unsigned char buf[9]; 166a8e1175bSopenharmony_ci unsigned char *c = buf + sizeof(buf); 167a8e1175bSopenharmony_ci size_t len = 0; 168a8e1175bSopenharmony_ci 169a8e1175bSopenharmony_ci memset(buf, 0, sizeof(buf)); 170a8e1175bSopenharmony_ci 171a8e1175bSopenharmony_ci if (is_ca && max_pathlen > 127) { 172a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 173a8e1175bSopenharmony_ci } 174a8e1175bSopenharmony_ci 175a8e1175bSopenharmony_ci if (is_ca) { 176a8e1175bSopenharmony_ci if (max_pathlen >= 0) { 177a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 178a8e1175bSopenharmony_ci max_pathlen)); 179a8e1175bSopenharmony_ci } 180a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(&c, buf, 1)); 181a8e1175bSopenharmony_ci } 182a8e1175bSopenharmony_ci 183a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 184a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, 185a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | 186a8e1175bSopenharmony_ci MBEDTLS_ASN1_SEQUENCE)); 187a8e1175bSopenharmony_ci 188a8e1175bSopenharmony_ci return 189a8e1175bSopenharmony_ci mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, 190a8e1175bSopenharmony_ci MBEDTLS_OID_SIZE(MBEDTLS_OID_BASIC_CONSTRAINTS), 191a8e1175bSopenharmony_ci is_ca, buf + sizeof(buf) - len, len); 192a8e1175bSopenharmony_ci} 193a8e1175bSopenharmony_ci 194a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA1) 195a8e1175bSopenharmony_cistatic int mbedtls_x509write_crt_set_key_identifier(mbedtls_x509write_cert *ctx, 196a8e1175bSopenharmony_ci int is_ca, 197a8e1175bSopenharmony_ci unsigned char tag) 198a8e1175bSopenharmony_ci{ 199a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 200a8e1175bSopenharmony_ci unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ 201a8e1175bSopenharmony_ci unsigned char *c = buf + sizeof(buf); 202a8e1175bSopenharmony_ci size_t len = 0; 203a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO) 204a8e1175bSopenharmony_ci psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 205a8e1175bSopenharmony_ci size_t hash_length; 206a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */ 207a8e1175bSopenharmony_ci 208a8e1175bSopenharmony_ci memset(buf, 0, sizeof(buf)); 209a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 210a8e1175bSopenharmony_ci mbedtls_pk_write_pubkey(&c, 211a8e1175bSopenharmony_ci buf, 212a8e1175bSopenharmony_ci is_ca ? 213a8e1175bSopenharmony_ci ctx->issuer_key : 214a8e1175bSopenharmony_ci ctx->subject_key)); 215a8e1175bSopenharmony_ci 216a8e1175bSopenharmony_ci 217a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO) 218a8e1175bSopenharmony_ci status = psa_hash_compute(PSA_ALG_SHA_1, 219a8e1175bSopenharmony_ci buf + sizeof(buf) - len, 220a8e1175bSopenharmony_ci len, 221a8e1175bSopenharmony_ci buf + sizeof(buf) - 20, 222a8e1175bSopenharmony_ci 20, 223a8e1175bSopenharmony_ci &hash_length); 224a8e1175bSopenharmony_ci if (status != PSA_SUCCESS) { 225a8e1175bSopenharmony_ci return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 226a8e1175bSopenharmony_ci } 227a8e1175bSopenharmony_ci#else 228a8e1175bSopenharmony_ci ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 229a8e1175bSopenharmony_ci buf + sizeof(buf) - len, len, 230a8e1175bSopenharmony_ci buf + sizeof(buf) - 20); 231a8e1175bSopenharmony_ci if (ret != 0) { 232a8e1175bSopenharmony_ci return ret; 233a8e1175bSopenharmony_ci } 234a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */ 235a8e1175bSopenharmony_ci 236a8e1175bSopenharmony_ci c = buf + sizeof(buf) - 20; 237a8e1175bSopenharmony_ci len = 20; 238a8e1175bSopenharmony_ci 239a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 240a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, tag)); 241a8e1175bSopenharmony_ci 242a8e1175bSopenharmony_ci if (is_ca) { // writes AuthorityKeyIdentifier sequence 243a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 244a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 245a8e1175bSopenharmony_ci mbedtls_asn1_write_tag(&c, 246a8e1175bSopenharmony_ci buf, 247a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | 248a8e1175bSopenharmony_ci MBEDTLS_ASN1_SEQUENCE)); 249a8e1175bSopenharmony_ci } 250a8e1175bSopenharmony_ci 251a8e1175bSopenharmony_ci if (is_ca) { 252a8e1175bSopenharmony_ci return mbedtls_x509write_crt_set_extension(ctx, 253a8e1175bSopenharmony_ci MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, 254a8e1175bSopenharmony_ci MBEDTLS_OID_SIZE( 255a8e1175bSopenharmony_ci MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER), 256a8e1175bSopenharmony_ci 0, buf + sizeof(buf) - len, len); 257a8e1175bSopenharmony_ci } else { 258a8e1175bSopenharmony_ci return mbedtls_x509write_crt_set_extension(ctx, 259a8e1175bSopenharmony_ci MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, 260a8e1175bSopenharmony_ci MBEDTLS_OID_SIZE( 261a8e1175bSopenharmony_ci MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER), 262a8e1175bSopenharmony_ci 0, buf + sizeof(buf) - len, len); 263a8e1175bSopenharmony_ci } 264a8e1175bSopenharmony_ci} 265a8e1175bSopenharmony_ci 266a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx) 267a8e1175bSopenharmony_ci{ 268a8e1175bSopenharmony_ci return mbedtls_x509write_crt_set_key_identifier(ctx, 269a8e1175bSopenharmony_ci 0, 270a8e1175bSopenharmony_ci MBEDTLS_ASN1_OCTET_STRING); 271a8e1175bSopenharmony_ci} 272a8e1175bSopenharmony_ci 273a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx) 274a8e1175bSopenharmony_ci{ 275a8e1175bSopenharmony_ci return mbedtls_x509write_crt_set_key_identifier(ctx, 276a8e1175bSopenharmony_ci 1, 277a8e1175bSopenharmony_ci (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0)); 278a8e1175bSopenharmony_ci} 279a8e1175bSopenharmony_ci#endif /* MBEDTLS_MD_CAN_SHA1 */ 280a8e1175bSopenharmony_ci 281a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx, 282a8e1175bSopenharmony_ci unsigned int key_usage) 283a8e1175bSopenharmony_ci{ 284a8e1175bSopenharmony_ci unsigned char buf[5] = { 0 }, ku[2] = { 0 }; 285a8e1175bSopenharmony_ci unsigned char *c; 286a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 287a8e1175bSopenharmony_ci const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE | 288a8e1175bSopenharmony_ci MBEDTLS_X509_KU_NON_REPUDIATION | 289a8e1175bSopenharmony_ci MBEDTLS_X509_KU_KEY_ENCIPHERMENT | 290a8e1175bSopenharmony_ci MBEDTLS_X509_KU_DATA_ENCIPHERMENT | 291a8e1175bSopenharmony_ci MBEDTLS_X509_KU_KEY_AGREEMENT | 292a8e1175bSopenharmony_ci MBEDTLS_X509_KU_KEY_CERT_SIGN | 293a8e1175bSopenharmony_ci MBEDTLS_X509_KU_CRL_SIGN | 294a8e1175bSopenharmony_ci MBEDTLS_X509_KU_ENCIPHER_ONLY | 295a8e1175bSopenharmony_ci MBEDTLS_X509_KU_DECIPHER_ONLY; 296a8e1175bSopenharmony_ci 297a8e1175bSopenharmony_ci /* Check that nothing other than the allowed flags is set */ 298a8e1175bSopenharmony_ci if ((key_usage & ~allowed_bits) != 0) { 299a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; 300a8e1175bSopenharmony_ci } 301a8e1175bSopenharmony_ci 302a8e1175bSopenharmony_ci c = buf + 5; 303a8e1175bSopenharmony_ci MBEDTLS_PUT_UINT16_LE(key_usage, ku, 0); 304a8e1175bSopenharmony_ci ret = mbedtls_asn1_write_named_bitstring(&c, buf, ku, 9); 305a8e1175bSopenharmony_ci 306a8e1175bSopenharmony_ci if (ret < 0) { 307a8e1175bSopenharmony_ci return ret; 308a8e1175bSopenharmony_ci } else if (ret < 3 || ret > 5) { 309a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_FORMAT; 310a8e1175bSopenharmony_ci } 311a8e1175bSopenharmony_ci 312a8e1175bSopenharmony_ci ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_KEY_USAGE, 313a8e1175bSopenharmony_ci MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), 314a8e1175bSopenharmony_ci 1, c, (size_t) ret); 315a8e1175bSopenharmony_ci if (ret != 0) { 316a8e1175bSopenharmony_ci return ret; 317a8e1175bSopenharmony_ci } 318a8e1175bSopenharmony_ci 319a8e1175bSopenharmony_ci return 0; 320a8e1175bSopenharmony_ci} 321a8e1175bSopenharmony_ci 322a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx, 323a8e1175bSopenharmony_ci const mbedtls_asn1_sequence *exts) 324a8e1175bSopenharmony_ci{ 325a8e1175bSopenharmony_ci unsigned char buf[256]; 326a8e1175bSopenharmony_ci unsigned char *c = buf + sizeof(buf); 327a8e1175bSopenharmony_ci int ret; 328a8e1175bSopenharmony_ci size_t len = 0; 329a8e1175bSopenharmony_ci const mbedtls_asn1_sequence *last_ext = NULL; 330a8e1175bSopenharmony_ci const mbedtls_asn1_sequence *ext; 331a8e1175bSopenharmony_ci 332a8e1175bSopenharmony_ci memset(buf, 0, sizeof(buf)); 333a8e1175bSopenharmony_ci 334a8e1175bSopenharmony_ci /* We need at least one extension: SEQUENCE SIZE (1..MAX) OF KeyPurposeId */ 335a8e1175bSopenharmony_ci if (exts == NULL) { 336a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 337a8e1175bSopenharmony_ci } 338a8e1175bSopenharmony_ci 339a8e1175bSopenharmony_ci /* Iterate over exts backwards, so we write them out in the requested order */ 340a8e1175bSopenharmony_ci while (last_ext != exts) { 341a8e1175bSopenharmony_ci for (ext = exts; ext->next != last_ext; ext = ext->next) { 342a8e1175bSopenharmony_ci } 343a8e1175bSopenharmony_ci if (ext->buf.tag != MBEDTLS_ASN1_OID) { 344a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BAD_INPUT_DATA; 345a8e1175bSopenharmony_ci } 346a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, ext->buf.p, ext->buf.len)); 347a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ext->buf.len)); 348a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_OID)); 349a8e1175bSopenharmony_ci last_ext = ext; 350a8e1175bSopenharmony_ci } 351a8e1175bSopenharmony_ci 352a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 353a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 354a8e1175bSopenharmony_ci mbedtls_asn1_write_tag(&c, buf, 355a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 356a8e1175bSopenharmony_ci 357a8e1175bSopenharmony_ci return mbedtls_x509write_crt_set_extension(ctx, 358a8e1175bSopenharmony_ci MBEDTLS_OID_EXTENDED_KEY_USAGE, 359a8e1175bSopenharmony_ci MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE), 360a8e1175bSopenharmony_ci 1, c, len); 361a8e1175bSopenharmony_ci} 362a8e1175bSopenharmony_ci 363a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx, 364a8e1175bSopenharmony_ci unsigned char ns_cert_type) 365a8e1175bSopenharmony_ci{ 366a8e1175bSopenharmony_ci unsigned char buf[4] = { 0 }; 367a8e1175bSopenharmony_ci unsigned char *c; 368a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 369a8e1175bSopenharmony_ci 370a8e1175bSopenharmony_ci c = buf + 4; 371a8e1175bSopenharmony_ci 372a8e1175bSopenharmony_ci ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8); 373a8e1175bSopenharmony_ci if (ret < 3 || ret > 4) { 374a8e1175bSopenharmony_ci return ret; 375a8e1175bSopenharmony_ci } 376a8e1175bSopenharmony_ci 377a8e1175bSopenharmony_ci ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE, 378a8e1175bSopenharmony_ci MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), 379a8e1175bSopenharmony_ci 0, c, (size_t) ret); 380a8e1175bSopenharmony_ci if (ret != 0) { 381a8e1175bSopenharmony_ci return ret; 382a8e1175bSopenharmony_ci } 383a8e1175bSopenharmony_ci 384a8e1175bSopenharmony_ci return 0; 385a8e1175bSopenharmony_ci} 386a8e1175bSopenharmony_ci 387a8e1175bSopenharmony_cistatic int x509_write_time(unsigned char **p, unsigned char *start, 388a8e1175bSopenharmony_ci const char *t, size_t size) 389a8e1175bSopenharmony_ci{ 390a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 391a8e1175bSopenharmony_ci size_t len = 0; 392a8e1175bSopenharmony_ci 393a8e1175bSopenharmony_ci /* 394a8e1175bSopenharmony_ci * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) 395a8e1175bSopenharmony_ci */ 396a8e1175bSopenharmony_ci if (t[0] < '2' || (t[0] == '2' && t[1] == '0' && t[2] < '5')) { 397a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, 398a8e1175bSopenharmony_ci (const unsigned char *) t + 2, 399a8e1175bSopenharmony_ci size - 2)); 400a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 401a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, 402a8e1175bSopenharmony_ci MBEDTLS_ASN1_UTC_TIME)); 403a8e1175bSopenharmony_ci } else { 404a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, 405a8e1175bSopenharmony_ci (const unsigned char *) t, 406a8e1175bSopenharmony_ci size)); 407a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 408a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, 409a8e1175bSopenharmony_ci MBEDTLS_ASN1_GENERALIZED_TIME)); 410a8e1175bSopenharmony_ci } 411a8e1175bSopenharmony_ci 412a8e1175bSopenharmony_ci return (int) len; 413a8e1175bSopenharmony_ci} 414a8e1175bSopenharmony_ci 415a8e1175bSopenharmony_ciint mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, 416a8e1175bSopenharmony_ci unsigned char *buf, size_t size, 417a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), 418a8e1175bSopenharmony_ci void *p_rng) 419a8e1175bSopenharmony_ci{ 420a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 421a8e1175bSopenharmony_ci const char *sig_oid; 422a8e1175bSopenharmony_ci size_t sig_oid_len = 0; 423a8e1175bSopenharmony_ci unsigned char *c, *c2; 424a8e1175bSopenharmony_ci unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; 425a8e1175bSopenharmony_ci size_t hash_length = 0; 426a8e1175bSopenharmony_ci unsigned char hash[MBEDTLS_MD_MAX_SIZE]; 427a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO) 428a8e1175bSopenharmony_ci psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 429a8e1175bSopenharmony_ci psa_algorithm_t psa_algorithm; 430a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */ 431a8e1175bSopenharmony_ci 432a8e1175bSopenharmony_ci size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; 433a8e1175bSopenharmony_ci size_t len = 0; 434a8e1175bSopenharmony_ci mbedtls_pk_type_t pk_alg; 435a8e1175bSopenharmony_ci int write_sig_null_par; 436a8e1175bSopenharmony_ci 437a8e1175bSopenharmony_ci /* 438a8e1175bSopenharmony_ci * Prepare data to be signed at the end of the target buffer 439a8e1175bSopenharmony_ci */ 440a8e1175bSopenharmony_ci c = buf + size; 441a8e1175bSopenharmony_ci 442a8e1175bSopenharmony_ci /* Signature algorithm needed in TBS, and later for actual signature */ 443a8e1175bSopenharmony_ci 444a8e1175bSopenharmony_ci /* There's no direct way of extracting a signature algorithm 445a8e1175bSopenharmony_ci * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ 446a8e1175bSopenharmony_ci if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_RSA)) { 447a8e1175bSopenharmony_ci pk_alg = MBEDTLS_PK_RSA; 448a8e1175bSopenharmony_ci } else if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_ECDSA)) { 449a8e1175bSopenharmony_ci pk_alg = MBEDTLS_PK_ECDSA; 450a8e1175bSopenharmony_ci } else { 451a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_INVALID_ALG; 452a8e1175bSopenharmony_ci } 453a8e1175bSopenharmony_ci 454a8e1175bSopenharmony_ci if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, 455a8e1175bSopenharmony_ci &sig_oid, &sig_oid_len)) != 0) { 456a8e1175bSopenharmony_ci return ret; 457a8e1175bSopenharmony_ci } 458a8e1175bSopenharmony_ci 459a8e1175bSopenharmony_ci /* 460a8e1175bSopenharmony_ci * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 461a8e1175bSopenharmony_ci */ 462a8e1175bSopenharmony_ci 463a8e1175bSopenharmony_ci /* Only for v3 */ 464a8e1175bSopenharmony_ci if (ctx->version == MBEDTLS_X509_CRT_VERSION_3) { 465a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 466a8e1175bSopenharmony_ci mbedtls_x509_write_extensions(&c, 467a8e1175bSopenharmony_ci buf, ctx->extensions)); 468a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 469a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 470a8e1175bSopenharmony_ci mbedtls_asn1_write_tag(&c, buf, 471a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | 472a8e1175bSopenharmony_ci MBEDTLS_ASN1_SEQUENCE)); 473a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 474a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 475a8e1175bSopenharmony_ci mbedtls_asn1_write_tag(&c, buf, 476a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONTEXT_SPECIFIC | 477a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | 3)); 478a8e1175bSopenharmony_ci } 479a8e1175bSopenharmony_ci 480a8e1175bSopenharmony_ci /* 481a8e1175bSopenharmony_ci * SubjectPublicKeyInfo 482a8e1175bSopenharmony_ci */ 483a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(pub_len, 484a8e1175bSopenharmony_ci mbedtls_pk_write_pubkey_der(ctx->subject_key, 485a8e1175bSopenharmony_ci buf, (size_t) (c - buf))); 486a8e1175bSopenharmony_ci c -= pub_len; 487a8e1175bSopenharmony_ci len += pub_len; 488a8e1175bSopenharmony_ci 489a8e1175bSopenharmony_ci /* 490a8e1175bSopenharmony_ci * Subject ::= Name 491a8e1175bSopenharmony_ci */ 492a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 493a8e1175bSopenharmony_ci mbedtls_x509_write_names(&c, buf, 494a8e1175bSopenharmony_ci ctx->subject)); 495a8e1175bSopenharmony_ci 496a8e1175bSopenharmony_ci /* 497a8e1175bSopenharmony_ci * Validity ::= SEQUENCE { 498a8e1175bSopenharmony_ci * notBefore Time, 499a8e1175bSopenharmony_ci * notAfter Time } 500a8e1175bSopenharmony_ci */ 501a8e1175bSopenharmony_ci sub_len = 0; 502a8e1175bSopenharmony_ci 503a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(sub_len, 504a8e1175bSopenharmony_ci x509_write_time(&c, buf, ctx->not_after, 505a8e1175bSopenharmony_ci MBEDTLS_X509_RFC5280_UTC_TIME_LEN)); 506a8e1175bSopenharmony_ci 507a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(sub_len, 508a8e1175bSopenharmony_ci x509_write_time(&c, buf, ctx->not_before, 509a8e1175bSopenharmony_ci MBEDTLS_X509_RFC5280_UTC_TIME_LEN)); 510a8e1175bSopenharmony_ci 511a8e1175bSopenharmony_ci len += sub_len; 512a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, sub_len)); 513a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 514a8e1175bSopenharmony_ci mbedtls_asn1_write_tag(&c, buf, 515a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | 516a8e1175bSopenharmony_ci MBEDTLS_ASN1_SEQUENCE)); 517a8e1175bSopenharmony_ci 518a8e1175bSopenharmony_ci /* 519a8e1175bSopenharmony_ci * Issuer ::= Name 520a8e1175bSopenharmony_ci */ 521a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, 522a8e1175bSopenharmony_ci ctx->issuer)); 523a8e1175bSopenharmony_ci 524a8e1175bSopenharmony_ci /* 525a8e1175bSopenharmony_ci * Signature ::= AlgorithmIdentifier 526a8e1175bSopenharmony_ci */ 527a8e1175bSopenharmony_ci if (pk_alg == MBEDTLS_PK_ECDSA) { 528a8e1175bSopenharmony_ci /* 529a8e1175bSopenharmony_ci * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature 530a8e1175bSopenharmony_ci * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and 531a8e1175bSopenharmony_ci * https://www.rfc-editor.org/rfc/rfc5758#section-3. 532a8e1175bSopenharmony_ci */ 533a8e1175bSopenharmony_ci write_sig_null_par = 0; 534a8e1175bSopenharmony_ci } else { 535a8e1175bSopenharmony_ci write_sig_null_par = 1; 536a8e1175bSopenharmony_ci } 537a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 538a8e1175bSopenharmony_ci mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, 539a8e1175bSopenharmony_ci sig_oid, strlen(sig_oid), 540a8e1175bSopenharmony_ci 0, write_sig_null_par)); 541a8e1175bSopenharmony_ci 542a8e1175bSopenharmony_ci /* 543a8e1175bSopenharmony_ci * Serial ::= INTEGER 544a8e1175bSopenharmony_ci * 545a8e1175bSopenharmony_ci * Written data is: 546a8e1175bSopenharmony_ci * - "ctx->serial_len" bytes for the raw serial buffer 547a8e1175bSopenharmony_ci * - if MSb of "serial" is 1, then prepend an extra 0x00 byte 548a8e1175bSopenharmony_ci * - 1 byte for the length 549a8e1175bSopenharmony_ci * - 1 byte for the TAG 550a8e1175bSopenharmony_ci */ 551a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, 552a8e1175bSopenharmony_ci ctx->serial, ctx->serial_len)); 553a8e1175bSopenharmony_ci if (*c & 0x80) { 554a8e1175bSopenharmony_ci if (c - buf < 1) { 555a8e1175bSopenharmony_ci return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; 556a8e1175bSopenharmony_ci } 557a8e1175bSopenharmony_ci *(--c) = 0x0; 558a8e1175bSopenharmony_ci len++; 559a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, 560a8e1175bSopenharmony_ci ctx->serial_len + 1)); 561a8e1175bSopenharmony_ci } else { 562a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, 563a8e1175bSopenharmony_ci ctx->serial_len)); 564a8e1175bSopenharmony_ci } 565a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, 566a8e1175bSopenharmony_ci MBEDTLS_ASN1_INTEGER)); 567a8e1175bSopenharmony_ci 568a8e1175bSopenharmony_ci /* 569a8e1175bSopenharmony_ci * Version ::= INTEGER { v1(0), v2(1), v3(2) } 570a8e1175bSopenharmony_ci */ 571a8e1175bSopenharmony_ci 572a8e1175bSopenharmony_ci /* Can be omitted for v1 */ 573a8e1175bSopenharmony_ci if (ctx->version != MBEDTLS_X509_CRT_VERSION_1) { 574a8e1175bSopenharmony_ci sub_len = 0; 575a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(sub_len, 576a8e1175bSopenharmony_ci mbedtls_asn1_write_int(&c, buf, ctx->version)); 577a8e1175bSopenharmony_ci len += sub_len; 578a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 579a8e1175bSopenharmony_ci mbedtls_asn1_write_len(&c, buf, sub_len)); 580a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 581a8e1175bSopenharmony_ci mbedtls_asn1_write_tag(&c, buf, 582a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONTEXT_SPECIFIC | 583a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | 0)); 584a8e1175bSopenharmony_ci } 585a8e1175bSopenharmony_ci 586a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 587a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, 588a8e1175bSopenharmony_ci mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | 589a8e1175bSopenharmony_ci MBEDTLS_ASN1_SEQUENCE)); 590a8e1175bSopenharmony_ci 591a8e1175bSopenharmony_ci /* 592a8e1175bSopenharmony_ci * Make signature 593a8e1175bSopenharmony_ci */ 594a8e1175bSopenharmony_ci 595a8e1175bSopenharmony_ci /* Compute hash of CRT. */ 596a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO) 597a8e1175bSopenharmony_ci psa_algorithm = mbedtls_md_psa_alg_from_type(ctx->md_alg); 598a8e1175bSopenharmony_ci 599a8e1175bSopenharmony_ci status = psa_hash_compute(psa_algorithm, 600a8e1175bSopenharmony_ci c, 601a8e1175bSopenharmony_ci len, 602a8e1175bSopenharmony_ci hash, 603a8e1175bSopenharmony_ci sizeof(hash), 604a8e1175bSopenharmony_ci &hash_length); 605a8e1175bSopenharmony_ci if (status != PSA_SUCCESS) { 606a8e1175bSopenharmony_ci return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 607a8e1175bSopenharmony_ci } 608a8e1175bSopenharmony_ci#else 609a8e1175bSopenharmony_ci if ((ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, 610a8e1175bSopenharmony_ci len, hash)) != 0) { 611a8e1175bSopenharmony_ci return ret; 612a8e1175bSopenharmony_ci } 613a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */ 614a8e1175bSopenharmony_ci 615a8e1175bSopenharmony_ci 616a8e1175bSopenharmony_ci if ((ret = mbedtls_pk_sign(ctx->issuer_key, ctx->md_alg, 617a8e1175bSopenharmony_ci hash, hash_length, sig, sizeof(sig), &sig_len, 618a8e1175bSopenharmony_ci f_rng, p_rng)) != 0) { 619a8e1175bSopenharmony_ci return ret; 620a8e1175bSopenharmony_ci } 621a8e1175bSopenharmony_ci 622a8e1175bSopenharmony_ci /* Move CRT to the front of the buffer to have space 623a8e1175bSopenharmony_ci * for the signature. */ 624a8e1175bSopenharmony_ci memmove(buf, c, len); 625a8e1175bSopenharmony_ci c = buf + len; 626a8e1175bSopenharmony_ci 627a8e1175bSopenharmony_ci /* Add signature at the end of the buffer, 628a8e1175bSopenharmony_ci * making sure that it doesn't underflow 629a8e1175bSopenharmony_ci * into the CRT buffer. */ 630a8e1175bSopenharmony_ci c2 = buf + size; 631a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, mbedtls_x509_write_sig(&c2, c, 632a8e1175bSopenharmony_ci sig_oid, sig_oid_len, 633a8e1175bSopenharmony_ci sig, sig_len, pk_alg)); 634a8e1175bSopenharmony_ci 635a8e1175bSopenharmony_ci /* 636a8e1175bSopenharmony_ci * Memory layout after this step: 637a8e1175bSopenharmony_ci * 638a8e1175bSopenharmony_ci * buf c=buf+len c2 buf+size 639a8e1175bSopenharmony_ci * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm] 640a8e1175bSopenharmony_ci */ 641a8e1175bSopenharmony_ci 642a8e1175bSopenharmony_ci /* Move raw CRT to just before the signature. */ 643a8e1175bSopenharmony_ci c = c2 - len; 644a8e1175bSopenharmony_ci memmove(c, buf, len); 645a8e1175bSopenharmony_ci 646a8e1175bSopenharmony_ci len += sig_and_oid_len; 647a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 648a8e1175bSopenharmony_ci MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, 649a8e1175bSopenharmony_ci MBEDTLS_ASN1_CONSTRUCTED | 650a8e1175bSopenharmony_ci MBEDTLS_ASN1_SEQUENCE)); 651a8e1175bSopenharmony_ci 652a8e1175bSopenharmony_ci return (int) len; 653a8e1175bSopenharmony_ci} 654a8e1175bSopenharmony_ci 655a8e1175bSopenharmony_ci#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" 656a8e1175bSopenharmony_ci#define PEM_END_CRT "-----END CERTIFICATE-----\n" 657a8e1175bSopenharmony_ci 658a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_WRITE_C) 659a8e1175bSopenharmony_ciint mbedtls_x509write_crt_pem(mbedtls_x509write_cert *crt, 660a8e1175bSopenharmony_ci unsigned char *buf, size_t size, 661a8e1175bSopenharmony_ci int (*f_rng)(void *, unsigned char *, size_t), 662a8e1175bSopenharmony_ci void *p_rng) 663a8e1175bSopenharmony_ci{ 664a8e1175bSopenharmony_ci int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 665a8e1175bSopenharmony_ci size_t olen; 666a8e1175bSopenharmony_ci 667a8e1175bSopenharmony_ci if ((ret = mbedtls_x509write_crt_der(crt, buf, size, 668a8e1175bSopenharmony_ci f_rng, p_rng)) < 0) { 669a8e1175bSopenharmony_ci return ret; 670a8e1175bSopenharmony_ci } 671a8e1175bSopenharmony_ci 672a8e1175bSopenharmony_ci if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CRT, PEM_END_CRT, 673a8e1175bSopenharmony_ci buf + size - ret, ret, 674a8e1175bSopenharmony_ci buf, size, &olen)) != 0) { 675a8e1175bSopenharmony_ci return ret; 676a8e1175bSopenharmony_ci } 677a8e1175bSopenharmony_ci 678a8e1175bSopenharmony_ci return 0; 679a8e1175bSopenharmony_ci} 680a8e1175bSopenharmony_ci#endif /* MBEDTLS_PEM_WRITE_C */ 681a8e1175bSopenharmony_ci 682a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_CRT_WRITE_C */ 683