Rtos API example

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 || buflen == 0 )
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     if( csr->version != 0 )
00172     {
00173         mbedtls_x509_csr_free( csr );
00174         return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
00175     }
00176 
00177     csr->version++;
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      *  The list of possible attributes is open-ended, though RFC 2985
00212      *  (PKCS#9) defines a few in section 5.4. We currently don't support any,
00213      *  so we just ignore them. This is a safe thing to do as the worst thing
00214      *  that could happen is that we issue a certificate that does not match
00215      *  the requester's expectations - this cannot cause a violation of our
00216      *  signature policies.
00217      */
00218     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00219             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
00220     {
00221         mbedtls_x509_csr_free( csr );
00222         return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
00223     }
00224 
00225     p += len;
00226 
00227     end = csr->raw.p + csr->raw.len;
00228 
00229     /*
00230      *  signatureAlgorithm   AlgorithmIdentifier,
00231      *  signature            BIT STRING
00232      */
00233     if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 )
00234     {
00235         mbedtls_x509_csr_free( csr );
00236         return( ret );
00237     }
00238 
00239     if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params,
00240                                   &csr->sig_md, &csr->sig_pk,
00241                                   &csr->sig_opts ) ) != 0 )
00242     {
00243         mbedtls_x509_csr_free( csr );
00244         return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG );
00245     }
00246 
00247     if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 )
00248     {
00249         mbedtls_x509_csr_free( csr );
00250         return( ret );
00251     }
00252 
00253     if( p != end )
00254     {
00255         mbedtls_x509_csr_free( csr );
00256         return( MBEDTLS_ERR_X509_INVALID_FORMAT +
00257                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
00258     }
00259 
00260     return( 0 );
00261 }
00262 
00263 /*
00264  * Parse a CSR, allowing for PEM or raw DER encoding
00265  */
00266 int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen )
00267 {
00268 #if defined(MBEDTLS_PEM_PARSE_C)
00269     int ret;
00270     size_t use_len;
00271     mbedtls_pem_context pem;
00272 #endif
00273 
00274     /*
00275      * Check for valid input
00276      */
00277     if( csr == NULL || buf == NULL || buflen == 0 )
00278         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
00279 
00280 #if defined(MBEDTLS_PEM_PARSE_C)
00281     mbedtls_pem_init( &pem );
00282 
00283     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
00284     if( buf[buflen - 1] != '\0' )
00285         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
00286     else
00287         ret = mbedtls_pem_read_buffer( &pem,
00288                                "-----BEGIN CERTIFICATE REQUEST-----",
00289                                "-----END CERTIFICATE REQUEST-----",
00290                                buf, NULL, 0, &use_len );
00291 
00292     if( ret == 0 )
00293     {
00294         /*
00295          * Was PEM encoded, parse the result
00296          */
00297         if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf , pem.buflen  ) ) != 0 )
00298             return( ret );
00299 
00300         mbedtls_pem_free( &pem );
00301         return( 0 );
00302     }
00303     else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
00304     {
00305         mbedtls_pem_free( &pem );
00306         return( ret );
00307     }
00308     else
00309 #endif /* MBEDTLS_PEM_PARSE_C */
00310     return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) );
00311 }
00312 
00313 #if defined(MBEDTLS_FS_IO)
00314 /*
00315  * Load a CSR into the structure
00316  */
00317 int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path )
00318 {
00319     int ret;
00320     size_t n;
00321     unsigned char *buf;
00322 
00323     if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
00324         return( ret );
00325 
00326     ret = mbedtls_x509_csr_parse( csr, buf, n );
00327 
00328     mbedtls_zeroize( buf, n );
00329     mbedtls_free( buf );
00330 
00331     return( ret );
00332 }
00333 #endif /* MBEDTLS_FS_IO */
00334 
00335 #define BEFORE_COLON    14
00336 #define BC              "14"
00337 /*
00338  * Return an informational string about the CSR.
00339  */
00340 int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix,
00341                    const mbedtls_x509_csr *csr )
00342 {
00343     int ret;
00344     size_t n;
00345     char *p;
00346     char key_size_str[BEFORE_COLON];
00347 
00348     p = buf;
00349     n = size;
00350 
00351     ret = mbedtls_snprintf( p, n, "%sCSR version   : %d",
00352                                prefix, csr->version );
00353     MBEDTLS_X509_SAFE_SNPRINTF;
00354 
00355     ret = mbedtls_snprintf( p, n, "\n%ssubject name  : ", prefix );
00356     MBEDTLS_X509_SAFE_SNPRINTF;
00357     ret = mbedtls_x509_dn_gets( p, n, &csr->subject );
00358     MBEDTLS_X509_SAFE_SNPRINTF;
00359 
00360     ret = mbedtls_snprintf( p, n, "\n%ssigned using  : ", prefix );
00361     MBEDTLS_X509_SAFE_SNPRINTF;
00362 
00363     ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
00364                              csr->sig_opts );
00365     MBEDTLS_X509_SAFE_SNPRINTF;
00366 
00367     if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
00368                                       mbedtls_pk_get_name( &csr->pk ) ) ) != 0 )
00369     {
00370         return( ret );
00371     }
00372 
00373     ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
00374                           (int) mbedtls_pk_get_bitlen( &csr->pk ) );
00375     MBEDTLS_X509_SAFE_SNPRINTF;
00376 
00377     return( (int) ( size - n ) );
00378 }
00379 
00380 /*
00381  * Initialize a CSR
00382  */
00383 void mbedtls_x509_csr_init( mbedtls_x509_csr *csr )
00384 {
00385     memset( csr, 0, sizeof(mbedtls_x509_csr) );
00386 }
00387 
00388 /*
00389  * Unallocate all CSR data
00390  */
00391 void mbedtls_x509_csr_free( mbedtls_x509_csr *csr )
00392 {
00393     mbedtls_x509_name *name_cur;
00394     mbedtls_x509_name *name_prv;
00395 
00396     if( csr == NULL )
00397         return;
00398 
00399     mbedtls_pk_free( &csr->pk );
00400 
00401 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
00402     mbedtls_free( csr->sig_opts );
00403 #endif
00404 
00405     name_cur = csr->subject.next;
00406     while( name_cur != NULL )
00407     {
00408         name_prv = name_cur;
00409         name_cur = name_cur->next;
00410         mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
00411         mbedtls_free( name_prv );
00412     }
00413 
00414     if( csr->raw.p != NULL )
00415     {
00416         mbedtls_zeroize( csr->raw.p, csr->raw.len );
00417         mbedtls_free( csr->raw.p );
00418     }
00419 
00420     mbedtls_zeroize( csr, sizeof( mbedtls_x509_csr ) );
00421 }
00422 
00423 #endif /* MBEDTLS_X509_CSR_PARSE_C */