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