1 // SPDX-License-Identifier: Apache-2.0 2 /* 3 * X.509 Certificate Signing Request writing 4 * 5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 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 * This file is part of mbed TLS (https://tls.mbed.org) 20 */ 21 /* 22 * References: 23 * - CSRs: PKCS#10 v1.7 aka RFC 2986 24 * - attributes: PKCS#9 v2.0 aka RFC 2985 25 */ 26 27 #if !defined(MBEDTLS_CONFIG_FILE) 28 #include "mbedtls/config.h" 29 #else 30 #include MBEDTLS_CONFIG_FILE 31 #endif 32 33 #if defined(MBEDTLS_X509_CSR_WRITE_C) 34 35 #include "mbedtls/x509_csr.h" 36 #include "mbedtls/asn1write.h" 37 #include "mbedtls/error.h" 38 #include "mbedtls/oid.h" 39 #include "mbedtls/platform_util.h" 40 41 #if defined(MBEDTLS_USE_PSA_CRYPTO) 42 #include "psa/crypto.h" 43 #include "mbedtls/psa_util.h" 44 #endif 45 46 #include <string.h> 47 #include <stdlib.h> 48 49 #if defined(MBEDTLS_PEM_WRITE_C) 50 #include "mbedtls/pem.h" 51 #endif 52 53 void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) 54 { 55 memset( ctx, 0, sizeof( mbedtls_x509write_csr ) ); 56 } 57 58 void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) 59 { 60 mbedtls_asn1_free_named_data_list( &ctx->subject ); 61 mbedtls_asn1_free_named_data_list( &ctx->extensions ); 62 63 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) ); 64 } 65 66 void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) 67 { 68 ctx->md_alg = md_alg; 69 } 70 71 void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ) 72 { 73 ctx->key = key; 74 } 75 76 int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, 77 const char *subject_name ) 78 { 79 return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); 80 } 81 82 int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, 83 const char *oid, size_t oid_len, 84 const unsigned char *val, size_t val_len ) 85 { 86 return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, 87 0, val, val_len ); 88 } 89 90 int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) 91 { 92 unsigned char buf[4]; 93 unsigned char *c; 94 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 95 96 c = buf + 4; 97 98 ret = mbedtls_asn1_write_named_bitstring( &c, buf, &key_usage, 8 ); 99 if( ret < 3 || ret > 4 ) 100 return( ret ); 101 102 ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, 103 MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), 104 c, (size_t)ret ); 105 if( ret != 0 ) 106 return( ret ); 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]; 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 ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, 125 MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), 126 c, (size_t)ret ); 127 if( ret != 0 ) 128 return( ret ); 129 130 return( 0 ); 131 } 132 133 int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t 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[64]; 142 unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; 143 unsigned char tmp_buf[2048]; 144 size_t pub_len = 0, sig_and_oid_len = 0, sig_len; 145 size_t len = 0; 146 mbedtls_pk_type_t pk_alg; 147 #if defined(MBEDTLS_USE_PSA_CRYPTO) 148 psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; 149 size_t hash_len; 150 psa_algorithm_t hash_alg = mbedtls_psa_translate_md( ctx->md_alg ); 151 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 152 /* 153 * Prepare data to be signed in tmp_buf 154 */ 155 c = tmp_buf + sizeof( tmp_buf ); 156 157 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); 158 159 if( len ) 160 { 161 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 162 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 163 MBEDTLS_ASN1_SEQUENCE ) ); 164 165 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 166 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 167 MBEDTLS_ASN1_SET ) ); 168 169 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, 170 MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); 171 172 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 173 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 174 MBEDTLS_ASN1_SEQUENCE ) ); 175 } 176 177 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 178 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 179 MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); 180 181 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, 182 tmp_buf, c - tmp_buf ) ); 183 c -= pub_len; 184 len += pub_len; 185 186 /* 187 * Subject ::= Name 188 */ 189 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); 190 191 /* 192 * Version ::= INTEGER { v1(0), v2(1), v3(2) } 193 */ 194 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) ); 195 196 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 197 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 198 MBEDTLS_ASN1_SEQUENCE ) ); 199 200 /* 201 * Prepare signature 202 * Note: hash errors can happen only after an internal error 203 */ 204 #if defined(MBEDTLS_USE_PSA_CRYPTO) 205 if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS ) 206 return( MBEDTLS_ERR_X509_FATAL_ERROR ); 207 208 if( psa_hash_update( &hash_operation, c, len ) != PSA_SUCCESS ) 209 return( MBEDTLS_ERR_X509_FATAL_ERROR ); 210 211 if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len ) 212 != PSA_SUCCESS ) 213 { 214 return( MBEDTLS_ERR_X509_FATAL_ERROR ); 215 } 216 #else /* MBEDTLS_USE_PSA_CRYPTO */ 217 ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); 218 if( ret != 0 ) 219 return( ret ); 220 #endif 221 if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, 222 f_rng, p_rng ) ) != 0 ) 223 { 224 return( ret ); 225 } 226 227 if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) ) 228 pk_alg = MBEDTLS_PK_RSA; 229 else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) ) 230 pk_alg = MBEDTLS_PK_ECDSA; 231 else 232 return( MBEDTLS_ERR_X509_INVALID_ALG ); 233 234 if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, 235 &sig_oid, &sig_oid_len ) ) != 0 ) 236 { 237 return( ret ); 238 } 239 240 /* 241 * Write data to output buffer 242 */ 243 c2 = buf + size; 244 MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, 245 sig_oid, sig_oid_len, sig, sig_len ) ); 246 247 if( len > (size_t)( c2 - buf ) ) 248 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 249 250 c2 -= len; 251 memcpy( c2, c, len ); 252 253 len += sig_and_oid_len; 254 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); 255 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | 256 MBEDTLS_ASN1_SEQUENCE ) ); 257 258 return( (int) len ); 259 } 260 261 #define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" 262 #define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" 263 264 #if defined(MBEDTLS_PEM_WRITE_C) 265 int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, 266 int (*f_rng)(void *, unsigned char *, size_t), 267 void *p_rng ) 268 { 269 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 270 size_t olen = 0; 271 272 if( ( ret = mbedtls_x509write_csr_der( ctx, buf, size, 273 f_rng, p_rng ) ) < 0 ) 274 { 275 return( ret ); 276 } 277 278 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, 279 buf + size - ret, 280 ret, buf, size, &olen ) ) != 0 ) 281 { 282 return( ret ); 283 } 284 285 return( 0 ); 286 } 287 #endif /* MBEDTLS_PEM_WRITE_C */ 288 289 #endif /* MBEDTLS_X509_CSR_WRITE_C */ 290