iPXE
x509.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <errno.h>
00029 #include <assert.h>
00030 #include <ipxe/list.h>
00031 #include <ipxe/base16.h>
00032 #include <ipxe/asn1.h>
00033 #include <ipxe/crypto.h>
00034 #include <ipxe/md5.h>
00035 #include <ipxe/sha1.h>
00036 #include <ipxe/sha256.h>
00037 #include <ipxe/rsa.h>
00038 #include <ipxe/rootcert.h>
00039 #include <ipxe/certstore.h>
00040 #include <ipxe/socket.h>
00041 #include <ipxe/in.h>
00042 #include <ipxe/image.h>
00043 #include <ipxe/ocsp.h>
00044 #include <ipxe/x509.h>
00045 #include <config/crypto.h>
00046 
00047 /** @file
00048  *
00049  * X.509 certificates
00050  *
00051  * The structure of X.509v3 certificates is documented in RFC 5280
00052  * section 4.1.
00053  */
00054 
00055 /* Disambiguate the various error causes */
00056 #define ENOTSUP_ALGORITHM \
00057         __einfo_error ( EINFO_ENOTSUP_ALGORITHM )
00058 #define EINFO_ENOTSUP_ALGORITHM \
00059         __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" )
00060 #define ENOTSUP_EXTENSION \
00061         __einfo_error ( EINFO_ENOTSUP_EXTENSION )
00062 #define EINFO_ENOTSUP_EXTENSION \
00063         __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported extension" )
00064 #define EINVAL_ALGORITHM \
00065         __einfo_error ( EINFO_EINVAL_ALGORITHM )
00066 #define EINFO_EINVAL_ALGORITHM \
00067         __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" )
00068 #define EINVAL_ALGORITHM_MISMATCH \
00069         __einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH )
00070 #define EINFO_EINVAL_ALGORITHM_MISMATCH \
00071         __einfo_uniqify ( EINFO_EINVAL, 0x04, "Signature algorithm mismatch" )
00072 #define EINVAL_PATH_LEN \
00073         __einfo_error ( EINFO_EINVAL_PATH_LEN )
00074 #define EINFO_EINVAL_PATH_LEN \
00075         __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid pathLenConstraint" )
00076 #define EINVAL_VERSION \
00077         __einfo_error ( EINFO_EINVAL_VERSION )
00078 #define EINFO_EINVAL_VERSION \
00079         __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid version" )
00080 #define EACCES_WRONG_ISSUER \
00081         __einfo_error ( EINFO_EACCES_WRONG_ISSUER )
00082 #define EINFO_EACCES_WRONG_ISSUER \
00083         __einfo_uniqify ( EINFO_EACCES, 0x01, "Wrong issuer" )
00084 #define EACCES_NOT_CA \
00085         __einfo_error ( EINFO_EACCES_NOT_CA )
00086 #define EINFO_EACCES_NOT_CA \
00087         __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a CA certificate" )
00088 #define EACCES_KEY_USAGE \
00089         __einfo_error ( EINFO_EACCES_KEY_USAGE )
00090 #define EINFO_EACCES_KEY_USAGE \
00091         __einfo_uniqify ( EINFO_EACCES, 0x03, "Incorrect key usage" )
00092 #define EACCES_EXPIRED \
00093         __einfo_error ( EINFO_EACCES_EXPIRED )
00094 #define EINFO_EACCES_EXPIRED \
00095         __einfo_uniqify ( EINFO_EACCES, 0x04, "Expired (or not yet valid)" )
00096 #define EACCES_PATH_LEN \
00097         __einfo_error ( EINFO_EACCES_PATH_LEN )
00098 #define EINFO_EACCES_PATH_LEN \
00099         __einfo_uniqify ( EINFO_EACCES, 0x05, "Maximum path length exceeded" )
00100 #define EACCES_UNTRUSTED \
00101         __einfo_error ( EINFO_EACCES_UNTRUSTED )
00102 #define EINFO_EACCES_UNTRUSTED \
00103         __einfo_uniqify ( EINFO_EACCES, 0x06, "Untrusted root certificate" )
00104 #define EACCES_OUT_OF_ORDER \
00105         __einfo_error ( EINFO_EACCES_OUT_OF_ORDER )
00106 #define EINFO_EACCES_OUT_OF_ORDER \
00107         __einfo_uniqify ( EINFO_EACCES, 0x07, "Validation out of order" )
00108 #define EACCES_EMPTY \
00109         __einfo_error ( EINFO_EACCES_EMPTY )
00110 #define EINFO_EACCES_EMPTY \
00111         __einfo_uniqify ( EINFO_EACCES, 0x08, "Empty certificate chain" )
00112 #define EACCES_OCSP_REQUIRED \
00113         __einfo_error ( EINFO_EACCES_OCSP_REQUIRED )
00114 #define EINFO_EACCES_OCSP_REQUIRED \
00115         __einfo_uniqify ( EINFO_EACCES, 0x09, "OCSP check required" )
00116 #define EACCES_WRONG_NAME \
00117         __einfo_error ( EINFO_EACCES_WRONG_NAME )
00118 #define EINFO_EACCES_WRONG_NAME \
00119         __einfo_uniqify ( EINFO_EACCES, 0x0a, "Incorrect certificate name" )
00120 #define EACCES_USELESS \
00121         __einfo_error ( EINFO_EACCES_USELESS )
00122 #define EINFO_EACCES_USELESS \
00123         __einfo_uniqify ( EINFO_EACCES, 0x0b, "No usable certificates" )
00124 
00125 /**
00126  * Get X.509 certificate display name
00127  *
00128  * @v cert              X.509 certificate
00129  * @ret name            Display name
00130  */
00131 const char * x509_name ( struct x509_certificate *cert ) {
00132         struct asn1_cursor *common_name = &cert->subject.common_name;
00133         struct digest_algorithm *digest = &sha1_algorithm;
00134         static char buf[64];
00135         uint8_t fingerprint[ digest->digestsize ];
00136         size_t len;
00137 
00138         len = common_name->len;
00139         if ( len ) {
00140                 /* Certificate has a commonName: use that */
00141                 if ( len > ( sizeof ( buf ) - 1 /* NUL */ ) )
00142                         len = ( sizeof ( buf ) - 1 /* NUL */ );
00143                 memcpy ( buf, common_name->data, len );
00144                 buf[len] = '\0';
00145         } else {
00146                 /* Certificate has no commonName: use SHA-1 fingerprint */
00147                 x509_fingerprint ( cert, digest, fingerprint );
00148                 base16_encode ( fingerprint, sizeof ( fingerprint ),
00149                                 buf, sizeof ( buf ) );
00150         }
00151         return buf;
00152 }
00153 
00154 /** "commonName" object identifier */
00155 static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME };
00156 
00157 /** "commonName" object identifier cursor */
00158 static struct asn1_cursor oid_common_name_cursor =
00159         ASN1_OID_CURSOR ( oid_common_name );
00160 
00161 /**
00162  * Parse X.509 certificate version
00163  *
00164  * @v cert              X.509 certificate
00165  * @v raw               ASN.1 cursor
00166  * @ret rc              Return status code
00167  */
00168 static int x509_parse_version ( struct x509_certificate *cert,
00169                                 const struct asn1_cursor *raw ) {
00170         struct asn1_cursor cursor;
00171         int version;
00172         int rc;
00173 
00174         /* Enter version */
00175         memcpy ( &cursor, raw, sizeof ( cursor ) );
00176         asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
00177 
00178         /* Parse integer */
00179         if ( ( rc = asn1_integer ( &cursor, &version ) ) != 0 ) {
00180                 DBGC ( cert, "X509 %p cannot parse version: %s\n",
00181                        cert, strerror ( rc ) );
00182                 DBGC_HDA ( cert, 0, raw->data, raw->len );
00183                 return rc;
00184         }
00185 
00186         /* Sanity check */
00187         if ( version < 0 ) {
00188                 DBGC ( cert, "X509 %p invalid version %d\n", cert, version );
00189                 DBGC_HDA ( cert, 0, raw->data, raw->len );
00190                 return -EINVAL_VERSION;
00191         }
00192 
00193         /* Record version */
00194         cert->version = version;
00195         DBGC2 ( cert, "X509 %p is a version %d certificate\n",
00196                 cert, ( cert->version + 1 ) );
00197 
00198         return 0;
00199 }
00200 
00201 /**
00202  * Parse X.509 certificate serial number
00203  *
00204  * @v cert              X.509 certificate
00205  * @v raw               ASN.1 cursor
00206  * @ret rc              Return status code
00207  */
00208 static int x509_parse_serial ( struct x509_certificate *cert,
00209                                const struct asn1_cursor *raw ) {
00210         struct x509_serial *serial = &cert->serial;
00211         int rc;
00212 
00213         /* Record raw serial number */
00214         memcpy ( &serial->raw, raw, sizeof ( serial->raw ) );
00215         if ( ( rc = asn1_shrink ( &serial->raw, ASN1_INTEGER ) ) != 0 ) {
00216                 DBGC ( cert, "X509 %p cannot shrink serialNumber: %s\n",
00217                        cert, strerror ( rc ) );
00218                 return rc;
00219         }
00220         DBGC2 ( cert, "X509 %p issuer is:\n", cert );
00221         DBGC2_HDA ( cert, 0, serial->raw.data, serial->raw.len );
00222 
00223         return 0;
00224 }
00225 
00226 /**
00227  * Parse X.509 certificate issuer
00228  *
00229  * @v cert              X.509 certificate
00230  * @v raw               ASN.1 cursor
00231  * @ret rc              Return status code
00232  */
00233 static int x509_parse_issuer ( struct x509_certificate *cert,
00234                                const struct asn1_cursor *raw ) {
00235         struct x509_issuer *issuer = &cert->issuer;
00236         int rc;
00237 
00238         /* Record raw issuer */
00239         memcpy ( &issuer->raw, raw, sizeof ( issuer->raw ) );
00240         if ( ( rc = asn1_shrink ( &issuer->raw, ASN1_SEQUENCE ) ) != 0 ) {
00241                 DBGC ( cert, "X509 %p cannot shrink issuer: %s\n",
00242                        cert, strerror ( rc ) );
00243                 return rc;
00244         }
00245         DBGC2 ( cert, "X509 %p issuer is:\n", cert );
00246         DBGC2_HDA ( cert, 0, issuer->raw.data, issuer->raw.len );
00247 
00248         return 0;
00249 }
00250 
00251 /**
00252  * Parse X.509 certificate validity
00253  *
00254  * @v cert              X.509 certificate
00255  * @v raw               ASN.1 cursor
00256  * @ret rc              Return status code
00257  */
00258 static int x509_parse_validity ( struct x509_certificate *cert,
00259                                  const struct asn1_cursor *raw ) {
00260         struct x509_validity *validity = &cert->validity;
00261         struct x509_time *not_before = &validity->not_before;
00262         struct x509_time *not_after = &validity->not_after;
00263         struct asn1_cursor cursor;
00264         int rc;
00265 
00266         /* Enter validity */
00267         memcpy ( &cursor, raw, sizeof ( cursor ) );
00268         asn1_enter ( &cursor, ASN1_SEQUENCE );
00269 
00270         /* Parse notBefore */
00271         if ( ( rc = asn1_generalized_time ( &cursor,
00272                                             &not_before->time ) ) != 0 ) {
00273                 DBGC ( cert, "X509 %p cannot parse notBefore: %s\n",
00274                        cert, strerror ( rc ) );
00275                 return rc;
00276         }
00277         DBGC2 ( cert, "X509 %p valid from time %lld\n",
00278                 cert, not_before->time );
00279         asn1_skip_any ( &cursor );
00280 
00281         /* Parse notAfter */
00282         if ( ( rc = asn1_generalized_time ( &cursor,
00283                                             &not_after->time ) ) != 0 ) {
00284                 DBGC ( cert, "X509 %p cannot parse notAfter: %s\n",
00285                        cert, strerror ( rc ) );
00286                 return rc;
00287         }
00288         DBGC2 ( cert, "X509 %p valid until time %lld\n",
00289                 cert, not_after->time );
00290 
00291         return 0;
00292 }
00293 
00294 /**
00295  * Parse X.509 certificate common name
00296  *
00297  * @v cert              X.509 certificate
00298  * @v raw               ASN.1 cursor
00299  * @ret rc              Return status code
00300  */
00301 static int x509_parse_common_name ( struct x509_certificate *cert,
00302                                     const struct asn1_cursor *raw ) {
00303         struct asn1_cursor cursor;
00304         struct asn1_cursor oid_cursor;
00305         struct asn1_cursor name_cursor;
00306         int rc;
00307 
00308         /* Enter name */
00309         memcpy ( &cursor, raw, sizeof ( cursor ) );
00310         asn1_enter ( &cursor, ASN1_SEQUENCE );
00311 
00312         /* Scan through name list */
00313         for ( ; cursor.len ; asn1_skip_any ( &cursor ) ) {
00314 
00315                 /* Check for "commonName" OID */
00316                 memcpy ( &oid_cursor, &cursor, sizeof ( oid_cursor ) );
00317                 asn1_enter ( &oid_cursor, ASN1_SET );
00318                 asn1_enter ( &oid_cursor, ASN1_SEQUENCE );
00319                 memcpy ( &name_cursor, &oid_cursor, sizeof ( name_cursor ) );
00320                 asn1_enter ( &oid_cursor, ASN1_OID );
00321                 if ( asn1_compare ( &oid_common_name_cursor, &oid_cursor ) != 0)
00322                         continue;
00323                 asn1_skip_any ( &name_cursor );
00324                 if ( ( rc = asn1_enter_any ( &name_cursor ) ) != 0 ) {
00325                         DBGC ( cert, "X509 %p cannot locate name:\n", cert );
00326                         DBGC_HDA ( cert, 0, raw->data, raw->len );
00327                         return rc;
00328                 }
00329 
00330                 /* Record common name */
00331                 memcpy ( &cert->subject.common_name, &name_cursor,
00332                          sizeof ( cert->subject.common_name ) );
00333 
00334                 return 0;
00335         }
00336 
00337         /* Certificates may not have a commonName */
00338         DBGC2 ( cert, "X509 %p no commonName found:\n", cert );
00339         return 0;
00340 }
00341 
00342 /**
00343  * Parse X.509 certificate subject
00344  *
00345  * @v cert              X.509 certificate
00346  * @v raw               ASN.1 cursor
00347  * @ret rc              Return status code
00348  */
00349 static int x509_parse_subject ( struct x509_certificate *cert,
00350                                 const struct asn1_cursor *raw ) {
00351         struct x509_subject *subject = &cert->subject;
00352         int rc;
00353 
00354         /* Record raw subject */
00355         memcpy ( &subject->raw, raw, sizeof ( subject->raw ) );
00356         asn1_shrink_any ( &subject->raw );
00357         DBGC2 ( cert, "X509 %p subject is:\n", cert );
00358         DBGC2_HDA ( cert, 0, subject->raw.data, subject->raw.len );
00359 
00360         /* Parse common name */
00361         if ( ( rc = x509_parse_common_name ( cert, raw ) ) != 0 )
00362                 return rc;
00363         DBGC2 ( cert, "X509 %p common name is \"%s\":\n", cert,
00364                 x509_name ( cert ) );
00365 
00366         return 0;
00367 }
00368 
00369 /**
00370  * Parse X.509 certificate public key information
00371  *
00372  * @v cert              X.509 certificate
00373  * @v raw               ASN.1 cursor
00374  * @ret rc              Return status code
00375  */
00376 static int x509_parse_public_key ( struct x509_certificate *cert,
00377                                    const struct asn1_cursor *raw ) {
00378         struct x509_public_key *public_key = &cert->subject.public_key;
00379         struct asn1_algorithm **algorithm = &public_key->algorithm;
00380         struct asn1_bit_string *raw_bits = &public_key->raw_bits;
00381         struct asn1_cursor cursor;
00382         int rc;
00383 
00384         /* Record raw subjectPublicKeyInfo */
00385         memcpy ( &cursor, raw, sizeof ( cursor ) );
00386         asn1_shrink_any ( &cursor );
00387         memcpy ( &public_key->raw, &cursor, sizeof ( public_key->raw ) );
00388         DBGC2 ( cert, "X509 %p public key is:\n", cert );
00389         DBGC2_HDA ( cert, 0, public_key->raw.data, public_key->raw.len );
00390 
00391         /* Enter subjectPublicKeyInfo */
00392         asn1_enter ( &cursor, ASN1_SEQUENCE );
00393 
00394         /* Parse algorithm */
00395         if ( ( rc = asn1_pubkey_algorithm ( &cursor, algorithm ) ) != 0 ) {
00396                 DBGC ( cert, "X509 %p could not parse public key algorithm: "
00397                        "%s\n", cert, strerror ( rc ) );
00398                 return rc;
00399         }
00400         DBGC2 ( cert, "X509 %p public key algorithm is %s\n",
00401                 cert, (*algorithm)->name );
00402         asn1_skip_any ( &cursor );
00403 
00404         /* Parse bit string */
00405         if ( ( rc = asn1_bit_string ( &cursor, raw_bits ) ) != 0 ) {
00406                 DBGC ( cert, "X509 %p could not parse public key bits: %s\n",
00407                        cert, strerror ( rc ) );
00408                 return rc;
00409         }
00410 
00411         return 0;
00412 }
00413 
00414 /**
00415  * Parse X.509 certificate basic constraints
00416  *
00417  * @v cert              X.509 certificate
00418  * @v raw               ASN.1 cursor
00419  * @ret rc              Return status code
00420  */
00421 static int x509_parse_basic_constraints ( struct x509_certificate *cert,
00422                                           const struct asn1_cursor *raw ) {
00423         struct x509_basic_constraints *basic = &cert->extensions.basic;
00424         struct asn1_cursor cursor;
00425         int ca = 0;
00426         int path_len;
00427         int rc;
00428 
00429         /* Enter basicConstraints */
00430         memcpy ( &cursor, raw, sizeof ( cursor ) );
00431         asn1_enter ( &cursor, ASN1_SEQUENCE );
00432 
00433         /* Parse "cA", if present */
00434         if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) {
00435                 ca = asn1_boolean ( &cursor );
00436                 if ( ca < 0 ) {
00437                         rc = ca;
00438                         DBGC ( cert, "X509 %p cannot parse cA: %s\n",
00439                                cert, strerror ( rc ) );
00440                         DBGC_HDA ( cert, 0, raw->data, raw->len );
00441                         return rc;
00442                 }
00443                 asn1_skip_any ( &cursor );
00444         }
00445         basic->ca = ca;
00446         DBGC2 ( cert, "X509 %p is %sa CA certificate\n",
00447                 cert, ( basic->ca ? "" : "not " ) );
00448 
00449         /* Ignore everything else unless "cA" is true */
00450         if ( ! ca )
00451                 return 0;
00452 
00453         /* Parse "pathLenConstraint", if present and applicable */
00454         basic->path_len = X509_PATH_LEN_UNLIMITED;
00455         if ( asn1_type ( &cursor ) == ASN1_INTEGER ) {
00456                 if ( ( rc = asn1_integer ( &cursor, &path_len ) ) != 0 ) {
00457                         DBGC ( cert, "X509 %p cannot parse pathLenConstraint: "
00458                                "%s\n", cert, strerror ( rc ) );
00459                         DBGC_HDA ( cert, 0, raw->data, raw->len );
00460                         return rc;
00461                 }
00462                 if ( path_len < 0 ) {
00463                         DBGC ( cert, "X509 %p invalid pathLenConstraint %d\n",
00464                                cert, path_len );
00465                         DBGC_HDA ( cert, 0, raw->data, raw->len );
00466                         return -EINVAL;
00467                 }
00468                 basic->path_len = path_len;
00469                 DBGC2 ( cert, "X509 %p path length constraint is %d\n",
00470                         cert, basic->path_len );
00471         }
00472 
00473         return 0;
00474 }
00475 
00476 /**
00477  * Parse X.509 certificate key usage
00478  *
00479  * @v cert              X.509 certificate
00480  * @v raw               ASN.1 cursor
00481  * @ret rc              Return status code
00482  */
00483 static int x509_parse_key_usage ( struct x509_certificate *cert,
00484                                   const struct asn1_cursor *raw ) {
00485         struct x509_key_usage *usage = &cert->extensions.usage;
00486         struct asn1_bit_string bit_string;
00487         const uint8_t *bytes;
00488         size_t len;
00489         unsigned int i;
00490         int rc;
00491 
00492         /* Mark extension as present */
00493         usage->present = 1;
00494 
00495         /* Parse bit string */
00496         if ( ( rc = asn1_bit_string ( raw, &bit_string ) ) != 0 ) {
00497                 DBGC ( cert, "X509 %p could not parse key usage: %s\n",
00498                        cert, strerror ( rc ) );
00499                 return rc;
00500         }
00501 
00502         /* Parse key usage bits */
00503         bytes = bit_string.data;
00504         len = bit_string.len;
00505         if ( len > sizeof ( usage->bits ) )
00506                 len = sizeof ( usage->bits );
00507         for ( i = 0 ; i < len ; i++ ) {
00508                 usage->bits |= ( *(bytes++) << ( 8 * i ) );
00509         }
00510         DBGC2 ( cert, "X509 %p key usage is %08x\n", cert, usage->bits );
00511 
00512         return 0;
00513 }
00514 
00515 /** "id-kp-codeSigning" object identifier */
00516 static uint8_t oid_code_signing[] = { ASN1_OID_CODESIGNING };
00517 
00518 /** "id-kp-OCSPSigning" object identifier */
00519 static uint8_t oid_ocsp_signing[] = { ASN1_OID_OCSPSIGNING };
00520 
00521 /** Supported key purposes */
00522 static struct x509_key_purpose x509_key_purposes[] = {
00523         {
00524                 .name = "codeSigning",
00525                 .bits = X509_CODE_SIGNING,
00526                 .oid = ASN1_OID_CURSOR ( oid_code_signing ),
00527         },
00528         {
00529                 .name = "ocspSigning",
00530                 .bits = X509_OCSP_SIGNING,
00531                 .oid = ASN1_OID_CURSOR ( oid_ocsp_signing ),
00532         },
00533 };
00534 
00535 /**
00536  * Parse X.509 certificate key purpose identifier
00537  *
00538  * @v cert              X.509 certificate
00539  * @v raw               ASN.1 cursor
00540  * @ret rc              Return status code
00541  */
00542 static int x509_parse_key_purpose ( struct x509_certificate *cert,
00543                                     const struct asn1_cursor *raw ) {
00544         struct x509_extended_key_usage *ext_usage = &cert->extensions.ext_usage;
00545         struct x509_key_purpose *purpose;
00546         struct asn1_cursor cursor;
00547         unsigned int i;
00548         int rc;
00549 
00550         /* Enter keyPurposeId */
00551         memcpy ( &cursor, raw, sizeof ( cursor ) );
00552         if ( ( rc = asn1_enter ( &cursor, ASN1_OID ) ) != 0 ) {
00553                 DBGC ( cert, "X509 %p invalid keyPurposeId:\n", cert );
00554                 DBGC_HDA ( cert, 0, raw->data, raw->len );
00555                 return rc;
00556         }
00557 
00558         /* Identify key purpose */
00559         for ( i = 0 ; i < ( sizeof ( x509_key_purposes ) /
00560                             sizeof ( x509_key_purposes[0] ) ) ; i++ ) {
00561                 purpose = &x509_key_purposes[i];
00562                 if ( asn1_compare ( &cursor, &purpose->oid ) == 0 ) {
00563                         DBGC2 ( cert, "X509 %p has key purpose %s\n",
00564                                 cert, purpose->name );
00565                         ext_usage->bits |= purpose->bits;
00566                         return 0;
00567                 }
00568         }
00569 
00570         /* Ignore unrecognised key purposes */
00571         return 0;
00572 }
00573 
00574 /**
00575  * Parse X.509 certificate extended key usage
00576  *
00577  * @v cert              X.509 certificate
00578  * @v raw               ASN.1 cursor
00579  * @ret rc              Return status code
00580  */
00581 static int x509_parse_extended_key_usage ( struct x509_certificate *cert,
00582                                            const struct asn1_cursor *raw ) {
00583         struct asn1_cursor cursor;
00584         int rc;
00585 
00586         /* Enter extKeyUsage */
00587         memcpy ( &cursor, raw, sizeof ( cursor ) );
00588         asn1_enter ( &cursor, ASN1_SEQUENCE );
00589 
00590         /* Parse each extended key usage in turn */
00591         while ( cursor.len ) {
00592                 if ( ( rc = x509_parse_key_purpose ( cert, &cursor ) ) != 0 )
00593                         return rc;
00594                 asn1_skip_any ( &cursor );
00595         }
00596 
00597         return 0;
00598 }
00599 
00600 /**
00601  * Parse X.509 certificate OCSP access method
00602  *
00603  * @v cert              X.509 certificate
00604  * @v raw               ASN.1 cursor
00605  * @ret rc              Return status code
00606  */
00607 static int x509_parse_ocsp ( struct x509_certificate *cert,
00608                              const struct asn1_cursor *raw ) {
00609         struct x509_ocsp_responder *ocsp = &cert->extensions.auth_info.ocsp;
00610         struct asn1_cursor *uri = &ocsp->uri;
00611         int rc;
00612 
00613         /* Enter accessLocation */
00614         memcpy ( uri, raw, sizeof ( *uri ) );
00615         if ( ( rc = asn1_enter ( uri, X509_GENERAL_NAME_URI ) ) != 0 ) {
00616                 DBGC ( cert, "X509 %p OCSP does not contain "
00617                        "uniformResourceIdentifier:\n", cert );
00618                 DBGC_HDA ( cert, 0, raw->data, raw->len );
00619                 return rc;
00620         }
00621         DBGC2 ( cert, "X509 %p OCSP URI is:\n", cert );
00622         DBGC2_HDA ( cert, 0, uri->data, uri->len );
00623 
00624         return 0;
00625 }
00626 
00627 /** "id-ad-ocsp" object identifier */
00628 static uint8_t oid_ad_ocsp[] = { ASN1_OID_OCSP };
00629 
00630 /** Supported access methods */
00631 static struct x509_access_method x509_access_methods[] = {
00632         {
00633                 .name = "OCSP",
00634                 .oid = ASN1_OID_CURSOR ( oid_ad_ocsp ),
00635                 .parse = x509_parse_ocsp,
00636         },
00637 };
00638 
00639 /**
00640  * Identify X.509 access method by OID
00641  *
00642  * @v oid               OID
00643  * @ret method          Access method, or NULL
00644  */
00645 static struct x509_access_method *
00646 x509_find_access_method ( const struct asn1_cursor *oid ) {
00647         struct x509_access_method *method;
00648         unsigned int i;
00649 
00650         for ( i = 0 ; i < ( sizeof ( x509_access_methods ) /
00651                             sizeof ( x509_access_methods[0] ) ) ; i++ ) {
00652                 method = &x509_access_methods[i];
00653                 if ( asn1_compare ( &method->oid, oid ) == 0 )
00654                         return method;
00655         }
00656 
00657         return NULL;
00658 }
00659 
00660 /**
00661  * Parse X.509 certificate access description
00662  *
00663  * @v cert              X.509 certificate
00664  * @v raw               ASN.1 cursor
00665  * @ret rc              Return status code
00666  */
00667 static int x509_parse_access_description ( struct x509_certificate *cert,
00668                                            const struct asn1_cursor *raw ) {
00669         struct asn1_cursor cursor;
00670         struct asn1_cursor subcursor;
00671         struct x509_access_method *method;
00672         int rc;
00673 
00674         /* Enter keyPurposeId */
00675         memcpy ( &cursor, raw, sizeof ( cursor ) );
00676         asn1_enter ( &cursor, ASN1_SEQUENCE );
00677 
00678         /* Try to identify access method */
00679         memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
00680         asn1_enter ( &subcursor, ASN1_OID );
00681         method = x509_find_access_method ( &subcursor );
00682         asn1_skip_any ( &cursor );
00683         DBGC2 ( cert, "X509 %p found access method %s\n",
00684                 cert, ( method ? method->name : "<unknown>" ) );
00685 
00686         /* Parse access location, if applicable */
00687         if ( method && ( ( rc = method->parse ( cert, &cursor ) ) != 0 ) )
00688                 return rc;
00689 
00690         return 0;
00691 }
00692 
00693 /**
00694  * Parse X.509 certificate authority information access
00695  *
00696  * @v cert              X.509 certificate
00697  * @v raw               ASN.1 cursor
00698  * @ret rc              Return status code
00699  */
00700 static int x509_parse_authority_info_access ( struct x509_certificate *cert,
00701                                               const struct asn1_cursor *raw ) {
00702         struct asn1_cursor cursor;
00703         int rc;
00704 
00705         /* Enter authorityInfoAccess */
00706         memcpy ( &cursor, raw, sizeof ( cursor ) );
00707         asn1_enter ( &cursor, ASN1_SEQUENCE );
00708 
00709         /* Parse each access description in turn */
00710         while ( cursor.len ) {
00711                 if ( ( rc = x509_parse_access_description ( cert,
00712                                                             &cursor ) ) != 0 )
00713                         return rc;
00714                 asn1_skip_any ( &cursor );
00715         }
00716 
00717         return 0;
00718 }
00719 
00720 /**
00721  * Parse X.509 certificate subject alternative name
00722  *
00723  * @v cert              X.509 certificate
00724  * @v raw               ASN.1 cursor
00725  * @ret rc              Return status code
00726  */
00727 static int x509_parse_subject_alt_name ( struct x509_certificate *cert,
00728                                          const struct asn1_cursor *raw ) {
00729         struct x509_subject_alt_name *alt_name = &cert->extensions.alt_name;
00730         struct asn1_cursor *names = &alt_name->names;
00731         int rc;
00732 
00733         /* Enter subjectAltName */
00734         memcpy ( names, raw, sizeof ( *names ) );
00735         if ( ( rc = asn1_enter ( names, ASN1_SEQUENCE ) ) != 0 ) {
00736                 DBGC ( cert, "X509 %p invalid subjectAltName: %s\n",
00737                        cert, strerror ( rc ) );
00738                 DBGC_HDA ( cert, 0, raw->data, raw->len );
00739                 return rc;
00740         }
00741         DBGC2 ( cert, "X509 %p has subjectAltName:\n", cert );
00742         DBGC2_HDA ( cert, 0, names->data, names->len );
00743 
00744         return 0;
00745 }
00746 
00747 /** "id-ce-basicConstraints" object identifier */
00748 static uint8_t oid_ce_basic_constraints[] =
00749         { ASN1_OID_BASICCONSTRAINTS };
00750 
00751 /** "id-ce-keyUsage" object identifier */
00752 static uint8_t oid_ce_key_usage[] =
00753         { ASN1_OID_KEYUSAGE };
00754 
00755 /** "id-ce-extKeyUsage" object identifier */
00756 static uint8_t oid_ce_ext_key_usage[] =
00757         { ASN1_OID_EXTKEYUSAGE };
00758 
00759 /** "id-pe-authorityInfoAccess" object identifier */
00760 static uint8_t oid_pe_authority_info_access[] =
00761         { ASN1_OID_AUTHORITYINFOACCESS };
00762 
00763 /** "id-ce-subjectAltName" object identifier */
00764 static uint8_t oid_ce_subject_alt_name[] =
00765         { ASN1_OID_SUBJECTALTNAME };
00766 
00767 /** Supported certificate extensions */
00768 static struct x509_extension x509_extensions[] = {
00769         {
00770                 .name = "basicConstraints",
00771                 .oid = ASN1_OID_CURSOR ( oid_ce_basic_constraints ),
00772                 .parse = x509_parse_basic_constraints,
00773         },
00774         {
00775                 .name = "keyUsage",
00776                 .oid = ASN1_OID_CURSOR ( oid_ce_key_usage ),
00777                 .parse = x509_parse_key_usage,
00778         },
00779         {
00780                 .name = "extKeyUsage",
00781                 .oid = ASN1_OID_CURSOR ( oid_ce_ext_key_usage ),
00782                 .parse = x509_parse_extended_key_usage,
00783         },
00784         {
00785                 .name = "authorityInfoAccess",
00786                 .oid = ASN1_OID_CURSOR ( oid_pe_authority_info_access ),
00787                 .parse = x509_parse_authority_info_access,
00788         },
00789         {
00790                 .name = "subjectAltName",
00791                 .oid = ASN1_OID_CURSOR ( oid_ce_subject_alt_name ),
00792                 .parse = x509_parse_subject_alt_name,
00793         },
00794 };
00795 
00796 /**
00797  * Identify X.509 extension by OID
00798  *
00799  * @v oid               OID
00800  * @ret extension       Extension, or NULL
00801  */
00802 static struct x509_extension *
00803 x509_find_extension ( const struct asn1_cursor *oid ) {
00804         struct x509_extension *extension;
00805         unsigned int i;
00806 
00807         for ( i = 0 ; i < ( sizeof ( x509_extensions ) /
00808                             sizeof ( x509_extensions[0] ) ) ; i++ ) {
00809                 extension = &x509_extensions[i];
00810                 if ( asn1_compare ( &extension->oid, oid ) == 0 )
00811                         return extension;
00812         }
00813 
00814         return NULL;
00815 }
00816 
00817 /**
00818  * Parse X.509 certificate extension
00819  *
00820  * @v cert              X.509 certificate
00821  * @v raw               ASN.1 cursor
00822  * @ret rc              Return status code
00823  */
00824 static int x509_parse_extension ( struct x509_certificate *cert,
00825                                   const struct asn1_cursor *raw ) {
00826         struct asn1_cursor cursor;
00827         struct asn1_cursor subcursor;
00828         struct x509_extension *extension;
00829         int is_critical = 0;
00830         int rc;
00831 
00832         /* Enter extension */
00833         memcpy ( &cursor, raw, sizeof ( cursor ) );
00834         asn1_enter ( &cursor, ASN1_SEQUENCE );
00835 
00836         /* Try to identify extension */
00837         memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
00838         asn1_enter ( &subcursor, ASN1_OID );
00839         extension = x509_find_extension ( &subcursor );
00840         asn1_skip_any ( &cursor );
00841         DBGC2 ( cert, "X509 %p found extension %s\n",
00842                 cert, ( extension ? extension->name : "<unknown>" ) );
00843 
00844         /* Identify criticality */
00845         if ( asn1_type ( &cursor ) == ASN1_BOOLEAN ) {
00846                 is_critical = asn1_boolean ( &cursor );
00847                 if ( is_critical < 0 ) {
00848                         rc = is_critical;
00849                         DBGC ( cert, "X509 %p cannot parse extension "
00850                                "criticality: %s\n", cert, strerror ( rc ) );
00851                         DBGC_HDA ( cert, 0, raw->data, raw->len );
00852                         return rc;
00853                 }
00854                 asn1_skip_any ( &cursor );
00855         }
00856 
00857         /* Handle unknown extensions */
00858         if ( ! extension ) {
00859                 if ( is_critical ) {
00860                         /* Fail if we cannot handle a critical extension */
00861                         DBGC ( cert, "X509 %p cannot handle critical "
00862                                "extension:\n", cert );
00863                         DBGC_HDA ( cert, 0, raw->data, raw->len );
00864                         return -ENOTSUP_EXTENSION;
00865                 } else {
00866                         /* Ignore unknown non-critical extensions */
00867                         return 0;
00868                 }
00869         };
00870 
00871         /* Extract extnValue */
00872         if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) {
00873                 DBGC ( cert, "X509 %p extension missing extnValue:\n", cert );
00874                 DBGC_HDA ( cert, 0, raw->data, raw->len );
00875                 return rc;
00876         }
00877 
00878         /* Parse extension */
00879         if ( ( rc = extension->parse ( cert, &cursor ) ) != 0 )
00880                 return rc;
00881 
00882         return 0;
00883 }
00884 
00885 /**
00886  * Parse X.509 certificate extensions, if present
00887  *
00888  * @v cert              X.509 certificate
00889  * @v raw               ASN.1 cursor
00890  * @ret rc              Return status code
00891  */
00892 static int x509_parse_extensions ( struct x509_certificate *cert,
00893                                    const struct asn1_cursor *raw ) {
00894         struct asn1_cursor cursor;
00895         int rc;
00896 
00897         /* Enter extensions, if present */
00898         memcpy ( &cursor, raw, sizeof ( cursor ) );
00899         asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 3 ) );
00900         asn1_enter ( &cursor, ASN1_SEQUENCE );
00901 
00902         /* Parse each extension in turn */
00903         while ( cursor.len ) {
00904                 if ( ( rc = x509_parse_extension ( cert, &cursor ) ) != 0 )
00905                         return rc;
00906                 asn1_skip_any ( &cursor );
00907         }
00908 
00909         return 0;
00910 }
00911 
00912 /**
00913  * Parse X.509 certificate tbsCertificate
00914  *
00915  * @v cert              X.509 certificate
00916  * @v raw               ASN.1 cursor
00917  * @ret rc              Return status code
00918  */
00919 static int x509_parse_tbscertificate ( struct x509_certificate *cert,
00920                                        const struct asn1_cursor *raw ) {
00921         struct asn1_algorithm **algorithm = &cert->signature_algorithm;
00922         struct asn1_cursor cursor;
00923         int rc;
00924 
00925         /* Record raw tbsCertificate */
00926         memcpy ( &cursor, raw, sizeof ( cursor ) );
00927         asn1_shrink_any ( &cursor );
00928         memcpy ( &cert->tbs, &cursor, sizeof ( cert->tbs ) );
00929 
00930         /* Enter tbsCertificate */
00931         asn1_enter ( &cursor, ASN1_SEQUENCE );
00932 
00933         /* Parse version, if present */
00934         if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) {
00935                 if ( ( rc = x509_parse_version ( cert, &cursor ) ) != 0 )
00936                         return rc;
00937                 asn1_skip_any ( &cursor );
00938         }
00939 
00940         /* Parse serialNumber */
00941         if ( ( rc = x509_parse_serial ( cert, &cursor ) ) != 0 )
00942                 return rc;
00943         asn1_skip_any ( &cursor );
00944 
00945         /* Parse signature */
00946         if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) {
00947                 DBGC ( cert, "X509 %p could not parse signature algorithm: "
00948                        "%s\n", cert, strerror ( rc ) );
00949                 return rc;
00950         }
00951         DBGC2 ( cert, "X509 %p tbsCertificate signature algorithm is %s\n",
00952                 cert, (*algorithm)->name );
00953         asn1_skip_any ( &cursor );
00954 
00955         /* Parse issuer */
00956         if ( ( rc = x509_parse_issuer ( cert, &cursor ) ) != 0 )
00957                 return rc;
00958         asn1_skip_any ( &cursor );
00959 
00960         /* Parse validity */
00961         if ( ( rc = x509_parse_validity ( cert, &cursor ) ) != 0 )
00962                 return rc;
00963         asn1_skip_any ( &cursor );
00964 
00965         /* Parse subject */
00966         if ( ( rc = x509_parse_subject ( cert, &cursor ) ) != 0 )
00967                 return rc;
00968         asn1_skip_any ( &cursor );
00969 
00970         /* Parse subjectPublicKeyInfo */
00971         if ( ( rc = x509_parse_public_key ( cert, &cursor ) ) != 0 )
00972                 return rc;
00973         asn1_skip_any ( &cursor );
00974 
00975         /* Parse extensions, if present */
00976         if ( ( rc = x509_parse_extensions ( cert, &cursor ) ) != 0 )
00977                 return rc;
00978 
00979         return 0;
00980 }
00981 
00982 /**
00983  * Parse X.509 certificate from ASN.1 data
00984  *
00985  * @v cert              X.509 certificate
00986  * @v raw               ASN.1 cursor
00987  * @ret rc              Return status code
00988  */
00989 int x509_parse ( struct x509_certificate *cert,
00990                  const struct asn1_cursor *raw ) {
00991         struct x509_signature *signature = &cert->signature;
00992         struct asn1_algorithm **signature_algorithm = &signature->algorithm;
00993         struct asn1_bit_string *signature_value = &signature->value;
00994         struct asn1_cursor cursor;
00995         int rc;
00996 
00997         /* Record raw certificate */
00998         memcpy ( &cursor, raw, sizeof ( cursor ) );
00999         memcpy ( &cert->raw, &cursor, sizeof ( cert->raw ) );
01000 
01001         /* Enter certificate */
01002         asn1_enter ( &cursor, ASN1_SEQUENCE );
01003 
01004         /* Parse tbsCertificate */
01005         if ( ( rc = x509_parse_tbscertificate ( cert, &cursor ) ) != 0 )
01006                 return rc;
01007         asn1_skip_any ( &cursor );
01008 
01009         /* Parse signatureAlgorithm */
01010         if ( ( rc = asn1_signature_algorithm ( &cursor,
01011                                                signature_algorithm ) ) != 0 ) {
01012                 DBGC ( cert, "X509 %p could not parse signature algorithm: "
01013                        "%s\n", cert, strerror ( rc ) );
01014                 return rc;
01015         }
01016         DBGC2 ( cert, "X509 %p signatureAlgorithm is %s\n",
01017                 cert, (*signature_algorithm)->name );
01018         asn1_skip_any ( &cursor );
01019 
01020         /* Parse signatureValue */
01021         if ( ( rc = asn1_integral_bit_string ( &cursor,
01022                                                signature_value ) ) != 0 ) {
01023                 DBGC ( cert, "X509 %p could not parse signature value: %s\n",
01024                        cert, strerror ( rc ) );
01025                 return rc;
01026         }
01027         DBGC2 ( cert, "X509 %p signatureValue is:\n", cert );
01028         DBGC2_HDA ( cert, 0, signature_value->data, signature_value->len );
01029 
01030         /* Check that algorithm in tbsCertificate matches algorithm in
01031          * signature
01032          */
01033         if ( signature->algorithm != (*signature_algorithm) ) {
01034                 DBGC ( cert, "X509 %p signature algorithm %s does not match "
01035                        "signatureAlgorithm %s\n",
01036                        cert, signature->algorithm->name,
01037                        (*signature_algorithm)->name );
01038                 return -EINVAL_ALGORITHM_MISMATCH;
01039         }
01040 
01041         return 0;
01042 }
01043 
01044 /**
01045  * Create X.509 certificate
01046  *
01047  * @v data              Raw certificate data
01048  * @v len               Length of raw data
01049  * @ret cert            X.509 certificate
01050  * @ret rc              Return status code
01051  *
01052  * On success, the caller holds a reference to the X.509 certificate,
01053  * and is responsible for ultimately calling x509_put().
01054  */
01055 int x509_certificate ( const void *data, size_t len,
01056                        struct x509_certificate **cert ) {
01057         struct asn1_cursor cursor;
01058         void *raw;
01059         int rc;
01060 
01061         /* Initialise cursor */
01062         cursor.data = data;
01063         cursor.len = len;
01064         asn1_shrink_any ( &cursor );
01065 
01066         /* Return stored certificate, if present */
01067         if ( ( *cert = certstore_find ( &cursor ) ) != NULL ) {
01068 
01069                 /* Add caller's reference */
01070                 x509_get ( *cert );
01071                 return 0;
01072         }
01073 
01074         /* Allocate and initialise certificate */
01075         *cert = zalloc ( sizeof ( **cert ) + cursor.len );
01076         if ( ! *cert )
01077                 return -ENOMEM;
01078         ref_init ( &(*cert)->refcnt, NULL );
01079         raw = ( *cert + 1 );
01080 
01081         /* Copy raw data */
01082         memcpy ( raw, cursor.data, cursor.len );
01083         cursor.data = raw;
01084 
01085         /* Parse certificate */
01086         if ( ( rc = x509_parse ( *cert, &cursor ) ) != 0 ) {
01087                 x509_put ( *cert );
01088                 *cert = NULL;
01089                 return rc;
01090         }
01091 
01092         /* Add certificate to store */
01093         certstore_add ( *cert );
01094 
01095         return 0;
01096 }
01097 
01098 /**
01099  * Check X.509 certificate signature
01100  *
01101  * @v cert              X.509 certificate
01102  * @v public_key        X.509 public key
01103  * @ret rc              Return status code
01104  */
01105 static int x509_check_signature ( struct x509_certificate *cert,
01106                                   struct x509_public_key *public_key ) {
01107         struct x509_signature *signature = &cert->signature;
01108         struct asn1_algorithm *algorithm = signature->algorithm;
01109         struct digest_algorithm *digest = algorithm->digest;
01110         struct pubkey_algorithm *pubkey = algorithm->pubkey;
01111         uint8_t digest_ctx[ digest->ctxsize ];
01112         uint8_t digest_out[ digest->digestsize ];
01113         uint8_t pubkey_ctx[ pubkey->ctxsize ];
01114         int rc;
01115 
01116         /* Sanity check */
01117         assert ( cert->signature_algorithm == cert->signature.algorithm );
01118 
01119         /* Calculate certificate digest */
01120         digest_init ( digest, digest_ctx );
01121         digest_update ( digest, digest_ctx, cert->tbs.data, cert->tbs.len );
01122         digest_final ( digest, digest_ctx, digest_out );
01123         DBGC2 ( cert, "X509 %p \"%s\" digest:\n", cert, x509_name ( cert ) );
01124         DBGC2_HDA ( cert, 0, digest_out, sizeof ( digest_out ) );
01125 
01126         /* Check that signature public key algorithm matches signer */
01127         if ( public_key->algorithm->pubkey != pubkey ) {
01128                 DBGC ( cert, "X509 %p \"%s\" signature algorithm %s does not "
01129                        "match signer's algorithm %s\n",
01130                        cert, x509_name ( cert ), algorithm->name,
01131                        public_key->algorithm->name );
01132                 rc = -EINVAL_ALGORITHM_MISMATCH;
01133                 goto err_mismatch;
01134         }
01135 
01136         /* Verify signature using signer's public key */
01137         if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
01138                                   public_key->raw.len ) ) != 0 ) {
01139                 DBGC ( cert, "X509 %p \"%s\" cannot initialise public key: "
01140                        "%s\n", cert, x509_name ( cert ), strerror ( rc ) );
01141                 goto err_pubkey_init;
01142         }
01143         if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out,
01144                                     signature->value.data,
01145                                     signature->value.len ) ) != 0 ) {
01146                 DBGC ( cert, "X509 %p \"%s\" signature verification failed: "
01147                        "%s\n", cert, x509_name ( cert ), strerror ( rc ) );
01148                 goto err_pubkey_verify;
01149         }
01150 
01151         /* Success */
01152         rc = 0;
01153 
01154  err_pubkey_verify:
01155         pubkey_final ( pubkey, pubkey_ctx );
01156  err_pubkey_init:
01157  err_mismatch:
01158         return rc;
01159 }
01160 
01161 /**
01162  * Check X.509 certificate against issuer certificate
01163  *
01164  * @v cert              X.509 certificate
01165  * @v issuer            X.509 issuer certificate
01166  * @ret rc              Return status code
01167  */
01168 int x509_check_issuer ( struct x509_certificate *cert,
01169                         struct x509_certificate *issuer ) {
01170         struct x509_public_key *public_key = &issuer->subject.public_key;
01171         int rc;
01172 
01173         /* Check issuer.  In theory, this should be a full X.500 DN
01174          * comparison, which would require support for a plethora of
01175          * abominations such as TeletexString (which allows the
01176          * character set to be changed mid-string using escape codes).
01177          * In practice, we assume that anyone who deliberately changes
01178          * the encoding of the issuer DN is probably a masochist who
01179          * will rather enjoy the process of figuring out exactly why
01180          * their certificate doesn't work.
01181          *
01182          * See http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
01183          * for some enjoyable ranting on this subject.
01184          */
01185         if ( asn1_compare ( &cert->issuer.raw, &issuer->subject.raw ) != 0 ) {
01186                 DBGC ( cert, "X509 %p \"%s\" issuer does not match ",
01187                        cert, x509_name ( cert ) );
01188                 DBGC ( cert, "X509 %p \"%s\" subject\n",
01189                        issuer, x509_name ( issuer ) );
01190                 DBGC_HDA ( cert, 0, cert->issuer.raw.data,
01191                            cert->issuer.raw.len );
01192                 DBGC_HDA ( issuer, 0, issuer->subject.raw.data,
01193                            issuer->subject.raw.len );
01194                 return -EACCES_WRONG_ISSUER;
01195         }
01196 
01197         /* Check that issuer is allowed to sign certificates */
01198         if ( ! issuer->extensions.basic.ca ) {
01199                 DBGC ( issuer, "X509 %p \"%s\" cannot sign ",
01200                        issuer, x509_name ( issuer ) );
01201                 DBGC ( issuer, "X509 %p \"%s\": not a CA certificate\n",
01202                        cert, x509_name ( cert ) );
01203                 return -EACCES_NOT_CA;
01204         }
01205         if ( issuer->extensions.usage.present &&
01206              ( ! ( issuer->extensions.usage.bits & X509_KEY_CERT_SIGN ) ) ) {
01207                 DBGC ( issuer, "X509 %p \"%s\" cannot sign ",
01208                        issuer, x509_name ( issuer ) );
01209                 DBGC ( issuer, "X509 %p \"%s\": no keyCertSign usage\n",
01210                        cert, x509_name ( cert ) );
01211                 return -EACCES_KEY_USAGE;
01212         }
01213 
01214         /* Check signature */
01215         if ( ( rc = x509_check_signature ( cert, public_key ) ) != 0 )
01216                 return rc;
01217 
01218         return 0;
01219 }
01220 
01221 /**
01222  * Calculate X.509 certificate fingerprint
01223  *
01224  * @v cert              X.509 certificate
01225  * @v digest            Digest algorithm
01226  * @v fingerprint       Fingerprint buffer
01227  */
01228 void x509_fingerprint ( struct x509_certificate *cert,
01229                         struct digest_algorithm *digest,
01230                         void *fingerprint ) {
01231         uint8_t ctx[ digest->ctxsize ];
01232 
01233         /* Calculate fingerprint */
01234         digest_init ( digest, ctx );
01235         digest_update ( digest, ctx, cert->raw.data, cert->raw.len );
01236         digest_final ( digest, ctx, fingerprint );
01237 }
01238 
01239 /**
01240  * Check X.509 root certificate
01241  *
01242  * @v cert              X.509 certificate
01243  * @v root              X.509 root certificate list
01244  * @ret rc              Return status code
01245  */
01246 int x509_check_root ( struct x509_certificate *cert, struct x509_root *root ) {
01247         struct digest_algorithm *digest = root->digest;
01248         uint8_t fingerprint[ digest->digestsize ];
01249         const uint8_t *root_fingerprint = root->fingerprints;
01250         unsigned int i;
01251 
01252         /* Calculate certificate fingerprint */
01253         x509_fingerprint ( cert, digest, fingerprint );
01254 
01255         /* Check fingerprint against all root certificates */
01256         for ( i = 0 ; i < root->count ; i++ ) {
01257                 if ( memcmp ( fingerprint, root_fingerprint,
01258                               sizeof ( fingerprint ) ) == 0 ) {
01259                         DBGC ( cert, "X509 %p \"%s\" is a root certificate\n",
01260                                cert, x509_name ( cert ) );
01261                         return 0;
01262                 }
01263                 root_fingerprint += sizeof ( fingerprint );
01264         }
01265 
01266         DBGC2 ( cert, "X509 %p \"%s\" is not a root certificate\n",
01267                 cert, x509_name ( cert ) );
01268         return -ENOENT;
01269 }
01270 
01271 /**
01272  * Check X.509 certificate validity period
01273  *
01274  * @v cert              X.509 certificate
01275  * @v time              Time at which to check certificate
01276  * @ret rc              Return status code
01277  */
01278 int x509_check_time ( struct x509_certificate *cert, time_t time ) {
01279         struct x509_validity *validity = &cert->validity;
01280 
01281         /* Check validity period */
01282         if ( validity->not_before.time > ( time + TIMESTAMP_ERROR_MARGIN ) ) {
01283                 DBGC ( cert, "X509 %p \"%s\" is not yet valid (at time %lld)\n",
01284                        cert, x509_name ( cert ), time );
01285                 return -EACCES_EXPIRED;
01286         }
01287         if ( validity->not_after.time < ( time - TIMESTAMP_ERROR_MARGIN ) ) {
01288                 DBGC ( cert, "X509 %p \"%s\" has expired (at time %lld)\n",
01289                        cert, x509_name ( cert ), time );
01290                 return -EACCES_EXPIRED;
01291         }
01292 
01293         DBGC2 ( cert, "X509 %p \"%s\" is valid (at time %lld)\n",
01294                 cert, x509_name ( cert ), time );
01295         return 0;
01296 }
01297 
01298 /**
01299  * Validate X.509 certificate
01300  *
01301  * @v cert              X.509 certificate
01302  * @v issuer            Issuing X.509 certificate (or NULL)
01303  * @v time              Time at which to validate certificate
01304  * @v root              Root certificate list, or NULL to use default
01305  * @ret rc              Return status code
01306  *
01307  * The issuing certificate must have already been validated.
01308  *
01309  * Validation results are cached: if a certificate has already been
01310  * successfully validated then @c issuer, @c time, and @c root will be
01311  * ignored.
01312  */
01313 int x509_validate ( struct x509_certificate *cert,
01314                     struct x509_certificate *issuer,
01315                     time_t time, struct x509_root *root ) {
01316         unsigned int max_path_remaining;
01317         int rc;
01318 
01319         /* Use default root certificate store if none specified */
01320         if ( ! root )
01321                 root = &root_certificates;
01322 
01323         /* Return success if certificate has already been validated */
01324         if ( x509_is_valid ( cert ) )
01325                 return 0;
01326 
01327         /* Fail if certificate is invalid at specified time */
01328         if ( ( rc = x509_check_time ( cert, time ) ) != 0 )
01329                 return rc;
01330 
01331         /* Succeed if certificate is a trusted root certificate */
01332         if ( x509_check_root ( cert, root ) == 0 ) {
01333                 cert->flags |= X509_FL_VALIDATED;
01334                 cert->path_remaining = ( cert->extensions.basic.path_len + 1 );
01335                 return 0;
01336         }
01337 
01338         /* Fail unless we have an issuer */
01339         if ( ! issuer ) {
01340                 DBGC2 ( cert, "X509 %p \"%s\" has no issuer\n",
01341                         cert, x509_name ( cert ) );
01342                 return -EACCES_UNTRUSTED;
01343         }
01344 
01345         /* Fail unless issuer has already been validated */
01346         if ( ! x509_is_valid ( issuer ) ) {
01347                 DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) );
01348                 DBGC ( cert, "issuer %p \"%s\" has not yet been validated\n",
01349                        issuer, x509_name ( issuer ) );
01350                 return -EACCES_OUT_OF_ORDER;
01351         }
01352 
01353         /* Fail if issuing certificate cannot validate this certificate */
01354         if ( ( rc = x509_check_issuer ( cert, issuer ) ) != 0 )
01355                 return rc;
01356 
01357         /* Fail if path length constraint is violated */
01358         if ( issuer->path_remaining == 0 ) {
01359                 DBGC ( cert, "X509 %p \"%s\" ", cert, x509_name ( cert ) );
01360                 DBGC ( cert, "issuer %p \"%s\" path length exceeded\n",
01361                        issuer, x509_name ( issuer ) );
01362                 return -EACCES_PATH_LEN;
01363         }
01364 
01365         /* Fail if OCSP is required */
01366         if ( ocsp_required ( cert ) ) {
01367                 DBGC ( cert, "X509 %p \"%s\" requires an OCSP check\n",
01368                        cert, x509_name ( cert ) );
01369                 return -EACCES_OCSP_REQUIRED;
01370         }
01371 
01372         /* Calculate effective path length */
01373         cert->path_remaining = ( issuer->path_remaining - 1 );
01374         max_path_remaining = ( cert->extensions.basic.path_len + 1 );
01375         if ( cert->path_remaining > max_path_remaining )
01376                 cert->path_remaining = max_path_remaining;
01377 
01378         /* Mark certificate as valid */
01379         cert->flags |= X509_FL_VALIDATED;
01380 
01381         DBGC ( cert, "X509 %p \"%s\" successfully validated using ",
01382                cert, x509_name ( cert ) );
01383         DBGC ( cert, "issuer %p \"%s\"\n", issuer, x509_name ( issuer ) );
01384         return 0;
01385 }
01386 
01387 /**
01388  * Check X.509 certificate alternative dNSName
01389  *
01390  * @v cert              X.509 certificate
01391  * @v raw               ASN.1 cursor
01392  * @v name              Name
01393  * @ret rc              Return status code
01394  */
01395 static int x509_check_dnsname ( struct x509_certificate *cert,
01396                                 const struct asn1_cursor *raw,
01397                                 const char *name ) {
01398         const char *fullname = name;
01399         const char *dnsname = raw->data;
01400         size_t len = raw->len;
01401 
01402         /* Check for wildcards */
01403         if ( ( len >= 2 ) && ( dnsname[0] == '*' ) && ( dnsname[1] == '.' ) ) {
01404 
01405                 /* Skip initial "*." */
01406                 dnsname += 2;
01407                 len -= 2;
01408 
01409                 /* Skip initial portion of name to be tested */
01410                 name = strchr ( name, '.' );
01411                 if ( ! name )
01412                         return -ENOENT;
01413                 name++;
01414         }
01415 
01416         /* Compare names */
01417         if ( ! ( ( strlen ( name ) == len ) &&
01418                  ( memcmp ( name, dnsname, len ) == 0 ) ) )
01419                 return -ENOENT;
01420 
01421         if ( name != fullname ) {
01422                 DBGC2 ( cert, "X509 %p \"%s\" found wildcard match for "
01423                         "\"*.%s\"\n", cert, x509_name ( cert ), name );
01424         }
01425         return 0;
01426 }
01427 
01428 /**
01429  * Check X.509 certificate alternative iPAddress
01430  *
01431  * @v cert              X.509 certificate
01432  * @v raw               ASN.1 cursor
01433  * @v name              Name
01434  * @ret rc              Return status code
01435  */
01436 static int x509_check_ipaddress ( struct x509_certificate *cert,
01437                                   const struct asn1_cursor *raw,
01438                                   const char *name ) {
01439         struct sockaddr sa;
01440         sa_family_t family;
01441         const void *address;
01442         int rc;
01443 
01444         /* Determine address family */
01445         if ( raw->len == sizeof ( struct in_addr ) ) {
01446                 struct sockaddr_in *sin = ( ( struct sockaddr_in * ) &sa );
01447                 family = AF_INET;
01448                 address = &sin->sin_addr;
01449         } else if ( raw->len == sizeof ( struct in6_addr ) ) {
01450                 struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) &sa );
01451                 family = AF_INET6;
01452                 address = &sin6->sin6_addr;
01453         } else {
01454                 DBGC ( cert, "X509 %p \"%s\" has iPAddress with unexpected "
01455                        "length %zd\n", cert, x509_name ( cert ), raw->len );
01456                 DBGC_HDA ( cert, 0, raw->data, raw->len );
01457                 return -EINVAL;
01458         }
01459 
01460         /* Attempt to convert name to a socket address */
01461         if ( ( rc = sock_aton ( name, &sa ) ) != 0 ) {
01462                 DBGC2 ( cert, "X509 %p \"%s\" cannot parse \"%s\" as "
01463                         "iPAddress: %s\n", cert, x509_name ( cert ), name,
01464                         strerror ( rc ) );
01465                 return rc;
01466         }
01467         if ( sa.sa_family != family )
01468                 return -ENOENT;
01469 
01470         /* Compare addresses */
01471         if ( memcmp ( address, raw->data, raw->len ) != 0 )
01472                 return -ENOENT;
01473 
01474         DBGC2 ( cert, "X509 %p \"%s\" found iPAddress match for \"%s\"\n",
01475                 cert, x509_name ( cert ), sock_ntoa ( &sa ) );
01476         return 0;
01477 }
01478 
01479 /**
01480  * Check X.509 certificate alternative name
01481  *
01482  * @v cert              X.509 certificate
01483  * @v raw               ASN.1 cursor
01484  * @v name              Name
01485  * @ret rc              Return status code
01486  */
01487 static int x509_check_alt_name ( struct x509_certificate *cert,
01488                                  const struct asn1_cursor *raw,
01489                                  const char *name ) {
01490         struct asn1_cursor alt_name;
01491         unsigned int type;
01492 
01493         /* Enter generalName */
01494         memcpy ( &alt_name, raw, sizeof ( alt_name ) );
01495         type = asn1_type ( &alt_name );
01496         asn1_enter_any ( &alt_name );
01497 
01498         /* Check this name */
01499         switch ( type ) {
01500         case X509_GENERAL_NAME_DNS :
01501                 return x509_check_dnsname ( cert, &alt_name, name );
01502         case X509_GENERAL_NAME_IP :
01503                 return x509_check_ipaddress ( cert, &alt_name, name );
01504         default:
01505                 DBGC2 ( cert, "X509 %p \"%s\" unknown name of type %#02x:\n",
01506                         cert, x509_name ( cert ), type );
01507                 DBGC2_HDA ( cert, 0, alt_name.data, alt_name.len );
01508                 return -ENOTSUP;
01509         }
01510 }
01511 
01512 /**
01513  * Check X.509 certificate name
01514  *
01515  * @v cert              X.509 certificate
01516  * @v name              Name
01517  * @ret rc              Return status code
01518  */
01519 int x509_check_name ( struct x509_certificate *cert, const char *name ) {
01520         struct asn1_cursor *common_name = &cert->subject.common_name;
01521         struct asn1_cursor alt_name;
01522         int rc;
01523 
01524         /* Check commonName */
01525         if ( x509_check_dnsname ( cert, common_name, name ) == 0 ) {
01526                 DBGC2 ( cert, "X509 %p \"%s\" commonName matches \"%s\"\n",
01527                         cert, x509_name ( cert ), name );
01528                 return 0;
01529         }
01530 
01531         /* Check any subjectAlternativeNames */
01532         memcpy ( &alt_name, &cert->extensions.alt_name.names,
01533                  sizeof ( alt_name ) );
01534         for ( ; alt_name.len ; asn1_skip_any ( &alt_name ) ) {
01535                 if ( ( rc = x509_check_alt_name ( cert, &alt_name,
01536                                                   name ) ) == 0 ) {
01537                         DBGC2 ( cert, "X509 %p \"%s\" subjectAltName matches "
01538                                 "\"%s\"\n", cert, x509_name ( cert ), name );
01539                         return 0;
01540                 }
01541         }
01542 
01543         DBGC ( cert, "X509 %p \"%s\" does not match name \"%s\"\n",
01544                cert, x509_name ( cert ), name );
01545         return -EACCES_WRONG_NAME;
01546 }
01547 
01548 /**
01549  * Free X.509 certificate chain
01550  *
01551  * @v refcnt            Reference count
01552  */
01553 static void x509_free_chain ( struct refcnt *refcnt ) {
01554         struct x509_chain *chain =
01555                 container_of ( refcnt, struct x509_chain, refcnt );
01556         struct x509_link *link;
01557         struct x509_link *tmp;
01558 
01559         DBGC2 ( chain, "X509 chain %p freed\n", chain );
01560 
01561         /* Free each link in the chain */
01562         list_for_each_entry_safe ( link, tmp, &chain->links, list ) {
01563                 x509_put ( link->cert );
01564                 list_del ( &link->list );
01565                 free ( link );
01566         }
01567 
01568         /* Free chain */
01569         free ( chain );
01570 }
01571 
01572 /**
01573  * Allocate X.509 certificate chain
01574  *
01575  * @ret chain           X.509 certificate chain, or NULL
01576  */
01577 struct x509_chain * x509_alloc_chain ( void ) {
01578         struct x509_chain *chain;
01579 
01580         /* Allocate chain */
01581         chain = zalloc ( sizeof ( *chain ) );
01582         if ( ! chain )
01583                 return NULL;
01584 
01585         /* Initialise chain */
01586         ref_init ( &chain->refcnt, x509_free_chain );
01587         INIT_LIST_HEAD ( &chain->links );
01588 
01589         DBGC2 ( chain, "X509 chain %p allocated\n", chain );
01590         return chain;
01591 }
01592 
01593 /**
01594  * Append X.509 certificate to X.509 certificate chain
01595  *
01596  * @v chain             X.509 certificate chain
01597  * @v cert              X.509 certificate
01598  * @ret rc              Return status code
01599  */
01600 int x509_append ( struct x509_chain *chain, struct x509_certificate *cert ) {
01601         struct x509_link *link;
01602 
01603         /* Allocate link */
01604         link = zalloc ( sizeof ( *link ) );
01605         if ( ! link )
01606                 return -ENOMEM;
01607 
01608         /* Add link to chain */
01609         link->cert = x509_get ( cert );
01610         list_add_tail ( &link->list, &chain->links );
01611         DBGC ( chain, "X509 chain %p added X509 %p \"%s\"\n",
01612                chain, cert, x509_name ( cert ) );
01613 
01614         return 0;
01615 }
01616 
01617 /**
01618  * Append X.509 certificate to X.509 certificate chain
01619  *
01620  * @v chain             X.509 certificate chain
01621  * @v data              Raw certificate data
01622  * @v len               Length of raw data
01623  * @ret rc              Return status code
01624  */
01625 int x509_append_raw ( struct x509_chain *chain, const void *data,
01626                       size_t len ) {
01627         struct x509_certificate *cert;
01628         int rc;
01629 
01630         /* Parse certificate */
01631         if ( ( rc = x509_certificate ( data, len, &cert ) ) != 0 )
01632                 goto err_parse;
01633 
01634         /* Append certificate to chain */
01635         if ( ( rc = x509_append ( chain, cert ) ) != 0 )
01636                 goto err_append;
01637 
01638         /* Drop reference to certificate */
01639         x509_put ( cert );
01640 
01641         return 0;
01642 
01643  err_append:
01644         x509_put ( cert );
01645  err_parse:
01646         return rc;
01647 }
01648 
01649 /**
01650  * Identify X.509 certificate by subject
01651  *
01652  * @v certs             X.509 certificate list
01653  * @v subject           Subject
01654  * @ret cert            X.509 certificate, or NULL if not found
01655  */
01656 static struct x509_certificate *
01657 x509_find_subject ( struct x509_chain *certs,
01658                     const struct asn1_cursor *subject ) {
01659         struct x509_link *link;
01660         struct x509_certificate *cert;
01661 
01662         /* Scan through certificate list */
01663         list_for_each_entry ( link, &certs->links, list ) {
01664 
01665                 /* Check subject */
01666                 cert = link->cert;
01667                 if ( asn1_compare ( subject, &cert->subject.raw ) == 0 )
01668                         return cert;
01669         }
01670 
01671         return NULL;
01672 }
01673 
01674 /**
01675  * Append X.509 certificates to X.509 certificate chain
01676  *
01677  * @v chain             X.509 certificate chain
01678  * @v certs             X.509 certificate list
01679  * @ret rc              Return status code
01680  *
01681  * Certificates will be automatically appended to the chain based upon
01682  * the subject and issuer names.
01683  */
01684 int x509_auto_append ( struct x509_chain *chain, struct x509_chain *certs ) {
01685         struct x509_certificate *cert;
01686         struct x509_certificate *previous;
01687         int rc;
01688 
01689         /* Get current certificate */
01690         cert = x509_last ( chain );
01691         if ( ! cert ) {
01692                 DBGC ( chain, "X509 chain %p has no certificates\n", chain );
01693                 return -EACCES_EMPTY;
01694         }
01695 
01696         /* Append certificates, in order */
01697         while ( 1 ) {
01698 
01699                 /* Find issuing certificate */
01700                 previous = cert;
01701                 cert = x509_find_subject ( certs, &cert->issuer.raw );
01702                 if ( ! cert )
01703                         break;
01704                 if ( cert == previous )
01705                         break;
01706 
01707                 /* Append certificate to chain */
01708                 if ( ( rc = x509_append ( chain, cert ) ) != 0 )
01709                         return rc;
01710         }
01711 
01712         return 0;
01713 }
01714 
01715 /**
01716  * Validate X.509 certificate chain
01717  *
01718  * @v chain             X.509 certificate chain
01719  * @v time              Time at which to validate certificates
01720  * @v store             Certificate store, or NULL to use default
01721  * @v root              Root certificate list, or NULL to use default
01722  * @ret rc              Return status code
01723  */
01724 int x509_validate_chain ( struct x509_chain *chain, time_t time,
01725                           struct x509_chain *store, struct x509_root *root ) {
01726         struct x509_certificate *issuer = NULL;
01727         struct x509_link *link;
01728         int rc;
01729 
01730         /* Use default certificate store if none specified */
01731         if ( ! store )
01732                 store = &certstore;
01733 
01734         /* Append any applicable certificates from the certificate store */
01735         if ( ( rc = x509_auto_append ( chain, store ) ) != 0 )
01736                 return rc;
01737 
01738         /* Find first certificate that can be validated as a
01739          * standalone (i.e.  is already valid, or can be validated as
01740          * a trusted root certificate).
01741          */
01742         list_for_each_entry ( link, &chain->links, list ) {
01743 
01744                 /* Try validating this certificate as a standalone */
01745                 if ( ( rc = x509_validate ( link->cert, NULL, time,
01746                                             root ) ) != 0 )
01747                         continue;
01748 
01749                 /* Work back up to start of chain, performing pairwise
01750                  * validation.
01751                  */
01752                 issuer = link->cert;
01753                 list_for_each_entry_continue_reverse ( link, &chain->links,
01754                                                        list ) {
01755 
01756                         /* Validate this certificate against its issuer */
01757                         if ( ( rc = x509_validate ( link->cert, issuer, time,
01758                                                     root ) ) != 0 )
01759                                 return rc;
01760                         issuer = link->cert;
01761                 }
01762 
01763                 return 0;
01764         }
01765 
01766         DBGC ( chain, "X509 chain %p found no usable certificates\n", chain );
01767         return -EACCES_USELESS;
01768 }
01769 
01770 /**
01771  * Extract X.509 certificate object from image
01772  *
01773  * @v image             Image
01774  * @v offset            Offset within image
01775  * @ret cert            X.509 certificate
01776  * @ret next            Offset to next image, or negative error
01777  *
01778  * On success, the caller holds a reference to the X.509 certificate,
01779  * and is responsible for ultimately calling x509_put().
01780  */
01781 int image_x509 ( struct image *image, size_t offset,
01782                  struct x509_certificate **cert ) {
01783         struct asn1_cursor *cursor;
01784         int next;
01785         int rc;
01786 
01787         /* Get ASN.1 object */
01788         next = image_asn1 ( image, offset, &cursor );
01789         if ( next < 0 ) {
01790                 rc = next;
01791                 goto err_asn1;
01792         }
01793 
01794         /* Parse certificate */
01795         if ( ( rc = x509_certificate ( cursor->data, cursor->len,
01796                                        cert ) ) != 0 )
01797                 goto err_certificate;
01798 
01799         /* Free ASN.1 object */
01800         free ( cursor );
01801 
01802         return next;
01803 
01804         x509_put ( *cert );
01805  err_certificate:
01806         free ( cursor );
01807  err_asn1:
01808         return rc;
01809 }
01810 
01811 /* Drag in objects via x509_validate() */
01812 REQUIRING_SYMBOL ( x509_validate );
01813 
01814 /* Drag in certificate store */
01815 REQUIRE_OBJECT ( certstore );
01816 
01817 /* Drag in crypto configuration */
01818 REQUIRE_OBJECT ( config_crypto );