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 OmniWheels 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 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 Fri Jul 22 2022 04:54:05 by
1.7.2
