Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers x509_create.c Source File

x509_create.c

00001 /*
00002  *  X.509 base functions for creating certificates / CSRs
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 #if !defined(MBEDTLS_CONFIG_FILE)
00023 #include "mbedtls/config.h"
00024 #else
00025 #include MBEDTLS_CONFIG_FILE
00026 #endif
00027 
00028 #if defined(MBEDTLS_X509_CREATE_C)
00029 
00030 #include "mbedtls/x509.h"
00031 #include "mbedtls/asn1write.h"
00032 #include "mbedtls/oid.h"
00033 
00034 #include <string.h>
00035 
00036 typedef struct {
00037     const char *name;
00038     size_t name_len;
00039     const char*oid;
00040 } x509_attr_descriptor_t;
00041 
00042 #define ADD_STRLEN( s )     s, sizeof( s ) - 1
00043 
00044 static const x509_attr_descriptor_t x509_attrs[] =
00045 {
00046     { ADD_STRLEN( "CN" ),                       MBEDTLS_OID_AT_CN },
00047     { ADD_STRLEN( "commonName" ),               MBEDTLS_OID_AT_CN },
00048     { ADD_STRLEN( "C" ),                        MBEDTLS_OID_AT_COUNTRY },
00049     { ADD_STRLEN( "countryName" ),              MBEDTLS_OID_AT_COUNTRY },
00050     { ADD_STRLEN( "O" ),                        MBEDTLS_OID_AT_ORGANIZATION },
00051     { ADD_STRLEN( "organizationName" ),         MBEDTLS_OID_AT_ORGANIZATION },
00052     { ADD_STRLEN( "L" ),                        MBEDTLS_OID_AT_LOCALITY },
00053     { ADD_STRLEN( "locality" ),                 MBEDTLS_OID_AT_LOCALITY },
00054     { ADD_STRLEN( "R" ),                        MBEDTLS_OID_PKCS9_EMAIL },
00055     { ADD_STRLEN( "OU" ),                       MBEDTLS_OID_AT_ORG_UNIT },
00056     { ADD_STRLEN( "organizationalUnitName" ),   MBEDTLS_OID_AT_ORG_UNIT },
00057     { ADD_STRLEN( "ST" ),                       MBEDTLS_OID_AT_STATE },
00058     { ADD_STRLEN( "stateOrProvinceName" ),      MBEDTLS_OID_AT_STATE },
00059     { ADD_STRLEN( "emailAddress" ),             MBEDTLS_OID_PKCS9_EMAIL },
00060     { ADD_STRLEN( "serialNumber" ),             MBEDTLS_OID_AT_SERIAL_NUMBER },
00061     { ADD_STRLEN( "postalAddress" ),            MBEDTLS_OID_AT_POSTAL_ADDRESS },
00062     { ADD_STRLEN( "postalCode" ),               MBEDTLS_OID_AT_POSTAL_CODE },
00063     { ADD_STRLEN( "dnQualifier" ),              MBEDTLS_OID_AT_DN_QUALIFIER },
00064     { ADD_STRLEN( "title" ),                    MBEDTLS_OID_AT_TITLE },
00065     { ADD_STRLEN( "surName" ),                  MBEDTLS_OID_AT_SUR_NAME },
00066     { ADD_STRLEN( "SN" ),                       MBEDTLS_OID_AT_SUR_NAME },
00067     { ADD_STRLEN( "givenName" ),                MBEDTLS_OID_AT_GIVEN_NAME },
00068     { ADD_STRLEN( "GN" ),                       MBEDTLS_OID_AT_GIVEN_NAME },
00069     { ADD_STRLEN( "initials" ),                 MBEDTLS_OID_AT_INITIALS },
00070     { ADD_STRLEN( "pseudonym" ),                MBEDTLS_OID_AT_PSEUDONYM },
00071     { ADD_STRLEN( "generationQualifier" ),      MBEDTLS_OID_AT_GENERATION_QUALIFIER },
00072     { ADD_STRLEN( "domainComponent" ),          MBEDTLS_OID_DOMAIN_COMPONENT },
00073     { ADD_STRLEN( "DC" ),                       MBEDTLS_OID_DOMAIN_COMPONENT },
00074     { NULL, 0, NULL }
00075 };
00076 
00077 static const char *x509_at_oid_from_name( const char *name, size_t name_len )
00078 {
00079     const x509_attr_descriptor_t *cur;
00080 
00081     for( cur = x509_attrs; cur->name != NULL; cur++ )
00082         if( cur->name_len == name_len &&
00083             strncmp( cur->name, name, name_len ) == 0 )
00084             break;
00085 
00086     return( cur->oid );
00087 }
00088 
00089 int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name )
00090 {
00091     int ret = 0;
00092     const char *s = name, *c = s;
00093     const char *end = s + strlen( s );
00094     const char *oid = NULL;
00095     int in_tag = 1;
00096     char data[MBEDTLS_X509_MAX_DN_NAME_SIZE];
00097     char *d = data;
00098 
00099     /* Clear existing chain if present */
00100     mbedtls_asn1_free_named_data_list( head );
00101 
00102     while( c <= end )
00103     {
00104         if( in_tag && *c == '=' )
00105         {
00106             if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL )
00107             {
00108                 ret = MBEDTLS_ERR_X509_UNKNOWN_OID;
00109                 goto exit;
00110             }
00111 
00112             s = c + 1;
00113             in_tag = 0;
00114             d = data;
00115         }
00116 
00117         if( !in_tag && *c == '\\' && c != end )
00118         {
00119             c++;
00120 
00121             /* Check for valid escaped characters */
00122             if( c == end || *c != ',' )
00123             {
00124                 ret = MBEDTLS_ERR_X509_INVALID_NAME;
00125                 goto exit;
00126             }
00127         }
00128         else if( !in_tag && ( *c == ',' || c == end ) )
00129         {
00130             if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ),
00131                                        (unsigned char *) data,
00132                                        d - data ) == NULL )
00133             {
00134                 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
00135             }
00136 
00137             while( c < end && *(c + 1) == ' ' )
00138                 c++;
00139 
00140             s = c + 1;
00141             in_tag = 1;
00142         }
00143 
00144         if( !in_tag && s != c + 1 )
00145         {
00146             *(d++) = *c;
00147 
00148             if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE )
00149             {
00150                 ret = MBEDTLS_ERR_X509_INVALID_NAME;
00151                 goto exit;
00152             }
00153         }
00154 
00155         c++;
00156     }
00157 
00158 exit:
00159 
00160     return( ret );
00161 }
00162 
00163 /* The first byte of the value in the mbedtls_asn1_named_data structure is reserved
00164  * to store the critical boolean for us
00165  */
00166 int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
00167                         int critical, const unsigned char *val, size_t val_len )
00168 {
00169     mbedtls_asn1_named_data *cur;
00170 
00171     if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len,
00172                                        NULL, val_len + 1 ) ) == NULL )
00173     {
00174         return( MBEDTLS_ERR_X509_ALLOC_FAILED );
00175     }
00176 
00177     cur->val.p[0] = critical;
00178     memcpy( cur->val.p + 1, val, val_len );
00179 
00180     return( 0 );
00181 }
00182 
00183 /*
00184  *  RelativeDistinguishedName ::=
00185  *    SET OF AttributeTypeAndValue
00186  *
00187  *  AttributeTypeAndValue ::= SEQUENCE {
00188  *    type     AttributeType,
00189  *    value    AttributeValue }
00190  *
00191  *  AttributeType ::= OBJECT IDENTIFIER
00192  *
00193  *  AttributeValue ::= ANY DEFINED BY AttributeType
00194  */
00195 static int x509_write_name( unsigned char **p, unsigned char *start,
00196                             const char *oid, size_t oid_len,
00197                             const unsigned char *name, size_t name_len )
00198 {
00199     int ret;
00200     size_t len = 0;
00201 
00202     // Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL
00203     //
00204     if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len &&
00205         memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 )
00206     {
00207         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start,
00208                                                   (const char *) name,
00209                                                   name_len ) );
00210     }
00211     else
00212     {
00213         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start,
00214                                                         (const char *) name,
00215                                                         name_len ) );
00216     }
00217 
00218     // Write OID
00219     //
00220     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
00221 
00222     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00223     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
00224                                                  MBEDTLS_ASN1_SEQUENCE ) );
00225 
00226     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00227     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
00228                                                  MBEDTLS_ASN1_SET ) );
00229 
00230     return( (int) len );
00231 }
00232 
00233 int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
00234                       mbedtls_asn1_named_data *first )
00235 {
00236     int ret;
00237     size_t len = 0;
00238     mbedtls_asn1_named_data *cur = first;
00239 
00240     while( cur != NULL )
00241     {
00242         MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
00243                                             cur->oid.len,
00244                                             cur->val.p, cur->val.len ) );
00245         cur = cur->next;
00246     }
00247 
00248     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00249     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
00250                                                  MBEDTLS_ASN1_SEQUENCE ) );
00251 
00252     return( (int) len );
00253 }
00254 
00255 int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,
00256                     const char *oid, size_t oid_len,
00257                     unsigned char *sig, size_t size )
00258 {
00259     int ret;
00260     size_t len = 0;
00261 
00262     if( *p < start || (size_t)( *p - start ) < size )
00263         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00264 
00265     len = size;
00266     (*p) -= len;
00267     memcpy( *p, sig, len );
00268 
00269     if( *p - start < 1 )
00270         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00271 
00272     *--(*p) = 0;
00273     len += 1;
00274 
00275     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00276     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
00277 
00278     // Write OID
00279     //
00280     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid,
00281                                                         oid_len, 0 ) );
00282 
00283     return( (int) len );
00284 }
00285 
00286 static int x509_write_extension( unsigned char **p, unsigned char *start,
00287                                  mbedtls_asn1_named_data *ext )
00288 {
00289     int ret;
00290     size_t len = 0;
00291 
00292     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1,
00293                                               ext->val.len - 1 ) );
00294     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) );
00295     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
00296 
00297     if( ext->val.p[0] != 0 )
00298     {
00299         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) );
00300     }
00301 
00302     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p,
00303                                               ext->oid.len ) );
00304     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) );
00305     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );
00306 
00307     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00308     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
00309                                                  MBEDTLS_ASN1_SEQUENCE ) );
00310 
00311     return( (int) len );
00312 }
00313 
00314 /*
00315  * Extension  ::=  SEQUENCE  {
00316  *     extnID      OBJECT IDENTIFIER,
00317  *     critical    BOOLEAN DEFAULT FALSE,
00318  *     extnValue   OCTET STRING
00319  *                 -- contains the DER encoding of an ASN.1 value
00320  *                 -- corresponding to the extension type identified
00321  *                 -- by extnID
00322  *     }
00323  */
00324 int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,
00325                            mbedtls_asn1_named_data *first )
00326 {
00327     int ret;
00328     size_t len = 0;
00329     mbedtls_asn1_named_data *cur_ext = first;
00330 
00331     while( cur_ext != NULL )
00332     {
00333         MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
00334         cur_ext = cur_ext->next;
00335     }
00336 
00337     return( (int) len );
00338 }
00339 
00340 #endif /* MBEDTLS_X509_CREATE_C */