1/* 2 * X.509 internal, common functions for writing 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 */ 7#include "common.h" 8#if defined(MBEDTLS_X509_CSR_WRITE_C) || defined(MBEDTLS_X509_CRT_WRITE_C) 9 10#include "mbedtls/x509_crt.h" 11#include "x509_internal.h" 12#include "mbedtls/asn1write.h" 13#include "mbedtls/error.h" 14#include "mbedtls/oid.h" 15#include "mbedtls/platform.h" 16#include "mbedtls/platform_util.h" 17 18#include <string.h> 19#include <stdint.h> 20 21#if defined(MBEDTLS_PEM_WRITE_C) 22#include "mbedtls/pem.h" 23#endif /* MBEDTLS_PEM_WRITE_C */ 24 25#if defined(MBEDTLS_USE_PSA_CRYPTO) 26#include "psa/crypto.h" 27#include "mbedtls/psa_util.h" 28#include "md_psa.h" 29#endif /* MBEDTLS_USE_PSA_CRYPTO */ 30 31#define CHECK_OVERFLOW_ADD(a, b) \ 32 do \ 33 { \ 34 if (a > SIZE_MAX - (b)) \ 35 { \ 36 return MBEDTLS_ERR_X509_BAD_INPUT_DATA; \ 37 } \ 38 a += b; \ 39 } while (0) 40 41int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions, 42 const mbedtls_x509_san_list *san_list) 43{ 44 int ret = 0; 45 const mbedtls_x509_san_list *cur; 46 unsigned char *buf; 47 unsigned char *p; 48 size_t len; 49 size_t buflen = 0; 50 51 /* Determine the maximum size of the SubjectAltName list */ 52 for (cur = san_list; cur != NULL; cur = cur->next) { 53 /* Calculate size of the required buffer */ 54 switch (cur->node.type) { 55 case MBEDTLS_X509_SAN_DNS_NAME: 56 case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: 57 case MBEDTLS_X509_SAN_IP_ADDRESS: 58 case MBEDTLS_X509_SAN_RFC822_NAME: 59 /* length of value for each name entry, 60 * maximum 4 bytes for the length field, 61 * 1 byte for the tag/type. 62 */ 63 CHECK_OVERFLOW_ADD(buflen, cur->node.san.unstructured_name.len); 64 CHECK_OVERFLOW_ADD(buflen, 4 + 1); 65 break; 66 case MBEDTLS_X509_SAN_DIRECTORY_NAME: 67 { 68 const mbedtls_asn1_named_data *chunk = &cur->node.san.directory_name; 69 while (chunk != NULL) { 70 // Max 4 bytes for length, +1 for tag, 71 // additional 4 max for length, +1 for tag. 72 // See x509_write_name for more information. 73 CHECK_OVERFLOW_ADD(buflen, 4 + 1 + 4 + 1); 74 CHECK_OVERFLOW_ADD(buflen, chunk->oid.len); 75 CHECK_OVERFLOW_ADD(buflen, chunk->val.len); 76 chunk = chunk->next; 77 } 78 CHECK_OVERFLOW_ADD(buflen, 4 + 1); 79 break; 80 } 81 default: 82 /* Not supported - return. */ 83 return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; 84 } 85 } 86 87 /* Add the extra length field and tag */ 88 CHECK_OVERFLOW_ADD(buflen, 4 + 1); 89 90 /* Allocate buffer */ 91 buf = mbedtls_calloc(1, buflen); 92 if (buf == NULL) { 93 return MBEDTLS_ERR_ASN1_ALLOC_FAILED; 94 } 95 p = buf + buflen; 96 97 /* Write ASN.1-based structure */ 98 cur = san_list; 99 len = 0; 100 while (cur != NULL) { 101 size_t single_san_len = 0; 102 switch (cur->node.type) { 103 case MBEDTLS_X509_SAN_DNS_NAME: 104 case MBEDTLS_X509_SAN_RFC822_NAME: 105 case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: 106 case MBEDTLS_X509_SAN_IP_ADDRESS: 107 { 108 const unsigned char *unstructured_name = 109 (const unsigned char *) cur->node.san.unstructured_name.p; 110 size_t unstructured_name_len = cur->node.san.unstructured_name.len; 111 112 MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, 113 mbedtls_asn1_write_raw_buffer( 114 &p, buf, 115 unstructured_name, unstructured_name_len)); 116 MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_len( 117 &p, buf, unstructured_name_len)); 118 MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, 119 mbedtls_asn1_write_tag( 120 &p, buf, 121 MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type)); 122 } 123 break; 124 case MBEDTLS_X509_SAN_DIRECTORY_NAME: 125 MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, 126 mbedtls_x509_write_names(&p, buf, 127 (mbedtls_asn1_named_data *) & 128 cur->node 129 .san.directory_name)); 130 MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, 131 mbedtls_asn1_write_len(&p, buf, single_san_len)); 132 MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, 133 mbedtls_asn1_write_tag(&p, buf, 134 MBEDTLS_ASN1_CONTEXT_SPECIFIC | 135 MBEDTLS_ASN1_CONSTRUCTED | 136 MBEDTLS_X509_SAN_DIRECTORY_NAME)); 137 break; 138 default: 139 /* Error out on an unsupported SAN */ 140 ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; 141 goto cleanup; 142 } 143 cur = cur->next; 144 /* check for overflow */ 145 if (len > SIZE_MAX - single_san_len) { 146 ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; 147 goto cleanup; 148 } 149 len += single_san_len; 150 } 151 152 MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); 153 MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, 154 mbedtls_asn1_write_tag(&p, buf, 155 MBEDTLS_ASN1_CONSTRUCTED | 156 MBEDTLS_ASN1_SEQUENCE)); 157 158 ret = mbedtls_x509_set_extension(extensions, 159 MBEDTLS_OID_SUBJECT_ALT_NAME, 160 MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME), 161 0, 162 buf + buflen - len, len); 163 164 /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list 165 * was incorrectly calculated and memory is corrupted. */ 166 if (p < buf) { 167 ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; 168 } 169cleanup: 170 mbedtls_free(buf); 171 return ret; 172} 173 174#endif /* MBEDTLS_X509_CSR_WRITE_C || MBEDTLS_X509_CRT_WRITE_C */ 175