Marco Zecchini
/
Example_RTOS
Rtos API example
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 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 *t, 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( t[0] == '2' && t[1] == '0' && t[2] < '5' ) 00276 { 00277 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 00278 (const unsigned char *) t + 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 *) t, 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 if( len > (size_t)( c2 - buf ) ) 00417 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 00418 00419 c2 -= len; 00420 memcpy( c2, c, len ); 00421 00422 len += sig_and_oid_len; 00423 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); 00424 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | 00425 MBEDTLS_ASN1_SEQUENCE ) ); 00426 00427 return( (int) len ); 00428 } 00429 00430 #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" 00431 #define PEM_END_CRT "-----END CERTIFICATE-----\n" 00432 00433 #if defined(MBEDTLS_PEM_WRITE_C) 00434 int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, 00435 int (*f_rng)(void *, unsigned char *, size_t), 00436 void *p_rng ) 00437 { 00438 int ret; 00439 unsigned char output_buf[4096]; 00440 size_t olen = 0; 00441 00442 if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf), 00443 f_rng, p_rng ) ) < 0 ) 00444 { 00445 return( ret ); 00446 } 00447 00448 if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, 00449 output_buf + sizeof(output_buf) - ret, 00450 ret, buf, size, &olen ) ) != 0 ) 00451 { 00452 return( ret ); 00453 } 00454 00455 return( 0 ); 00456 } 00457 #endif /* MBEDTLS_PEM_WRITE_C */ 00458 00459 #endif /* MBEDTLS_X509_CRT_WRITE_C */
Generated on Sun Jul 17 2022 08:25:33 by 1.7.2