RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
Parent:
0:38ceb79fef03
2019-03-13

Who changed what in which revision?

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