Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 #include "mbedtls/platform_util.h" 00041 00042 #include <string.h> 00043 00044 #if defined(MBEDTLS_PEM_WRITE_C) 00045 #include "mbedtls/pem.h" 00046 #endif /* MBEDTLS_PEM_WRITE_C */ 00047 00048 void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) 00049 { 00050 memset( ctx, 0, sizeof( mbedtls_x509write_cert ) ); 00051 00052 mbedtls_mpi_init( &ctx->serial ); 00053 ctx->version = MBEDTLS_X509_CRT_VERSION_3; 00054 } 00055 00056 void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) 00057 { 00058 mbedtls_mpi_free( &ctx->serial ); 00059 00060 mbedtls_asn1_free_named_data_list( &ctx->subject ); 00061 mbedtls_asn1_free_named_data_list( &ctx->issuer ); 00062 mbedtls_asn1_free_named_data_list( &ctx->extensions ); 00063 00064 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); 00065 } 00066 00067 void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ) 00068 { 00069 ctx->version = version; 00070 } 00071 00072 void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ) 00073 { 00074 ctx->md_alg = md_alg; 00075 } 00076 00077 void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) 00078 { 00079 ctx->subject_key = key; 00080 } 00081 00082 void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) 00083 { 00084 ctx->issuer_key = key; 00085 } 00086 00087 int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, 00088 const char *subject_name ) 00089 { 00090 return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); 00091 } 00092 00093 int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, 00094 const char *issuer_name ) 00095 { 00096 return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); 00097 } 00098 00099 int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ) 00100 { 00101 int ret; 00102 00103 if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 ) 00104 return( ret ); 00105 00106 return( 0 ); 00107 } 00108 00109 int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, 00110 const char *not_after ) 00111 { 00112 if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || 00113 strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) 00114 { 00115 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); 00116 } 00117 strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); 00118 strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); 00119 ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; 00120 ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; 00121 00122 return( 0 ); 00123 } 00124 00125 int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, 00126 const char *oid, size_t oid_len, 00127 int critical, 00128 const unsigned char *val, size_t val_len ) 00129 { 00130 return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, 00131 critical, val, val_len ); 00132 } 00133 00134 int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, 00135 int is_ca, int max_pathlen ) 00136 { 00137 int ret; 00138 unsigned char buf[9]; 00139 unsigned char *c = buf + sizeof(buf); 00140 size_t len = 0; 00141 00142 memset( buf, 0, sizeof(buf) ); 00143 00144 if( is_ca && max_pathlen > 127 ) 00145 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); 00146 00147 if( is_ca ) 00148 { 00149 if( max_pathlen >= 0 ) 00150 { 00151 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) ); 00152 } 00153 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); 00154 } 00155 00156 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 00157 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | 00158 MBEDTLS_ASN1_SEQUENCE ) ); 00159 00160 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, 00161 MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), 00162 0, buf + sizeof(buf) - len, len ); 00163 } 00164 00165 #if defined(MBEDTLS_SHA1_C) 00166 int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ) 00167 { 00168 int ret; 00169 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ 00170 unsigned char *c = buf + sizeof(buf); 00171 size_t len = 0; 00172 00173 memset( buf, 0, sizeof(buf) ); 00174 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); 00175 00176 ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, 00177 buf + sizeof( buf ) - 20 ); 00178 if( ret != 0 ) 00179 return( ret ); 00180 c = buf + sizeof( buf ) - 20; 00181 len = 20; 00182 00183 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 00184 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); 00185 00186 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, 00187 MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), 00188 0, buf + sizeof(buf) - len, len ); 00189 } 00190 00191 int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) 00192 { 00193 int ret; 00194 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ 00195 unsigned char *c = buf + sizeof( buf ); 00196 size_t len = 0; 00197 00198 memset( buf, 0, sizeof(buf) ); 00199 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); 00200 00201 ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, 00202 buf + sizeof( buf ) - 20 ); 00203 if( ret != 0 ) 00204 return( ret ); 00205 c = buf + sizeof( buf ) - 20; 00206 len = 20; 00207 00208 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 00209 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); 00210 00211 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 00212 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | 00213 MBEDTLS_ASN1_SEQUENCE ) ); 00214 00215 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, 00216 MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), 00217 0, buf + sizeof( buf ) - len, len ); 00218 } 00219 #endif /* MBEDTLS_SHA1_C */ 00220 00221 int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, 00222 unsigned int key_usage ) 00223 { 00224 unsigned char buf[4], ku; 00225 unsigned char *c; 00226 int ret; 00227 00228 /* We currently only support 7 bits, from 0x80 to 0x02 */ 00229 if( ( key_usage & ~0xfe ) != 0 ) 00230 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); 00231 00232 c = buf + 4; 00233 ku = (unsigned char) key_usage; 00234 00235 if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 ) 00236 return( ret ); 00237 00238 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, 00239 MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), 00240 1, buf, 4 ); 00241 if( ret != 0 ) 00242 return( ret ); 00243 00244 return( 0 ); 00245 } 00246 00247 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, 00248 unsigned char ns_cert_type ) 00249 { 00250 unsigned char buf[4]; 00251 unsigned char *c; 00252 int ret; 00253 00254 c = buf + 4; 00255 00256 if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) 00257 return( ret ); 00258 00259 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, 00260 MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), 00261 0, buf, 4 ); 00262 if( ret != 0 ) 00263 return( ret ); 00264 00265 return( 0 ); 00266 } 00267 00268 static int x509_write_time( unsigned char **p, unsigned char *start, 00269 const char *t, size_t size ) 00270 { 00271 int ret; 00272 size_t len = 0; 00273 00274 /* 00275 * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) 00276 */ 00277 if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) 00278 { 00279 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 00280 (const unsigned char *) t + 2, 00281 size - 2 ) ); 00282 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 00283 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); 00284 } 00285 else 00286 { 00287 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 00288 (const unsigned char *) t, 00289 size ) ); 00290 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 00291 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); 00292 } 00293 00294 return( (int) len ); 00295 } 00296 00297 int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, 00298 int (*f_rng)(void *, unsigned char *, size_t), 00299 void *p_rng ) 00300 { 00301 int ret; 00302 const char *sig_oid; 00303 size_t sig_oid_len = 0; 00304 unsigned char *c, *c2; 00305 unsigned char hash[64]; 00306 unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; 00307 unsigned char tmp_buf[2048]; 00308 size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; 00309 size_t len = 0; 00310 mbedtls_pk_type_t pk_alg; 00311 00312 /* 00313 * Prepare data to be signed in tmp_buf 00314 */ 00315 c = tmp_buf + sizeof( tmp_buf ); 00316 00317 /* Signature algorithm needed in TBS, and later for actual signature */ 00318 00319 /* There's no direct way of extracting a signature algorithm 00320 * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ 00321 if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) ) 00322 pk_alg = MBEDTLS_PK_RSA; 00323 else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) ) 00324 pk_alg = MBEDTLS_PK_ECDSA; 00325 else 00326 return( MBEDTLS_ERR_X509_INVALID_ALG ); 00327 00328 if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, 00329 &sig_oid, &sig_oid_len ) ) != 0 ) 00330 { 00331 return( ret ); 00332 } 00333 00334 /* 00335 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 00336 */ 00337 00338 /* Only for v3 */ 00339 if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 ) 00340 { 00341 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); 00342 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 00343 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 00344 MBEDTLS_ASN1_SEQUENCE ) ); 00345 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 00346 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 00347 MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); 00348 } 00349 00350 /* 00351 * SubjectPublicKeyInfo 00352 */ 00353 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key, 00354 tmp_buf, c - tmp_buf ) ); 00355 c -= pub_len; 00356 len += pub_len; 00357 00358 /* 00359 * Subject ::= Name 00360 */ 00361 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); 00362 00363 /* 00364 * Validity ::= SEQUENCE { 00365 * notBefore Time, 00366 * notAfter Time } 00367 */ 00368 sub_len = 0; 00369 00370 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, 00371 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); 00372 00373 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, 00374 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); 00375 00376 len += sub_len; 00377 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); 00378 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 00379 MBEDTLS_ASN1_SEQUENCE ) ); 00380 00381 /* 00382 * Issuer ::= Name 00383 */ 00384 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) ); 00385 00386 /* 00387 * Signature ::= AlgorithmIdentifier 00388 */ 00389 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf, 00390 sig_oid, strlen( sig_oid ), 0 ) ); 00391 00392 /* 00393 * Serial ::= INTEGER 00394 */ 00395 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); 00396 00397 /* 00398 * Version ::= INTEGER { v1(0), v2(1), v3(2) } 00399 */ 00400 00401 /* Can be omitted for v1 */ 00402 if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 ) 00403 { 00404 sub_len = 0; 00405 MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) ); 00406 len += sub_len; 00407 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); 00408 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 00409 MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); 00410 } 00411 00412 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 00413 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 00414 MBEDTLS_ASN1_SEQUENCE ) ); 00415 00416 /* 00417 * Make signature 00418 */ 00419 if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, 00420 len, hash ) ) != 0 ) 00421 { 00422 return( ret ); 00423 } 00424 00425 if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, 00426 f_rng, p_rng ) ) != 0 ) 00427 { 00428 return( ret ); 00429 } 00430 00431 /* 00432 * Write data to output buffer 00433 */ 00434 c2 = buf + size; 00435 MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, 00436 sig_oid, sig_oid_len, sig, sig_len ) ); 00437 00438 if( len > (size_t)( c2 - buf ) ) 00439 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 00440 00441 c2 -= len; 00442 memcpy( c2, c, len ); 00443 00444 len += sig_and_oid_len; 00445 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); 00446 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | 00447 MBEDTLS_ASN1_SEQUENCE ) ); 00448 00449 return( (int) len ); 00450 } 00451 00452 #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" 00453 #define PEM_END_CRT "-----END CERTIFICATE-----\n" 00454 00455 #if defined(MBEDTLS_PEM_WRITE_C) 00456 int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, 00457 int (*f_rng)(void *, unsigned char *, size_t), 00458 void *p_rng ) 00459 { 00460 int ret; 00461 unsigned char output_buf[4096]; 00462 size_t olen = 0; 00463 00464 if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf), 00465 f_rng, p_rng ) ) < 0 ) 00466 { 00467 return( ret ); 00468 } 00469 00470 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, 00471 output_buf + sizeof(output_buf) - ret, 00472 ret, buf, size, &olen ) ) != 0 ) 00473 { 00474 return( ret ); 00475 } 00476 00477 return( 0 ); 00478 } 00479 #endif /* MBEDTLS_PEM_WRITE_C */ 00480 00481 #endif /* MBEDTLS_X509_CRT_WRITE_C */
Generated on Tue Aug 9 2022 00:37:25 by
1.7.2