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 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_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 static size_t csr_get_unused_bits_for_named_bitstring( unsigned char bitstring, 91 size_t bit_offset ) 92 { 93 size_t unused_bits; 94 95 /* Count the unused bits removing trailing 0s */ 96 for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ ) 97 if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 ) 98 break; 99 100 return( unused_bits ); 101 } 102 103 int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) 104 { 105 unsigned char buf[4]; 106 unsigned char *c; 107 size_t unused_bits; 108 int ret; 109 110 c = buf + 4; 111 112 unused_bits = csr_get_unused_bits_for_named_bitstring( key_usage, 0 ); 113 ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 8 - unused_bits ); 114 115 if( ret < 0 ) 116 return( ret ); 117 else if( ret < 3 || ret > 4 ) 118 return( MBEDTLS_ERR_X509_INVALID_FORMAT ); 119 120 ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, 121 MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), 122 c, (size_t)ret ); 123 if( ret != 0 ) 124 return( ret ); 125 126 return( 0 ); 127 } 128 129 int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, 130 unsigned char ns_cert_type ) 131 { 132 unsigned char buf[4]; 133 unsigned char *c; 134 size_t unused_bits; 135 int ret; 136 137 c = buf + 4; 138 139 unused_bits = csr_get_unused_bits_for_named_bitstring( ns_cert_type, 0 ); 140 ret = mbedtls_asn1_write_bitstring( &c, 141 buf, 142 &ns_cert_type, 143 8 - unused_bits ); 144 145 if( ret < 0 ) 146 return( ret ); 147 else if( ret < 3 || ret > 4 ) 148 return( ret ); 149 150 ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, 151 MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), 152 c, (size_t)ret ); 153 if( ret != 0 ) 154 return( ret ); 155 156 return( 0 ); 157 } 158 159 int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, 160 int (*f_rng)(void *, unsigned char *, size_t), 161 void *p_rng ) 162 { 163 int ret; 164 const char *sig_oid; 165 size_t sig_oid_len = 0; 166 unsigned char *c, *c2; 167 unsigned char hash[64]; 168 unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; 169 unsigned char tmp_buf[2048]; 170 size_t pub_len = 0, sig_and_oid_len = 0, sig_len; 171 size_t len = 0; 172 mbedtls_pk_type_t pk_alg; 173 174 /* 175 * Prepare data to be signed in tmp_buf 176 */ 177 c = tmp_buf + sizeof( tmp_buf ); 178 179 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); 180 181 if( len ) 182 { 183 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 184 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 185 MBEDTLS_ASN1_SEQUENCE ) ); 186 187 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 188 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 189 MBEDTLS_ASN1_SET ) ); 190 191 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, 192 MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); 193 194 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 195 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 196 MBEDTLS_ASN1_SEQUENCE ) ); 197 } 198 199 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 200 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 201 MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); 202 203 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, 204 tmp_buf, c - tmp_buf ) ); 205 c -= pub_len; 206 len += pub_len; 207 208 /* 209 * Subject ::= Name 210 */ 211 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); 212 213 /* 214 * Version ::= INTEGER { v1(0), v2(1), v3(2) } 215 */ 216 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) ); 217 218 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 219 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 220 MBEDTLS_ASN1_SEQUENCE ) ); 221 222 /* 223 * Prepare signature 224 */ 225 mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); 226 227 if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, 228 f_rng, p_rng ) ) != 0 ) 229 { 230 return( ret ); 231 } 232 233 if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) ) 234 pk_alg = MBEDTLS_PK_RSA; 235 else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) ) 236 pk_alg = MBEDTLS_PK_ECDSA; 237 else 238 return( MBEDTLS_ERR_X509_INVALID_ALG ); 239 240 if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, 241 &sig_oid, &sig_oid_len ) ) != 0 ) 242 { 243 return( ret ); 244 } 245 246 /* 247 * Write data to output buffer 248 */ 249 c2 = buf + size; 250 MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, 251 sig_oid, sig_oid_len, sig, sig_len ) ); 252 253 if( len > (size_t)( c2 - buf ) ) 254 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 255 256 c2 -= len; 257 memcpy( c2, c, len ); 258 259 len += sig_and_oid_len; 260 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); 261 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | 262 MBEDTLS_ASN1_SEQUENCE ) ); 263 264 return( (int) len ); 265 } 266 267 #define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" 268 #define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" 269 270 #if defined(MBEDTLS_PEM_WRITE_C) 271 int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, 272 int (*f_rng)(void *, unsigned char *, size_t), 273 void *p_rng ) 274 { 275 int ret; 276 unsigned char output_buf[4096]; 277 size_t olen = 0; 278 279 if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf), 280 f_rng, p_rng ) ) < 0 ) 281 { 282 return( ret ); 283 } 284 285 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, 286 output_buf + sizeof(output_buf) - ret, 287 ret, buf, size, &olen ) ) != 0 ) 288 { 289 return( ret ); 290 } 291 292 return( 0 ); 293 } 294 #endif /* MBEDTLS_PEM_WRITE_C */ 295 296 #endif /* MBEDTLS_X509_CSR_WRITE_C */ 297