mbed TLS upgraded to 2.6.0

Fork of mbedtls by Mark Radbourne

Committer:
markrad
Date:
Thu Jan 05 00:18:44 2017 +0000
Revision:
0:cdf462088d13
Child:
2:bbdeda018a3c
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
markrad 0:cdf462088d13 1 /*
markrad 0:cdf462088d13 2 * X.509 certificate writing
markrad 0:cdf462088d13 3 *
markrad 0:cdf462088d13 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
markrad 0:cdf462088d13 5 * SPDX-License-Identifier: Apache-2.0
markrad 0:cdf462088d13 6 *
markrad 0:cdf462088d13 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
markrad 0:cdf462088d13 8 * not use this file except in compliance with the License.
markrad 0:cdf462088d13 9 * You may obtain a copy of the License at
markrad 0:cdf462088d13 10 *
markrad 0:cdf462088d13 11 * http://www.apache.org/licenses/LICENSE-2.0
markrad 0:cdf462088d13 12 *
markrad 0:cdf462088d13 13 * Unless required by applicable law or agreed to in writing, software
markrad 0:cdf462088d13 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
markrad 0:cdf462088d13 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
markrad 0:cdf462088d13 16 * See the License for the specific language governing permissions and
markrad 0:cdf462088d13 17 * limitations under the License.
markrad 0:cdf462088d13 18 *
markrad 0:cdf462088d13 19 * This file is part of mbed TLS (https://tls.mbed.org)
markrad 0:cdf462088d13 20 */
markrad 0:cdf462088d13 21 /*
markrad 0:cdf462088d13 22 * References:
markrad 0:cdf462088d13 23 * - certificates: RFC 5280, updated by RFC 6818
markrad 0:cdf462088d13 24 * - CSRs: PKCS#10 v1.7 aka RFC 2986
markrad 0:cdf462088d13 25 * - attributes: PKCS#9 v2.0 aka RFC 2985
markrad 0:cdf462088d13 26 */
markrad 0:cdf462088d13 27
markrad 0:cdf462088d13 28 #if !defined(MBEDTLS_CONFIG_FILE)
markrad 0:cdf462088d13 29 #include "mbedtls/config.h"
markrad 0:cdf462088d13 30 #else
markrad 0:cdf462088d13 31 #include MBEDTLS_CONFIG_FILE
markrad 0:cdf462088d13 32 #endif
markrad 0:cdf462088d13 33
markrad 0:cdf462088d13 34 #if defined(MBEDTLS_X509_CRT_WRITE_C)
markrad 0:cdf462088d13 35
markrad 0:cdf462088d13 36 #include "mbedtls/x509_crt.h"
markrad 0:cdf462088d13 37 #include "mbedtls/oid.h"
markrad 0:cdf462088d13 38 #include "mbedtls/asn1write.h"
markrad 0:cdf462088d13 39 #include "mbedtls/sha1.h"
markrad 0:cdf462088d13 40
markrad 0:cdf462088d13 41 #include <string.h>
markrad 0:cdf462088d13 42
markrad 0:cdf462088d13 43 #if defined(MBEDTLS_PEM_WRITE_C)
markrad 0:cdf462088d13 44 #include "mbedtls/pem.h"
markrad 0:cdf462088d13 45 #endif /* MBEDTLS_PEM_WRITE_C */
markrad 0:cdf462088d13 46
markrad 0:cdf462088d13 47 /* Implementation that should never be optimized out by the compiler */
markrad 0:cdf462088d13 48 static void mbedtls_zeroize( void *v, size_t n ) {
markrad 0:cdf462088d13 49 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
markrad 0:cdf462088d13 50 }
markrad 0:cdf462088d13 51
markrad 0:cdf462088d13 52 void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
markrad 0:cdf462088d13 53 {
markrad 0:cdf462088d13 54 memset( ctx, 0, sizeof(mbedtls_x509write_cert) );
markrad 0:cdf462088d13 55
markrad 0:cdf462088d13 56 mbedtls_mpi_init( &ctx->serial );
markrad 0:cdf462088d13 57 ctx->version = MBEDTLS_X509_CRT_VERSION_3;
markrad 0:cdf462088d13 58 }
markrad 0:cdf462088d13 59
markrad 0:cdf462088d13 60 void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx )
markrad 0:cdf462088d13 61 {
markrad 0:cdf462088d13 62 mbedtls_mpi_free( &ctx->serial );
markrad 0:cdf462088d13 63
markrad 0:cdf462088d13 64 mbedtls_asn1_free_named_data_list( &ctx->subject );
markrad 0:cdf462088d13 65 mbedtls_asn1_free_named_data_list( &ctx->issuer );
markrad 0:cdf462088d13 66 mbedtls_asn1_free_named_data_list( &ctx->extensions );
markrad 0:cdf462088d13 67
markrad 0:cdf462088d13 68 mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_cert) );
markrad 0:cdf462088d13 69 }
markrad 0:cdf462088d13 70
markrad 0:cdf462088d13 71 void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version )
markrad 0:cdf462088d13 72 {
markrad 0:cdf462088d13 73 ctx->version = version;
markrad 0:cdf462088d13 74 }
markrad 0:cdf462088d13 75
markrad 0:cdf462088d13 76 void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg )
markrad 0:cdf462088d13 77 {
markrad 0:cdf462088d13 78 ctx->md_alg = md_alg;
markrad 0:cdf462088d13 79 }
markrad 0:cdf462088d13 80
markrad 0:cdf462088d13 81 void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
markrad 0:cdf462088d13 82 {
markrad 0:cdf462088d13 83 ctx->subject_key = key;
markrad 0:cdf462088d13 84 }
markrad 0:cdf462088d13 85
markrad 0:cdf462088d13 86 void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
markrad 0:cdf462088d13 87 {
markrad 0:cdf462088d13 88 ctx->issuer_key = key;
markrad 0:cdf462088d13 89 }
markrad 0:cdf462088d13 90
markrad 0:cdf462088d13 91 int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx,
markrad 0:cdf462088d13 92 const char *subject_name )
markrad 0:cdf462088d13 93 {
markrad 0:cdf462088d13 94 return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
markrad 0:cdf462088d13 95 }
markrad 0:cdf462088d13 96
markrad 0:cdf462088d13 97 int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx,
markrad 0:cdf462088d13 98 const char *issuer_name )
markrad 0:cdf462088d13 99 {
markrad 0:cdf462088d13 100 return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name );
markrad 0:cdf462088d13 101 }
markrad 0:cdf462088d13 102
markrad 0:cdf462088d13 103 int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial )
markrad 0:cdf462088d13 104 {
markrad 0:cdf462088d13 105 int ret;
markrad 0:cdf462088d13 106
markrad 0:cdf462088d13 107 if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
markrad 0:cdf462088d13 108 return( ret );
markrad 0:cdf462088d13 109
markrad 0:cdf462088d13 110 return( 0 );
markrad 0:cdf462088d13 111 }
markrad 0:cdf462088d13 112
markrad 0:cdf462088d13 113 int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before,
markrad 0:cdf462088d13 114 const char *not_after )
markrad 0:cdf462088d13 115 {
markrad 0:cdf462088d13 116 if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
markrad 0:cdf462088d13 117 strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 )
markrad 0:cdf462088d13 118 {
markrad 0:cdf462088d13 119 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
markrad 0:cdf462088d13 120 }
markrad 0:cdf462088d13 121 strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
markrad 0:cdf462088d13 122 strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
markrad 0:cdf462088d13 123 ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
markrad 0:cdf462088d13 124 ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
markrad 0:cdf462088d13 125
markrad 0:cdf462088d13 126 return( 0 );
markrad 0:cdf462088d13 127 }
markrad 0:cdf462088d13 128
markrad 0:cdf462088d13 129 int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
markrad 0:cdf462088d13 130 const char *oid, size_t oid_len,
markrad 0:cdf462088d13 131 int critical,
markrad 0:cdf462088d13 132 const unsigned char *val, size_t val_len )
markrad 0:cdf462088d13 133 {
markrad 0:cdf462088d13 134 return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
markrad 0:cdf462088d13 135 critical, val, val_len );
markrad 0:cdf462088d13 136 }
markrad 0:cdf462088d13 137
markrad 0:cdf462088d13 138 int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
markrad 0:cdf462088d13 139 int is_ca, int max_pathlen )
markrad 0:cdf462088d13 140 {
markrad 0:cdf462088d13 141 int ret;
markrad 0:cdf462088d13 142 unsigned char buf[9];
markrad 0:cdf462088d13 143 unsigned char *c = buf + sizeof(buf);
markrad 0:cdf462088d13 144 size_t len = 0;
markrad 0:cdf462088d13 145
markrad 0:cdf462088d13 146 memset( buf, 0, sizeof(buf) );
markrad 0:cdf462088d13 147
markrad 0:cdf462088d13 148 if( is_ca && max_pathlen > 127 )
markrad 0:cdf462088d13 149 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
markrad 0:cdf462088d13 150
markrad 0:cdf462088d13 151 if( is_ca )
markrad 0:cdf462088d13 152 {
markrad 0:cdf462088d13 153 if( max_pathlen >= 0 )
markrad 0:cdf462088d13 154 {
markrad 0:cdf462088d13 155 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) );
markrad 0:cdf462088d13 156 }
markrad 0:cdf462088d13 157 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
markrad 0:cdf462088d13 158 }
markrad 0:cdf462088d13 159
markrad 0:cdf462088d13 160 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
markrad 0:cdf462088d13 161 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
markrad 0:cdf462088d13 162 MBEDTLS_ASN1_SEQUENCE ) );
markrad 0:cdf462088d13 163
markrad 0:cdf462088d13 164 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
markrad 0:cdf462088d13 165 MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
markrad 0:cdf462088d13 166 0, buf + sizeof(buf) - len, len );
markrad 0:cdf462088d13 167 }
markrad 0:cdf462088d13 168
markrad 0:cdf462088d13 169 #if defined(MBEDTLS_SHA1_C)
markrad 0:cdf462088d13 170 int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
markrad 0:cdf462088d13 171 {
markrad 0:cdf462088d13 172 int ret;
markrad 0:cdf462088d13 173 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
markrad 0:cdf462088d13 174 unsigned char *c = buf + sizeof(buf);
markrad 0:cdf462088d13 175 size_t len = 0;
markrad 0:cdf462088d13 176
markrad 0:cdf462088d13 177 memset( buf, 0, sizeof(buf) );
markrad 0:cdf462088d13 178 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) );
markrad 0:cdf462088d13 179
markrad 0:cdf462088d13 180 mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
markrad 0:cdf462088d13 181 c = buf + sizeof(buf) - 20;
markrad 0:cdf462088d13 182 len = 20;
markrad 0:cdf462088d13 183
markrad 0:cdf462088d13 184 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
markrad 0:cdf462088d13 185 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) );
markrad 0:cdf462088d13 186
markrad 0:cdf462088d13 187 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
markrad 0:cdf462088d13 188 MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
markrad 0:cdf462088d13 189 0, buf + sizeof(buf) - len, len );
markrad 0:cdf462088d13 190 }
markrad 0:cdf462088d13 191
markrad 0:cdf462088d13 192 int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
markrad 0:cdf462088d13 193 {
markrad 0:cdf462088d13 194 int ret;
markrad 0:cdf462088d13 195 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
markrad 0:cdf462088d13 196 unsigned char *c = buf + sizeof(buf);
markrad 0:cdf462088d13 197 size_t len = 0;
markrad 0:cdf462088d13 198
markrad 0:cdf462088d13 199 memset( buf, 0, sizeof(buf) );
markrad 0:cdf462088d13 200 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
markrad 0:cdf462088d13 201
markrad 0:cdf462088d13 202 mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
markrad 0:cdf462088d13 203 c = buf + sizeof(buf) - 20;
markrad 0:cdf462088d13 204 len = 20;
markrad 0:cdf462088d13 205
markrad 0:cdf462088d13 206 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
markrad 0:cdf462088d13 207 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) );
markrad 0:cdf462088d13 208
markrad 0:cdf462088d13 209 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
markrad 0:cdf462088d13 210 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
markrad 0:cdf462088d13 211 MBEDTLS_ASN1_SEQUENCE ) );
markrad 0:cdf462088d13 212
markrad 0:cdf462088d13 213 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
markrad 0:cdf462088d13 214 MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
markrad 0:cdf462088d13 215 0, buf + sizeof(buf) - len, len );
markrad 0:cdf462088d13 216 }
markrad 0:cdf462088d13 217 #endif /* MBEDTLS_SHA1_C */
markrad 0:cdf462088d13 218
markrad 0:cdf462088d13 219 int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
markrad 0:cdf462088d13 220 unsigned int key_usage )
markrad 0:cdf462088d13 221 {
markrad 0:cdf462088d13 222 unsigned char buf[4], ku;
markrad 0:cdf462088d13 223 unsigned char *c;
markrad 0:cdf462088d13 224 int ret;
markrad 0:cdf462088d13 225
markrad 0:cdf462088d13 226 /* We currently only support 7 bits, from 0x80 to 0x02 */
markrad 0:cdf462088d13 227 if( ( key_usage & ~0xfe ) != 0 )
markrad 0:cdf462088d13 228 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
markrad 0:cdf462088d13 229
markrad 0:cdf462088d13 230 c = buf + 4;
markrad 0:cdf462088d13 231 ku = (unsigned char) key_usage;
markrad 0:cdf462088d13 232
markrad 0:cdf462088d13 233 if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 )
markrad 0:cdf462088d13 234 return( ret );
markrad 0:cdf462088d13 235
markrad 0:cdf462088d13 236 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
markrad 0:cdf462088d13 237 MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
markrad 0:cdf462088d13 238 1, buf, 4 );
markrad 0:cdf462088d13 239 if( ret != 0 )
markrad 0:cdf462088d13 240 return( ret );
markrad 0:cdf462088d13 241
markrad 0:cdf462088d13 242 return( 0 );
markrad 0:cdf462088d13 243 }
markrad 0:cdf462088d13 244
markrad 0:cdf462088d13 245 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
markrad 0:cdf462088d13 246 unsigned char ns_cert_type )
markrad 0:cdf462088d13 247 {
markrad 0:cdf462088d13 248 unsigned char buf[4];
markrad 0:cdf462088d13 249 unsigned char *c;
markrad 0:cdf462088d13 250 int ret;
markrad 0:cdf462088d13 251
markrad 0:cdf462088d13 252 c = buf + 4;
markrad 0:cdf462088d13 253
markrad 0:cdf462088d13 254 if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
markrad 0:cdf462088d13 255 return( ret );
markrad 0:cdf462088d13 256
markrad 0:cdf462088d13 257 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
markrad 0:cdf462088d13 258 MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
markrad 0:cdf462088d13 259 0, buf, 4 );
markrad 0:cdf462088d13 260 if( ret != 0 )
markrad 0:cdf462088d13 261 return( ret );
markrad 0:cdf462088d13 262
markrad 0:cdf462088d13 263 return( 0 );
markrad 0:cdf462088d13 264 }
markrad 0:cdf462088d13 265
markrad 0:cdf462088d13 266 static int x509_write_time( unsigned char **p, unsigned char *start,
markrad 0:cdf462088d13 267 const char *time, size_t size )
markrad 0:cdf462088d13 268 {
markrad 0:cdf462088d13 269 int ret;
markrad 0:cdf462088d13 270 size_t len = 0;
markrad 0:cdf462088d13 271
markrad 0:cdf462088d13 272 /*
markrad 0:cdf462088d13 273 * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
markrad 0:cdf462088d13 274 */
markrad 0:cdf462088d13 275 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
markrad 0:cdf462088d13 276 {
markrad 0:cdf462088d13 277 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
markrad 0:cdf462088d13 278 (const unsigned char *) time + 2,
markrad 0:cdf462088d13 279 size - 2 ) );
markrad 0:cdf462088d13 280 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
markrad 0:cdf462088d13 281 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) );
markrad 0:cdf462088d13 282 }
markrad 0:cdf462088d13 283 else
markrad 0:cdf462088d13 284 {
markrad 0:cdf462088d13 285 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
markrad 0:cdf462088d13 286 (const unsigned char *) time,
markrad 0:cdf462088d13 287 size ) );
markrad 0:cdf462088d13 288 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
markrad 0:cdf462088d13 289 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) );
markrad 0:cdf462088d13 290 }
markrad 0:cdf462088d13 291
markrad 0:cdf462088d13 292 return( (int) len );
markrad 0:cdf462088d13 293 }
markrad 0:cdf462088d13 294
markrad 0:cdf462088d13 295 int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size,
markrad 0:cdf462088d13 296 int (*f_rng)(void *, unsigned char *, size_t),
markrad 0:cdf462088d13 297 void *p_rng )
markrad 0:cdf462088d13 298 {
markrad 0:cdf462088d13 299 int ret;
markrad 0:cdf462088d13 300 const char *sig_oid;
markrad 0:cdf462088d13 301 size_t sig_oid_len = 0;
markrad 0:cdf462088d13 302 unsigned char *c, *c2;
markrad 0:cdf462088d13 303 unsigned char hash[64];
markrad 0:cdf462088d13 304 unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
markrad 0:cdf462088d13 305 unsigned char tmp_buf[2048];
markrad 0:cdf462088d13 306 size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
markrad 0:cdf462088d13 307 size_t len = 0;
markrad 0:cdf462088d13 308 mbedtls_pk_type_t pk_alg;
markrad 0:cdf462088d13 309
markrad 0:cdf462088d13 310 /*
markrad 0:cdf462088d13 311 * Prepare data to be signed in tmp_buf
markrad 0:cdf462088d13 312 */
markrad 0:cdf462088d13 313 c = tmp_buf + sizeof( tmp_buf );
markrad 0:cdf462088d13 314
markrad 0:cdf462088d13 315 /* Signature algorithm needed in TBS, and later for actual signature */
markrad 0:cdf462088d13 316 pk_alg = mbedtls_pk_get_type( ctx->issuer_key );
markrad 0:cdf462088d13 317 if( pk_alg == MBEDTLS_PK_ECKEY )
markrad 0:cdf462088d13 318 pk_alg = MBEDTLS_PK_ECDSA;
markrad 0:cdf462088d13 319
markrad 0:cdf462088d13 320 if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
markrad 0:cdf462088d13 321 &sig_oid, &sig_oid_len ) ) != 0 )
markrad 0:cdf462088d13 322 {
markrad 0:cdf462088d13 323 return( ret );
markrad 0:cdf462088d13 324 }
markrad 0:cdf462088d13 325
markrad 0:cdf462088d13 326 /*
markrad 0:cdf462088d13 327 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
markrad 0:cdf462088d13 328 */
markrad 0:cdf462088d13 329 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
markrad 0:cdf462088d13 330 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
markrad 0:cdf462088d13 331 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
markrad 0:cdf462088d13 332 MBEDTLS_ASN1_SEQUENCE ) );
markrad 0:cdf462088d13 333 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
markrad 0:cdf462088d13 334 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
markrad 0:cdf462088d13 335 MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
markrad 0:cdf462088d13 336
markrad 0:cdf462088d13 337 /*
markrad 0:cdf462088d13 338 * SubjectPublicKeyInfo
markrad 0:cdf462088d13 339 */
markrad 0:cdf462088d13 340 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key,
markrad 0:cdf462088d13 341 tmp_buf, c - tmp_buf ) );
markrad 0:cdf462088d13 342 c -= pub_len;
markrad 0:cdf462088d13 343 len += pub_len;
markrad 0:cdf462088d13 344
markrad 0:cdf462088d13 345 /*
markrad 0:cdf462088d13 346 * Subject ::= Name
markrad 0:cdf462088d13 347 */
markrad 0:cdf462088d13 348 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) );
markrad 0:cdf462088d13 349
markrad 0:cdf462088d13 350 /*
markrad 0:cdf462088d13 351 * Validity ::= SEQUENCE {
markrad 0:cdf462088d13 352 * notBefore Time,
markrad 0:cdf462088d13 353 * notAfter Time }
markrad 0:cdf462088d13 354 */
markrad 0:cdf462088d13 355 sub_len = 0;
markrad 0:cdf462088d13 356
markrad 0:cdf462088d13 357 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
markrad 0:cdf462088d13 358 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
markrad 0:cdf462088d13 359
markrad 0:cdf462088d13 360 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
markrad 0:cdf462088d13 361 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
markrad 0:cdf462088d13 362
markrad 0:cdf462088d13 363 len += sub_len;
markrad 0:cdf462088d13 364 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
markrad 0:cdf462088d13 365 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
markrad 0:cdf462088d13 366 MBEDTLS_ASN1_SEQUENCE ) );
markrad 0:cdf462088d13 367
markrad 0:cdf462088d13 368 /*
markrad 0:cdf462088d13 369 * Issuer ::= Name
markrad 0:cdf462088d13 370 */
markrad 0:cdf462088d13 371 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) );
markrad 0:cdf462088d13 372
markrad 0:cdf462088d13 373 /*
markrad 0:cdf462088d13 374 * Signature ::= AlgorithmIdentifier
markrad 0:cdf462088d13 375 */
markrad 0:cdf462088d13 376 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf,
markrad 0:cdf462088d13 377 sig_oid, strlen( sig_oid ), 0 ) );
markrad 0:cdf462088d13 378
markrad 0:cdf462088d13 379 /*
markrad 0:cdf462088d13 380 * Serial ::= INTEGER
markrad 0:cdf462088d13 381 */
markrad 0:cdf462088d13 382 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
markrad 0:cdf462088d13 383
markrad 0:cdf462088d13 384 /*
markrad 0:cdf462088d13 385 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
markrad 0:cdf462088d13 386 */
markrad 0:cdf462088d13 387 sub_len = 0;
markrad 0:cdf462088d13 388 MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) );
markrad 0:cdf462088d13 389 len += sub_len;
markrad 0:cdf462088d13 390 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
markrad 0:cdf462088d13 391 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
markrad 0:cdf462088d13 392 MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
markrad 0:cdf462088d13 393
markrad 0:cdf462088d13 394 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
markrad 0:cdf462088d13 395 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
markrad 0:cdf462088d13 396 MBEDTLS_ASN1_SEQUENCE ) );
markrad 0:cdf462088d13 397
markrad 0:cdf462088d13 398 /*
markrad 0:cdf462088d13 399 * Make signature
markrad 0:cdf462088d13 400 */
markrad 0:cdf462088d13 401 mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
markrad 0:cdf462088d13 402
markrad 0:cdf462088d13 403 if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
markrad 0:cdf462088d13 404 f_rng, p_rng ) ) != 0 )
markrad 0:cdf462088d13 405 {
markrad 0:cdf462088d13 406 return( ret );
markrad 0:cdf462088d13 407 }
markrad 0:cdf462088d13 408
markrad 0:cdf462088d13 409 /*
markrad 0:cdf462088d13 410 * Write data to output buffer
markrad 0:cdf462088d13 411 */
markrad 0:cdf462088d13 412 c2 = buf + size;
markrad 0:cdf462088d13 413 MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
markrad 0:cdf462088d13 414 sig_oid, sig_oid_len, sig, sig_len ) );
markrad 0:cdf462088d13 415
markrad 0:cdf462088d13 416 if( len > (size_t)( c2 - buf ) )
markrad 0:cdf462088d13 417 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
markrad 0:cdf462088d13 418
markrad 0:cdf462088d13 419 c2 -= len;
markrad 0:cdf462088d13 420 memcpy( c2, c, len );
markrad 0:cdf462088d13 421
markrad 0:cdf462088d13 422 len += sig_and_oid_len;
markrad 0:cdf462088d13 423 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
markrad 0:cdf462088d13 424 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED |
markrad 0:cdf462088d13 425 MBEDTLS_ASN1_SEQUENCE ) );
markrad 0:cdf462088d13 426
markrad 0:cdf462088d13 427 return( (int) len );
markrad 0:cdf462088d13 428 }
markrad 0:cdf462088d13 429
markrad 0:cdf462088d13 430 #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
markrad 0:cdf462088d13 431 #define PEM_END_CRT "-----END CERTIFICATE-----\n"
markrad 0:cdf462088d13 432
markrad 0:cdf462088d13 433 #if defined(MBEDTLS_PEM_WRITE_C)
markrad 0:cdf462088d13 434 int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size,
markrad 0:cdf462088d13 435 int (*f_rng)(void *, unsigned char *, size_t),
markrad 0:cdf462088d13 436 void *p_rng )
markrad 0:cdf462088d13 437 {
markrad 0:cdf462088d13 438 int ret;
markrad 0:cdf462088d13 439 unsigned char output_buf[4096];
markrad 0:cdf462088d13 440 size_t olen = 0;
markrad 0:cdf462088d13 441
markrad 0:cdf462088d13 442 if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf),
markrad 0:cdf462088d13 443 f_rng, p_rng ) ) < 0 )
markrad 0:cdf462088d13 444 {
markrad 0:cdf462088d13 445 return( ret );
markrad 0:cdf462088d13 446 }
markrad 0:cdf462088d13 447
markrad 0:cdf462088d13 448 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
markrad 0:cdf462088d13 449 output_buf + sizeof(output_buf) - ret,
markrad 0:cdf462088d13 450 ret, buf, size, &olen ) ) != 0 )
markrad 0:cdf462088d13 451 {
markrad 0:cdf462088d13 452 return( ret );
markrad 0:cdf462088d13 453 }
markrad 0:cdf462088d13 454
markrad 0:cdf462088d13 455 return( 0 );
markrad 0:cdf462088d13 456 }
markrad 0:cdf462088d13 457 #endif /* MBEDTLS_PEM_WRITE_C */
markrad 0:cdf462088d13 458
markrad 0:cdf462088d13 459 #endif /* MBEDTLS_X509_CRT_WRITE_C */