Example program to test AES-GCM functionality. Used for a workshop

Dependencies:   mbed

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