Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers x509.c Source File

x509.c

Go to the documentation of this file.
00001 /**
00002  * @file x509.c
00003  * @brief X.509 certificate parsing and verification
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneCrypto Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (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
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include <string.h>
00034 #include <ctype.h>
00035 #include "crypto.h"
00036 #include "x509.h"
00037 #include "asn1.h"
00038 #include "oid.h"
00039 #include "rsa.h"
00040 #include "dsa.h"
00041 #include "ecdsa.h"
00042 #include "md5.h"
00043 #include "sha1.h"
00044 #include "sha224.h"
00045 #include "sha256.h"
00046 #include "sha384.h"
00047 #include "sha512.h"
00048 #include "debug.h"
00049 
00050 //Check crypto library configuration
00051 #if (X509_SUPPORT == ENABLED)
00052 
00053 //Common Name OID (2.5.4.3)
00054 const uint8_t X509_COMMON_NAME_OID[3] = {0x55, 0x04, 0x03};
00055 //Surname OID (2.5.4.4)
00056 const uint8_t X509_SURNAME_OID[3] = {0x55, 0x04, 0x04};
00057 //Serial Number OID (2.5.4.5)
00058 const uint8_t X509_SERIAL_NUMBER_OID[3] = {0x55, 0x04, 0x05};
00059 //Country Name OID (2.5.4.6)
00060 const uint8_t X509_COUNTRY_NAME_OID[3] = {0x55, 0x04, 0x06};
00061 //Locality Name OID (2.5.4.7)
00062 const uint8_t X509_LOCALITY_NAME_OID[3] = {0x55, 0x04, 0x07};
00063 //State Or Province Name OID (2.5.4.8)
00064 const uint8_t X509_STATE_OR_PROVINCE_NAME_OID[] = {0x55, 0x04, 0x08};
00065 //Organization Name OID (2.5.4.10)
00066 const uint8_t X509_ORGANIZATION_NAME_OID[3] = {0x55, 0x04, 0x0A};
00067 //Organizational Unit Name OID (2.5.4.11)
00068 const uint8_t X509_ORGANIZATIONAL_UNIT_NAME_OID[3] = {0x55, 0x04, 0x0B};
00069 //Title OID (2.5.4.12)
00070 const uint8_t X509_TITLE_OID[3] = {0x55, 0x04, 0x0C};
00071 //Name OID (2.5.4.41)
00072 const uint8_t X509_NAME_OID[3] = {0x55, 0x04, 0x29};
00073 //Given Name OID (2.5.4.42)
00074 const uint8_t X509_GIVEN_NAME_OID[3] = {0x55, 0x04, 0x2A};
00075 //Initials OID (2.5.4.43)
00076 const uint8_t X509_INITIALS_OID[3] = {0x55, 0x04, 0x2B};
00077 //Generation Qualifier OID (2.5.4.44)
00078 const uint8_t X509_GENERATION_QUALIFIER_OID[3] = {0x55, 0x04, 0x2C};
00079 //DN Qualifier OID (2.5.4.46)
00080 const uint8_t X509_DN_QUALIFIER_OID[3] = {0x55, 0x04, 0x2E};
00081 //Pseudonym OID (2.5.4.65)
00082 const uint8_t X509_PSEUDONYM_OID[3] = {0x55, 0x04, 0x41};
00083 
00084 //Subject Directory Attributes OID (2.5.29.9)
00085 const uint8_t X509_SUBJECT_DIRECTORY_ATTR_OID[3] = {0x55, 0x1D, 0x09};
00086 //Subject Key Identifier OID (2.5.29.14)
00087 const uint8_t X509_SUBJECT_KEY_ID_OID[3] = {0x55, 0x1D, 0x0E};
00088 //Key Usage OID (2.5.29.15)
00089 const uint8_t X509_KEY_USAGE_OID[3] = {0x55, 0x1D, 0x0F};
00090 //Subject Alternative Name OID (2.5.29.17)
00091 const uint8_t X509_SUBJECT_ALT_NAME_OID[3] = {0x55, 0x1D, 0x11};
00092 //Issuer Alternative Name OID (2.5.29.18)
00093 const uint8_t X509_ISSUER_ALT_NAME_OID[3] = {0x55, 0x1D, 0x12};
00094 //Basic Constraints OID (2.5.29.19)
00095 const uint8_t X509_BASIC_CONSTRAINTS_OID[3] = {0x55, 0x1D, 0x13};
00096 //Name Constraints OID (2.5.29.30)
00097 const uint8_t X509_NAME_CONSTRAINTS_OID[3] = {0x55, 0x1D, 0x1E};
00098 //CRL Distribution Points OID (2.5.29.31)
00099 const uint8_t X509_CRL_DISTR_POINTS_OID[3] = {0x55, 0x1D, 0x1F};
00100 //Certificate Policies OID (2.5.29.32)
00101 const uint8_t X509_CERTIFICATE_POLICIES_OID[3] = {0x55, 0x1D, 0x20};
00102 //Policy Mappings OID (2.5.29.33)
00103 const uint8_t X509_POLICY_MAPPINGS_OID[3] = {0x55, 0x1D, 0x21};
00104 //Authority Key Identifier OID (2.5.29.35)
00105 const uint8_t X509_AUTHORITY_KEY_ID_OID[3] = {0x55, 0x1D, 0x23};
00106 //Policy Constraints OID (2.5.29.36)
00107 const uint8_t X509_POLICY_CONSTRAINTS_OID[3] = {0x55, 0x1D, 0x24};
00108 //Extended Key Usage OID (2.5.29.37)
00109 const uint8_t X509_EXTENDED_KEY_USAGE_OID[3] = {0x55, 0x1D, 0x25};
00110 //Freshest CRL OID (2.5.29.46)
00111 const uint8_t X509_FRESHEST_CRL_OID[3] = {0x55, 0x1D, 0x2E};
00112 //Inhibit Any-Policy OID (2.5.29.54)
00113 const uint8_t X509_INHIBIT_ANY_POLICY_OID[3] = {0x55, 0x1D, 0x36};
00114 
00115 
00116 /**
00117  * @brief Parse a X.509 certificate
00118  * @param[in] data Pointer to the X.509 certificate to parse
00119  * @param[in] length Length of the X.509 certificate
00120  * @param[out] certInfo Information resulting from the parsing process
00121  * @return Error code
00122  **/
00123 
00124 error_t x509ParseCertificate(const uint8_t *data, size_t length,
00125    X509CertificateInfo *certInfo)
00126 {
00127    error_t error;
00128    size_t totalLength;
00129    Asn1Tag tag;
00130 
00131    //Debug message
00132    TRACE_DEBUG("Parsing X.509 certificate...\r\n");
00133    //Clear the certificate information structure
00134    memset(certInfo, 0, sizeof(X509CertificateInfo));
00135 
00136    //Read the contents of the certificate
00137    error = asn1ReadTag(data, length, &tag);
00138    //Failed to decode ASN.1 tag?
00139    if(error)
00140       return ERROR_BAD_CERTIFICATE;
00141 
00142    //Point to the very first field
00143    data = tag.value;
00144    length = tag.length;
00145 
00146    //Parse TBSCertificate structure
00147    error = x509ParseTbsCertificate(data, length, &totalLength, certInfo);
00148    //Any error to report?
00149    if(error)
00150       return ERROR_BAD_CERTIFICATE;
00151 
00152    //Point to the next field
00153    data += totalLength;
00154    length -= totalLength;
00155 
00156    //Parse SignatureAlgorithm structure
00157    error = x509ParseSignatureAlgo(data, length, &totalLength, certInfo);
00158    //Any error to report?
00159    if(error)
00160       return ERROR_BAD_CERTIFICATE;
00161 
00162    //Point to the next field
00163    data += totalLength;
00164    length -= totalLength;
00165 
00166    //Parse SignatureValue structure
00167    error = x509ParseSignatureValue(data, length, &totalLength, certInfo);
00168    //Any error to report?
00169    if(error)
00170       return ERROR_BAD_CERTIFICATE;
00171 
00172    //Certificate successfully parsed
00173    return NO_ERROR;
00174 }
00175 
00176 
00177 /**
00178  * @brief Parse TBSCertificate structure
00179  * @param[in] data Pointer to the ASN.1 structure to parse
00180  * @param[in] length Length of the ASN.1 structure
00181  * @param[out] totalLength Number of bytes that have been parsed
00182  * @param[out] certInfo Information resulting from the parsing process
00183  * @return Error code
00184  **/
00185 
00186 error_t x509ParseTbsCertificate(const uint8_t *data, size_t length,
00187    size_t *totalLength, X509CertificateInfo *certInfo)
00188 {
00189    error_t error;
00190    size_t n;
00191    Asn1Tag tag;
00192 
00193    //Debug message
00194    TRACE_DEBUG("  Parsing TBSCertificate...\r\n");
00195 
00196    //Read the contents of the TBSCertificate structure
00197    error = asn1ReadTag(data, length, &tag);
00198    //Failed to decode ASN.1 tag?
00199    if(error)
00200       return error;
00201 
00202    //Save the total length of the field
00203    *totalLength = tag.totalLength;
00204 
00205    //The ASN.1 DER encoded tbsCertificate is used as the input to the signature function
00206    certInfo->tbsCertificate = data;
00207    certInfo->tbsCertificateLen = tag.totalLength;
00208 
00209    //Point to the very first field of the TBSCertificate
00210    data = tag.value;
00211    length = tag.length;
00212 
00213    //Parse Version field
00214    error = x509ParseVersion(data, length, &n, certInfo);
00215    //Failed to parse Version field?
00216    if(error)
00217       return error;
00218 
00219    //Point to the next field
00220    data += n;
00221    length -= n;
00222 
00223    //Read SerialNumber field
00224    error = x509ParseSerialNumber(data, length, &n, certInfo);
00225    //Failed to parse SerialNumber field?
00226    if(error)
00227       return error;
00228 
00229    //Point to the next field
00230    data += n;
00231    length -= n;
00232 
00233    //Read Signature field
00234    error = x509ParseSignature(data, length, &n, certInfo);
00235    //Failed to parse Signature field?
00236    if(error)
00237       return error;
00238 
00239    //Point to the next field
00240    data += n;
00241    length -= n;
00242 
00243    //Read Issuer field
00244    error = x509ParseName(data, length, &n, &certInfo->issuer);
00245    //Failed to parse Issuer field?
00246    if(error)
00247       return error;
00248 
00249    //Point to the next field
00250    data += n;
00251    length -= n;
00252 
00253    //Read Validity field
00254    error = x509ParseValidity(data, length, &n, certInfo);
00255    //Failed to parse Validity field?
00256    if(error)
00257       return error;
00258 
00259    //Point to the next field
00260    data += n;
00261    length -= n;
00262 
00263    //Read Subject field
00264    error = x509ParseName(data, length, &n, &certInfo->subject);
00265    //Failed to parse Subject field?
00266    if(error)
00267       return error;
00268 
00269    //Point to the next field
00270    data += n;
00271    length -= n;
00272 
00273    //Read SubjectPublicKeyInfo field
00274    error = x509ParseSubjectPublicKeyInfo(data, length, &n, certInfo);
00275    //Failed to parse Version field?
00276    if(error)
00277       return error;
00278 
00279    //Point to the next field
00280    data += n;
00281    length -= n;
00282 
00283    //Read IssuerUniqueID field (optional)
00284    error = x509ParseIssuerUniqueId(data, length, &n, certInfo);
00285    //Failed to parse Version field?
00286    if(error)
00287       return error;
00288 
00289    //Point to the next field
00290    data += n;
00291    length -= n;
00292 
00293    //Read SubjectUniqueID field (optional)
00294    error = x509ParseSubjectUniqueId(data, length, &n, certInfo);
00295    //Failed to parse Version field?
00296    if(error)
00297       return error;
00298 
00299    //Point to the next field
00300    data += n;
00301    length -= n;
00302 
00303    //Read SubjectUniqueID field (optional)
00304    error = x509ParseExtensions(data, length, &n, certInfo);
00305    //Failed to parse Version field?
00306    if(error)
00307       return error;
00308 
00309    //No error to report
00310    return NO_ERROR;
00311 }
00312 
00313 
00314 /**
00315  * @brief Parse Version field
00316  * @param[in] data Pointer to the ASN.1 structure to parse
00317  * @param[in] length Length of the ASN.1 structure
00318  * @param[out] totalLength Number of bytes that have been parsed
00319  * @param[out] certInfo Information resulting from the parsing process
00320  * @return Error code
00321  **/
00322 
00323 error_t x509ParseVersion(const uint8_t *data, size_t length,
00324    size_t *totalLength, X509CertificateInfo *certInfo)
00325 {
00326    error_t error;
00327    Asn1Tag tag;
00328 
00329    //Debug message
00330    TRACE_DEBUG("    Parsing Version...\r\n");
00331 
00332    //Explicit tagging shall be used to encode version
00333    error = asn1ReadTag(data, length, &tag);
00334    //Failed to decode ASN.1 tag?
00335    if(error)
00336       return error;
00337 
00338    //Enforce encoding, class and type
00339    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 0);
00340 
00341    //The tag does not match the criteria?
00342    if(error)
00343    {
00344       //Assume X.509v1 format
00345       certInfo->version = X509_VERSION_1;
00346       //Skip the current field
00347       *totalLength = 0;
00348       //Exit immediately
00349       return NO_ERROR;
00350    }
00351 
00352    //Save the total length of the field
00353    *totalLength = tag.totalLength;
00354 
00355    //Read the inner tag
00356    error = asn1ReadTag(tag.value, tag.length, &tag);
00357    //Failed to decode ASN.1 tag?
00358    if(error)
00359       return error;
00360 
00361    //Enforce encoding, class and type
00362    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER);
00363    //The tag does not match the criteria?
00364    if(error)
00365       return error;
00366 
00367    //Check length field
00368    if(tag.length != 1)
00369       return ERROR_INVALID_LENGTH;
00370    //Check version field
00371    if(tag.value[0] > X509_VERSION_3)
00372       return ERROR_INVALID_VERSION;
00373 
00374    //Save certificate version
00375    certInfo->version = tag.value[0];
00376    //No error to report
00377    return NO_ERROR;
00378 }
00379 
00380 
00381 /**
00382  * @brief Parse SerialNumber field
00383  * @param[in] data Pointer to the ASN.1 structure to parse
00384  * @param[in] length Length of the ASN.1 structure
00385  * @param[out] totalLength Number of bytes that have been parsed
00386  * @param[out] certInfo Information resulting from the parsing process
00387  * @return Error code
00388  **/
00389 
00390 error_t x509ParseSerialNumber(const uint8_t *data, size_t length,
00391    size_t *totalLength, X509CertificateInfo *certInfo)
00392 {
00393    error_t error;
00394    Asn1Tag tag;
00395 
00396    //Debug message
00397    TRACE_DEBUG("    Parsing SerialNumber...\r\n");
00398 
00399    //Read the contents of the SerialNumber structure
00400    error = asn1ReadTag(data, length, &tag);
00401    //Failed to decode ASN.1 tag?
00402    if(error)
00403       return error;
00404 
00405    //Save the total length of the field
00406    *totalLength = tag.totalLength;
00407 
00408    //Enforce encoding, class and type
00409    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER);
00410    //The tag does not match the criteria?
00411    if(error)
00412       return error;
00413 
00414    //Get the signature value
00415    certInfo->serialNumber = tag.value;
00416    certInfo->serialNumberLen = tag.length;
00417 
00418    //No error to report
00419    return NO_ERROR;
00420 }
00421 
00422 
00423 /**
00424  * @brief Parse Signature field
00425  * @param[in] data Pointer to the ASN.1 structure to parse
00426  * @param[in] length Length of the ASN.1 structure
00427  * @param[out] totalLength Number of bytes that have been parsed
00428  * @param[out] certInfo Information resulting from the parsing process
00429  * @return Error code
00430  **/
00431 
00432 error_t x509ParseSignature(const uint8_t *data, size_t length,
00433    size_t *totalLength, X509CertificateInfo *certInfo)
00434 {
00435    error_t error;
00436    Asn1Tag tag;
00437 
00438    //Debug message
00439    TRACE_DEBUG("    Parsing Signature...\r\n");
00440 
00441    //Read the contents of the Signature structure
00442    error = asn1ReadTag(data, length, &tag);
00443    //Failed to decode ASN.1 tag?
00444    if(error)
00445       return error;
00446 
00447    //Save the total length of the field
00448    *totalLength = tag.totalLength;
00449 
00450    //Enforce encoding, class and type
00451    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
00452    //The tag does not match the criteria?
00453    if(error)
00454       return error;
00455 
00456    //Read the inner tag
00457    error = asn1ReadTag(tag.value, tag.length, &tag);
00458    //Failed to decode ASN.1 tag?
00459    if(error)
00460       return error;
00461 
00462    //Enforce encoding, class and type
00463    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OBJECT_IDENTIFIER);
00464    //The tag does not match the criteria?
00465    if(error)
00466       return error;
00467 
00468    //Get the signature algorithm identifier
00469    certInfo->signatureAlgo = tag.value;
00470    certInfo->signatureAlgoLen = tag.length;
00471 
00472    //Validity field successfully parsed
00473    return NO_ERROR;
00474 }
00475 
00476 
00477 /**
00478  * @brief Parse Name structure
00479  * @param[in] data Pointer to the ASN.1 structure to parse
00480  * @param[in] length Length of the ASN.1 structure
00481  * @param[out] totalLength Number of bytes that have been parsed
00482  * @param[out] name Information resulting from the parsing process
00483  * @return Error code
00484  **/
00485 
00486 error_t x509ParseName(const uint8_t *data, size_t length,
00487    size_t *totalLength, X509Name *name)
00488 {
00489    error_t error;
00490    Asn1Tag tag;
00491    Asn1Tag attrType;
00492    Asn1Tag attrValue;
00493 
00494    //Debug message
00495    TRACE_DEBUG("    Parsing Name...\r\n");
00496 
00497    //Read the contents of the Name structure
00498    error = asn1ReadTag(data, length, &tag);
00499    //Failed to decode ASN.1 tag?
00500    if(error)
00501       return error;
00502 
00503    //Save the total length of the field
00504    *totalLength = tag.totalLength;
00505 
00506    //Raw ASN.1 sequence
00507    name->rawData = data;
00508    name->rawDataLen = tag.totalLength;
00509 
00510    //Enforce encoding, class and type
00511    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
00512    //The tag does not match the criteria?
00513    if(error)
00514       return error;
00515 
00516    //The Name describes a hierarchical name composed of attributes
00517    data = tag.value;
00518    length = tag.length;
00519 
00520    //Loop through all the attributes
00521    while(length > 0)
00522    {
00523       //Read current attribute
00524       error = asn1ReadTag(data, length, &tag);
00525       //Failed to decode ASN.1 tag?
00526       if(error)
00527          return error;
00528 
00529       //Enforce encoding, class and type
00530       error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SET);
00531       //The tag does not match the criteria?
00532       if(error)
00533          return error;
00534 
00535       //Point to the next attribute
00536       data += tag.totalLength;
00537       length -= tag.totalLength;
00538 
00539       //Read the inner tag
00540       error = asn1ReadTag(tag.value, tag.length, &tag);
00541       //Failed to decode ASN.1 tag?
00542       if(error)
00543          return error;
00544 
00545       //Enforce encoding, class and type
00546       error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
00547       //The tag does not match the criteria?
00548       if(error)
00549          return error;
00550 
00551       //Read attribute type
00552       error = asn1ReadTag(tag.value, tag.length, &attrType);
00553       //Failed to decode ASN.1 tag?
00554       if(error)
00555          return error;
00556 
00557       //Enforce encoding, class and type
00558       error = asn1CheckTag(&attrType, FALSE,
00559          ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OBJECT_IDENTIFIER);
00560       //The tag does not match the criteria?
00561       if(error)
00562          return error;
00563 
00564       //Read attribute value
00565       error = asn1ReadTag(tag.value + attrType.totalLength,
00566          tag.length - attrType.totalLength, &attrValue);
00567       //Failed to decode ASN.1 tag?
00568       if(error)
00569          return error;
00570 
00571       //Check the length of the OID
00572       if(attrType.length == 3)
00573       {
00574          //Common Name attribute found?
00575          if(!memcmp(attrType.value, X509_COMMON_NAME_OID, 3))
00576          {
00577             name->commonName = (const char_t *) attrValue.value;
00578             name->commonNameLen = attrValue.length;
00579          }
00580          //Surname attribute found?
00581          else if(!memcmp(attrType.value, X509_SURNAME_OID, 3))
00582          {
00583             name->surname = (const char_t *) attrValue.value;
00584             name->surnameLen = attrValue.length;
00585          }
00586          //Serial Number attribute found?
00587          else if(!memcmp(attrType.value, X509_SERIAL_NUMBER_OID, 3))
00588          {
00589             name->serialNumber = (const char_t *) attrValue.value;
00590             name->serialNumberLen = attrValue.length;
00591          }
00592          //Country Name attribute found?
00593          else if(!memcmp(attrType.value, X509_COUNTRY_NAME_OID, 3))
00594          {
00595             name->countryName = (const char_t *) attrValue.value;
00596             name->countryNameLen = attrValue.length;
00597          }
00598          //Locality Name attribute found?
00599          else if(!memcmp(attrType.value, X509_LOCALITY_NAME_OID, 3))
00600          {
00601             name->localityName = (const char_t *) attrValue.value;
00602             name->localityNameLen = attrValue.length;
00603          }
00604          //State Or Province Name attribute found?
00605          else if(!memcmp(attrType.value, X509_STATE_OR_PROVINCE_NAME_OID, 3))
00606          {
00607             name->stateOrProvinceName = (const char_t *) attrValue.value;
00608             name->stateOrProvinceNameLen = attrValue.length;
00609          }
00610          //Organization Name attribute found?
00611          else if(!memcmp(attrType.value, X509_ORGANIZATION_NAME_OID, 3))
00612          {
00613             name->organizationName = (const char_t *) attrValue.value;
00614             name->organizationNameLen = attrValue.length;
00615          }
00616          //Organizational Unit Name attribute found?
00617          else if(!memcmp(attrType.value, X509_ORGANIZATIONAL_UNIT_NAME_OID, 3))
00618          {
00619             name->organizationalUnitName = (const char_t *) attrValue.value;
00620             name->organizationalUnitNameLen = attrValue.length;
00621          }
00622          //Title attribute found?
00623          else if(!memcmp(attrType.value, X509_TITLE_OID, 3))
00624          {
00625             name->title = (const char_t *) attrValue.value;
00626             name->titleLen = attrValue.length;
00627          }
00628          //Name attribute found?
00629          else if(!memcmp(attrType.value, X509_NAME_OID, 3))
00630          {
00631             name->name = (const char_t *) attrValue.value;
00632             name->nameLen = attrValue.length;
00633          }
00634          //Given Name attribute found?
00635          else if(!memcmp(attrType.value, X509_GIVEN_NAME_OID, 3))
00636          {
00637             name->givenName = (const char_t *) attrValue.value;
00638             name->givenNameLen = attrValue.length;
00639          }
00640          //Initials attribute OID (2.5.4.43)
00641          else if(!memcmp(attrType.value, X509_INITIALS_OID, 3))
00642          {
00643             name->initials = (const char_t *) attrValue.value;
00644             name->initialsLen = attrValue.length;
00645          }
00646          //Generation Qualifier attribute found?
00647          else if(!memcmp(attrType.value, X509_GENERATION_QUALIFIER_OID, 3))
00648          {
00649             name->generationQualifier = (const char_t *) attrValue.value;
00650             name->generationQualifierLen = attrValue.length;
00651          }
00652          //DN Qualifier attribute found?
00653          else if(!memcmp(attrType.value, X509_DN_QUALIFIER_OID, 3))
00654          {
00655             name->dnQualifier = (const char_t *) attrValue.value;
00656             name->dnQualifierLen = attrValue.length;
00657          }
00658          //Pseudonym attribute found?
00659          else if(!memcmp(attrType.value, X509_PSEUDONYM_OID, 3))
00660          {
00661             name->pseudonym = (const char_t *) attrValue.value;
00662             name->pseudonymLen = attrValue.length;
00663          }
00664       }
00665    }
00666 
00667    //Name field successfully parsed
00668    return NO_ERROR;
00669 }
00670 
00671 
00672 /**
00673  * @brief Parse Validity field
00674  * @param[in] data Pointer to the ASN.1 structure to parse
00675  * @param[in] length Length of the ASN.1 structure
00676  * @param[out] totalLength Number of bytes that have been parsed
00677  * @param[out] certInfo Information resulting from the parsing process
00678  * @return Error code
00679  **/
00680 
00681 error_t x509ParseValidity(const uint8_t *data, size_t length,
00682    size_t *totalLength, X509CertificateInfo *certInfo)
00683 {
00684    error_t error;
00685    size_t n;
00686    Asn1Tag tag;
00687 
00688    //Debug message
00689    TRACE_DEBUG("    Parsing Validity...\r\n");
00690 
00691    //Read current ASN.1 tag
00692    error = asn1ReadTag(data, length, &tag);
00693    //Failed to decode ASN.1 tag?
00694    if(error)
00695       return error;
00696 
00697    //Save the total length of the field
00698    *totalLength = tag.totalLength;
00699 
00700    //Enforce encoding, class and type
00701    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
00702    //The tag does not match the criteria?
00703    if(error)
00704       return error;
00705 
00706    //Point to the very first field of the sequence
00707    data = tag.value;
00708    length = tag.length;
00709 
00710    //NotBefore field may be encoded as UTCTime or GeneralizedTime
00711    error = x509ParseTime(data, length, &n, &certInfo->validity.notBefore);
00712    //Failed to decode ASN.1 tag?
00713    if(error)
00714       return error;
00715 
00716    //Point to the next field
00717    data += n;
00718    length -= n;
00719 
00720    //NotAfter field may be encoded as UTCTime or GeneralizedTime
00721    error = x509ParseTime(data, length, &n, &certInfo->validity.notAfter);
00722    //Failed to decode ASN.1 tag?
00723    if(error)
00724       return error;
00725 
00726    //Validity field successfully parsed
00727    return NO_ERROR;
00728 }
00729 
00730 
00731 /**
00732  * @brief Parse UTCTime or GeneralizedTime structure
00733  * @param[in] data Pointer to the ASN.1 structure to parse
00734  * @param[in] length Length of the ASN.1 structure
00735  * @param[out] totalLength Number of bytes that have been parsed
00736  * @param[out] dateTime date resulting from the parsing process
00737  * @return Error code
00738  **/
00739 
00740 error_t x509ParseTime(const uint8_t *data, size_t length,
00741    size_t *totalLength, DateTime *dateTime)
00742 {
00743    error_t error;
00744    uint_t value;
00745    Asn1Tag tag;
00746 
00747    //Debug message
00748    TRACE_DEBUG("      Parsing Time...\r\n");
00749 
00750    //Read current ASN.1 tag
00751    error = asn1ReadTag(data, length, &tag);
00752    //Failed to decode ASN.1 tag?
00753    if(error)
00754       return error;
00755 
00756    //Save the total length of the field
00757    *totalLength = tag.totalLength;
00758 
00759    //The date may be encoded as UTCTime or GeneralizedTime
00760    if(!asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_UTC_TIME))
00761    {
00762       //Check the length of the UTCTime field
00763       if(tag.length < 12)
00764          return ERROR_INVALID_SYNTAX;
00765 
00766       //The UTCTime uses a 2-digit representation of the year
00767       error = x509ParseInt(tag.value, 2, &value);
00768       //Any error to report?
00769       if(error)
00770          return error;
00771 
00772       //If YY is greater than or equal to 50, the year shall be interpreted
00773       //as 19YY. If YY is less than 50, the year shall be interpreted as 20YY
00774       if(value >= 50)
00775          dateTime->year = 1900 + value;
00776       else
00777          dateTime->year = 2000 + value;
00778 
00779       //Point to the next field
00780       data = tag.value + 2;
00781    }
00782    else if(!asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_GENERALIZED_TIME))
00783    {
00784       //Check the length of the GeneralizedTime field
00785       if(tag.length < 14)
00786          return ERROR_INVALID_SYNTAX;
00787 
00788       //The GeneralizedTime uses a 4-digit representation of the year
00789       error = x509ParseInt(tag.value, 4, &value);
00790       //Any error to report?
00791       if(error)
00792          return error;
00793 
00794       //Point to the next field
00795       data = tag.value + 4;
00796    }
00797    else
00798    {
00799       //The tag does not contain a valid date
00800       return ERROR_FAILURE;
00801    }
00802 
00803    //Month
00804    error = x509ParseInt(data, 2, &value);
00805    //Any error to report?
00806    if(error)
00807       return error;
00808 
00809    //Save the resulting value
00810    dateTime->month = value;
00811 
00812    //Day
00813    error = x509ParseInt(data + 2, 2, &value);
00814    //Any error to report?
00815    if(error)
00816       return error;
00817 
00818    //Save the resulting value
00819    dateTime->day = value;
00820 
00821    //Hours
00822    error = x509ParseInt(data + 4, 2, &value);
00823    //Any error to report?
00824    if(error)
00825       return error;
00826 
00827    //Save the resulting value
00828    dateTime->hours = value;
00829 
00830    //Minutes
00831    error = x509ParseInt(data + 6, 2, &value);
00832    //Any error to report?
00833    if(error)
00834       return error;
00835 
00836    //Save the resulting value
00837    dateTime->minutes = value;
00838 
00839    //Seconds
00840    error = x509ParseInt(data + 8, 2, &value);
00841    //Any error to report?
00842    if(error)
00843       return error;
00844 
00845    //Save the resulting value
00846    dateTime->seconds = value;
00847 
00848    //Milliseconds
00849    dateTime->milliseconds = 0;
00850 
00851    //UTCTime or GeneralizedTime field successfully parsed
00852    return NO_ERROR;
00853 }
00854 
00855 
00856 /**
00857  * @brief Parse SubjectPublicKeyInfo structure
00858  * @param[in] data Pointer to the ASN.1 structure to parse
00859  * @param[in] length Length of the ASN.1 structure
00860  * @param[out] totalLength Number of bytes that have been parsed
00861  * @param[out] certInfo Information resulting from the parsing process
00862  * @return Error code
00863  **/
00864 
00865 error_t x509ParseSubjectPublicKeyInfo(const uint8_t *data, size_t length,
00866    size_t *totalLength, X509CertificateInfo *certInfo)
00867 {
00868    error_t error;
00869    size_t n;
00870    Asn1Tag tag;
00871 
00872    //Debug message
00873    TRACE_DEBUG("    Parsing SubjectPublicKeyInfo...\r\n");
00874 
00875    //Read SubjectPublicKeyInfo field
00876    error = asn1ReadTag(data, length, &tag);
00877    //Failed to decode ASN.1 tag?
00878    if(error)
00879       return error;
00880 
00881    //Save the total length of the field
00882    *totalLength = tag.totalLength;
00883 
00884    //Enforce encoding, class and type
00885    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
00886    //The tag does not match the criteria?
00887    if(error)
00888       return error;
00889 
00890    //Point to the first field
00891    data = tag.value;
00892    length = tag.length;
00893 
00894    //Read AlgorithmIdentifier field
00895    error = x509ParseAlgorithmIdentifier(data, length, &n, certInfo);
00896    //Any error to report?
00897    if(error)
00898       return error;
00899 
00900    //Point to the next field
00901    data += n;
00902    length -= n;
00903 
00904    //The SubjectPublicKey structure is encapsulated within a bit string
00905    error = asn1ReadTag(data, length, &tag);
00906    //Failed to decode ASN.1 tag?
00907    if(error)
00908       return error;
00909 
00910    //Enforce encoding, class and type
00911    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_BIT_STRING);
00912    //The tag does not match the criteria?
00913    if(error)
00914       return error;
00915 
00916    //The bit string shall contain an initial octet which encodes
00917    //the number of unused bits in the final subsequent octet
00918    if(tag.length < 1 || tag.value[0] != 0x00)
00919       return ERROR_FAILURE;
00920 
00921 #if (RSA_SUPPORT == ENABLED)
00922    //RSA algorithm identifier?
00923    if(!oidComp(certInfo->subjectPublicKeyInfo.oid, certInfo->subjectPublicKeyInfo.oidLen,
00924       RSA_ENCRYPTION_OID, sizeof(RSA_ENCRYPTION_OID)))
00925    {
00926       //Read RSAPublicKey structure
00927       error = x509ParseRsaPublicKey(tag.value + 1, tag.length - 1, certInfo);
00928    }
00929    else
00930 #endif
00931 #if (DSA_SUPPORT == ENABLED)
00932    //DSA algorithm identifier?
00933    if(!oidComp(certInfo->subjectPublicKeyInfo.oid, certInfo->subjectPublicKeyInfo.oidLen,
00934       DSA_OID, sizeof(DSA_OID)))
00935    {
00936       //Read DSAPublicKey structure
00937       error = x509ParseDsaPublicKey(tag.value + 1, tag.length - 1, certInfo);
00938    }
00939    else
00940 #endif
00941 #if (EC_SUPPORT == ENABLED)
00942    //EC public key identifier?
00943    if(!oidComp(certInfo->subjectPublicKeyInfo.oid, certInfo->subjectPublicKeyInfo.oidLen,
00944       EC_PUBLIC_KEY_OID, sizeof(EC_PUBLIC_KEY_OID)))
00945    {
00946       //Read ECPublicKey structure
00947       error = x509ParseEcPublicKey(tag.value + 1, tag.length - 1, certInfo);
00948    }
00949    else
00950 #endif
00951    //The certificate does not contain any valid public key...
00952    {
00953       //Report an error
00954       error = ERROR_BAD_CERTIFICATE;
00955    }
00956 
00957    //Return status code
00958    return error;
00959 }
00960 
00961 
00962 /**
00963  * @brief Parse AlgorithmIdentifier structure
00964  * @param[in] data Pointer to the ASN.1 structure to parse
00965  * @param[in] length Length of the ASN.1 structure
00966  * @param[out] totalLength Number of bytes that have been parsed
00967  * @param[out] certInfo Information resulting from the parsing process
00968  * @return Error code
00969  **/
00970 
00971 error_t x509ParseAlgorithmIdentifier(const uint8_t *data, size_t length,
00972    size_t *totalLength, X509CertificateInfo *certInfo)
00973 {
00974    error_t error;
00975    Asn1Tag tag;
00976 
00977    //Debug message
00978    TRACE_DEBUG("      Parsing AlgorithmIdentifier...\r\n");
00979 
00980    //Read AlgorithmIdentifier field
00981    error = asn1ReadTag(data, length, &tag);
00982    //Failed to decode ASN.1 tag?
00983    if(error)
00984       return error;
00985 
00986    //Save the total length of the field
00987    *totalLength = tag.totalLength;
00988 
00989    //Enforce encoding, class and type
00990    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
00991    //The tag does not match the criteria?
00992    if(error)
00993       return error;
00994 
00995    //Point to the first field
00996    data = tag.value;
00997    length = tag.length;
00998 
00999    //Read algorithm identifier (OID)
01000    error = asn1ReadTag(data, length, &tag);
01001    //Failed to decode ASN.1 tag?
01002    if(error)
01003       return error;
01004 
01005    //Enforce encoding, class and type
01006    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OBJECT_IDENTIFIER);
01007    //The tag does not match the criteria?
01008    if(error)
01009       return error;
01010 
01011    //Save the algorithm identifier
01012    certInfo->subjectPublicKeyInfo.oid = tag.value;
01013    certInfo->subjectPublicKeyInfo.oidLen = tag.length;
01014 
01015    //Point to the next field (if any)
01016    data += tag.totalLength;
01017    length -= tag.totalLength;
01018 
01019 #if (RSA_SUPPORT == ENABLED)
01020    //RSA algorithm identifier?
01021    if(!asn1CheckOid(&tag, RSA_ENCRYPTION_OID, sizeof(RSA_ENCRYPTION_OID)))
01022    {
01023       //RSA does not require any additional parameters
01024       error = NO_ERROR;
01025    }
01026    else
01027 #endif
01028 #if (DSA_SUPPORT == ENABLED)
01029    //DSA algorithm identifier?
01030    if(!asn1CheckOid(&tag, DSA_OID, sizeof(DSA_OID)))
01031    {
01032       //Read DsaParameters structure
01033       error = x509ParseDsaParameters(data, length, certInfo);
01034    }
01035    else
01036 #endif
01037 #if (EC_SUPPORT == ENABLED)
01038    //EC public key identifier?
01039    if(!asn1CheckOid(&tag, EC_PUBLIC_KEY_OID, sizeof(EC_PUBLIC_KEY_OID)))
01040    {
01041       //Read ECParameters structure
01042       error = x509ParseEcParameters(data, length, certInfo);
01043    }
01044    else
01045 #endif
01046    //The certificate does not contain any valid public key...
01047    {
01048       //Report an error
01049       error = ERROR_BAD_CERTIFICATE;
01050    }
01051 
01052    //Return status code
01053    return error;
01054 }
01055 
01056 
01057 /**
01058  * @brief Parse RSAPublicKey structure
01059  * @param[in] data Pointer to the ASN.1 structure to parse
01060  * @param[in] length Length of the ASN.1 structure
01061  * @param[out] certInfo Information resulting from the parsing process
01062  * @return Error code
01063  **/
01064 
01065 error_t x509ParseRsaPublicKey(const uint8_t *data,
01066    size_t length, X509CertificateInfo *certInfo)
01067 {
01068 #if (RSA_SUPPORT == ENABLED)
01069    error_t error;
01070    Asn1Tag tag;
01071 
01072    //Debug message
01073    TRACE_DEBUG("      Parsing RSAPublicKey...\r\n");
01074 
01075    //Read RSAPublicKey structure
01076    error = asn1ReadTag(data, length, &tag);
01077    //Failed to decode ASN.1 tag?
01078    if(error)
01079       return error;
01080 
01081    //Enforce encoding, class and type
01082    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
01083    //The tag does not match the criteria?
01084    if(error)
01085       return error;
01086 
01087    //Point to the first field
01088    data = tag.value;
01089    length = tag.length;
01090 
01091    //Read Modulus field
01092    error = asn1ReadTag(data, length, &tag);
01093    //Failed to decode ASN.1 tag?
01094    if(error)
01095       return error;
01096 
01097    //Enforce encoding, class and type
01098    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER);
01099    //The tag does not match the criteria?
01100    if(error)
01101       return error;
01102 
01103    //Get the modulus
01104    certInfo->subjectPublicKeyInfo.rsaPublicKey.n = tag.value;
01105    certInfo->subjectPublicKeyInfo.rsaPublicKey.nLen = tag.length;
01106 
01107    //Point to the next field
01108    data += tag.totalLength;
01109    length -= tag.totalLength;
01110 
01111    //Read PublicExponent field
01112    error = asn1ReadTag(data, length, &tag);
01113    //Failed to decode ASN.1 tag?
01114    if(error)
01115       return error;
01116 
01117    //Enforce encoding, class and type
01118    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER);
01119    //The tag does not match the criteria?
01120    if(error)
01121       return error;
01122 
01123    //Get the public exponent
01124    certInfo->subjectPublicKeyInfo.rsaPublicKey.e = tag.value;
01125    certInfo->subjectPublicKeyInfo.rsaPublicKey.eLen = tag.length;
01126 
01127    //Successful processing
01128    return NO_ERROR;
01129 #else
01130    //Not implemented
01131    return ERROR_NOT_IMPLEMENTED;
01132 #endif
01133 }
01134 
01135 
01136 /**
01137  * @brief Parse DSA domain parameters
01138  * @param[in] data Pointer to the ASN.1 structure to parse
01139  * @param[in] length Length of the ASN.1 structure
01140  * @param[out] certInfo Information resulting from the parsing process
01141  * @return Error code
01142  **/
01143 
01144 error_t x509ParseDsaParameters(const uint8_t *data,
01145    size_t length, X509CertificateInfo *certInfo)
01146 {
01147 #if (DSA_SUPPORT == ENABLED)
01148    error_t error;
01149    Asn1Tag tag;
01150 
01151    //Debug message
01152    TRACE_DEBUG("        Parsing DSAParameters...\r\n");
01153 
01154    //Read DSAParameters structure
01155    error = asn1ReadTag(data, length, &tag);
01156    //Failed to decode ASN.1 tag?
01157    if(error)
01158       return error;
01159 
01160    //Enforce encoding, class and type
01161    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
01162    //The tag does not match the criteria?
01163    if(error)
01164       return error;
01165 
01166    //Point to the first field
01167    data = tag.value;
01168    length = tag.length;
01169 
01170    //Read the parameter p
01171    error = asn1ReadTag(data, length, &tag);
01172    //Failed to decode ASN.1 tag?
01173    if(error)
01174       return error;
01175 
01176    //Enforce encoding, class and type
01177    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER);
01178    //The tag does not match the criteria?
01179    if(error)
01180       return error;
01181 
01182    //Save the parameter p
01183    certInfo->subjectPublicKeyInfo.dsaParams.p = tag.value;
01184    certInfo->subjectPublicKeyInfo.dsaParams.pLen = tag.length;
01185 
01186    //Point to the next field
01187    data += tag.totalLength;
01188    length -= tag.totalLength;
01189 
01190    //Read the parameter q
01191    error = asn1ReadTag(data, length, &tag);
01192    //Failed to decode ASN.1 tag?
01193    if(error)
01194       return error;
01195 
01196    //Enforce encoding, class and type
01197    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER);
01198    //The tag does not match the criteria?
01199    if(error)
01200       return error;
01201 
01202    //Save the parameter q
01203    certInfo->subjectPublicKeyInfo.dsaParams.q = tag.value;
01204    certInfo->subjectPublicKeyInfo.dsaParams.qLen = tag.length;
01205 
01206    //Point to the next field
01207    data += tag.totalLength;
01208    length -= tag.totalLength;
01209 
01210    //Read the parameter g
01211    error = asn1ReadTag(data, length, &tag);
01212    //Failed to decode ASN.1 tag?
01213    if(error)
01214       return error;
01215 
01216    //Enforce encoding, class and type
01217    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER);
01218    //The tag does not match the criteria?
01219    if(error)
01220       return error;
01221 
01222    //Save the parameter g
01223    certInfo->subjectPublicKeyInfo.dsaParams.g = tag.value;
01224    certInfo->subjectPublicKeyInfo.dsaParams.gLen = tag.length;
01225 
01226    //Successful processing
01227    return NO_ERROR;
01228 #else
01229    //Not implemented
01230    return ERROR_NOT_IMPLEMENTED;
01231 #endif
01232 }
01233 
01234 
01235 /**
01236  * @brief Parse DSAPublicKey structure
01237  * @param[in] data Pointer to the ASN.1 structure to parse
01238  * @param[in] length Length of the ASN.1 structure
01239  * @param[out] certInfo Information resulting from the parsing process
01240  * @return Error code
01241  **/
01242 
01243 error_t x509ParseDsaPublicKey(const uint8_t *data,
01244    size_t length, X509CertificateInfo *certInfo)
01245 {
01246 #if (DSA_SUPPORT == ENABLED)
01247    error_t error;
01248    Asn1Tag tag;
01249 
01250    //Debug message
01251    TRACE_DEBUG("      Parsing DSAPublicKey...\r\n");
01252 
01253    //Read DSAPublicKey structure
01254    error = asn1ReadTag(data, length, &tag);
01255    //Failed to decode ASN.1 tag?
01256    if(error)
01257       return error;
01258 
01259    //Enforce encoding, class and type
01260    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER);
01261    //The tag does not match the criteria?
01262    if(error)
01263       return error;
01264 
01265    //Save the DSA public value
01266    certInfo->subjectPublicKeyInfo.dsaPublicKey.y = tag.value;
01267    certInfo->subjectPublicKeyInfo.dsaPublicKey.yLen = tag.length;
01268 
01269    //Successful processing
01270    return NO_ERROR;
01271 #else
01272    //Not implemented
01273    return ERROR_NOT_IMPLEMENTED;
01274 #endif
01275 }
01276 
01277 
01278 /**
01279  * @brief Parse ECParameters structure
01280  * @param[in] data Pointer to the ASN.1 structure to parse
01281  * @param[in] length Length of the ASN.1 structure
01282  * @param[out] certInfo Information resulting from the parsing process
01283  * @return Error code
01284  **/
01285 
01286 error_t x509ParseEcParameters(const uint8_t *data,
01287    size_t length, X509CertificateInfo *certInfo)
01288 {
01289 #if (EC_SUPPORT == ENABLED)
01290    error_t error;
01291    Asn1Tag tag;
01292 
01293    //Debug message
01294    TRACE_DEBUG("        Parsing ECParameters...\r\n");
01295 
01296    //Read namedCurve field
01297    error = asn1ReadTag(data, length, &tag);
01298    //Failed to decode ASN.1 tag?
01299    if(error)
01300       return error;
01301 
01302    //Enforce encoding, class and type
01303    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OBJECT_IDENTIFIER);
01304    //The tag does not match the criteria?
01305    if(error)
01306       return error;
01307 
01308    //The namedCurve field identifies all the required values for a particular
01309    //set of elliptic curve domain parameters to be represented by an object
01310    //identifier
01311    certInfo->subjectPublicKeyInfo.ecParams.namedCurve = tag.value;
01312    certInfo->subjectPublicKeyInfo.ecParams.namedCurveLen = tag.length;
01313 
01314    //Successful processing
01315    return NO_ERROR;
01316 #else
01317    //Not implemented
01318    return ERROR_NOT_IMPLEMENTED;
01319 #endif
01320 }
01321 
01322 
01323 /**
01324  * @brief Parse ECPublicKey structure
01325  * @param[in] data Pointer to the ASN.1 structure to parse
01326  * @param[in] length Length of the ASN.1 structure
01327  * @param[out] certInfo Information resulting from the parsing process
01328  * @return Error code
01329  **/
01330 
01331 error_t x509ParseEcPublicKey(const uint8_t *data,
01332    size_t length, X509CertificateInfo *certInfo)
01333 {
01334 #if (EC_SUPPORT == ENABLED)
01335    //Debug message
01336    TRACE_DEBUG("      Parsing ECPublicKey...\r\n");
01337 
01338    //Make sure the EC public key is valid
01339    if(!length)
01340       return ERROR_BAD_CERTIFICATE;
01341 
01342    //Save the EC public value
01343    certInfo->subjectPublicKeyInfo.ecPublicKey.q = data;
01344    certInfo->subjectPublicKeyInfo.ecPublicKey.qLen = length;
01345 
01346    //Successful processing
01347    return NO_ERROR;
01348 #else
01349    //Not implemented
01350    return ERROR_NOT_IMPLEMENTED;
01351 #endif
01352 }
01353 
01354 
01355 /**
01356  * @brief Parse IssuerUniqueID structure
01357  * @param[in] data Pointer to the ASN.1 structure to parse
01358  * @param[in] length Length of the ASN.1 structure
01359  * @param[out] totalLength Number of bytes that have been parsed
01360  * @param[out] certInfo Information resulting from the parsing process
01361  * @return Error code
01362  **/
01363 
01364 error_t x509ParseIssuerUniqueId(const uint8_t *data, size_t length,
01365    size_t *totalLength, X509CertificateInfo *certInfo)
01366 {
01367    error_t error;
01368    Asn1Tag tag;
01369 
01370    //No more data to process?
01371    if(!length)
01372    {
01373       //The IssuerUniqueID field is optional
01374       *totalLength = 0;
01375       //Exit immediately
01376       return NO_ERROR;
01377    }
01378 
01379    //Explicit tagging is used to encode the IssuerUniqueID field
01380    error = asn1ReadTag(data, length, &tag);
01381    //Failed to decode ASN.1 tag?
01382    if(error)
01383       return error;
01384 
01385    //Enforce encoding, class and type
01386    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 1);
01387    //The tag does not match the criteria?
01388    if(error)
01389    {
01390       //The IssuerUniqueID field is optional
01391       *totalLength = 0;
01392       //Exit immediately
01393       return NO_ERROR;
01394    }
01395 
01396    //Save the total length of the field
01397    *totalLength = tag.totalLength;
01398 
01399    //Debug message
01400    TRACE_DEBUG("    Parsing IssuerUniqueID...\r\n");
01401 
01402    //This field must only appear if the version is 2 or 3
01403    if(certInfo->version < X509_VERSION_2)
01404       return ERROR_INVALID_VERSION;
01405 
01406    //Successful processing
01407    return NO_ERROR;
01408 }
01409 
01410 
01411 /**
01412  * @brief Parse SubjectUniqueID structure
01413  * @param[in] data Pointer to the ASN.1 structure to parse
01414  * @param[in] length Length of the ASN.1 structure
01415  * @param[out] totalLength Number of bytes that have been parsed
01416  * @param[out] certInfo Information resulting from the parsing process
01417  * @return Error code
01418  **/
01419 
01420 error_t x509ParseSubjectUniqueId(const uint8_t *data, size_t length,
01421    size_t *totalLength, X509CertificateInfo *certInfo)
01422 {
01423    error_t error;
01424    Asn1Tag tag;
01425 
01426    //No more data to process?
01427    if(!length)
01428    {
01429       //The SubjectUniqueID field is optional
01430       *totalLength = 0;
01431       //Exit immediately
01432       return NO_ERROR;
01433    }
01434 
01435    //Explicit tagging is used to encode the SubjectUniqueID field
01436    error = asn1ReadTag(data, length, &tag);
01437    //Failed to decode ASN.1 tag?
01438    if(error)
01439       return error;
01440 
01441    //Enforce encoding, class and type
01442    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 2);
01443    //The tag does not match the criteria?
01444    if(error)
01445    {
01446       //The SubjectUniqueID field is optional
01447       *totalLength = 0;
01448       //Exit immediately
01449       return NO_ERROR;
01450    }
01451 
01452    //Save the total length of the field
01453    *totalLength = tag.totalLength;
01454 
01455    //Debug message
01456    TRACE_DEBUG("    Parsing SubjectUniqueID...\r\n");
01457 
01458    //This field must only appear if the version is 2 or 3
01459    if(certInfo->version < X509_VERSION_2)
01460       return ERROR_INVALID_VERSION;
01461 
01462    //Successful processing
01463    return NO_ERROR;
01464 }
01465 
01466 
01467 /**
01468  * @brief Parse Extensions structure
01469  * @param[in] data Pointer to the ASN.1 structure to parse
01470  * @param[in] length Length of the ASN.1 structure
01471  * @param[out] totalLength Number of bytes that have been parsed
01472  * @param[out] certInfo Information resulting from the parsing process
01473  * @return Error code
01474  **/
01475 
01476 error_t x509ParseExtensions(const uint8_t *data, size_t length,
01477    size_t *totalLength, X509CertificateInfo *certInfo)
01478 {
01479    error_t error;
01480    bool_t critical;
01481    const uint8_t *extensionData;
01482    size_t extensionLength;
01483    Asn1Tag tag;
01484    Asn1Tag oidTag;
01485 
01486    //No more data to process?
01487    if(!length)
01488    {
01489       //The Extensions field is optional
01490       *totalLength = 0;
01491       //Exit immediately
01492       return NO_ERROR;
01493    }
01494 
01495    //Explicit tagging is used to encode the Extensions field
01496    error = asn1ReadTag(data, length, &tag);
01497    //Failed to decode ASN.1 tag?
01498    if(error)
01499       return error;
01500 
01501    //Enforce encoding, class and type
01502    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_CONTEXT_SPECIFIC, 3);
01503    //The tag does not match the criteria?
01504    if(error)
01505    {
01506       //The Extensions field is optional
01507       *totalLength = 0;
01508       //Exit immediately
01509       return NO_ERROR;
01510    }
01511 
01512    //Save the total length of the field
01513    *totalLength = tag.totalLength;
01514 
01515    //Debug message
01516    TRACE_DEBUG("    Parsing Extensions...\r\n");
01517 
01518    //This field must only appear if the version is 3
01519    if(certInfo->version < X509_VERSION_3)
01520       return ERROR_INVALID_VERSION;
01521 
01522    //Read inner tag
01523    error = asn1ReadTag(tag.value, tag.length, &tag);
01524    //Failed to decode ASN.1 tag?
01525    if(error)
01526       return error;
01527 
01528    //Enforce encoding, class and type
01529    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
01530    //The tag does not match the criteria?
01531    if(error)
01532       return error;
01533 
01534    //This field is a sequence of one or more certificate extensions
01535    data = tag.value;
01536    length = tag.length;
01537 
01538    //Loop through the extensions
01539    while(length > 0)
01540    {
01541       //Read current extension
01542       error = asn1ReadTag(data, length, &tag);
01543       //Failed to decode ASN.1 tag?
01544       if(error)
01545          return error;
01546 
01547       //Enforce encoding, class and type
01548       error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
01549       //The tag does not match the criteria?
01550       if(error)
01551          return error;
01552 
01553       //Point to the next extension
01554       data += tag.totalLength;
01555       length -= tag.totalLength;
01556 
01557       //Contents of the current extension
01558       extensionData = tag.value;
01559       extensionLength = tag.length;
01560 
01561       //Read the object identifier
01562       error = asn1ReadTag(extensionData, extensionLength, &oidTag);
01563       //Failed to decode ASN.1 tag?
01564       if(error)
01565          return error;
01566 
01567       //Enforce encoding, class and type
01568       error = asn1CheckTag(&oidTag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OBJECT_IDENTIFIER);
01569       //The tag does not match the criteria?
01570       if(error)
01571          return error;
01572 
01573       //Next item
01574       extensionData += oidTag.totalLength;
01575       extensionLength -= oidTag.totalLength;
01576 
01577       //Read the Critical flag (if present)
01578       error = asn1ReadTag(extensionData, extensionLength, &tag);
01579       //Failed to decode ASN.1 tag?
01580       if(error)
01581          return error;
01582 
01583       //Enforce encoding, class and type
01584       error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_BOOLEAN);
01585 
01586       //Check whether the Critical field is present
01587       if(!error)
01588       {
01589          //Make sure the length of the boolean is valid
01590          if(tag.length != 1)
01591             return ERROR_INVALID_LENGTH;
01592 
01593          //Each extension in a certificate is designated as either
01594          //critical or non-critical
01595          critical = tag.value[0] ? TRUE : FALSE;
01596 
01597          //Next item
01598          extensionData += tag.totalLength;
01599          extensionLength -= tag.totalLength;
01600       }
01601       else
01602       {
01603          //The extension is considered as non-critical
01604          critical = FALSE;
01605       }
01606 
01607       //The extension itself is encapsulated in an octet string
01608       error = asn1ReadTag(extensionData, extensionLength, &tag);
01609       //Failed to decode ASN.1 tag?
01610       if(error)
01611          return error;
01612 
01613       //Enforce encoding, class and type
01614       error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OCTET_STRING);
01615       //The tag does not match the criteria?
01616       if(error)
01617          return error;
01618 
01619       //The current extension matches the BasicConstraints OID?
01620       if(!oidComp(oidTag.value, oidTag.length, X509_BASIC_CONSTRAINTS_OID, 3))
01621       {
01622          //Parse BasicConstraints extension
01623          error = x509ParseBasicConstraints(tag.value, tag.length, certInfo);
01624          //Any error to report?
01625          if(error)
01626             return error;
01627       }
01628       //The current extension matches the KeyUsage OID?
01629       else if(!oidComp(oidTag.value, oidTag.length, X509_KEY_USAGE_OID, 3))
01630       {
01631          //Parse KeyUsage extension
01632       }
01633       //The current extension matches the ExtendedKeyUsage OID?
01634       else if(!oidComp(oidTag.value, oidTag.length, X509_EXTENDED_KEY_USAGE_OID, 3))
01635       {
01636          //Parse ExtendedKeyUsage extension
01637       }
01638       //The current extension is marked as critical?
01639       else if(critical)
01640       {
01641          //A certificate-using system must reject the certificate if it encounters
01642          //a critical extension it does not recognize or a critical extension that
01643          //contains information that it cannot process
01644          return ERROR_UNSUPPORTED_EXTENSION;
01645       }
01646    }
01647 
01648    //Successful processing
01649    return NO_ERROR;
01650 }
01651 
01652 
01653 /**
01654  * @brief Parse BasicConstraints structure
01655  * @param[in] data Pointer to the ASN.1 structure to parse
01656  * @param[in] length Length of the ASN.1 structure
01657  * @param[out] certInfo Information resulting from the parsing process
01658  * @return Error code
01659  **/
01660 
01661 error_t x509ParseBasicConstraints(const uint8_t *data,
01662    size_t length, X509CertificateInfo *certInfo)
01663 {
01664    error_t error;
01665    Asn1Tag tag;
01666 
01667    //Debug message
01668    TRACE_DEBUG("      Parsing BasicConstraints...\r\n");
01669 
01670    //The BasicConstraints structure shall contain a valid sequence
01671    error = asn1ReadTag(data, length, &tag);
01672    //Failed to decode ASN.1 tag?
01673    if(error)
01674       return error;
01675 
01676    //Enforce encoding, class and type
01677    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
01678    //The tag does not match the criteria?
01679    if(error)
01680       return error;
01681 
01682    //Point to the first item of the sequence
01683    data = tag.value;
01684    length = tag.length;
01685 
01686    //The cA boolean is optional...
01687    if(length > 0)
01688    {
01689       //The cA boolean indicates whether the certified public key
01690       //may be used to verify certificate signatures
01691       error = asn1ReadTag(data, length, &tag);
01692       //Failed to decode ASN.1 tag?
01693       if(error)
01694          return error;
01695 
01696       //Enforce encoding, class and type
01697       error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_BOOLEAN);
01698 
01699       //The cA field is present?
01700       if(!error)
01701       {
01702          //The tag should be 1-byte long
01703          if(tag.length != 1)
01704             return ERROR_INVALID_LENGTH;
01705 
01706          //Get boolean value
01707          certInfo->basicConstraints.ca = tag.value ? TRUE : FALSE;
01708 
01709          //Point to the next item
01710          data += tag.totalLength;
01711          length -= tag.totalLength;
01712       }
01713    }
01714 
01715    //The pathLenConstraint field is optional...
01716    if(length > 0)
01717    {
01718       //The pathLenConstraint field gives the maximum number of non-self-issued
01719       //intermediate certificates that may follow this certificate in a valid
01720       //certification path
01721       error = asn1ReadTag(data, length, &tag);
01722       //Failed to decode ASN.1 tag?
01723       if(error)
01724          return error;
01725 
01726       //Enforce encoding, class and type
01727       error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER);
01728       //The tag does not match the criteria?
01729       if(error)
01730          return error;
01731 
01732       //The pathLenConstraint field is not supported
01733       certInfo->basicConstraints.pathLenConstraint = 0;
01734    }
01735 
01736    //Successful processing
01737    return NO_ERROR;
01738 }
01739 
01740 
01741 /**
01742  * @brief Parse SignatureAlgorithm structure
01743  * @param[in] data Pointer to the ASN.1 structure to parse
01744  * @param[in] length Length of the ASN.1 structure
01745  * @param[out] totalLength Number of bytes that have been parsed
01746  * @param[out] certInfo Information resulting from the parsing process
01747  * @return Error code
01748  **/
01749 
01750 error_t x509ParseSignatureAlgo(const uint8_t *data, size_t length,
01751    size_t *totalLength, X509CertificateInfo *certInfo)
01752 {
01753    error_t error;
01754    Asn1Tag tag;
01755 
01756    //Debug message
01757    TRACE_DEBUG("  Parsing SignatureAlgorithm...\r\n");
01758 
01759    //Read the contents of the SignatureAlgorithm field
01760    error = asn1ReadTag(data, length, &tag);
01761    //Failed to decode ASN.1 tag?
01762    if(error)
01763       return error;
01764 
01765    //Save the total length of the field
01766    *totalLength = tag.totalLength;
01767 
01768    //Enforce encoding, class and type
01769    error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE);
01770    //The tag does not match the criteria?
01771    if(error)
01772       return error;
01773 
01774    //Read the inner tag
01775    error = asn1ReadTag(tag.value, tag.length, &tag);
01776    //Failed to decode ASN.1 tag?
01777    if(error)
01778       return error;
01779 
01780    //This field must contain the same algorithm identifier
01781    //as the signature field in the TBSCertificate sequence
01782    error = asn1CheckOid(&tag, certInfo->signatureAlgo, certInfo->signatureAlgoLen);
01783    //The tag does not match the criteria?
01784    if(error)
01785       return error;
01786 
01787    //Successful processing
01788    return NO_ERROR;
01789 }
01790 
01791 
01792 /**
01793  * @brief Parse SignatureValue field
01794  * @param[in] data Pointer to the ASN.1 structure to parse
01795  * @param[in] length Length of the ASN.1 structure
01796  * @param[out] totalLength Number of bytes that have been parsed
01797  * @param[out] certInfo Information resulting from the parsing process
01798  * @return Error code
01799  **/
01800 
01801 error_t x509ParseSignatureValue(const uint8_t *data, size_t length,
01802    size_t *totalLength, X509CertificateInfo *certInfo)
01803 {
01804    error_t error;
01805    Asn1Tag tag;
01806 
01807    //Debug message
01808    TRACE_DEBUG("  Parsing SignatureValue...\r\n");
01809 
01810    //Read the contents of the SignatureValue structure
01811    error = asn1ReadTag(data, length, &tag);
01812    //Failed to decode ASN.1 tag?
01813    if(error)
01814       return error;
01815 
01816    //Save the total length of the field
01817    *totalLength = tag.totalLength;
01818 
01819    //Enforce encoding, class and type
01820    error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_BIT_STRING);
01821    //The tag does not match the criteria?
01822    if(error)
01823       return error;
01824 
01825    //The bit string shall contain an initial octet which encodes
01826    //the number of unused bits in the final subsequent octet
01827    if(tag.length < 1 || tag.value[0] != 0x00)
01828       return ERROR_FAILURE;
01829 
01830    //Get the signature value
01831    certInfo->signatureValue = tag.value + 1;
01832    certInfo->signatureValueLen = tag.length - 1;
01833 
01834    //Successful processing
01835    return NO_ERROR;
01836 }
01837 
01838 
01839 /**
01840  * @brief Convert string to integer
01841  * @param[in] data String containing the representation of an integral number
01842  * @param[in] length Length of the string
01843  * @param[out] value On success, the function returns the converted integral number
01844  * @return Error code
01845  **/
01846 
01847 error_t x509ParseInt(const uint8_t *data, size_t length, uint_t *value)
01848 {
01849    //Initialize integer value
01850    *value = 0;
01851 
01852    //Parse the string
01853    while(length > 0)
01854    {
01855       //Check whether the character is decimal digit
01856       if(!isdigit(*data))
01857          return ERROR_FAILURE;
01858 
01859       //Convert the string to integer
01860       *value = *value * 10 + (*data - '0');
01861 
01862       //Next character
01863       data++;
01864       length--;
01865    }
01866 
01867    //Successful processing
01868    return NO_ERROR;
01869 }
01870 
01871 
01872 /**
01873  * @brief Read a RSA public key
01874  * @param[in] certInfo X.509 certificate
01875  * @param[out] key RSA public key
01876  * @return Error code
01877  **/
01878 
01879 error_t x509ReadRsaPublicKey(const X509CertificateInfo *certInfo, RsaPublicKey *key)
01880 {
01881 #if (RSA_SUPPORT == ENABLED)
01882    error_t error;
01883 
01884    //The certificate shall contain a valid RSA public key
01885    if(!certInfo->subjectPublicKeyInfo.rsaPublicKey.n ||
01886       !certInfo->subjectPublicKeyInfo.rsaPublicKey.e)
01887    {
01888       //Report an error
01889       return ERROR_INVALID_KEY;
01890    }
01891 
01892    //Convert the modulus to a big number
01893    error = mpiReadRaw(&key->n, certInfo->subjectPublicKeyInfo.rsaPublicKey.n,
01894       certInfo->subjectPublicKeyInfo.rsaPublicKey.nLen);
01895    //Convertion failed?
01896    if(error)
01897       return error;
01898 
01899    //Convert the public exponent to a big number
01900    error = mpiReadRaw(&key->e, certInfo->subjectPublicKeyInfo.rsaPublicKey.e,
01901       certInfo->subjectPublicKeyInfo.rsaPublicKey.eLen);
01902    //Convertion failed?
01903    if(error)
01904       return error;
01905 
01906    //Debug message
01907    TRACE_DEBUG("RSA public key:\r\n");
01908    TRACE_DEBUG("  Modulus:\r\n");
01909    TRACE_DEBUG_MPI("    ", &key->n);
01910    TRACE_DEBUG("  Public exponent:\r\n");
01911    TRACE_DEBUG_MPI("    ", &key->e);
01912 
01913    //Successful processing
01914    return NO_ERROR;
01915 #else
01916    //Not implemented
01917    return ERROR_NOT_IMPLEMENTED;
01918 #endif
01919 }
01920 
01921 
01922 /**
01923  * @brief Read a DSA public key
01924  * @param[in] certInfo X.509 certificate
01925  * @param[out] key DSA public key
01926  * @return Error code
01927  **/
01928 
01929 error_t x509ReadDsaPublicKey(const X509CertificateInfo *certInfo, DsaPublicKey *key)
01930 {
01931 #if (DSA_SUPPORT == ENABLED)
01932    error_t error;
01933 
01934    //The certificate shall contain a valid DSA public key
01935    if(!certInfo->subjectPublicKeyInfo.dsaParams.p ||
01936       !certInfo->subjectPublicKeyInfo.dsaParams.q ||
01937       !certInfo->subjectPublicKeyInfo.dsaParams.g ||
01938       !certInfo->subjectPublicKeyInfo.dsaPublicKey.y)
01939    {
01940       //Report an error
01941       return ERROR_INVALID_KEY;
01942    }
01943 
01944    //Convert the parameter p to a big number
01945    error = mpiReadRaw(&key->p, certInfo->subjectPublicKeyInfo.dsaParams.p,
01946       certInfo->subjectPublicKeyInfo.dsaParams.pLen);
01947    //Convertion failed?
01948    if(error)
01949       return error;
01950 
01951    //Convert the parameter q to a big number
01952    error = mpiReadRaw(&key->q, certInfo->subjectPublicKeyInfo.dsaParams.q,
01953       certInfo->subjectPublicKeyInfo.dsaParams.qLen);
01954    //Convertion failed?
01955    if(error)
01956       return error;
01957 
01958    //Convert the parameter g to a big number
01959    error = mpiReadRaw(&key->g, certInfo->subjectPublicKeyInfo.dsaParams.g,
01960       certInfo->subjectPublicKeyInfo.dsaParams.gLen);
01961    //Convertion failed?
01962    if(error)
01963       return error;
01964 
01965    //Convert the public value to a big number
01966    error = mpiReadRaw(&key->y, certInfo->subjectPublicKeyInfo.dsaPublicKey.y,
01967       certInfo->subjectPublicKeyInfo.dsaPublicKey.yLen);
01968    //Convertion failed?
01969    if(error)
01970       return error;
01971 
01972    //Debug message
01973    TRACE_DEBUG("DSA public key:\r\n");
01974    TRACE_DEBUG("  Parameter p:\r\n");
01975    TRACE_DEBUG_MPI("    ", &key->p);
01976    TRACE_DEBUG("  Parameter q:\r\n");
01977    TRACE_DEBUG_MPI("    ", &key->q);
01978    TRACE_DEBUG("  Parameter g:\r\n");
01979    TRACE_DEBUG_MPI("    ", &key->g);
01980    TRACE_DEBUG("  Public value y:\r\n");
01981    TRACE_DEBUG_MPI("    ", &key->y);
01982 
01983    //Successful processing
01984    return NO_ERROR;
01985 #else
01986    //Not implemented
01987    return ERROR_NOT_IMPLEMENTED;
01988 #endif
01989 }
01990 
01991 
01992 /**
01993  * @brief X.509 certificate validation
01994  * @param[in] certInfo X.509 certificate to be verified
01995  * @param[in] issuerCertInfo Issuer certificate
01996  * @return Error code
01997  **/
01998 
01999 error_t x509ValidateCertificate(const X509CertificateInfo *certInfo,
02000    const X509CertificateInfo *issuerCertInfo)
02001 {
02002    error_t error;
02003    time_t currentTime;
02004    time_t notBefore;
02005    time_t notAfter;
02006    const HashAlgo *hashAlgo;
02007    HashContext *hashContext;
02008 
02009    //Use RSA, DSA or ECDSA signature algorithm?
02010 #if (RSA_SUPPORT == ENABLED)
02011    bool_t rsaSignAlgo = FALSE;
02012 #endif
02013 #if (DSA_SUPPORT == ENABLED)
02014    bool_t dsaSignAlgo = FALSE;
02015 #endif
02016 #if (ECDSA_SUPPORT == ENABLED)
02017    bool_t ecdsaSignAlgo = FALSE;
02018 #endif
02019 
02020    //Retrieve current time
02021    currentTime = getCurrentUnixTime();
02022 
02023    //Any real-time clock implemented?
02024    if(currentTime != 0)
02025    {
02026       //Convert NotBefore and NotAfter to Unix timestamps
02027       notBefore = convertDateToUnixTime(&certInfo->validity.notBefore);
02028       notAfter = convertDateToUnixTime(&certInfo->validity.notAfter);
02029 
02030       //Check the certificate validity period
02031       if(currentTime < notBefore || currentTime > notAfter)
02032          return ERROR_CERTIFICATE_EXPIRED;
02033    }
02034 
02035    //Make sure that the subject and issuer names chain correctly
02036    if(certInfo->issuer.rawDataLen != issuerCertInfo->subject.rawDataLen)
02037       return ERROR_BAD_CERTIFICATE;
02038    if(memcmp(certInfo->issuer.rawData, issuerCertInfo->subject.rawData, certInfo->issuer.rawDataLen))
02039       return ERROR_BAD_CERTIFICATE;
02040 
02041    //Ensure that the issuer certificate is a CA certificate
02042    if(issuerCertInfo->version >= X509_VERSION_3 && !issuerCertInfo->basicConstraints.ca)
02043       return ERROR_BAD_CERTIFICATE;
02044 
02045    //Retrieve the signature algorithm that has been used to sign the certificate
02046 #if (RSA_SUPPORT == ENABLED && MD5_SUPPORT == ENABLED)
02047    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02048       MD5_WITH_RSA_ENCRYPTION_OID, sizeof(MD5_WITH_RSA_ENCRYPTION_OID)))
02049    {
02050       //MD5 with RSA signature algorithm
02051       rsaSignAlgo = TRUE;
02052       hashAlgo = MD5_HASH_ALGO;
02053    }
02054    else
02055 #endif
02056 #if (RSA_SUPPORT == ENABLED && SHA1_SUPPORT == ENABLED)
02057    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02058       SHA1_WITH_RSA_ENCRYPTION_OID, sizeof(SHA1_WITH_RSA_ENCRYPTION_OID)))
02059    {
02060       //SHA-1 with RSA signature algorithm
02061       rsaSignAlgo = TRUE;
02062       hashAlgo = SHA1_HASH_ALGO;
02063    }
02064    else
02065 #endif
02066 #if (RSA_SUPPORT == ENABLED && SHA256_SUPPORT == ENABLED)
02067    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02068       SHA256_WITH_RSA_ENCRYPTION_OID, sizeof(SHA256_WITH_RSA_ENCRYPTION_OID)))
02069    {
02070       //SHA-256 with RSA signature algorithm
02071       rsaSignAlgo = TRUE;
02072       hashAlgo = SHA256_HASH_ALGO;
02073    }
02074    else
02075 #endif
02076 #if (RSA_SUPPORT == ENABLED && SHA384_SUPPORT == ENABLED)
02077    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02078       SHA384_WITH_RSA_ENCRYPTION_OID, sizeof(SHA384_WITH_RSA_ENCRYPTION_OID)))
02079    {
02080       //SHA-384 with RSA signature algorithm
02081       rsaSignAlgo = TRUE;
02082       hashAlgo = SHA384_HASH_ALGO;
02083    }
02084    else
02085 #endif
02086 #if (RSA_SUPPORT == ENABLED && SHA512_SUPPORT == ENABLED)
02087    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02088       SHA512_WITH_RSA_ENCRYPTION_OID, sizeof(SHA512_WITH_RSA_ENCRYPTION_OID)))
02089    {
02090       //SHA-512 with RSA signature algorithm
02091       rsaSignAlgo = TRUE;
02092       hashAlgo = SHA512_HASH_ALGO;
02093    }
02094    else
02095 #endif
02096 #if (DSA_SUPPORT == ENABLED && SHA1_SUPPORT == ENABLED)
02097    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02098       DSA_WITH_SHA1_OID, sizeof(DSA_WITH_SHA1_OID)))
02099    {
02100       //DSA with SHA-1 signature algorithm
02101       dsaSignAlgo = TRUE;
02102       hashAlgo = SHA1_HASH_ALGO;
02103    }
02104    else
02105 #endif
02106 #if (DSA_SUPPORT == ENABLED && SHA224_SUPPORT == ENABLED)
02107    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02108       DSA_WITH_SHA224_OID, sizeof(DSA_WITH_SHA224_OID)))
02109    {
02110       //DSA with SHA-224 signature algorithm
02111       dsaSignAlgo = TRUE;
02112       hashAlgo = SHA224_HASH_ALGO;
02113    }
02114    else
02115 #endif
02116 #if (DSA_SUPPORT == ENABLED && SHA256_SUPPORT == ENABLED)
02117    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02118       DSA_WITH_SHA256_OID, sizeof(DSA_WITH_SHA256_OID)))
02119    {
02120       //DSA with SHA-256 signature algorithm
02121       dsaSignAlgo = TRUE;
02122       hashAlgo = SHA256_HASH_ALGO;
02123    }
02124    else
02125 #endif
02126 #if (ECDSA_SUPPORT == ENABLED && SHA1_SUPPORT == ENABLED)
02127    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02128       ECDSA_WITH_SHA1_OID, sizeof(ECDSA_WITH_SHA1_OID)))
02129    {
02130       //ECDSA with SHA-1 signature algorithm
02131       ecdsaSignAlgo = TRUE;
02132       hashAlgo = SHA1_HASH_ALGO;
02133    }
02134    else
02135 #endif
02136 #if (ECDSA_SUPPORT == ENABLED && SHA224_SUPPORT == ENABLED)
02137    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02138       ECDSA_WITH_SHA224_OID, sizeof(ECDSA_WITH_SHA224_OID)))
02139    {
02140       //ECDSA with SHA-224 signature algorithm
02141       ecdsaSignAlgo = TRUE;
02142       hashAlgo = SHA224_HASH_ALGO;
02143    }
02144    else
02145 #endif
02146 #if (ECDSA_SUPPORT == ENABLED && SHA256_SUPPORT == ENABLED)
02147    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02148       ECDSA_WITH_SHA256_OID, sizeof(ECDSA_WITH_SHA256_OID)))
02149    {
02150       //ECDSA with SHA-256 signature algorithm
02151       ecdsaSignAlgo = TRUE;
02152       hashAlgo = SHA256_HASH_ALGO;
02153    }
02154    else
02155 #endif
02156 #if (ECDSA_SUPPORT == ENABLED && SHA384_SUPPORT == ENABLED)
02157    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02158       ECDSA_WITH_SHA384_OID, sizeof(ECDSA_WITH_SHA384_OID)))
02159    {
02160       //ECDSA with SHA-384 signature algorithm
02161       ecdsaSignAlgo = TRUE;
02162       hashAlgo = SHA384_HASH_ALGO;
02163    }
02164    else
02165 #endif
02166 #if (ECDSA_SUPPORT == ENABLED && SHA512_SUPPORT == ENABLED)
02167    if(!oidComp(certInfo->signatureAlgo, certInfo->signatureAlgoLen,
02168       ECDSA_WITH_SHA512_OID, sizeof(ECDSA_WITH_SHA512_OID)))
02169    {
02170       //ECDSA with SHA-512 signature algorithm
02171       ecdsaSignAlgo = TRUE;
02172       hashAlgo = SHA512_HASH_ALGO;
02173    }
02174    else
02175 #endif
02176    {
02177       //The specified signature algorithm is not supported
02178       return ERROR_UNSUPPORTED_SIGNATURE_ALGO;
02179    }
02180 
02181    //Allocate a memory buffer to hold the hash context
02182    hashContext = cryptoAllocMem(hashAlgo->contextSize);
02183    //Failed to allocate memory?
02184    if(hashContext == NULL)
02185       return ERROR_OUT_OF_MEMORY;
02186 
02187    //Digest the TBSCertificate structure using the specified hash algorithm
02188    hashAlgo->init(hashContext);
02189    hashAlgo->update(hashContext, certInfo->tbsCertificate, certInfo->tbsCertificateLen);
02190    hashAlgo->final(hashContext, NULL);
02191 
02192    //Check signature algorithm
02193 #if (RSA_SUPPORT == ENABLED)
02194    if(rsaSignAlgo)
02195    {
02196       RsaPublicKey publicKey;
02197 
02198       //Initialize RSA public key
02199       rsaInitPublicKey(&publicKey);
02200 
02201       //Get the RSA public key
02202       error = x509ReadRsaPublicKey(issuerCertInfo, &publicKey);
02203 
02204       //Check status code
02205       if(!error)
02206       {
02207          //Verify RSA signature
02208          error = rsassaPkcs1v15Verify(&publicKey, hashAlgo, hashContext->digest,
02209             certInfo->signatureValue, certInfo->signatureValueLen);
02210       }
02211 
02212       //Release previously allocated resources
02213       rsaFreePublicKey(&publicKey);
02214    }
02215    else
02216 #endif
02217 #if (DSA_SUPPORT == ENABLED)
02218    if(dsaSignAlgo)
02219    {
02220       DsaPublicKey publicKey;
02221       DsaSignature signature;
02222 
02223       //Initialize DSA public key
02224       dsaInitPublicKey(&publicKey);
02225       //Initialize DSA signature
02226       dsaInitSignature(&signature);
02227 
02228       //Get the DSA public key
02229       error = x509ReadDsaPublicKey(issuerCertInfo, &publicKey);
02230 
02231       //Check status code
02232       if(!error)
02233       {
02234          //Read the ASN.1 encoded signature
02235          error = dsaReadSignature(certInfo->signatureValue,
02236             certInfo->signatureValueLen, &signature);
02237       }
02238 
02239       //Check status code
02240       if(!error)
02241       {
02242          //Verify DSA signature
02243          error = dsaVerifySignature(&publicKey, hashContext->digest,
02244             hashAlgo->digestSize, &signature);
02245       }
02246 
02247       //Release previously allocated resources
02248       dsaFreePublicKey(&publicKey);
02249       dsaFreeSignature(&signature);
02250    }
02251    else
02252 #endif
02253 #if (ECDSA_SUPPORT == ENABLED)
02254    if(ecdsaSignAlgo)
02255    {
02256       const EcCurveInfo *curveInfo;
02257       EcDomainParameters params;
02258       EcPoint publicKey;
02259       EcdsaSignature signature;
02260 
02261       //Initialize EC domain parameters
02262       ecInitDomainParameters(&params);
02263       //Initialize ECDSA public key
02264       ecInit(&publicKey);
02265       //Initialize ECDSA signature
02266       ecdsaInitSignature(&signature);
02267 
02268       //Retrieve EC domain parameters
02269       curveInfo = ecGetCurveInfo(issuerCertInfo->subjectPublicKeyInfo.ecParams.namedCurve,
02270          issuerCertInfo->subjectPublicKeyInfo.ecParams.namedCurveLen);
02271 
02272       //Make sure the specified elliptic curve is supported
02273       error = (curveInfo == NULL) ? ERROR_BAD_CERTIFICATE : NO_ERROR;
02274 
02275       //Check status code
02276       if(!error)
02277       {
02278          //Load EC domain parameters
02279          error = ecLoadDomainParameters(&params, curveInfo);
02280       }
02281 
02282       //Check status code
02283       if(!error)
02284       {
02285          //Retrieve the EC public key
02286          error = ecImport(&params, &publicKey, issuerCertInfo->subjectPublicKeyInfo.ecPublicKey.q,
02287             issuerCertInfo->subjectPublicKeyInfo.ecPublicKey.qLen);
02288       }
02289 
02290       //Check status code
02291       if(!error)
02292       {
02293          //Read the ASN.1 encoded signature
02294          error = ecdsaReadSignature(certInfo->signatureValue,
02295             certInfo->signatureValueLen, &signature);
02296       }
02297 
02298       //Check status code
02299       if(!error)
02300       {
02301          //Verify ECDSA signature
02302          error = ecdsaVerifySignature(&params, &publicKey,
02303             hashContext->digest, hashAlgo->digestSize, &signature);
02304       }
02305 
02306       //Release previously allocated resources
02307       ecFreeDomainParameters(&params);
02308       ecFree(&publicKey);
02309       ecdsaFreeSignature(&signature);
02310    }
02311    else
02312 #endif
02313    {
02314       //The signature algorithm is not supported...
02315       error = ERROR_UNSUPPORTED_SIGNATURE_ALGO;
02316    }
02317 
02318    //Release hash algorithm context
02319    cryptoFreeMem(hashContext);
02320    //Return status code
02321    return error;
02322 }
02323 
02324 #endif
02325