1/* 2 * X.509 Certificate Signing Request writing 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 */ 7/* 8 * References: 9 * - CSRs: PKCS#10 v1.7 aka RFC 2986 10 * - attributes: PKCS#9 v2.0 aka RFC 2985 11 */ 12 13#include "common.h" 14 15#if defined(MBEDTLS_X509_CSR_WRITE_C) 16 17#include "x509_internal.h" 18#include "mbedtls/x509_csr.h" 19#include "mbedtls/asn1write.h" 20#include "mbedtls/error.h" 21#include "mbedtls/oid.h" 22#include "mbedtls/platform_util.h" 23 24#if defined(MBEDTLS_USE_PSA_CRYPTO) 25#include "psa/crypto.h" 26#include "psa_util_internal.h" 27#include "mbedtls/psa_util.h" 28#endif /* MBEDTLS_USE_PSA_CRYPTO */ 29 30#include <string.h> 31#include <stdlib.h> 32 33#if defined(MBEDTLS_PEM_WRITE_C) 34#include "mbedtls/pem.h" 35#endif 36 37#include "mbedtls/platform.h" 38 39void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx) 40{ 41 memset(ctx, 0, sizeof(mbedtls_x509write_csr)); 42} 43 44void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx) 45{ 46 mbedtls_asn1_free_named_data_list(&ctx->subject); 47 mbedtls_asn1_free_named_data_list(&ctx->extensions); 48 49 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr)); 50} 51 52void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg) 53{ 54 ctx->md_alg = md_alg; 55} 56 57void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key) 58{ 59 ctx->key = key; 60} 61 62int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx, 63 const char *subject_name) 64{ 65 return mbedtls_x509_string_to_names(&ctx->subject, subject_name); 66} 67 68int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, 69 const char *oid, size_t oid_len, 70 int critical, 71 const unsigned char *val, size_t val_len) 72{ 73 return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, 74 critical, val, val_len); 75} 76 77int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, 78 const mbedtls_x509_san_list *san_list) 79{ 80 return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list); 81} 82 83int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage) 84{ 85 unsigned char buf[4] = { 0 }; 86 unsigned char *c; 87 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 88 89 c = buf + 4; 90 91 ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8); 92 if (ret < 3 || ret > 4) { 93 return ret; 94 } 95 96 ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE, 97 MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), 98 0, c, (size_t) ret); 99 if (ret != 0) { 100 return ret; 101 } 102 103 return 0; 104} 105 106int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, 107 unsigned char ns_cert_type) 108{ 109 unsigned char buf[4] = { 0 }; 110 unsigned char *c; 111 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 112 113 c = buf + 4; 114 115 ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8); 116 if (ret < 3 || ret > 4) { 117 return ret; 118 } 119 120 ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE, 121 MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), 122 0, c, (size_t) ret); 123 if (ret != 0) { 124 return ret; 125 } 126 127 return 0; 128} 129 130static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, 131 unsigned char *buf, 132 size_t size, 133 unsigned char *sig, size_t sig_size, 134 int (*f_rng)(void *, unsigned char *, size_t), 135 void *p_rng) 136{ 137 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 138 const char *sig_oid; 139 size_t sig_oid_len = 0; 140 unsigned char *c, *c2; 141 unsigned char hash[MBEDTLS_MD_MAX_SIZE]; 142 size_t pub_len = 0, sig_and_oid_len = 0, sig_len; 143 size_t len = 0; 144 mbedtls_pk_type_t pk_alg; 145#if defined(MBEDTLS_USE_PSA_CRYPTO) 146 size_t hash_len; 147 psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ctx->md_alg); 148#endif /* MBEDTLS_USE_PSA_CRYPTO */ 149 150 /* Write the CSR backwards starting from the end of buf */ 151 c = buf + size; 152 153 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf, 154 ctx->extensions)); 155 156 if (len) { 157 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 158 MBEDTLS_ASN1_CHK_ADD(len, 159 mbedtls_asn1_write_tag( 160 &c, buf, 161 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 162 163 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 164 MBEDTLS_ASN1_CHK_ADD(len, 165 mbedtls_asn1_write_tag( 166 &c, buf, 167 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)); 168 169 MBEDTLS_ASN1_CHK_ADD(len, 170 mbedtls_asn1_write_oid( 171 &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, 172 MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ))); 173 174 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 175 MBEDTLS_ASN1_CHK_ADD(len, 176 mbedtls_asn1_write_tag( 177 &c, buf, 178 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 179 } 180 181 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 182 MBEDTLS_ASN1_CHK_ADD(len, 183 mbedtls_asn1_write_tag( 184 &c, buf, 185 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)); 186 187 MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key, 188 buf, (size_t) (c - buf))); 189 c -= pub_len; 190 len += pub_len; 191 192 /* 193 * Subject ::= Name 194 */ 195 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, 196 ctx->subject)); 197 198 /* 199 * Version ::= INTEGER { v1(0), v2(1), v3(2) } 200 */ 201 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); 202 203 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 204 MBEDTLS_ASN1_CHK_ADD(len, 205 mbedtls_asn1_write_tag( 206 &c, buf, 207 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 208 209 /* 210 * Sign the written CSR data into the sig buffer 211 * Note: hash errors can happen only after an internal error 212 */ 213#if defined(MBEDTLS_USE_PSA_CRYPTO) 214 if (psa_hash_compute(hash_alg, 215 c, 216 len, 217 hash, 218 sizeof(hash), 219 &hash_len) != PSA_SUCCESS) { 220 return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 221 } 222#else /* MBEDTLS_USE_PSA_CRYPTO */ 223 ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash); 224 if (ret != 0) { 225 return ret; 226 } 227#endif 228 if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0, 229 sig, sig_size, &sig_len, 230 f_rng, p_rng)) != 0) { 231 return ret; 232 } 233 234 if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) { 235 pk_alg = MBEDTLS_PK_RSA; 236 } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) { 237 pk_alg = MBEDTLS_PK_ECDSA; 238 } else { 239 return MBEDTLS_ERR_X509_INVALID_ALG; 240 } 241 242 if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, 243 &sig_oid, &sig_oid_len)) != 0) { 244 return ret; 245 } 246 247 /* 248 * Move the written CSR data to the start of buf to create space for 249 * writing the signature into buf. 250 */ 251 memmove(buf, c, len); 252 253 /* 254 * Write sig and its OID into buf backwards from the end of buf. 255 * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len 256 * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. 257 */ 258 c2 = buf + size; 259 MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, 260 mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len, 261 sig, sig_len, pk_alg)); 262 263 /* 264 * Compact the space between the CSR data and signature by moving the 265 * CSR data to the start of the signature. 266 */ 267 c2 -= len; 268 memmove(c2, buf, len); 269 270 /* ASN encode the total size and tag the CSR data with it. */ 271 len += sig_and_oid_len; 272 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len)); 273 MBEDTLS_ASN1_CHK_ADD(len, 274 mbedtls_asn1_write_tag( 275 &c2, buf, 276 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 277 278 /* Zero the unused bytes at the start of buf */ 279 memset(buf, 0, (size_t) (c2 - buf)); 280 281 return (int) len; 282} 283 284int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, 285 size_t size, 286 int (*f_rng)(void *, unsigned char *, size_t), 287 void *p_rng) 288{ 289 int ret; 290 unsigned char *sig; 291 292 if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) { 293 return MBEDTLS_ERR_X509_ALLOC_FAILED; 294 } 295 296 ret = x509write_csr_der_internal(ctx, buf, size, 297 sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE, 298 f_rng, p_rng); 299 300 mbedtls_free(sig); 301 302 return ret; 303} 304 305#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" 306#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" 307 308#if defined(MBEDTLS_PEM_WRITE_C) 309int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, 310 int (*f_rng)(void *, unsigned char *, size_t), 311 void *p_rng) 312{ 313 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 314 size_t olen = 0; 315 316 if ((ret = mbedtls_x509write_csr_der(ctx, buf, size, 317 f_rng, p_rng)) < 0) { 318 return ret; 319 } 320 321 if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR, 322 buf + size - ret, 323 ret, buf, size, &olen)) != 0) { 324 return ret; 325 } 326 327 return 0; 328} 329#endif /* MBEDTLS_PEM_WRITE_C */ 330 331#endif /* MBEDTLS_X509_CSR_WRITE_C */ 332