mbedtls ported to mbed-classic

Fork of mbedtls by Christopher Haster

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers x509_csr.c Source File

x509_csr.c

00001 /*
00002  *  X.509 Certificate Signing Request (CSR) parsing
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  *  The ITU-T X.509 standard defines a certificate format for PKI.
00023  *
00024  *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
00025  *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
00026  *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
00027  *
00028  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
00029  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
00030  */
00031 
00032 #if !defined(MBEDTLS_CONFIG_FILE)
00033 #include "mbedtls/config.h"
00034 #else
00035 #include MBEDTLS_CONFIG_FILE
00036 #endif
00037 
00038 #if defined(MBEDTLS_X509_CSR_PARSE_C)
00039 
00040 #include "mbedtls/x509_csr.h"
00041 #include "mbedtls/oid.h"
00042 
00043 #include <string.h>
00044 
00045 #if defined(MBEDTLS_PEM_PARSE_C)
00046 #include "mbedtls/pem.h"
00047 #endif
00048 
00049 #if defined(MBEDTLS_PLATFORM_C)
00050 #include "mbedtls/platform.h"
00051 #else
00052 #include <stdlib.h>
00053 #include <stdio.h>
00054 #define mbedtls_free       free
00055 #define mbedtls_calloc    calloc
00056 #define mbedtls_snprintf   snprintf
00057 #endif
00058 
00059 #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
00060 #include <stdio.h>
00061 #endif
00062 
00063 /* Implementation that should never be optimized out by the compiler */
00064 static void mbedtls_zeroize( void *v, size_t n ) {
00065     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
00066 }
00067 
00068 /*
00069  *  Version  ::=  INTEGER  {  v1(0)  }
00070  */
00071 static int x509_csr_get_version( unsigned char **p,
00072                              const unsigned char *end,
00073                              int *ver )
00074 {
00075     int ret;
00076 
00077     if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
00078     {
00079         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
00080         {
00081             *ver = 0;
00082             return( 0 );
00083         }
00084 
00085         return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
00086     }
00087 
00088     return( 0 );
00089 }
00090 
00091 /*
00092  * Parse a CSR in DER format
00093  */
00094 int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr,
00095                         const unsigned char *buf, size_t buflen )
00096 {
00097     int ret;
00098     size_t len;
00099     unsigned char *p, *end;
00100     mbedtls_x509_buf sig_params;
00101 
00102     memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) );
00103 
00104     /*
00105      * Check for valid input
00106      */
00107     if( csr == NULL || buf == NULL )
00108         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
00109 
00110     mbedtls_x509_csr_init( csr );
00111 
00112     /*
00113      * first copy the raw DER data
00114      */
00115     p = mbedtls_calloc( 1, len = buflen );
00116 
00117     if( p == NULL )
00118         return( MBEDTLS_ERR_X509_ALLOC_FAILED );
00119 
00120     memcpy( p, buf, buflen );
00121 
00122     csr->raw.p = p;
00123     csr->raw.len = len;
00124     end = p + len;
00125 
00126     /*
00127      *  CertificationRequest ::= SEQUENCE {
00128      *       certificationRequestInfo CertificationRequestInfo,
00129      *       signatureAlgorithm AlgorithmIdentifier,
00130      *       signature          BIT STRING
00131      *  }
00132      */
00133     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00134             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00135     {
00136         mbedtls_x509_csr_free( csr );
00137         return( MBEDTLS_ERR_X509_INVALID_FORMAT );
00138     }
00139 
00140     if( len != (size_t) ( end - p ) )
00141     {
00142         mbedtls_x509_csr_free( csr );
00143         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
00144                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00145     }
00146 
00147     /*
00148      *  CertificationRequestInfo ::= SEQUENCE {
00149      */
00150     csr->cri.p = p;
00151 
00152     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00153             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00154     {
00155         mbedtls_x509_csr_free( csr );
00156         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
00157     }
00158 
00159     end = p + len;
00160     csr->cri.len = end - csr->cri.p;
00161 
00162     /*
00163      *  Version  ::=  INTEGER {  v1(0) }
00164      */
00165     if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 )
00166     {
00167         mbedtls_x509_csr_free( csr );
00168         return( ret );
00169     }
00170 
00171     csr->version++;
00172 
00173     if( csr->version != 1 )
00174     {
00175         mbedtls_x509_csr_free( csr );
00176         return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
00177     }
00178 
00179     /*
00180      *  subject               Name
00181      */
00182     csr->subject_raw.p = p;
00183 
00184     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00185             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00186     {
00187         mbedtls_x509_csr_free( csr );
00188         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
00189     }
00190 
00191     if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 )
00192     {
00193         mbedtls_x509_csr_free( csr );
00194         return( ret );
00195     }
00196 
00197     csr->subject_raw.len = p - csr->subject_raw.p;
00198 
00199     /*
00200      *  subjectPKInfo SubjectPublicKeyInfo
00201      */
00202     if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 )
00203     {
00204         mbedtls_x509_csr_free( csr );
00205         return( ret );
00206     }
00207 
00208     /*
00209      *  attributes    [0] Attributes
00210      */
00211     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00212             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
00213     {
00214         mbedtls_x509_csr_free( csr );
00215         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
00216     }
00217     // TODO Parse Attributes / extension requests
00218 
00219     p += len;
00220 
00221     end = csr->raw.p + csr->raw.len;
00222 
00223     /*
00224      *  signatureAlgorithm   AlgorithmIdentifier,
00225      *  signature            BIT STRING
00226      */
00227     if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 )
00228     {
00229         mbedtls_x509_csr_free( csr );
00230         return( ret );
00231     }
00232 
00233     if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params,
00234                                   &csr->sig_md, &csr->sig_pk,
00235                                   &csr->sig_opts ) ) != 0 )
00236     {
00237         mbedtls_x509_csr_free( csr );
00238         return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG );
00239     }
00240 
00241     if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 )
00242     {
00243         mbedtls_x509_csr_free( csr );
00244         return( ret );
00245     }
00246 
00247     if( p != end )
00248     {
00249         mbedtls_x509_csr_free( csr );
00250         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
00251                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00252     }
00253 
00254     return( 0 );
00255 }
00256 
00257 /*
00258  * Parse a CSR, allowing for PEM or raw DER encoding
00259  */
00260 int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen )
00261 {
00262     int ret;
00263 #if defined(MBEDTLS_PEM_PARSE_C)
00264     size_t use_len;
00265     mbedtls_pem_context pem;
00266 #endif
00267 
00268     /*
00269      * Check for valid input
00270      */
00271     if( csr == NULL || buf == NULL )
00272         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
00273 
00274 #if defined(MBEDTLS_PEM_PARSE_C)
00275     mbedtls_pem_init( &pem );
00276 
00277     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
00278     if( buflen == 0 || buf[buflen - 1] != '\0' )
00279         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
00280     else
00281         ret = mbedtls_pem_read_buffer( &pem,
00282                                "-----BEGIN CERTIFICATE REQUEST-----",
00283                                "-----END CERTIFICATE REQUEST-----",
00284                                buf, NULL, 0, &use_len );
00285 
00286     if( ret == 0 )
00287     {
00288         /*
00289          * Was PEM encoded, parse the result
00290          */
00291         if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf , pem.buflen  ) ) != 0 )
00292             return( ret );
00293 
00294         mbedtls_pem_free( &pem );
00295         return( 0 );
00296     }
00297     else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
00298     {
00299         mbedtls_pem_free( &pem );
00300         return( ret );
00301     }
00302     else
00303 #endif /* MBEDTLS_PEM_PARSE_C */
00304     return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) );
00305 }
00306 
00307 #if defined(MBEDTLS_FS_IO)
00308 /*
00309  * Load a CSR into the structure
00310  */
00311 int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path )
00312 {
00313     int ret;
00314     size_t n;
00315     unsigned char *buf;
00316 
00317     if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
00318         return( ret );
00319 
00320     ret = mbedtls_x509_csr_parse( csr, buf, n );
00321 
00322     mbedtls_zeroize( buf, n );
00323     mbedtls_free( buf );
00324 
00325     return( ret );
00326 }
00327 #endif /* MBEDTLS_FS_IO */
00328 
00329 #define BEFORE_COLON    14
00330 #define BC              "14"
00331 /*
00332  * Return an informational string about the CSR.
00333  */
00334 int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix,
00335                    const mbedtls_x509_csr *csr )
00336 {
00337     int ret;
00338     size_t n;
00339     char *p;
00340     char key_size_str[BEFORE_COLON];
00341 
00342     p = buf;
00343     n = size;
00344 
00345     ret = mbedtls_snprintf( p, n, "%sCSR version   : %d",
00346                                prefix, csr->version );
00347     MBEDTLS_X509_SAFE_SNPRINTF;
00348 
00349     ret = mbedtls_snprintf( p, n, "\n%ssubject name  : ", prefix );
00350     MBEDTLS_X509_SAFE_SNPRINTF;
00351     ret = mbedtls_x509_dn_gets( p, n, &csr->subject );
00352     MBEDTLS_X509_SAFE_SNPRINTF;
00353 
00354     ret = mbedtls_snprintf( p, n, "\n%ssigned using  : ", prefix );
00355     MBEDTLS_X509_SAFE_SNPRINTF;
00356 
00357     ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
00358                              csr->sig_opts );
00359     MBEDTLS_X509_SAFE_SNPRINTF;
00360 
00361     if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
00362                                       mbedtls_pk_get_name( &csr->pk ) ) ) != 0 )
00363     {
00364         return( ret );
00365     }
00366 
00367     ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
00368                           (int) mbedtls_pk_get_bitlen( &csr->pk ) );
00369     MBEDTLS_X509_SAFE_SNPRINTF;
00370 
00371     return( (int) ( size - n ) );
00372 }
00373 
00374 /*
00375  * Initialize a CSR
00376  */
00377 void mbedtls_x509_csr_init( mbedtls_x509_csr *csr )
00378 {
00379     memset( csr, 0, sizeof(mbedtls_x509_csr) );
00380 }
00381 
00382 /*
00383  * Unallocate all CSR data
00384  */
00385 void mbedtls_x509_csr_free( mbedtls_x509_csr *csr )
00386 {
00387     mbedtls_x509_name *name_cur;
00388     mbedtls_x509_name *name_prv;
00389 
00390     if( csr == NULL )
00391         return;
00392 
00393     mbedtls_pk_free( &csr->pk );
00394 
00395 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
00396     mbedtls_free( csr->sig_opts );
00397 #endif
00398 
00399     name_cur = csr->subject.next;
00400     while( name_cur != NULL )
00401     {
00402         name_prv = name_cur;
00403         name_cur = name_cur->next;
00404         mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
00405         mbedtls_free( name_prv );
00406     }
00407 
00408     if( csr->raw.p != NULL )
00409     {
00410         mbedtls_zeroize( csr->raw.p, csr->raw.len );
00411         mbedtls_free( csr->raw.p );
00412     }
00413 
00414     mbedtls_zeroize( csr, sizeof( mbedtls_x509_csr ) );
00415 }
00416 
00417 #endif /* MBEDTLS_X509_CSR_PARSE_C */