1 /* 2 * X.509 Certificate Signing Request writing 3 * 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 5 * SPDX-License-Identifier: GPL-2.0 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * This file is part of mbed TLS (https://tls.mbed.org) 22 */ 23 /* 24 * References: 25 * - CSRs: PKCS#10 v1.7 aka RFC 2986 26 * - attributes: PKCS#9 v2.0 aka RFC 2985 27 */ 28 29 #if !defined(MBEDTLS_CONFIG_FILE) 30 #include "mbedtls/config.h" 31 #else 32 #include MBEDTLS_CONFIG_FILE 33 #endif 34 35 #if defined(MBEDTLS_X509_CSR_WRITE_C) 36 37 #include "mbedtls/x509_csr.h" 38 #include "mbedtls/oid.h" 39 #include "mbedtls/asn1write.h" 40 41 #include <string.h> 42 #include <stdlib.h> 43 44 #if defined(MBEDTLS_PEM_WRITE_C) 45 #include "mbedtls/pem.h" 46 #endif 47 48 /* Implementation that should never be optimized out by the compiler */ 49 static void mbedtls_zeroize( void *v, size_t n ) { 50 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 51 } 52 53 /* 54 * For the currently used signature algorithms the buffer to store any signature 55 * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE) 56 */ 57 #if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE 58 #define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN 59 #else 60 #define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE 61 #endif 62 63 void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) 64 { 65 memset( ctx, 0, sizeof( mbedtls_x509write_csr ) ); 66 } 67 68 void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) 69 { 70 mbedtls_asn1_free_named_data_list( &ctx->subject ); 71 mbedtls_asn1_free_named_data_list( &ctx->extensions ); 72 73 mbedtls_zeroize( ctx, sizeof( mbedtls_x509write_csr ) ); 74 } 75 76 void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) 77 { 78 ctx->md_alg = md_alg; 79 } 80 81 void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ) 82 { 83 ctx->key = key; 84 } 85 86 int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, 87 const char *subject_name ) 88 { 89 return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); 90 } 91 92 int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, 93 const char *oid, size_t oid_len, 94 const unsigned char *val, size_t val_len ) 95 { 96 return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, 97 0, val, val_len ); 98 } 99 100 static size_t csr_get_unused_bits_for_named_bitstring( unsigned char bitstring, 101 size_t bit_offset ) 102 { 103 size_t unused_bits; 104 105 /* Count the unused bits removing trailing 0s */ 106 for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ ) 107 if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 ) 108 break; 109 110 return( unused_bits ); 111 } 112 113 int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) 114 { 115 unsigned char buf[4]; 116 unsigned char *c; 117 size_t unused_bits; 118 int ret; 119 120 c = buf + 4; 121 122 unused_bits = csr_get_unused_bits_for_named_bitstring( key_usage, 0 ); 123 ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 8 - unused_bits ); 124 125 if( ret < 0 ) 126 return( ret ); 127 else if( ret < 3 || ret > 4 ) 128 return( MBEDTLS_ERR_X509_INVALID_FORMAT ); 129 130 ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, 131 MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), 132 c, (size_t)ret ); 133 if( ret != 0 ) 134 return( ret ); 135 136 return( 0 ); 137 } 138 139 int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, 140 unsigned char ns_cert_type ) 141 { 142 unsigned char buf[4]; 143 unsigned char *c; 144 size_t unused_bits; 145 int ret; 146 147 c = buf + 4; 148 149 unused_bits = csr_get_unused_bits_for_named_bitstring( ns_cert_type, 0 ); 150 ret = mbedtls_asn1_write_bitstring( &c, 151 buf, 152 &ns_cert_type, 153 8 - unused_bits ); 154 155 if( ret < 0 ) 156 return( ret ); 157 else if( ret < 3 || ret > 4 ) 158 return( ret ); 159 160 ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, 161 MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), 162 c, (size_t)ret ); 163 if( ret != 0 ) 164 return( ret ); 165 166 return( 0 ); 167 } 168 169 int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, 170 int (*f_rng)(void *, unsigned char *, size_t), 171 void *p_rng ) 172 { 173 int ret; 174 const char *sig_oid; 175 size_t sig_oid_len = 0; 176 unsigned char *c, *c2; 177 unsigned char hash[64]; 178 unsigned char sig[SIGNATURE_MAX_SIZE]; 179 unsigned char tmp_buf[2048]; 180 size_t pub_len = 0, sig_and_oid_len = 0, sig_len; 181 size_t len = 0; 182 mbedtls_pk_type_t pk_alg; 183 184 /* 185 * Prepare data to be signed in tmp_buf 186 */ 187 c = tmp_buf + sizeof( tmp_buf ); 188 189 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); 190 191 if( len ) 192 { 193 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 194 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 195 MBEDTLS_ASN1_SEQUENCE ) ); 196 197 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 198 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 199 MBEDTLS_ASN1_SET ) ); 200 201 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, 202 MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); 203 204 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 205 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 206 MBEDTLS_ASN1_SEQUENCE ) ); 207 } 208 209 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 210 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 211 MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); 212 213 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, 214 tmp_buf, c - tmp_buf ) ); 215 c -= pub_len; 216 len += pub_len; 217 218 /* 219 * Subject ::= Name 220 */ 221 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); 222 223 /* 224 * Version ::= INTEGER { v1(0), v2(1), v3(2) } 225 */ 226 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) ); 227 228 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 229 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 230 MBEDTLS_ASN1_SEQUENCE ) ); 231 232 /* 233 * Prepare signature 234 */ 235 ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); 236 if( ret != 0 ) 237 return( ret ); 238 239 if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, 240 f_rng, p_rng ) ) != 0 ) 241 { 242 return( ret ); 243 } 244 245 if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) ) 246 pk_alg = MBEDTLS_PK_RSA; 247 else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) ) 248 pk_alg = MBEDTLS_PK_ECDSA; 249 else 250 return( MBEDTLS_ERR_X509_INVALID_ALG ); 251 252 if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, 253 &sig_oid, &sig_oid_len ) ) != 0 ) 254 { 255 return( ret ); 256 } 257 258 /* 259 * Write data to output buffer 260 */ 261 c2 = buf + size; 262 MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, 263 sig_oid, sig_oid_len, sig, sig_len ) ); 264 265 if( len > (size_t)( c2 - buf ) ) 266 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 267 268 c2 -= len; 269 memcpy( c2, c, len ); 270 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, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | 274 MBEDTLS_ASN1_SEQUENCE ) ); 275 276 return( (int) len ); 277 } 278 279 #define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" 280 #define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" 281 282 #if defined(MBEDTLS_PEM_WRITE_C) 283 int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, 284 int (*f_rng)(void *, unsigned char *, size_t), 285 void *p_rng ) 286 { 287 int ret; 288 unsigned char output_buf[4096]; 289 size_t olen = 0; 290 291 if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf), 292 f_rng, p_rng ) ) < 0 ) 293 { 294 return( ret ); 295 } 296 297 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, 298 output_buf + sizeof(output_buf) - ret, 299 ret, buf, size, &olen ) ) != 0 ) 300 { 301 return( ret ); 302 } 303 304 return( 0 ); 305 } 306 #endif /* MBEDTLS_PEM_WRITE_C */ 307 308 #endif /* MBEDTLS_X509_CSR_WRITE_C */ 309