1 /* 2 * X.509 Certificate Signing Request writing 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may 8 * not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 /* 20 * References: 21 * - CSRs: PKCS#10 v1.7 aka RFC 2986 22 * - attributes: PKCS#9 v2.0 aka RFC 2985 23 */ 24 25 #include "common.h" 26 27 #if defined(MBEDTLS_X509_CSR_WRITE_C) 28 29 #include "mbedtls/x509.h" 30 #include "mbedtls/x509_csr.h" 31 #include "mbedtls/asn1write.h" 32 #include "mbedtls/error.h" 33 #include "mbedtls/oid.h" 34 #include "mbedtls/platform_util.h" 35 36 #if defined(MBEDTLS_USE_PSA_CRYPTO) 37 #include "psa/crypto.h" 38 #include "mbedtls/psa_util.h" 39 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 40 #include "hash_info.h" 41 42 #include <string.h> 43 #include <stdlib.h> 44 45 #if defined(MBEDTLS_PEM_WRITE_C) 46 #include "mbedtls/pem.h" 47 #endif 48 49 #include "mbedtls/platform.h" 50 51 void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx) 52 { 53 memset(ctx, 0, sizeof(mbedtls_x509write_csr)); 54 } 55 56 void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx) 57 { 58 mbedtls_asn1_free_named_data_list(&ctx->subject); 59 mbedtls_asn1_free_named_data_list(&ctx->extensions); 60 61 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr)); 62 } 63 64 void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg) 65 { 66 ctx->md_alg = md_alg; 67 } 68 69 void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key) 70 { 71 ctx->key = key; 72 } 73 74 int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx, 75 const char *subject_name) 76 { 77 return mbedtls_x509_string_to_names(&ctx->subject, subject_name); 78 } 79 80 int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, 81 const char *oid, size_t oid_len, 82 int critical, 83 const unsigned char *val, size_t val_len) 84 { 85 return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, 86 critical, val, val_len); 87 } 88 89 int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, 90 const mbedtls_x509_san_list *san_list) 91 { 92 int ret = 0; 93 const mbedtls_x509_san_list *cur; 94 unsigned char *buf; 95 unsigned char *p; 96 size_t len; 97 size_t buflen = 0; 98 99 /* Determine the maximum size of the SubjectAltName list */ 100 for (cur = san_list; cur != NULL; cur = cur->next) { 101 /* Calculate size of the required buffer */ 102 switch (cur->node.type) { 103 case MBEDTLS_X509_SAN_DNS_NAME: 104 case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: 105 case MBEDTLS_X509_SAN_IP_ADDRESS: 106 /* length of value for each name entry, 107 * maximum 4 bytes for the length field, 108 * 1 byte for the tag/type. 109 */ 110 buflen += cur->node.san.unstructured_name.len + 4 + 1; 111 break; 112 113 default: 114 /* Not supported - skip. */ 115 break; 116 } 117 } 118 119 /* Add the extra length field and tag */ 120 buflen += 4 + 1; 121 122 /* Allocate buffer */ 123 buf = mbedtls_calloc(1, buflen); 124 if (buf == NULL) { 125 return MBEDTLS_ERR_ASN1_ALLOC_FAILED; 126 } 127 128 mbedtls_platform_zeroize(buf, buflen); 129 p = buf + buflen; 130 131 /* Write ASN.1-based structure */ 132 cur = san_list; 133 len = 0; 134 while (cur != NULL) { 135 switch (cur->node.type) { 136 case MBEDTLS_X509_SAN_DNS_NAME: 137 case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: 138 case MBEDTLS_X509_SAN_IP_ADDRESS: 139 { 140 const unsigned char *unstructured_name = 141 (const unsigned char *) cur->node.san.unstructured_name.p; 142 size_t unstructured_name_len = cur->node.san.unstructured_name.len; 143 144 MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, 145 mbedtls_asn1_write_raw_buffer( 146 &p, buf, 147 unstructured_name, unstructured_name_len)); 148 MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len( 149 &p, buf, unstructured_name_len)); 150 MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, 151 mbedtls_asn1_write_tag( 152 &p, buf, 153 MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type)); 154 } 155 break; 156 default: 157 /* Skip unsupported names. */ 158 break; 159 } 160 cur = cur->next; 161 } 162 163 MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); 164 MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, 165 mbedtls_asn1_write_tag(&p, buf, 166 MBEDTLS_ASN1_CONSTRUCTED | 167 MBEDTLS_ASN1_SEQUENCE)); 168 169 ret = mbedtls_x509write_csr_set_extension( 170 ctx, 171 MBEDTLS_OID_SUBJECT_ALT_NAME, 172 MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME), 173 0, 174 buf + buflen - len, 175 len); 176 177 /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list 178 * was incorrectly calculated and memory is corrupted. */ 179 if (p < buf) { 180 ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; 181 } 182 183 cleanup: 184 mbedtls_free(buf); 185 return ret; 186 } 187 188 int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage) 189 { 190 unsigned char buf[4] = { 0 }; 191 unsigned char *c; 192 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 193 194 c = buf + 4; 195 196 ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8); 197 if (ret < 3 || ret > 4) { 198 return ret; 199 } 200 201 ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE, 202 MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), 203 0, c, (size_t) ret); 204 if (ret != 0) { 205 return ret; 206 } 207 208 return 0; 209 } 210 211 int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, 212 unsigned char ns_cert_type) 213 { 214 unsigned char buf[4] = { 0 }; 215 unsigned char *c; 216 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 217 218 c = buf + 4; 219 220 ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8); 221 if (ret < 3 || ret > 4) { 222 return ret; 223 } 224 225 ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE, 226 MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), 227 0, c, (size_t) ret); 228 if (ret != 0) { 229 return ret; 230 } 231 232 return 0; 233 } 234 235 static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, 236 unsigned char *buf, 237 size_t size, 238 unsigned char *sig, size_t sig_size, 239 int (*f_rng)(void *, unsigned char *, size_t), 240 void *p_rng) 241 { 242 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 243 const char *sig_oid; 244 size_t sig_oid_len = 0; 245 unsigned char *c, *c2; 246 unsigned char hash[MBEDTLS_HASH_MAX_SIZE]; 247 size_t pub_len = 0, sig_and_oid_len = 0, sig_len; 248 size_t len = 0; 249 mbedtls_pk_type_t pk_alg; 250 #if defined(MBEDTLS_USE_PSA_CRYPTO) 251 size_t hash_len; 252 psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(ctx->md_alg); 253 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 254 255 /* Write the CSR backwards starting from the end of buf */ 256 c = buf + size; 257 258 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf, 259 ctx->extensions)); 260 261 if (len) { 262 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 263 MBEDTLS_ASN1_CHK_ADD(len, 264 mbedtls_asn1_write_tag( 265 &c, buf, 266 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 267 268 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 269 MBEDTLS_ASN1_CHK_ADD(len, 270 mbedtls_asn1_write_tag( 271 &c, buf, 272 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)); 273 274 MBEDTLS_ASN1_CHK_ADD(len, 275 mbedtls_asn1_write_oid( 276 &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, 277 MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ))); 278 279 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 280 MBEDTLS_ASN1_CHK_ADD(len, 281 mbedtls_asn1_write_tag( 282 &c, buf, 283 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 284 } 285 286 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 287 MBEDTLS_ASN1_CHK_ADD(len, 288 mbedtls_asn1_write_tag( 289 &c, buf, 290 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)); 291 292 MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key, 293 buf, c - buf)); 294 c -= pub_len; 295 len += pub_len; 296 297 /* 298 * Subject ::= Name 299 */ 300 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, 301 ctx->subject)); 302 303 /* 304 * Version ::= INTEGER { v1(0), v2(1), v3(2) } 305 */ 306 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); 307 308 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); 309 MBEDTLS_ASN1_CHK_ADD(len, 310 mbedtls_asn1_write_tag( 311 &c, buf, 312 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 313 314 /* 315 * Sign the written CSR data into the sig buffer 316 * Note: hash errors can happen only after an internal error 317 */ 318 #if defined(MBEDTLS_USE_PSA_CRYPTO) 319 if (psa_hash_compute(hash_alg, 320 c, 321 len, 322 hash, 323 sizeof(hash), 324 &hash_len) != PSA_SUCCESS) { 325 return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 326 } 327 #else /* MBEDTLS_USE_PSA_CRYPTO */ 328 ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash); 329 if (ret != 0) { 330 return ret; 331 } 332 #endif 333 if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0, 334 sig, sig_size, &sig_len, 335 f_rng, p_rng)) != 0) { 336 return ret; 337 } 338 339 if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) { 340 pk_alg = MBEDTLS_PK_RSA; 341 } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) { 342 pk_alg = MBEDTLS_PK_ECDSA; 343 } else { 344 return MBEDTLS_ERR_X509_INVALID_ALG; 345 } 346 347 if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, 348 &sig_oid, &sig_oid_len)) != 0) { 349 return ret; 350 } 351 352 /* 353 * Move the written CSR data to the start of buf to create space for 354 * writing the signature into buf. 355 */ 356 memmove(buf, c, len); 357 358 /* 359 * Write sig and its OID into buf backwards from the end of buf. 360 * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len 361 * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. 362 */ 363 c2 = buf + size; 364 MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, 365 mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len, 366 sig, sig_len)); 367 368 /* 369 * Compact the space between the CSR data and signature by moving the 370 * CSR data to the start of the signature. 371 */ 372 c2 -= len; 373 memmove(c2, buf, len); 374 375 /* ASN encode the total size and tag the CSR data with it. */ 376 len += sig_and_oid_len; 377 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len)); 378 MBEDTLS_ASN1_CHK_ADD(len, 379 mbedtls_asn1_write_tag( 380 &c2, buf, 381 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); 382 383 /* Zero the unused bytes at the start of buf */ 384 memset(buf, 0, c2 - buf); 385 386 return (int) len; 387 } 388 389 int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, 390 size_t size, 391 int (*f_rng)(void *, unsigned char *, size_t), 392 void *p_rng) 393 { 394 int ret; 395 unsigned char *sig; 396 397 if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) { 398 return MBEDTLS_ERR_X509_ALLOC_FAILED; 399 } 400 401 ret = x509write_csr_der_internal(ctx, buf, size, 402 sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE, 403 f_rng, p_rng); 404 405 mbedtls_free(sig); 406 407 return ret; 408 } 409 410 #define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" 411 #define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" 412 413 #if defined(MBEDTLS_PEM_WRITE_C) 414 int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, 415 int (*f_rng)(void *, unsigned char *, size_t), 416 void *p_rng) 417 { 418 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 419 size_t olen = 0; 420 421 if ((ret = mbedtls_x509write_csr_der(ctx, buf, size, 422 f_rng, p_rng)) < 0) { 423 return ret; 424 } 425 426 if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR, 427 buf + size - ret, 428 ret, buf, size, &olen)) != 0) { 429 return ret; 430 } 431 432 return 0; 433 } 434 #endif /* MBEDTLS_PEM_WRITE_C */ 435 436 #endif /* MBEDTLS_X509_CSR_WRITE_C */ 437