Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers x509write_crt.c Source File

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 */