mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

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-2014, ARM Limited, All Rights Reserved
00005  *
00006  *  This file is part of mbed TLS (https://tls.mbed.org)
00007  *
00008  *  This program is free software; you can redistribute it and/or modify
00009  *  it under the terms of the GNU General Public License as published by
00010  *  the Free Software Foundation; either version 2 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU General Public License along
00019  *  with this program; if not, write to the Free Software Foundation, Inc.,
00020  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00021  */
00022 /*
00023  *  The ITU-T X.509 standard defines a certificate format for PKI.
00024  *
00025  *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
00026  *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
00027  *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
00028  *
00029  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
00030  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
00031  */
00032 
00033 #if !defined(POLARSSL_CONFIG_FILE)
00034 #include "polarssl/config.h"
00035 #else
00036 #include POLARSSL_CONFIG_FILE
00037 #endif
00038 
00039 #if defined(POLARSSL_X509_CSR_PARSE_C)
00040 
00041 #include "polarssl/x509_csr.h"
00042 #include "polarssl/oid.h"
00043 
00044 #include <string.h>
00045 
00046 #if defined(POLARSSL_PEM_PARSE_C)
00047 #include "polarssl/pem.h"
00048 #endif
00049 
00050 #if defined(POLARSSL_PLATFORM_C)
00051 #include "polarssl/platform.h"
00052 #else
00053 #include <stdlib.h>
00054 #include <stdio.h>
00055 #define polarssl_free       free
00056 #define polarssl_malloc     malloc
00057 #define polarssl_snprintf   snprintf
00058 #endif
00059 
00060 #if defined(POLARSSL_FS_IO) || defined(EFIX64) || defined(EFI32)
00061 #include <stdio.h>
00062 #endif
00063 
00064 /* Implementation that should never be optimized out by the compiler */
00065 static void polarssl_zeroize( void *v, size_t n ) {
00066     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
00067 }
00068 
00069 /*
00070  *  Version  ::=  INTEGER  {  v1(0)  }
00071  */
00072 static int x509_csr_get_version( unsigned char **p,
00073                              const unsigned char *end,
00074                              int *ver )
00075 {
00076     int ret;
00077 
00078     if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
00079     {
00080         if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
00081         {
00082             *ver = 0;
00083             return( 0 );
00084         }
00085 
00086         return( POLARSSL_ERR_X509_INVALID_VERSION + ret );
00087     }
00088 
00089     return( 0 );
00090 }
00091 
00092 /*
00093  * Parse a CSR in DER format
00094  */
00095 int x509_csr_parse_der( x509_csr *csr,
00096                         const unsigned char *buf, size_t buflen )
00097 {
00098     int ret;
00099     size_t len;
00100     unsigned char *p, *end;
00101     x509_buf sig_params;
00102 
00103     memset( &sig_params, 0, sizeof( x509_buf ) );
00104 
00105     /*
00106      * Check for valid input
00107      */
00108     if( csr == NULL || buf == NULL )
00109         return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
00110 
00111     x509_csr_init( csr );
00112 
00113     /*
00114      * first copy the raw DER data
00115      */
00116     p = polarssl_malloc( len = buflen );
00117 
00118     if( p == NULL )
00119         return( POLARSSL_ERR_X509_MALLOC_FAILED );
00120 
00121     memcpy( p, buf, buflen );
00122 
00123     csr->raw.p = p;
00124     csr->raw.len = len;
00125     end = p + len;
00126 
00127     /*
00128      *  CertificationRequest ::= SEQUENCE {
00129      *       certificationRequestInfo CertificationRequestInfo,
00130      *       signatureAlgorithm AlgorithmIdentifier,
00131      *       signature          BIT STRING
00132      *  }
00133      */
00134     if( ( ret = asn1_get_tag( &p, end, &len,
00135             ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00136     {
00137         x509_csr_free( csr );
00138         return( POLARSSL_ERR_X509_INVALID_FORMAT );
00139     }
00140 
00141     if( len != (size_t) ( end - p ) )
00142     {
00143         x509_csr_free( csr );
00144         return( POLARSSL_ERR_X509_INVALID_FORMAT +
00145                 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
00146     }
00147 
00148     /*
00149      *  CertificationRequestInfo ::= SEQUENCE {
00150      */
00151     csr->cri.p = p;
00152 
00153     if( ( ret = asn1_get_tag( &p, end, &len,
00154             ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00155     {
00156         x509_csr_free( csr );
00157         return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
00158     }
00159 
00160     end = p + len;
00161     csr->cri.len = end - csr->cri.p;
00162 
00163     /*
00164      *  Version  ::=  INTEGER {  v1(0) }
00165      */
00166     if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 )
00167     {
00168         x509_csr_free( csr );
00169         return( ret );
00170     }
00171 
00172     csr->version++;
00173 
00174     if( csr->version != 1 )
00175     {
00176         x509_csr_free( csr );
00177         return( POLARSSL_ERR_X509_UNKNOWN_VERSION );
00178     }
00179 
00180     /*
00181      *  subject               Name
00182      */
00183     csr->subject_raw.p = p;
00184 
00185     if( ( ret = asn1_get_tag( &p, end, &len,
00186             ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
00187     {
00188         x509_csr_free( csr );
00189         return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
00190     }
00191 
00192     if( ( ret = x509_get_name( &p, p + len, &csr->subject ) ) != 0 )
00193     {
00194         x509_csr_free( csr );
00195         return( ret );
00196     }
00197 
00198     csr->subject_raw.len = p - csr->subject_raw.p;
00199 
00200     /*
00201      *  subjectPKInfo SubjectPublicKeyInfo
00202      */
00203     if( ( ret = pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 )
00204     {
00205         x509_csr_free( csr );
00206         return( ret );
00207     }
00208 
00209     /*
00210      *  attributes    [0] Attributes
00211      */
00212     if( ( ret = asn1_get_tag( &p, end, &len,
00213             ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ) != 0 )
00214     {
00215         x509_csr_free( csr );
00216         return( POLARSSL_ERR_X509_INVALID_FORMAT + ret );
00217     }
00218     // TODO Parse Attributes / extension requests
00219 
00220     p += len;
00221 
00222     end = csr->raw.p + csr->raw.len;
00223 
00224     /*
00225      *  signatureAlgorithm   AlgorithmIdentifier,
00226      *  signature            BIT STRING
00227      */
00228     if( ( ret = x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 )
00229     {
00230         x509_csr_free( csr );
00231         return( ret );
00232     }
00233 
00234     if( ( ret = x509_get_sig_alg( &csr->sig_oid, &sig_params,
00235                                   &csr->sig_md, &csr->sig_pk,
00236                                   &csr->sig_opts ) ) != 0 )
00237     {
00238         x509_csr_free( csr );
00239         return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG );
00240     }
00241 
00242     if( ( ret = x509_get_sig( &p, end, &csr->sig ) ) != 0 )
00243     {
00244         x509_csr_free( csr );
00245         return( ret );
00246     }
00247 
00248     if( p != end )
00249     {
00250         x509_csr_free( csr );
00251         return( POLARSSL_ERR_X509_INVALID_FORMAT +
00252                 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
00253     }
00254 
00255     return( 0 );
00256 }
00257 
00258 /*
00259  * Parse a CSR, allowing for PEM or raw DER encoding
00260  */
00261 int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen )
00262 {
00263     int ret;
00264 #if defined(POLARSSL_PEM_PARSE_C)
00265     size_t use_len;
00266     pem_context pem;
00267 #endif
00268 
00269     /*
00270      * Check for valid input
00271      */
00272     if( csr == NULL || buf == NULL )
00273         return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
00274 
00275 #if defined(POLARSSL_PEM_PARSE_C)
00276     pem_init( &pem );
00277     ret = pem_read_buffer( &pem,
00278                            "-----BEGIN CERTIFICATE REQUEST-----",
00279                            "-----END CERTIFICATE REQUEST-----",
00280                            buf, NULL, 0, &use_len );
00281 
00282     if( ret == 0 )
00283     {
00284         /*
00285          * Was PEM encoded, parse the result
00286          */
00287         if( ( ret = x509_csr_parse_der( csr, pem.buf , pem.buflen  ) ) != 0 )
00288             return( ret );
00289 
00290         pem_free( &pem );
00291         return( 0 );
00292     }
00293     else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
00294     {
00295         pem_free( &pem );
00296         return( ret );
00297     }
00298     else
00299 #endif /* POLARSSL_PEM_PARSE_C */
00300     return( x509_csr_parse_der( csr, buf, buflen ) );
00301 }
00302 
00303 #if defined(POLARSSL_FS_IO)
00304 /*
00305  * Load a CSR into the structure
00306  */
00307 int x509_csr_parse_file( x509_csr *csr, const char *path )
00308 {
00309     int ret;
00310     size_t n;
00311     unsigned char *buf;
00312 
00313     if( ( ret = pk_load_file( path, &buf, &n ) ) != 0 )
00314         return( ret );
00315 
00316     ret = x509_csr_parse( csr, buf, n );
00317 
00318     polarssl_zeroize( buf, n + 1 );
00319     polarssl_free( buf );
00320 
00321     return( ret );
00322 }
00323 #endif /* POLARSSL_FS_IO */
00324 
00325 #if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
00326     !defined(EFI32)
00327 #include <stdarg.h>
00328 
00329 #if !defined vsnprintf
00330 #define vsnprintf _vsnprintf
00331 #endif // vsnprintf
00332 
00333 /*
00334  * Windows _snprintf and _vsnprintf are not compatible to linux versions.
00335  * Result value is not size of buffer needed, but -1 if no fit is possible.
00336  *
00337  * This fuction tries to 'fix' this by at least suggesting enlarging the
00338  * size by 20.
00339  */
00340 static int compat_snprintf( char *str, size_t size, const char *format, ... )
00341 {
00342     va_list ap;
00343     int res = -1;
00344 
00345     va_start( ap, format );
00346 
00347     res = vsnprintf( str, size, format, ap );
00348 
00349     va_end( ap );
00350 
00351     // No quick fix possible
00352     if( res < 0 )
00353         return( (int) size + 20 );
00354 
00355     return( res );
00356 }
00357 
00358 #define snprintf compat_snprintf
00359 #endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
00360 
00361 #define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL    -2
00362 
00363 #define SAFE_SNPRINTF()                             \
00364 {                                                   \
00365     if( ret == -1 )                                 \
00366         return( -1 );                               \
00367                                                     \
00368     if( (unsigned int) ret > n ) {                  \
00369         p[n - 1] = '\0';                            \
00370         return( POLARSSL_ERR_DEBUG_BUF_TOO_SMALL ); \
00371     }                                               \
00372                                                     \
00373     n -= (unsigned int) ret;                        \
00374     p += (unsigned int) ret;                        \
00375 }
00376 
00377 #define BEFORE_COLON    14
00378 #define BC              "14"
00379 /*
00380  * Return an informational string about the CSR.
00381  */
00382 int x509_csr_info( char *buf, size_t size, const char *prefix,
00383                    const x509_csr *csr )
00384 {
00385     int ret;
00386     size_t n;
00387     char *p;
00388     char key_size_str[BEFORE_COLON];
00389 
00390     p = buf;
00391     n = size;
00392 
00393     ret = polarssl_snprintf( p, n, "%sCSR version   : %d",
00394                                prefix, csr->version );
00395     SAFE_SNPRINTF();
00396 
00397     ret = polarssl_snprintf( p, n, "\n%ssubject name  : ", prefix );
00398     SAFE_SNPRINTF();
00399     ret = x509_dn_gets( p, n, &csr->subject );
00400     SAFE_SNPRINTF();
00401 
00402     ret = polarssl_snprintf( p, n, "\n%ssigned using  : ", prefix );
00403     SAFE_SNPRINTF();
00404 
00405     ret = x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
00406                              csr->sig_opts );
00407     SAFE_SNPRINTF();
00408 
00409     if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON,
00410                                       pk_get_name( &csr->pk ) ) ) != 0 )
00411     {
00412         return( ret );
00413     }
00414 
00415     ret = polarssl_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
00416                           (int) pk_get_size( &csr->pk ) );
00417     SAFE_SNPRINTF();
00418 
00419     return( (int) ( size - n ) );
00420 }
00421 
00422 /*
00423  * Initialize a CSR
00424  */
00425 void x509_csr_init( x509_csr *csr )
00426 {
00427     memset( csr, 0, sizeof(x509_csr) );
00428 }
00429 
00430 /*
00431  * Unallocate all CSR data
00432  */
00433 void x509_csr_free( x509_csr *csr )
00434 {
00435     x509_name *name_cur;
00436     x509_name *name_prv;
00437 
00438     if( csr == NULL )
00439         return;
00440 
00441     pk_free( &csr->pk );
00442 
00443 #if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT)
00444     polarssl_free( csr->sig_opts );
00445 #endif
00446 
00447     name_cur = csr->subject.next;
00448     while( name_cur != NULL )
00449     {
00450         name_prv = name_cur;
00451         name_cur = name_cur->next;
00452         polarssl_zeroize( name_prv, sizeof( x509_name ) );
00453         polarssl_free( name_prv );
00454     }
00455 
00456     if( csr->raw.p != NULL )
00457     {
00458         polarssl_zeroize( csr->raw.p, csr->raw.len );
00459         polarssl_free( csr->raw.p );
00460     }
00461 
00462     polarssl_zeroize( csr, sizeof( x509_csr ) );
00463 }
00464 
00465 #endif /* POLARSSL_X509_CSR_PARSE_C */
00466