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.
Fork of mbedtls by
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 mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); 00181 c = buf + sizeof(buf) - 20; 00182 len = 20; 00183 00184 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 00185 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); 00186 00187 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, 00188 MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), 00189 0, buf + sizeof(buf) - len, len ); 00190 } 00191 00192 int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) 00193 { 00194 int ret; 00195 unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ 00196 unsigned char *c = buf + sizeof(buf); 00197 size_t len = 0; 00198 00199 memset( buf, 0, sizeof(buf) ); 00200 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); 00201 00202 mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); 00203 c = buf + sizeof(buf) - 20; 00204 len = 20; 00205 00206 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 00207 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); 00208 00209 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); 00210 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | 00211 MBEDTLS_ASN1_SEQUENCE ) ); 00212 00213 return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, 00214 MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), 00215 0, buf + sizeof(buf) - len, len ); 00216 } 00217 #endif /* MBEDTLS_SHA1_C */ 00218 00219 int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, 00220 unsigned int key_usage ) 00221 { 00222 unsigned char buf[4], ku; 00223 unsigned char *c; 00224 int ret; 00225 00226 /* We currently only support 7 bits, from 0x80 to 0x02 */ 00227 if( ( key_usage & ~0xfe ) != 0 ) 00228 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); 00229 00230 c = buf + 4; 00231 ku = (unsigned char) key_usage; 00232 00233 if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 ) 00234 return( ret ); 00235 00236 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, 00237 MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), 00238 1, buf, 4 ); 00239 if( ret != 0 ) 00240 return( ret ); 00241 00242 return( 0 ); 00243 } 00244 00245 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, 00246 unsigned char ns_cert_type ) 00247 { 00248 unsigned char buf[4]; 00249 unsigned char *c; 00250 int ret; 00251 00252 c = buf + 4; 00253 00254 if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) 00255 return( ret ); 00256 00257 ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, 00258 MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), 00259 0, buf, 4 ); 00260 if( ret != 0 ) 00261 return( ret ); 00262 00263 return( 0 ); 00264 } 00265 00266 static int x509_write_time( unsigned char **p, unsigned char *start, 00267 const char *time, size_t size ) 00268 { 00269 int ret; 00270 size_t len = 0; 00271 00272 /* 00273 * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) 00274 */ 00275 if( time[0] == '2' && time[1] == '0' && time [2] < '5' ) 00276 { 00277 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 00278 (const unsigned char *) time + 2, 00279 size - 2 ) ); 00280 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 00281 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); 00282 } 00283 else 00284 { 00285 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 00286 (const unsigned char *) time, 00287 size ) ); 00288 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 00289 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); 00290 } 00291 00292 return( (int) len ); 00293 } 00294 00295 int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, 00296 int (*f_rng)(void *, unsigned char *, size_t), 00297 void *p_rng ) 00298 { 00299 int ret; 00300 const char *sig_oid; 00301 size_t sig_oid_len = 0; 00302 unsigned char *c, *c2; 00303 unsigned char hash[64]; 00304 unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; 00305 unsigned char tmp_buf[2048]; 00306 size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; 00307 size_t len = 0; 00308 mbedtls_pk_type_t pk_alg; 00309 00310 /* 00311 * Prepare data to be signed in tmp_buf 00312 */ 00313 c = tmp_buf + sizeof( tmp_buf ); 00314 00315 /* Signature algorithm needed in TBS, and later for actual signature */ 00316 pk_alg = mbedtls_pk_get_type( ctx->issuer_key ); 00317 if( pk_alg == MBEDTLS_PK_ECKEY ) 00318 pk_alg = MBEDTLS_PK_ECDSA; 00319 00320 if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, 00321 &sig_oid, &sig_oid_len ) ) != 0 ) 00322 { 00323 return( ret ); 00324 } 00325 00326 /* 00327 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 00328 */ 00329 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); 00330 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 00331 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 00332 MBEDTLS_ASN1_SEQUENCE ) ); 00333 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 00334 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 00335 MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); 00336 00337 /* 00338 * SubjectPublicKeyInfo 00339 */ 00340 MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key, 00341 tmp_buf, c - tmp_buf ) ); 00342 c -= pub_len; 00343 len += pub_len; 00344 00345 /* 00346 * Subject ::= Name 00347 */ 00348 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); 00349 00350 /* 00351 * Validity ::= SEQUENCE { 00352 * notBefore Time, 00353 * notAfter Time } 00354 */ 00355 sub_len = 0; 00356 00357 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, 00358 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); 00359 00360 MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, 00361 MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); 00362 00363 len += sub_len; 00364 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); 00365 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 00366 MBEDTLS_ASN1_SEQUENCE ) ); 00367 00368 /* 00369 * Issuer ::= Name 00370 */ 00371 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) ); 00372 00373 /* 00374 * Signature ::= AlgorithmIdentifier 00375 */ 00376 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf, 00377 sig_oid, strlen( sig_oid ), 0 ) ); 00378 00379 /* 00380 * Serial ::= INTEGER 00381 */ 00382 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); 00383 00384 /* 00385 * Version ::= INTEGER { v1(0), v2(1), v3(2) } 00386 */ 00387 sub_len = 0; 00388 MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) ); 00389 len += sub_len; 00390 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); 00391 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 00392 MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); 00393 00394 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); 00395 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | 00396 MBEDTLS_ASN1_SEQUENCE ) ); 00397 00398 /* 00399 * Make signature 00400 */ 00401 mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); 00402 00403 if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, 00404 f_rng, p_rng ) ) != 0 ) 00405 { 00406 return( ret ); 00407 } 00408 00409 /* 00410 * Write data to output buffer 00411 */ 00412 c2 = buf + size; 00413 MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, 00414 sig_oid, sig_oid_len, sig, sig_len ) ); 00415 00416 c2 -= len; 00417 memcpy( c2, c, len ); 00418 00419 len += sig_and_oid_len; 00420 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); 00421 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | 00422 MBEDTLS_ASN1_SEQUENCE ) ); 00423 00424 return( (int) len ); 00425 } 00426 00427 #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" 00428 #define PEM_END_CRT "-----END CERTIFICATE-----\n" 00429 00430 #if defined(MBEDTLS_PEM_WRITE_C) 00431 int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, 00432 int (*f_rng)(void *, unsigned char *, size_t), 00433 void *p_rng ) 00434 { 00435 int ret; 00436 unsigned char output_buf[4096]; 00437 size_t olen = 0; 00438 00439 if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf), 00440 f_rng, p_rng ) ) < 0 ) 00441 { 00442 return( ret ); 00443 } 00444 00445 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, 00446 output_buf + sizeof(output_buf) - ret, 00447 ret, buf, size, &olen ) ) != 0 ) 00448 { 00449 return( ret ); 00450 } 00451 00452 return( 0 ); 00453 } 00454 #endif /* MBEDTLS_PEM_WRITE_C */ 00455 00456 #endif /* MBEDTLS_X509_CRT_WRITE_C */
Generated on Tue Jul 12 2022 12:52:50 by
