~ubuntu-branches/ubuntu/raring/nss/raring-security

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/certhigh/ocsp.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2010-03-25 13:46:06 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20100325134606-bl6liuok2w9l7snv
Tags: 3.12.6-0ubuntu1
* New upstream release 3.12.6 RTM (NSS_3_12_6_RTM)
  - fixes CVE-2009-3555 aka US-CERT VU#120541
* Adjust patches to changed upstream code base
  - update debian/patches/38_kbsd.patch
  - update debian/patches/38_mips64_build.patch
  - update debian/patches/85_security_load.patch
* Remove patches that are merged upstream
  - delete debian/patches/91_nonexec_stack.patch
  - update debian/patches/series
* Bump nspr dependency to 4.8
  - update debian/control
* Add new symbols for 3.12.6
  - update debian/libnss3-1d.symbols

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
 * Implementation of OCSP services, for both client and server.
40
40
 * (XXX, really, mostly just for client right now, but intended to do both.)
41
41
 *
42
 
 * $Id: ocsp.c,v 1.58 2009/03/21 01:40:35 nelson%bolyard.com Exp $
 
42
 * $Id: ocsp.c,v 1.64 2010/02/01 20:09:31 wtc%google.com Exp $
43
43
 */
44
44
 
45
45
#include "prerror.h"
150
150
                              void *pwArg,
151
151
                              PRBool *certIDWasConsumed,
152
152
                              SECStatus *rv_ocsp);
 
153
 
 
154
static SECStatus
 
155
ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle,
 
156
                              CERTOCSPCertID *certID,
 
157
                              CERTCertificate *cert,
 
158
                              int64 time,
 
159
                              void *pwArg,
 
160
                              SECItem *encodedResponse,
 
161
                              PRBool *certIDWasConsumed,
 
162
                              PRBool cacheNegative,
 
163
                              SECStatus *rv_ocsp);
 
164
 
153
165
static SECStatus
154
166
ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle, 
155
167
                                        CERTOCSPResponse *response, 
158
170
                                        int64             time,
159
171
                                        CERTOCSPSingleResponse **pSingleResponse);
160
172
 
 
173
static SECStatus
 
174
ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, int64 time);
 
175
 
161
176
#ifndef DEBUG
162
177
#define OCSP_TRACE(msg)
163
178
#define OCSP_TRACE_TIME(msg, time)
730
745
    }
731
746
  
732
747
    if (cacheItem->haveNextUpdate) {
733
 
        OCSP_TRACE_TIME("have nextUpdate:", cacheItem->thisUpdate);
 
748
        OCSP_TRACE_TIME("have nextUpdate:", cacheItem->nextUpdate);
734
749
    }
735
750
  
736
751
    if (cacheItem->haveNextUpdate &&
4285
4300
static PRUint32 ocspsloptime = OCSP_SLOP;       /* seconds */
4286
4301
 
4287
4302
/*
 
4303
 * If an old response contains the revoked certificate status, we want
 
4304
 * to return SECSuccess so the response will be used.
 
4305
 */
 
4306
static SECStatus
 
4307
ocsp_HandleOldSingleResponse(CERTOCSPSingleResponse *single, PRTime time)
 
4308
{
 
4309
    SECStatus rv;
 
4310
    ocspCertStatus *status = single->certStatus;
 
4311
    if (status->certStatusType == ocspCertStatus_revoked) {
 
4312
        rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time);
 
4313
        if (rv != SECSuccess &&
 
4314
            PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE) {
 
4315
            /*
 
4316
             * Return SECSuccess now.  The subsequent ocsp_CertRevokedAfter
 
4317
             * call in ocsp_CertHasGoodStatus will cause
 
4318
             * ocsp_CertHasGoodStatus to fail with
 
4319
             * SEC_ERROR_REVOKED_CERTIFICATE.
 
4320
             */
 
4321
            return SECSuccess;
 
4322
        }
 
4323
 
 
4324
    }
 
4325
    PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE);
 
4326
    return SECFailure;
 
4327
}
 
4328
 
 
4329
/*
4288
4330
 * Check that this single response is okay.  A return of SECSuccess means:
4289
4331
 *   1. The signer (represented by "signerCert") is authorized to give status
4290
4332
 *      for the cert represented by the individual response in "single".
4365
4407
            return rv;
4366
4408
 
4367
4409
        LL_ADD(tmp, tmp, nextUpdate);
4368
 
        if (LL_CMP(tmp, <, now) || LL_CMP(producedAt, >, nextUpdate)) {
4369
 
            PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE);
4370
 
            return SECFailure;
4371
 
        }
 
4410
        if (LL_CMP(tmp, <, now) || LL_CMP(producedAt, >, nextUpdate))
 
4411
            return ocsp_HandleOldSingleResponse(single, now);
4372
4412
    } else if (ocsp_TimeIsRecent(thisUpdate) != PR_TRUE) {
4373
 
        PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE);
4374
 
        return SECFailure;
 
4413
        return ocsp_HandleOldSingleResponse(single, now);
4375
4414
    }
4376
4415
 
4377
4416
    return SECSuccess;
4645
4684
        /* having an arena means, we have a cached certStatus */
4646
4685
        if (cacheItem->certStatusArena) {
4647
4686
            *rvOcsp = ocsp_CertHasGoodStatus(&cacheItem->certStatus, time);
 
4687
            if (*rvOcsp != SECSuccess) {
 
4688
                *missingResponseError = PORT_GetError();
 
4689
            }
4648
4690
            rv = SECSuccess;
4649
4691
        } else {
4650
4692
            /*
4767
4809
}
4768
4810
 
4769
4811
/*
 
4812
 * FUNCTION: CERT_CacheOCSPResponseFromSideChannel
 
4813
 *   First, this function checks the OCSP cache to see if a good response
 
4814
 *   for the given certificate already exists. If it does, then the function
 
4815
 *   returns successfully.
 
4816
 *
 
4817
 *   If not, then it validates that the given OCSP response is a valid,
 
4818
 *   good response for the given certificate and inserts it into the
 
4819
 *   cache.
 
4820
 *
 
4821
 *   This function is intended for use when OCSP responses are provided via a
 
4822
 *   side-channel, i.e. TLS OCSP stapling (a.k.a. the status_request extension).
 
4823
 *
 
4824
 * INPUTS:
 
4825
 *   CERTCertDBHandle *handle
 
4826
 *     certificate DB of the cert that is being checked
 
4827
 *   CERTCertificate *cert
 
4828
 *     the certificate being checked
 
4829
 *   int64 time
 
4830
 *     time for which status is to be determined
 
4831
 *   SECItem *encodedResponse
 
4832
 *     the DER encoded bytes of the OCSP response
 
4833
 *   void *pwArg
 
4834
 *     argument for password prompting, if needed
 
4835
 * RETURN:
 
4836
 *   SECSuccess if the cert was found in the cache, or if the OCSP response was
 
4837
 *   found to be valid and inserted into the cache. SECFailure otherwise.
 
4838
 */
 
4839
SECStatus
 
4840
CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle,
 
4841
                                      CERTCertificate *cert,
 
4842
                                      int64 time,
 
4843
                                      SECItem *encodedResponse,
 
4844
                                      void *pwArg)
 
4845
{
 
4846
    CERTOCSPCertID *certID;
 
4847
    PRBool certIDWasConsumed = PR_FALSE;
 
4848
    SECStatus rv = SECFailure;
 
4849
    SECStatus rvOcsp;
 
4850
    SECErrorCodes dummy_error_code; /* we ignore this */
 
4851
 
 
4852
    certID = CERT_CreateOCSPCertID(cert, time);
 
4853
    if (!certID)
 
4854
        return SECFailure;
 
4855
    rv = ocsp_GetCachedOCSPResponseStatusIfFresh(
 
4856
        certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */
 
4857
        &rvOcsp, &dummy_error_code);
 
4858
    if (rv == SECSuccess && rvOcsp == SECSuccess) {
 
4859
        /* The cached value is good. We don't want to waste time validating
 
4860
         * this OCSP response. */
 
4861
        CERT_DestroyOCSPCertID(certID);
 
4862
        return rv;
 
4863
    }
 
4864
 
 
4865
    /* Since the OCSP response came from a side channel it is attacker
 
4866
     * controlled. The attacker can have chosen any valid OCSP response,
 
4867
     * including responses from the past. In this case,
 
4868
     * ocsp_GetVerifiedSingleResponseForCertID will fail. If we recorded a
 
4869
     * negative cache entry in this case, then the attacker would have
 
4870
     * 'poisoned' our cache (denial of service), so we don't record negative
 
4871
     * results. */
 
4872
    rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, pwArg,
 
4873
                                       encodedResponse, &certIDWasConsumed,
 
4874
                                       PR_FALSE /* don't cache failures */,
 
4875
                                       &rvOcsp);
 
4876
    if (!certIDWasConsumed) {
 
4877
        CERT_DestroyOCSPCertID(certID);
 
4878
    }
 
4879
    return rv == SECSuccess ? rvOcsp : rv;
 
4880
}
 
4881
 
 
4882
/*
4770
4883
 * Status in *certIDWasConsumed will always be correct, regardless of 
4771
4884
 * return value.
4772
4885
 */
4783
4896
    PRBool locationIsDefault;
4784
4897
    SECItem *encodedResponse = NULL;
4785
4898
    CERTOCSPRequest *request = NULL;
4786
 
    CERTOCSPResponse *response = NULL;
4787
 
    CERTCertificate *signerCert = NULL;
4788
 
    CERTCertificate *issuerCert = NULL;
4789
4899
    SECStatus rv = SECFailure;
4790
 
    CERTOCSPSingleResponse *single = NULL;
4791
4900
 
4792
4901
    if (!certIDWasConsumed || !rv_ocsp) {
4793
4902
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
4849
4958
        goto loser;
4850
4959
    }
4851
4960
 
 
4961
    rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, pwArg,
 
4962
                                       encodedResponse, certIDWasConsumed,
 
4963
                                       PR_TRUE /* cache failures */, rv_ocsp);
 
4964
 
 
4965
loser:
 
4966
    if (request != NULL)
 
4967
        CERT_DestroyOCSPRequest(request);
 
4968
    if (encodedResponse != NULL)
 
4969
        SECITEM_FreeItem(encodedResponse, PR_TRUE);
 
4970
    if (location != NULL)
 
4971
        PORT_Free(location);
 
4972
 
 
4973
    return rv;
 
4974
}
 
4975
 
 
4976
/*
 
4977
 * FUNCTION: ocsp_CacheEncodedOCSPResponse
 
4978
 *   This function decodes an OCSP response and checks for a valid response
 
4979
 *   concerning the given certificate. If such a response is not found
 
4980
 *   then nothing is cached. Otherwise, if it is a good response, or if
 
4981
 *   cacheNegative is true, the results are stored in the OCSP cache.
 
4982
 *
 
4983
 *   Note: a 'valid' response is one that parses successfully, is not an OCSP
 
4984
 *   exception (see RFC 2560 Section 2.3), is correctly signed and is current.
 
4985
 *   A 'good' response is a valid response that attests that the certificate
 
4986
 *   is not currently revoked (see RFC 2560 Section 2.2).
 
4987
 *
 
4988
 * INPUTS:
 
4989
 *   CERTCertDBHandle *handle
 
4990
 *     certificate DB of the cert that is being checked
 
4991
 *   CERTOCSPCertID *certID
 
4992
 *     the cert ID corresponding to |cert|
 
4993
 *   CERTCertificate *cert
 
4994
 *     the certificate being checked
 
4995
 *   int64 time
 
4996
 *     time for which status is to be determined
 
4997
 *   void *pwArg
 
4998
 *     the opaque argument to the password prompting function.
 
4999
 *   SECItem *encodedResponse
 
5000
 *     the DER encoded bytes of the OCSP response
 
5001
 *   PRBool *certIDWasConsumed
 
5002
 *     (output) on return, this is true iff |certID| was consumed by this
 
5003
 *     function.
 
5004
 *   SECStatus *rv_ocsp
 
5005
 *     (output) on return, this is SECSuccess iff the response is good (see
 
5006
 *     definition of 'good' above).
 
5007
 * RETURN:
 
5008
 *   SECSuccess iff the response is valid.
 
5009
 */
 
5010
static SECStatus
 
5011
ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle,
 
5012
                              CERTOCSPCertID *certID,
 
5013
                              CERTCertificate *cert,
 
5014
                              int64 time,
 
5015
                              void *pwArg,
 
5016
                              SECItem *encodedResponse,
 
5017
                              PRBool *certIDWasConsumed,
 
5018
                              PRBool cacheNegative,
 
5019
                              SECStatus *rv_ocsp)
 
5020
{
 
5021
    CERTOCSPResponse *response = NULL;
 
5022
    CERTCertificate *signerCert = NULL;
 
5023
    CERTCertificate *issuerCert = NULL;
 
5024
    CERTOCSPSingleResponse *single = NULL;
 
5025
    SECStatus rv = SECFailure;
 
5026
 
 
5027
    *certIDWasConsumed = PR_FALSE;
 
5028
    *rv_ocsp = SECFailure;
 
5029
 
4852
5030
    response = CERT_DecodeOCSPResponse(encodedResponse);
4853
5031
    if (response == NULL) {
4854
5032
        goto loser;
4896
5074
    *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(single, time);
4897
5075
 
4898
5076
loser:
4899
 
    PR_EnterMonitor(OCSP_Global.monitor);
4900
 
    if (OCSP_Global.maxCacheEntries >= 0) {
4901
 
        /* single == NULL means: remember response failure */
4902
 
        ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single, 
4903
 
                                      certIDWasConsumed);
4904
 
        /* ignore cache update failures */
 
5077
    if (cacheNegative || *rv_ocsp == SECSuccess) {
 
5078
        PR_EnterMonitor(OCSP_Global.monitor);
 
5079
        if (OCSP_Global.maxCacheEntries >= 0) {
 
5080
            /* single == NULL means: remember response failure */
 
5081
            ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single,
 
5082
                                          certIDWasConsumed);
 
5083
            /* ignore cache update failures */
 
5084
        }
 
5085
        PR_ExitMonitor(OCSP_Global.monitor);
4905
5086
    }
4906
 
    PR_ExitMonitor(OCSP_Global.monitor);
 
5087
 
 
5088
    /* 'single' points within the response so there's no need to free it. */
4907
5089
 
4908
5090
    if (issuerCert != NULL)
4909
5091
        CERT_DestroyCertificate(issuerCert);
4911
5093
        CERT_DestroyCertificate(signerCert);
4912
5094
    if (response != NULL)
4913
5095
        CERT_DestroyOCSPResponse(response);
4914
 
    if (request != NULL)
4915
 
        CERT_DestroyOCSPRequest(request);
4916
 
    if (encodedResponse != NULL)
4917
 
        SECITEM_FreeItem(encodedResponse, PR_TRUE);
4918
 
    if (location != NULL)
4919
 
        PORT_Free(location);
4920
5096
    return rv;
4921
5097
}
4922
5098