iPXE
ocsp.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012 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 (at your option) 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 
00020 FILE_LICENCE ( GPL2_OR_LATER );
00021 
00022 #include <stdint.h>
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <errno.h>
00027 #include <ipxe/asn1.h>
00028 #include <ipxe/x509.h>
00029 #include <ipxe/sha1.h>
00030 #include <ipxe/base64.h>
00031 #include <ipxe/uri.h>
00032 #include <ipxe/ocsp.h>
00033 #include <config/crypto.h>
00034 
00035 /** @file
00036  *
00037  * Online Certificate Status Protocol
00038  *
00039  */
00040 
00041 /* Disambiguate the various error causes */
00042 #define EACCES_CERT_STATUS                                              \
00043         __einfo_error ( EINFO_EACCES_CERT_STATUS )
00044 #define EINFO_EACCES_CERT_STATUS                                        \
00045         __einfo_uniqify ( EINFO_EACCES, 0x01,                           \
00046                           "Certificate status not good" )
00047 #define EACCES_CERT_MISMATCH                                            \
00048         __einfo_error ( EINFO_EACCES_CERT_MISMATCH )
00049 #define EINFO_EACCES_CERT_MISMATCH                                      \
00050         __einfo_uniqify ( EINFO_EACCES, 0x02,                           \
00051                           "Certificate ID mismatch" )
00052 #define EACCES_NON_OCSP_SIGNING                                         \
00053         __einfo_error ( EINFO_EACCES_NON_OCSP_SIGNING )
00054 #define EINFO_EACCES_NON_OCSP_SIGNING                                   \
00055         __einfo_uniqify ( EINFO_EACCES, 0x03,                           \
00056                           "Not an OCSP signing certificate" )
00057 #define EACCES_STALE                                                    \
00058         __einfo_error ( EINFO_EACCES_STALE )
00059 #define EINFO_EACCES_STALE                                              \
00060         __einfo_uniqify ( EINFO_EACCES, 0x04,                           \
00061                           "Stale (or premature) OCSP repsonse" )
00062 #define EACCES_NO_RESPONDER                                             \
00063         __einfo_error ( EINFO_EACCES_NO_RESPONDER )
00064 #define EINFO_EACCES_NO_RESPONDER                                       \
00065         __einfo_uniqify ( EINFO_EACCES, 0x05,                           \
00066                           "Missing OCSP responder certificate" )
00067 #define ENOTSUP_RESPONSE_TYPE                                           \
00068         __einfo_error ( EINFO_ENOTSUP_RESPONSE_TYPE )
00069 #define EINFO_ENOTSUP_RESPONSE_TYPE                                     \
00070         __einfo_uniqify ( EINFO_ENOTSUP, 0x01,                          \
00071                           "Unsupported OCSP response type" )
00072 #define ENOTSUP_RESPONDER_ID                                            \
00073         __einfo_error ( EINFO_ENOTSUP_RESPONDER_ID )
00074 #define EINFO_ENOTSUP_RESPONDER_ID                                      \
00075         __einfo_uniqify ( EINFO_ENOTSUP, 0x02,                          \
00076                           "Unsupported OCSP responder ID" )
00077 #define EPROTO_MALFORMED_REQUEST                                        \
00078         __einfo_error ( EINFO_EPROTO_MALFORMED_REQUEST )
00079 #define EINFO_EPROTO_MALFORMED_REQUEST                                  \
00080         __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_MALFORMED_REQUEST,  \
00081                           "Illegal confirmation request" )
00082 #define EPROTO_INTERNAL_ERROR                                           \
00083         __einfo_error ( EINFO_EPROTO_INTERNAL_ERROR )
00084 #define EINFO_EPROTO_INTERNAL_ERROR                                     \
00085         __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_INTERNAL_ERROR,     \
00086                           "Internal error in issuer" )
00087 #define EPROTO_TRY_LATER                                                \
00088         __einfo_error ( EINFO_EPROTO_TRY_LATER )
00089 #define EINFO_EPROTO_TRY_LATER                                          \
00090         __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_TRY_LATER,          \
00091                           "Try again later" )
00092 #define EPROTO_SIG_REQUIRED                                             \
00093         __einfo_error ( EINFO_EPROTO_SIG_REQUIRED )
00094 #define EINFO_EPROTO_SIG_REQUIRED                                       \
00095         __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_SIG_REQUIRED,       \
00096                           "Must sign the request" )
00097 #define EPROTO_UNAUTHORIZED                                             \
00098         __einfo_error ( EINFO_EPROTO_UNAUTHORIZED )
00099 #define EINFO_EPROTO_UNAUTHORIZED                                       \
00100         __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_UNAUTHORIZED,       \
00101                           "Request unauthorized" )
00102 #define EPROTO_STATUS( status )                                         \
00103         EUNIQ ( EINFO_EPROTO, (status), EPROTO_MALFORMED_REQUEST,       \
00104                 EPROTO_INTERNAL_ERROR, EPROTO_TRY_LATER,                \
00105                 EPROTO_SIG_REQUIRED, EPROTO_UNAUTHORIZED )
00106 
00107 /** OCSP digest algorithm */
00108 #define ocsp_digest_algorithm sha1_algorithm
00109 
00110 /** OCSP digest algorithm identifier */
00111 static const uint8_t ocsp_algorithm_id[] =
00112         { OCSP_ALGORITHM_IDENTIFIER ( ASN1_OID_SHA1 ) };
00113 
00114 /** OCSP basic response type */
00115 static const uint8_t oid_basic_response_type[] = { ASN1_OID_OCSP_BASIC };
00116 
00117 /** OCSP basic response type cursor */
00118 static struct asn1_cursor oid_basic_response_type_cursor =
00119         ASN1_OID_CURSOR ( oid_basic_response_type );
00120 
00121 /**
00122  * Free OCSP check
00123  *
00124  * @v refcnt            Reference count
00125  */
00126 static void ocsp_free ( struct refcnt *refcnt ) {
00127         struct ocsp_check *ocsp =
00128                 container_of ( refcnt, struct ocsp_check, refcnt );
00129 
00130         x509_put ( ocsp->cert );
00131         x509_put ( ocsp->issuer );
00132         free ( ocsp->uri_string );
00133         free ( ocsp->request.builder.data );
00134         free ( ocsp->response.data );
00135         x509_put ( ocsp->response.signer );
00136         free ( ocsp );
00137 }
00138 
00139 /**
00140  * Build OCSP request
00141  *
00142  * @v ocsp              OCSP check
00143  * @ret rc              Return status code
00144  */
00145 static int ocsp_request ( struct ocsp_check *ocsp ) {
00146         struct digest_algorithm *digest = &ocsp_digest_algorithm;
00147         struct asn1_builder *builder = &ocsp->request.builder;
00148         struct asn1_cursor *cert_id_tail = &ocsp->request.cert_id_tail;
00149         uint8_t digest_ctx[digest->ctxsize];
00150         uint8_t name_digest[digest->digestsize];
00151         uint8_t pubkey_digest[digest->digestsize];
00152         int rc;
00153 
00154         /* Generate digests */
00155         digest_init ( digest, digest_ctx );
00156         digest_update ( digest, digest_ctx, ocsp->cert->issuer.raw.data,
00157                         ocsp->cert->issuer.raw.len );
00158         digest_final ( digest, digest_ctx, name_digest );
00159         digest_init ( digest, digest_ctx );
00160         digest_update ( digest, digest_ctx,
00161                         ocsp->issuer->subject.public_key.raw_bits.data,
00162                         ocsp->issuer->subject.public_key.raw_bits.len );
00163         digest_final ( digest, digest_ctx, pubkey_digest );
00164 
00165         /* Construct request */
00166         if ( ( rc = ( asn1_prepend_raw ( builder, ocsp->cert->serial.raw.data,
00167                                          ocsp->cert->serial.raw.len ),
00168                       asn1_prepend ( builder, ASN1_OCTET_STRING,
00169                                      pubkey_digest, sizeof ( pubkey_digest ) ),
00170                       asn1_prepend ( builder, ASN1_OCTET_STRING,
00171                                      name_digest, sizeof ( name_digest ) ),
00172                       asn1_prepend ( builder, ASN1_SEQUENCE,
00173                                      ocsp_algorithm_id,
00174                                      sizeof ( ocsp_algorithm_id ) ),
00175                       asn1_wrap ( builder, ASN1_SEQUENCE ),
00176                       asn1_wrap ( builder, ASN1_SEQUENCE ),
00177                       asn1_wrap ( builder, ASN1_SEQUENCE ),
00178                       asn1_wrap ( builder, ASN1_SEQUENCE ),
00179                       asn1_wrap ( builder, ASN1_SEQUENCE ) ) ) != 0 ) {
00180                 DBGC ( ocsp, "OCSP %p \"%s\" could not build request: %s\n",
00181                        ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
00182                 return rc;
00183         }
00184         DBGC2 ( ocsp, "OCSP %p \"%s\" request is:\n",
00185                 ocsp, x509_name ( ocsp->cert ) );
00186         DBGC2_HDA ( ocsp, 0, builder->data, builder->len );
00187 
00188         /* Parse certificate ID for comparison with response */
00189         cert_id_tail->data = builder->data;
00190         cert_id_tail->len = builder->len;
00191         if ( ( rc = ( asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
00192                       asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
00193                       asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
00194                       asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
00195                       asn1_enter ( cert_id_tail, ASN1_SEQUENCE ),
00196                       asn1_skip ( cert_id_tail, ASN1_SEQUENCE ) ) ) != 0 ) {
00197                 DBGC ( ocsp, "OCSP %p \"%s\" could not locate certID: %s\n",
00198                        ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
00199                 return rc;
00200         }
00201 
00202         return 0;
00203 }
00204 
00205 /**
00206  * Build OCSP URI string
00207  *
00208  * @v ocsp              OCSP check
00209  * @ret rc              Return status code
00210  */
00211 static int ocsp_uri_string ( struct ocsp_check *ocsp ) {
00212         struct x509_ocsp_responder *responder =
00213                 &ocsp->cert->extensions.auth_info.ocsp;
00214         char *base64;
00215         char *sep;
00216         size_t base64_len;
00217         size_t uri_len;
00218         size_t len;
00219         int rc;
00220 
00221         /* Sanity check */
00222         if ( ! responder->uri.len ) {
00223                 DBGC ( ocsp, "OCSP %p \"%s\" has no OCSP URI\n",
00224                        ocsp, x509_name ( ocsp->cert ) );
00225                 rc = -ENOTTY;
00226                 goto err_no_uri;
00227         }
00228 
00229         /* Calculate base64-encoded request length */
00230         base64_len = ( base64_encoded_len ( ocsp->request.builder.len )
00231                        + 1 /* NUL */ );
00232 
00233         /* Allocate and construct the base64-encoded request */
00234         base64 = malloc ( base64_len );
00235         if ( ! base64 ) {
00236                 rc = -ENOMEM;
00237                 goto err_alloc_base64;
00238         }
00239         base64_encode ( ocsp->request.builder.data, ocsp->request.builder.len,
00240                         base64, base64_len );
00241 
00242         /* Calculate URI-encoded base64-encoded request length */
00243         uri_len = ( uri_encode ( URI_PATH, base64, ( base64_len - 1 /* NUL */ ),
00244                                  NULL, 0 ) + 1 /* NUL */ );
00245 
00246         /* Allocate and construct the URI string */
00247         len = ( responder->uri.len + 1 /* possible "/" */ + uri_len );
00248         ocsp->uri_string = zalloc ( len );
00249         if ( ! ocsp->uri_string ) {
00250                 rc = -ENOMEM;
00251                 goto err_alloc_uri;
00252         }
00253         memcpy ( ocsp->uri_string, responder->uri.data, responder->uri.len );
00254         sep = &ocsp->uri_string[ responder->uri.len - 1 ];
00255         if ( *sep != '/' )
00256                 *(++sep) = '/';
00257         uri_encode ( URI_PATH, base64, base64_len, ( sep + 1 ), uri_len );
00258         DBGC2 ( ocsp, "OCSP %p \"%s\" URI is %s\n",
00259                 ocsp, x509_name ( ocsp->cert ), ocsp->uri_string );
00260 
00261         /* Success */
00262         rc = 0;
00263 
00264  err_alloc_uri:
00265         free ( base64 );
00266  err_alloc_base64:
00267  err_no_uri:
00268         return rc;
00269 }
00270 
00271 /**
00272  * Create OCSP check
00273  *
00274  * @v cert              Certificate to check
00275  * @v issuer            Issuing certificate
00276  * @ret ocsp            OCSP check
00277  * @ret rc              Return status code
00278  */
00279 int ocsp_check ( struct x509_certificate *cert,
00280                  struct x509_certificate *issuer,
00281                  struct ocsp_check **ocsp ) {
00282         int rc;
00283 
00284         /* Sanity checks */
00285         assert ( cert != NULL );
00286         assert ( issuer != NULL );
00287         assert ( x509_is_valid ( issuer ) );
00288 
00289         /* Allocate and initialise check */
00290         *ocsp = zalloc ( sizeof ( **ocsp ) );
00291         if ( ! *ocsp ) {
00292                 rc = -ENOMEM;
00293                 goto err_alloc;
00294         }
00295         ref_init ( &(*ocsp)->refcnt, ocsp_free );
00296         (*ocsp)->cert = x509_get ( cert );
00297         (*ocsp)->issuer = x509_get ( issuer );
00298 
00299         /* Build request */
00300         if ( ( rc = ocsp_request ( *ocsp ) ) != 0 )
00301                 goto err_request;
00302 
00303         /* Build URI string */
00304         if ( ( rc = ocsp_uri_string ( *ocsp ) ) != 0 )
00305                 goto err_uri_string;
00306 
00307         return 0;
00308 
00309  err_uri_string:
00310  err_request:
00311         ocsp_put ( *ocsp );
00312  err_alloc:
00313         *ocsp = NULL;
00314         return rc;
00315 }
00316 
00317 /**
00318  * Parse OCSP response status
00319  *
00320  * @v ocsp              OCSP check
00321  * @v raw               ASN.1 cursor
00322  * @ret rc              Return status code
00323  */
00324 static int ocsp_parse_response_status ( struct ocsp_check *ocsp,
00325                                         const struct asn1_cursor *raw ) {
00326         struct asn1_cursor cursor;
00327         uint8_t status;
00328         int rc;
00329 
00330         /* Enter responseStatus */
00331         memcpy ( &cursor, raw, sizeof ( cursor ) );
00332         if ( ( rc = asn1_enter ( &cursor, ASN1_ENUMERATED ) ) != 0 ) {
00333                 DBGC ( ocsp, "OCSP %p \"%s\" could not locate responseStatus: "
00334                        "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
00335                 return rc;
00336         }
00337 
00338         /* Extract response status */
00339         if ( cursor.len != sizeof ( status ) ) {
00340                 DBGC ( ocsp, "OCSP %p \"%s\" invalid status:\n",
00341                        ocsp, x509_name ( ocsp->cert ) );
00342                 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
00343                 return -EINVAL;
00344         }
00345         memcpy ( &status, cursor.data, sizeof ( status ) );
00346 
00347         /* Check response status */
00348         if ( status != OCSP_STATUS_SUCCESSFUL ) {
00349                 DBGC ( ocsp, "OCSP %p \"%s\" response status %d\n",
00350                        ocsp, x509_name ( ocsp->cert ), status );
00351                 return EPROTO_STATUS ( status );
00352         }
00353 
00354         return 0;
00355 }
00356 
00357 /**
00358  * Parse OCSP response type
00359  *
00360  * @v ocsp              OCSP check
00361  * @v raw               ASN.1 cursor
00362  * @ret rc              Return status code
00363  */
00364 static int ocsp_parse_response_type ( struct ocsp_check *ocsp,
00365                                       const struct asn1_cursor *raw ) {
00366         struct asn1_cursor cursor;
00367 
00368         /* Enter responseType */
00369         memcpy ( &cursor, raw, sizeof ( cursor ) );
00370         asn1_enter ( &cursor, ASN1_OID );
00371 
00372         /* Check responseType is "basic" */
00373         if ( asn1_compare ( &oid_basic_response_type_cursor, &cursor ) != 0 ) {
00374                 DBGC ( ocsp, "OCSP %p \"%s\" response type not supported:\n",
00375                        ocsp, x509_name ( ocsp->cert ) );
00376                 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
00377                 return -ENOTSUP_RESPONSE_TYPE;
00378         }
00379 
00380         return 0;
00381 }
00382 
00383 /**
00384  * Compare responder's certificate name
00385  *
00386  * @v ocsp              OCSP check
00387  * @v cert              Certificate
00388  * @ret difference      Difference as returned by memcmp()
00389  */
00390 static int ocsp_compare_responder_name ( struct ocsp_check *ocsp,
00391                                          struct x509_certificate *cert ) {
00392         struct ocsp_responder *responder = &ocsp->response.responder;
00393 
00394         /* Compare responder ID with certificate's subject */
00395         return asn1_compare ( &responder->id, &cert->subject.raw );
00396 }
00397 
00398 /**
00399  * Compare responder's certificate public key hash
00400  *
00401  * @v ocsp              OCSP check
00402  * @v cert              Certificate
00403  * @ret difference      Difference as returned by memcmp()
00404  */
00405 static int ocsp_compare_responder_key_hash ( struct ocsp_check *ocsp,
00406                                              struct x509_certificate *cert ) {
00407         struct ocsp_responder *responder = &ocsp->response.responder;
00408         struct asn1_cursor key_hash;
00409         uint8_t ctx[SHA1_CTX_SIZE];
00410         uint8_t digest[SHA1_DIGEST_SIZE];
00411         int difference;
00412 
00413         /* Enter responder key hash */
00414         memcpy ( &key_hash, &responder->id, sizeof ( key_hash ) );
00415         asn1_enter ( &key_hash, ASN1_OCTET_STRING );
00416 
00417         /* Sanity check */
00418         difference = ( sizeof ( digest ) - key_hash.len );
00419         if ( difference )
00420                 return difference;
00421 
00422         /* Generate SHA1 hash of certificate's public key */
00423         digest_init ( &sha1_algorithm, ctx );
00424         digest_update ( &sha1_algorithm, ctx,
00425                         cert->subject.public_key.raw_bits.data,
00426                         cert->subject.public_key.raw_bits.len );
00427         digest_final ( &sha1_algorithm, ctx, digest );
00428 
00429         /* Compare responder key hash with hash of certificate's public key */
00430         return memcmp ( digest, key_hash.data, sizeof ( digest ) );
00431 }
00432 
00433 /**
00434  * Parse OCSP responder ID
00435  *
00436  * @v ocsp              OCSP check
00437  * @v raw               ASN.1 cursor
00438  * @ret rc              Return status code
00439  */
00440 static int ocsp_parse_responder_id ( struct ocsp_check *ocsp,
00441                                      const struct asn1_cursor *raw ) {
00442         struct ocsp_responder *responder = &ocsp->response.responder;
00443         struct asn1_cursor *responder_id = &responder->id;
00444         unsigned int type;
00445 
00446         /* Enter responder ID */
00447         memcpy ( responder_id, raw, sizeof ( *responder_id ) );
00448         type = asn1_type ( responder_id );
00449         asn1_enter_any ( responder_id );
00450 
00451         /* Identify responder ID type */
00452         switch ( type ) {
00453         case ASN1_EXPLICIT_TAG ( 1 ) :
00454                 DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by name\n",
00455                         ocsp, x509_name ( ocsp->cert ) );
00456                 responder->compare = ocsp_compare_responder_name;
00457                 return 0;
00458         case ASN1_EXPLICIT_TAG ( 2 ) :
00459                 DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by key "
00460                         "hash\n", ocsp, x509_name ( ocsp->cert ) );
00461                 responder->compare = ocsp_compare_responder_key_hash;
00462                 return 0;
00463         default:
00464                 DBGC ( ocsp, "OCSP %p \"%s\" unsupported responder ID type "
00465                        "%d\n", ocsp, x509_name ( ocsp->cert ), type );
00466                 return -ENOTSUP_RESPONDER_ID;
00467         }
00468 }
00469 
00470 /**
00471  * Parse OCSP certificate ID
00472  *
00473  * @v ocsp              OCSP check
00474  * @v raw               ASN.1 cursor
00475  * @ret rc              Return status code
00476  */
00477 static int ocsp_parse_cert_id ( struct ocsp_check *ocsp,
00478                                 const struct asn1_cursor *raw ) {
00479         struct asn1_cursor cursor;
00480         struct asn1_algorithm *algorithm;
00481         int rc;
00482 
00483         /* Check certID algorithm */
00484         memcpy ( &cursor, raw, sizeof ( cursor ) );
00485         asn1_enter ( &cursor, ASN1_SEQUENCE );
00486         if ( ( rc = asn1_digest_algorithm ( &cursor, &algorithm ) ) != 0 ) {
00487                 DBGC ( ocsp, "OCSP %p \"%s\" certID unknown algorithm: %s\n",
00488                        ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
00489                 return rc;
00490         }
00491         if ( algorithm->digest != &ocsp_digest_algorithm ) {
00492                 DBGC ( ocsp, "OCSP %p \"%s\" certID wrong algorithm %s\n",
00493                        ocsp, x509_name ( ocsp->cert ),
00494                        algorithm->digest->name );
00495                 return -EACCES_CERT_MISMATCH;
00496         }
00497 
00498         /* Check remaining certID fields */
00499         asn1_skip ( &cursor, ASN1_SEQUENCE );
00500         if ( asn1_compare ( &cursor, &ocsp->request.cert_id_tail ) != 0 ) {
00501                 DBGC ( ocsp, "OCSP %p \"%s\" certID mismatch:\n",
00502                        ocsp, x509_name ( ocsp->cert ) );
00503                 DBGC_HDA ( ocsp, 0, ocsp->request.cert_id_tail.data,
00504                            ocsp->request.cert_id_tail.len );
00505                 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
00506                 return -EACCES_CERT_MISMATCH;
00507         }
00508 
00509         return 0;
00510 }
00511 
00512 /**
00513  * Parse OCSP responses
00514  *
00515  * @v ocsp              OCSP check
00516  * @v raw               ASN.1 cursor
00517  * @ret rc              Return status code
00518  */
00519 static int ocsp_parse_responses ( struct ocsp_check *ocsp,
00520                                   const struct asn1_cursor *raw ) {
00521         struct ocsp_response *response = &ocsp->response;
00522         struct asn1_cursor cursor;
00523         int rc;
00524 
00525         /* Enter responses */
00526         memcpy ( &cursor, raw, sizeof ( cursor ) );
00527         asn1_enter ( &cursor, ASN1_SEQUENCE );
00528 
00529         /* Enter first singleResponse */
00530         asn1_enter ( &cursor, ASN1_SEQUENCE );
00531 
00532         /* Parse certID */
00533         if ( ( rc = ocsp_parse_cert_id ( ocsp, &cursor ) ) != 0 )
00534                 return rc;
00535         asn1_skip_any ( &cursor );
00536 
00537         /* Check certStatus */
00538         if ( asn1_type ( &cursor ) != ASN1_IMPLICIT_TAG ( 0 ) ) {
00539                 DBGC ( ocsp, "OCSP %p \"%s\" non-good certStatus:\n",
00540                        ocsp, x509_name ( ocsp->cert ) );
00541                 DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
00542                 return -EACCES_CERT_STATUS;
00543         }
00544         asn1_skip_any ( &cursor );
00545 
00546         /* Parse thisUpdate */
00547         if ( ( rc = asn1_generalized_time ( &cursor,
00548                                             &response->this_update ) ) != 0 ) {
00549                 DBGC ( ocsp, "OCSP %p \"%s\" could not parse thisUpdate: %s\n",
00550                        ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
00551                 return rc;
00552         }
00553         DBGC2 ( ocsp, "OCSP %p \"%s\" this update was at time %lld\n",
00554                 ocsp, x509_name ( ocsp->cert ), response->this_update );
00555         asn1_skip_any ( &cursor );
00556 
00557         /* Parse nextUpdate, if present */
00558         if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) {
00559                 asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
00560                 if ( ( rc = asn1_generalized_time ( &cursor,
00561                                              &response->next_update ) ) != 0 ) {
00562                         DBGC ( ocsp, "OCSP %p \"%s\" could not parse "
00563                                "nextUpdate: %s\n", ocsp,
00564                                x509_name ( ocsp->cert ), strerror ( rc ) );
00565                         return rc;
00566                 }
00567                 DBGC2 ( ocsp, "OCSP %p \"%s\" next update is at time %lld\n",
00568                         ocsp, x509_name ( ocsp->cert ), response->next_update );
00569         } else {
00570                 /* If no nextUpdate is present, this indicates that
00571                  * "newer revocation information is available all the
00572                  * time".  Actually, this indicates that there is no
00573                  * point to performing the OCSP check, since an
00574                  * attacker could replay the response at any future
00575                  * time and it would still be valid.
00576                  */
00577                 DBGC ( ocsp, "OCSP %p \"%s\" responder is a moron\n",
00578                        ocsp, x509_name ( ocsp->cert ) );
00579                 response->next_update = time ( NULL );
00580         }
00581 
00582         return 0;
00583 }
00584 
00585 /**
00586  * Parse OCSP response data
00587  *
00588  * @v ocsp              OCSP check
00589  * @v raw               ASN.1 cursor
00590  * @ret rc              Return status code
00591  */
00592 static int ocsp_parse_tbs_response_data ( struct ocsp_check *ocsp,
00593                                           const struct asn1_cursor *raw ) {
00594         struct ocsp_response *response = &ocsp->response;
00595         struct asn1_cursor cursor;
00596         int rc;
00597 
00598         /* Record raw tbsResponseData */
00599         memcpy ( &cursor, raw, sizeof ( cursor ) );
00600         asn1_shrink_any ( &cursor );
00601         memcpy ( &response->tbs, &cursor, sizeof ( response->tbs ) );
00602 
00603         /* Enter tbsResponseData */
00604         asn1_enter ( &cursor, ASN1_SEQUENCE );
00605 
00606         /* Skip version, if present */
00607         asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
00608 
00609         /* Parse responderID */
00610         if ( ( rc = ocsp_parse_responder_id ( ocsp, &cursor ) ) != 0 )
00611                 return rc;
00612         asn1_skip_any ( &cursor );
00613 
00614         /* Skip producedAt */
00615         asn1_skip_any ( &cursor );
00616 
00617         /* Parse responses */
00618         if ( ( rc = ocsp_parse_responses ( ocsp, &cursor ) ) != 0 )
00619                 return rc;
00620 
00621         return 0;
00622 }
00623 
00624 /**
00625  * Parse OCSP certificates
00626  *
00627  * @v ocsp              OCSP check
00628  * @v raw               ASN.1 cursor
00629  * @ret rc              Return status code
00630  */
00631 static int ocsp_parse_certs ( struct ocsp_check *ocsp,
00632                               const struct asn1_cursor *raw ) {
00633         struct ocsp_response *response = &ocsp->response;
00634         struct asn1_cursor cursor;
00635         struct x509_certificate *cert;
00636         int rc;
00637 
00638         /* Enter certs */
00639         memcpy ( &cursor, raw, sizeof ( cursor ) );
00640         asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
00641         asn1_enter ( &cursor, ASN1_SEQUENCE );
00642 
00643         /* Parse certificate, if present.  The data structure permits
00644          * multiple certificates, but the protocol requires that the
00645          * OCSP signing certificate must either be the issuer itself,
00646          * or must be directly issued by the issuer (see RFC2560
00647          * section 4.2.2.2 "Authorized Responders").  We therefore
00648          * need to identify only the single certificate matching the
00649          * Responder ID.
00650          */
00651         while ( cursor.len ) {
00652 
00653                 /* Parse certificate */
00654                 if ( ( rc = x509_certificate ( cursor.data, cursor.len,
00655                                                &cert ) ) != 0 ) {
00656                         DBGC ( ocsp, "OCSP %p \"%s\" could not parse "
00657                                "certificate: %s\n", ocsp,
00658                                x509_name ( ocsp->cert ), strerror ( rc ) );
00659                         DBGC_HDA ( ocsp, 0, cursor.data, cursor.len );
00660                         return rc;
00661                 }
00662 
00663                 /* Use if this certificate matches the responder ID */
00664                 if ( response->responder.compare ( ocsp, cert ) == 0 ) {
00665                         response->signer = cert;
00666                         DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by ",
00667                                 ocsp, x509_name ( ocsp->cert ) );
00668                         DBGC2 ( ocsp, "\"%s\"\n",
00669                                 x509_name ( response->signer ) );
00670                         return 0;
00671                 }
00672 
00673                 /* Otherwise, discard this certificate */
00674                 x509_put ( cert );
00675                 asn1_skip_any ( &cursor );
00676         }
00677 
00678         DBGC ( ocsp, "OCSP %p \"%s\" missing responder certificate\n",
00679                ocsp, x509_name ( ocsp->cert ) );
00680         return -EACCES_NO_RESPONDER;
00681 }
00682 
00683 /**
00684  * Parse OCSP basic response
00685  *
00686  * @v ocsp              OCSP check
00687  * @v raw               ASN.1 cursor
00688  * @ret rc              Return status code
00689  */
00690 static int ocsp_parse_basic_response ( struct ocsp_check *ocsp,
00691                                        const struct asn1_cursor *raw ) {
00692         struct ocsp_response *response = &ocsp->response;
00693         struct asn1_algorithm **algorithm = &response->algorithm;
00694         struct asn1_bit_string *signature = &response->signature;
00695         struct asn1_cursor cursor;
00696         int rc;
00697 
00698         /* Enter BasicOCSPResponse */
00699         memcpy ( &cursor, raw, sizeof ( cursor ) );
00700         asn1_enter ( &cursor, ASN1_SEQUENCE );
00701 
00702         /* Parse tbsResponseData */
00703         if ( ( rc = ocsp_parse_tbs_response_data ( ocsp, &cursor ) ) != 0 )
00704                 return rc;
00705         asn1_skip_any ( &cursor );
00706 
00707         /* Parse signatureAlgorithm */
00708         if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) {
00709                 DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature "
00710                        "algorithm: %s\n",
00711                        ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
00712                 return rc;
00713         }
00714         DBGC2 ( ocsp, "OCSP %p \"%s\" signature algorithm is %s\n",
00715                 ocsp, x509_name ( ocsp->cert ), (*algorithm)->name );
00716         asn1_skip_any ( &cursor );
00717 
00718         /* Parse signature */
00719         if ( ( rc = asn1_integral_bit_string ( &cursor, signature ) ) != 0 ) {
00720                 DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature: %s\n",
00721                        ocsp, x509_name ( ocsp->cert ), strerror ( rc ) );
00722                 return rc;
00723         }
00724         asn1_skip_any ( &cursor );
00725 
00726         /* Parse certs, if present */
00727         if ( ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) &&
00728              ( ( rc = ocsp_parse_certs ( ocsp, &cursor ) ) != 0 ) )
00729                 return rc;
00730 
00731         return 0;
00732 }
00733 
00734 /**
00735  * Parse OCSP response bytes
00736  *
00737  * @v ocsp              OCSP check
00738  * @v raw               ASN.1 cursor
00739  * @ret rc              Return status code
00740  */
00741 static int ocsp_parse_response_bytes ( struct ocsp_check *ocsp,
00742                                        const struct asn1_cursor *raw ) {
00743         struct asn1_cursor cursor;
00744         int rc;
00745 
00746         /* Enter responseBytes */
00747         memcpy ( &cursor, raw, sizeof ( cursor ) );
00748         asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
00749         asn1_enter ( &cursor, ASN1_SEQUENCE );
00750 
00751         /* Parse responseType */
00752         if ( ( rc = ocsp_parse_response_type ( ocsp, &cursor ) ) != 0 )
00753                 return rc;
00754         asn1_skip_any ( &cursor );
00755 
00756         /* Enter response */
00757         asn1_enter ( &cursor, ASN1_OCTET_STRING );
00758 
00759         /* Parse response */
00760         if ( ( rc = ocsp_parse_basic_response ( ocsp, &cursor ) ) != 0 )
00761                 return rc;
00762 
00763         return 0;
00764 }
00765 
00766 /**
00767  * Parse OCSP response
00768  *
00769  * @v ocsp              OCSP check
00770  * @v raw               ASN.1 cursor
00771  * @ret rc              Return status code
00772  */
00773 static int ocsp_parse_response ( struct ocsp_check *ocsp,
00774                                  const struct asn1_cursor *raw ) {
00775         struct asn1_cursor cursor;
00776         int rc;
00777 
00778         /* Enter OCSPResponse */
00779         memcpy ( &cursor, raw, sizeof ( cursor ) );
00780         asn1_enter ( &cursor, ASN1_SEQUENCE );
00781 
00782         /* Parse responseStatus */
00783         if ( ( rc = ocsp_parse_response_status ( ocsp, &cursor ) ) != 0 )
00784                 return rc;
00785         asn1_skip_any ( &cursor );
00786 
00787         /* Parse responseBytes */
00788         if ( ( rc = ocsp_parse_response_bytes ( ocsp, &cursor ) ) != 0 )
00789                 return rc;
00790 
00791         return 0;
00792 }
00793 
00794 /**
00795  * Receive OCSP response
00796  *
00797  * @v ocsp              OCSP check
00798  * @v data              Response data
00799  * @v len               Length of response data
00800  * @ret rc              Return status code
00801  */
00802 int ocsp_response ( struct ocsp_check *ocsp, const void *data, size_t len ) {
00803         struct ocsp_response *response = &ocsp->response;
00804         struct asn1_cursor cursor;
00805         int rc;
00806 
00807         /* Duplicate data */
00808         x509_put ( response->signer );
00809         response->signer = NULL;
00810         free ( response->data );
00811         response->data = malloc ( len );
00812         if ( ! response->data )
00813                 return -ENOMEM;
00814         memcpy ( response->data, data, len );
00815         cursor.data = response->data;
00816         cursor.len = len;
00817 
00818         /* Parse response */
00819         if ( ( rc = ocsp_parse_response ( ocsp, &cursor ) ) != 0 )
00820                 return rc;
00821 
00822         return 0;
00823 }
00824 
00825 /**
00826  * OCSP dummy root certificate store
00827  *
00828  * OCSP validation uses no root certificates, since it takes place
00829  * only when there already exists a validated issuer certificate.
00830  */
00831 static struct x509_root ocsp_root = {
00832         .digest = &ocsp_digest_algorithm,
00833         .count = 0,
00834         .fingerprints = NULL,
00835 };
00836 
00837 /**
00838  * Check OCSP response signature
00839  *
00840  * @v ocsp              OCSP check
00841  * @v signer            Signing certificate
00842  * @ret rc              Return status code
00843  */
00844 static int ocsp_check_signature ( struct ocsp_check *ocsp,
00845                                   struct x509_certificate *signer ) {
00846         struct ocsp_response *response = &ocsp->response;
00847         struct digest_algorithm *digest = response->algorithm->digest;
00848         struct pubkey_algorithm *pubkey = response->algorithm->pubkey;
00849         struct x509_public_key *public_key = &signer->subject.public_key;
00850         uint8_t digest_ctx[ digest->ctxsize ];
00851         uint8_t digest_out[ digest->digestsize ];
00852         uint8_t pubkey_ctx[ pubkey->ctxsize ];
00853         int rc;
00854 
00855         /* Generate digest */
00856         digest_init ( digest, digest_ctx );
00857         digest_update ( digest, digest_ctx, response->tbs.data,
00858                         response->tbs.len );
00859         digest_final ( digest, digest_ctx, digest_out );
00860 
00861         /* Initialise public-key algorithm */
00862         if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data,
00863                                   public_key->raw.len ) ) != 0 ) {
00864                 DBGC ( ocsp, "OCSP %p \"%s\" could not initialise public key: "
00865                        "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
00866                 goto err_init;
00867         }
00868 
00869         /* Verify digest */
00870         if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out,
00871                                     response->signature.data,
00872                                     response->signature.len ) ) != 0 ) {
00873                 DBGC ( ocsp, "OCSP %p \"%s\" signature verification failed: "
00874                        "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
00875                 goto err_verify;
00876         }
00877 
00878         DBGC2 ( ocsp, "OCSP %p \"%s\" signature is correct\n",
00879                 ocsp, x509_name ( ocsp->cert ) );
00880 
00881  err_verify:
00882         pubkey_final ( pubkey, pubkey_ctx );
00883  err_init:
00884         return rc;
00885 }
00886 
00887 /**
00888  * Validate OCSP response
00889  *
00890  * @v ocsp              OCSP check
00891  * @v time              Time at which to validate response
00892  * @ret rc              Return status code
00893  */
00894 int ocsp_validate ( struct ocsp_check *ocsp, time_t time ) {
00895         struct ocsp_response *response = &ocsp->response;
00896         struct x509_certificate *signer;
00897         int rc;
00898 
00899         /* Sanity checks */
00900         assert ( response->data != NULL );
00901 
00902         /* The response may include a signer certificate; if this is
00903          * not present then the response must have been signed
00904          * directly by the issuer.
00905          */
00906         signer = ( response->signer ? response->signer : ocsp->issuer );
00907 
00908         /* Validate signer, if applicable.  If the signer is not the
00909          * issuer, then it must be signed directly by the issuer.
00910          */
00911         if ( signer != ocsp->issuer ) {
00912                 /* Forcibly invalidate the signer, since we need to
00913                  * ensure that it was signed by our issuer (and not
00914                  * some other issuer).  This prevents a sub-CA's OCSP
00915                  * certificate from fraudulently signing OCSP
00916                  * responses from the parent CA.
00917                  */
00918                 x509_invalidate ( signer );
00919                 if ( ( rc = x509_validate ( signer, ocsp->issuer, time,
00920                                             &ocsp_root ) ) != 0 ) {
00921                         DBGC ( ocsp, "OCSP %p \"%s\" could not validate ",
00922                                ocsp, x509_name ( ocsp->cert ) );
00923                         DBGC ( ocsp, "signer \"%s\": %s\n",
00924                                x509_name ( signer ), strerror ( rc ) );
00925                         return rc;
00926                 }
00927 
00928                 /* If signer is not the issuer, then it must have the
00929                  * extendedKeyUsage id-kp-OCSPSigning.
00930                  */
00931                 if ( ! ( signer->extensions.ext_usage.bits &
00932                          X509_OCSP_SIGNING ) ) {
00933                         DBGC ( ocsp, "OCSP %p \"%s\" ",
00934                                ocsp, x509_name ( ocsp->cert ) );
00935                         DBGC ( ocsp, "signer \"%s\" is not an OCSP-signing "
00936                                "certificate\n", x509_name ( signer ) );
00937                         return -EACCES_NON_OCSP_SIGNING;
00938                 }
00939         }
00940 
00941         /* Check OCSP response signature */
00942         if ( ( rc = ocsp_check_signature ( ocsp, signer ) ) != 0 )
00943                 return rc;
00944 
00945         /* Check OCSP response is valid at the specified time
00946          * (allowing for some margin of error).
00947          */
00948         if ( response->this_update > ( time + TIMESTAMP_ERROR_MARGIN ) ) {
00949                 DBGC ( ocsp, "OCSP %p \"%s\" response is not yet valid (at "
00950                        "time %lld)\n", ocsp, x509_name ( ocsp->cert ), time );
00951                 return -EACCES_STALE;
00952         }
00953         if ( response->next_update < ( time - TIMESTAMP_ERROR_MARGIN ) ) {
00954                 DBGC ( ocsp, "OCSP %p \"%s\" response is stale (at time "
00955                        "%lld)\n", ocsp, x509_name ( ocsp->cert ), time );
00956                 return -EACCES_STALE;
00957         }
00958         DBGC2 ( ocsp, "OCSP %p \"%s\" response is valid (at time %lld)\n",
00959                 ocsp, x509_name ( ocsp->cert ), time );
00960 
00961         /* Mark certificate as passing OCSP verification */
00962         ocsp->cert->extensions.auth_info.ocsp.good = 1;
00963 
00964         /* Validate certificate against issuer */
00965         if ( ( rc = x509_validate ( ocsp->cert, ocsp->issuer, time,
00966                                     &ocsp_root ) ) != 0 ) {
00967                 DBGC ( ocsp, "OCSP %p \"%s\" could not validate certificate: "
00968                        "%s\n", ocsp, x509_name ( ocsp->cert ), strerror ( rc ));
00969                 return rc;
00970         }
00971         DBGC ( ocsp, "OCSP %p \"%s\" successfully validated ",
00972                ocsp, x509_name ( ocsp->cert ) );
00973         DBGC ( ocsp, "using \"%s\"\n", x509_name ( signer ) );
00974 
00975         return 0;
00976 }