BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
x509write_crt.c
00001 /* 00002 * X.509 certificate writing 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 /* 00022 * References: 00023 * - certificates: RFC 5280, updated by RFC 6818 00024 * - CSRs: PKCS#10 v1.7 aka RFC 2986 00025 * - attributes: PKCS#9 v2.0 aka RFC 2985 00026 */ 00027 00028 #if !defined(MBEDTLS_CONFIG_FILE) 00029 #include "mbedtls/config.h" 00030 #else 00031 #include MBEDTLS_CONFIG_FILE 00032 #endif 00033 00034 #if defined(MBEDTLS_X509_CRT_WRITE_C) 00035 00036 #include "mbedtls/x509_crt.h" 00037 #include "mbedtls/oid.h" 00038 #include "mbedtls/asn1write.h" 00039 #include "mbedtls/sha1.h" 00040 00041 #include <string.h> 00042 00043 #if defined(MBEDTLS_PEM_WRITE_C) 00044 #include "mbedtls/pem.h" 00045 #endif /* MBEDTLS_PEM_WRITE_C */ 00046 00047 /* Implementation that should never be optimized out by the compiler */ 00048 static void mbedtls_zeroize( void *v, size_t n ) { 00049 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 00050 } 00051 00052 void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) 00053 { 00054 memset( ctx, 0, sizeof( mbedtls_x509write_cert ) ); 00055 00056 mbedtls_mpi_init( &ctx->serial ); 00057 ctx->version = MBEDTLS_X509_CRT_VERSION_3; 00058 } 00059 00060 void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) 00061 { 00062 mbedtls_mpi_free( &ctx->serial ); 00063 00064 mbedtls_asn1_free_named_data_list( &ctx->subject ); 00065 mbedtls_asn1_free_named_data_list( &ctx->issuer ); 00066 mbedtls_asn1_free_named_data_list( &ctx->extensions ); 00067 00068 mbedtls_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); 00069 } 00070 00071 void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ) 00072 { 00073 ctx->version = version; 00074 } 00075 00076 void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ) 00077 { 00078 ctx->md_alg = md_alg; 00079 } 00080 00081 void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) 00082 { 00083 ctx->subject_key = key; 00084 } 00085 00086 void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) 00087 { 00088 ctx->issuer_key = key; 00089 } 00090 00091 int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, 00092 const char *subject_name ) 00093 { 00094 return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); 00095 } 00096 00097 int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, 00098 const char *issuer_name ) 00099 { 00100 return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); 00101 } 00102 00103 int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ) 00104 { 00105 int ret; 00106 00107 if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 ) 00108 return( ret ); 00109 00110 return( 0 ); 00111 } 00112 00113 int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, 00114 const char *not_after ) 00115 { 00116 if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || 00117 strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) 00118 { 00119 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); 00120 } 00121 strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); 00122 strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); 00123 ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; 00124 ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; 00125 00126 return( 0 ); 00127 } 00128 00129 int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, 00130 const char *oid, size_t oid_len, 00131 int critical, 00132 const unsigned char *val, size_t val_len ) 00133 { 00134 return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, 00135 critical, val, val_len ); 00136 } 00137 00138 int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, 00139 int is_ca, int max_pathlen ) 00140 { 00141 int ret; 00142 unsigned char buf[9]; 00143 unsigned char *c = buf + sizeof(buf); 00144 size_t len = 0; 00145 00146 memset( buf, 0, sizeof(buf) ); 00147 00148 if( is_ca && max_pathlen > 127 ) 00149 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); 00150 00151 if( is_ca ) 00152 { 00153 if( max_pathlen >= 0 ) 00154 { 00155 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) ); 00156 } 00157 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); 00158 } 00159 00160 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 00161 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | 00162 MBEDTLS_ASN1_SEQUENCE ) ); 00163 00164 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, 00165 MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), 00166 0, buf + sizeof(buf) - len, len ); 00167 } 00168 00169 #if defined(MBEDTLS_SHA1_C) 00170 int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ) 00171 { 00172 int ret; 00173 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ 00174 unsigned char *c = buf + sizeof(buf); 00175 size_t len = 0; 00176 00177 memset( buf, 0, sizeof(buf) ); 00178 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); 00179 00180 ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, 00181 buf + sizeof( buf ) - 20 ); 00182 if( ret != 0 ) 00183 return( ret ); 00184 c = buf + sizeof( buf ) - 20; 00185 len = 20; 00186 00187 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 00188 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); 00189 00190 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, 00191 MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), 00192 0, buf + sizeof(buf) - len, len ); 00193 } 00194 00195 int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) 00196 { 00197 int ret; 00198 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ 00199 unsigned char *c = buf + sizeof( buf ); 00200 size_t len = 0; 00201 00202 memset( buf, 0, sizeof(buf) ); 00203 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); 00204 00205 ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, 00206 buf + sizeof( buf ) - 20 ); 00207 if( ret != 0 ) 00208 return( ret ); 00209 c = buf + sizeof( buf ) - 20; 00210 len = 20; 00211 00212 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 00213 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); 00214 00215 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 00216 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | 00217 MBEDTLS_ASN1_SEQUENCE ) ); 00218 00219 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, 00220 MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), 00221 0, buf + sizeof( buf ) - len, len ); 00222 } 00223 #endif /* MBEDTLS_SHA1_C */ 00224 00225 int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, 00226 unsigned int key_usage ) 00227 { 00228 unsigned char buf[4], ku; 00229 unsigned char *c; 00230 int ret; 00231 00232 /* We currently only support 7 bits, from 0x80 to 0x02 */ 00233 if( ( key_usage & ~0xfe ) != 0 ) 00234 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); 00235 00236 c = buf + 4; 00237 ku = (unsigned char) key_usage; 00238 00239 if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 ) 00240 return( ret ); 00241 00242 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, 00243 MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), 00244 1, buf, 4 ); 00245 if( ret != 0 ) 00246 return( ret ); 00247 00248 return( 0 ); 00249 } 00250 00251 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, 00252 unsigned char ns_cert_type ) 00253 { 00254 unsigned char buf[4]; 00255 unsigned char *c; 00256 int ret; 00257 00258 c = buf + 4; 00259 00260 if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) 00261 return( ret ); 00262 00263 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, 00264 MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), 00265 0, buf, 4 ); 00266 if( ret != 0 ) 00267 return( ret ); 00268 00269 return( 0 ); 00270 } 00271 00272 static int x509_write_time( unsigned char **p, unsigned char *start, 00273 const char *t, size_t size ) 00274 { 00275 int ret; 00276 size_t len = 0; 00277 00278 /* 00279 * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) 00280 */ 00281 if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) 00282 { 00283 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 00284 (const unsigned char *) t + 2, 00285 size - 2 ) ); 00286 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 00287 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); 00288 } 00289 else 00290 { 00291 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 00292 (const unsigned char *) t, 00293 size ) ); 00294 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 00295 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); 00296 } 00297 00298 return( (int) len ); 00299 } 00300 00301 int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, 00302 int (*f_rng)(void *, unsigned char *, size_t), 00303 void *p_rng ) 00304 { 00305 int ret; 00306 const char *sig_oid; 00307 size_t sig_oid_len = 0; 00308 unsigned char *c, *c2; 00309 unsigned char hash[64]; 00310 unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; 00311 unsigned char tmp_buf[2048]; 00312 size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; 00313 size_t len = 0; 00314 mbedtls_pk_type_t pk_alg; 00315 00316 /* 00317 * Prepare data to be signed in tmp_buf 00318 */ 00319 c = tmp_buf + sizeof( tmp_buf ); 00320 00321 /* Signature algorithm needed in TBS, and later for actual signature */ 00322 00323 /* There's no direct way of extracting a signature algorithm 00324 * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ 00325 if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) ) 00326 pk_alg = MBEDTLS_PK_RSA; 00327 else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) ) 00328 pk_alg = MBEDTLS_PK_ECDSA; 00329 else 00330 return( MBEDTLS_ERR_X509_INVALID_ALG ); 00331 00332 if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, 00333 &sig_oid, &sig_oid_len ) ) != 0 ) 00334 { 00335 return( ret ); 00336 } 00337 00338 /* 00339 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 00340 */ 00341 00342 /* Only for v3 */ 00343 if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 ) 00344 { 00345 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); 00346 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 00347 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 00348 MBEDTLS_ASN1_SEQUENCE ) ); 00349 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 00350 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 00351 MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); 00352 } 00353 00354 /* 00355 * SubjectPublicKeyInfo 00356 */ 00357 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key, 00358 tmp_buf, c - tmp_buf ) ); 00359 c -= pub_len; 00360 len += pub_len; 00361 00362 /* 00363 * Subject ::= Name 00364 */ 00365 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); 00366 00367 /* 00368 * Validity ::= SEQUENCE { 00369 * notBefore Time, 00370 * notAfter Time } 00371 */ 00372 sub_len = 0; 00373 00374 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, 00375 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); 00376 00377 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, 00378 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); 00379 00380 len += sub_len; 00381 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); 00382 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 00383 MBEDTLS_ASN1_SEQUENCE ) ); 00384 00385 /* 00386 * Issuer ::= Name 00387 */ 00388 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) ); 00389 00390 /* 00391 * Signature ::= AlgorithmIdentifier 00392 */ 00393 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf, 00394 sig_oid, strlen( sig_oid ), 0 ) ); 00395 00396 /* 00397 * Serial ::= INTEGER 00398 */ 00399 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); 00400 00401 /* 00402 * Version ::= INTEGER { v1(0), v2(1), v3(2) } 00403 */ 00404 00405 /* Can be omitted for v1 */ 00406 if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 ) 00407 { 00408 sub_len = 0; 00409 MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) ); 00410 len += sub_len; 00411 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); 00412 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 00413 MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); 00414 } 00415 00416 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 00417 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 00418 MBEDTLS_ASN1_SEQUENCE ) ); 00419 00420 /* 00421 * Make signature 00422 */ 00423 if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, 00424 len, hash ) ) != 0 ) 00425 { 00426 return( ret ); 00427 } 00428 00429 if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, 00430 f_rng, p_rng ) ) != 0 ) 00431 { 00432 return( ret ); 00433 } 00434 00435 /* 00436 * Write data to output buffer 00437 */ 00438 c2 = buf + size; 00439 MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, 00440 sig_oid, sig_oid_len, sig, sig_len ) ); 00441 00442 if( len > (size_t)( c2 - buf ) ) 00443 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 00444 00445 c2 -= len; 00446 memcpy( c2, c, len ); 00447 00448 len += sig_and_oid_len; 00449 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); 00450 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | 00451 MBEDTLS_ASN1_SEQUENCE ) ); 00452 00453 return( (int) len ); 00454 } 00455 00456 #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" 00457 #define PEM_END_CRT "-----END CERTIFICATE-----\n" 00458 00459 #if defined(MBEDTLS_PEM_WRITE_C) 00460 int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, 00461 int (*f_rng)(void *, unsigned char *, size_t), 00462 void *p_rng ) 00463 { 00464 int ret; 00465 unsigned char output_buf[4096]; 00466 size_t olen = 0; 00467 00468 if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf), 00469 f_rng, p_rng ) ) < 0 ) 00470 { 00471 return( ret ); 00472 } 00473 00474 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, 00475 output_buf + sizeof(output_buf) - ret, 00476 ret, buf, size, &olen ) ) != 0 ) 00477 { 00478 return( ret ); 00479 } 00480 00481 return( 0 ); 00482 } 00483 #endif /* MBEDTLS_PEM_WRITE_C */ 00484 00485 #endif /* MBEDTLS_X509_CRT_WRITE_C */
Generated on Tue Jul 12 2022 12:22:29 by
