tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_pl_ocsprequest.c (13569B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * pkix_pl_ocsprequest.c
      6 *
      7 */
      8 
      9 #include "pkix_pl_ocsprequest.h"
     10 
     11 /* --Private-OcspRequest-Functions------------------------------------- */
     12 
     13 /*
     14 * FUNCTION: pkix_pl_OcspRequest_Destroy
     15 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
     16 */
     17 static PKIX_Error *
     18 pkix_pl_OcspRequest_Destroy(
     19        PKIX_PL_Object *object,
     20        void *plContext)
     21 {
     22        PKIX_PL_OcspRequest *ocspReq = NULL;
     23 
     24        PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Destroy");
     25        PKIX_NULLCHECK_ONE(object);
     26 
     27        PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext),
     28                    PKIX_OBJECTNOTOCSPREQUEST);
     29 
     30        ocspReq = (PKIX_PL_OcspRequest *)object;
     31 
     32        if (ocspReq->decoded != NULL) {
     33                CERT_DestroyOCSPRequest(ocspReq->decoded);
     34        }
     35 
     36        if (ocspReq->encoded != NULL) {
     37                SECITEM_FreeItem(ocspReq->encoded, PR_TRUE);
     38        }
     39 
     40        if (ocspReq->location != NULL) {
     41                PORT_Free(ocspReq->location);
     42        }
     43 
     44        PKIX_DECREF(ocspReq->cert);
     45        PKIX_DECREF(ocspReq->validity);
     46        PKIX_DECREF(ocspReq->signerCert);
     47 
     48 cleanup:
     49 
     50        PKIX_RETURN(OCSPREQUEST);
     51 }
     52 
     53 /*
     54 * FUNCTION: pkix_pl_OcspRequest_Hashcode
     55 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
     56 */
     57 static PKIX_Error *
     58 pkix_pl_OcspRequest_Hashcode(
     59        PKIX_PL_Object *object,
     60        PKIX_UInt32 *pHashcode,
     61        void *plContext)
     62 {
     63        PKIX_UInt32 certHash = 0;
     64        PKIX_UInt32 dateHash = 0;
     65        PKIX_UInt32 extensionHash = 0;
     66        PKIX_UInt32 signerHash = 0;
     67        PKIX_PL_OcspRequest *ocspRq = NULL;
     68 
     69        PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Hashcode");
     70        PKIX_NULLCHECK_TWO(object, pHashcode);
     71 
     72        PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPREQUEST_TYPE, plContext),
     73                    PKIX_OBJECTNOTOCSPREQUEST);
     74 
     75        ocspRq = (PKIX_PL_OcspRequest *)object;
     76 
     77        *pHashcode = 0;
     78 
     79        PKIX_HASHCODE(ocspRq->cert, &certHash, plContext,
     80                PKIX_CERTHASHCODEFAILED);
     81 
     82        PKIX_HASHCODE(ocspRq->validity, &dateHash, plContext,
     83                PKIX_DATEHASHCODEFAILED);
     84 
     85        if (ocspRq->addServiceLocator == PKIX_TRUE) {
     86                extensionHash = 0xff;
     87        }
     88 
     89        PKIX_HASHCODE(ocspRq->signerCert, &signerHash, plContext,
     90                PKIX_CERTHASHCODEFAILED);
     91 
     92        *pHashcode = (((((extensionHash << 8) | certHash) << 8) |
     93                dateHash) << 8) | signerHash;
     94 
     95 cleanup:
     96 
     97        PKIX_RETURN(OCSPREQUEST);
     98 
     99 }
    100 
    101 /*
    102 * FUNCTION: pkix_pl_OcspRequest_Equals
    103 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
    104 */
    105 static PKIX_Error *
    106 pkix_pl_OcspRequest_Equals(
    107        PKIX_PL_Object *firstObj,
    108        PKIX_PL_Object *secondObj,
    109        PKIX_Boolean *pResult,
    110        void *plContext)
    111 {
    112        PKIX_Boolean match = PKIX_FALSE;
    113        PKIX_UInt32 secondType = 0;
    114        PKIX_PL_OcspRequest *firstReq = NULL;
    115        PKIX_PL_OcspRequest *secondReq = NULL;
    116 
    117        PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Equals");
    118        PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
    119 
    120        /* test that firstObj is a OcspRequest */
    121        PKIX_CHECK(pkix_CheckType(firstObj, PKIX_OCSPREQUEST_TYPE, plContext),
    122                    PKIX_FIRSTOBJARGUMENTNOTOCSPREQUEST);
    123 
    124        /*
    125         * Since we know firstObj is a OcspRequest, if both references are
    126         * identical, they must be equal
    127         */
    128        if (firstObj == secondObj){
    129                match = PKIX_TRUE;
    130                goto cleanup;
    131        }
    132 
    133        /*
    134         * If secondObj isn't a OcspRequest, we don't throw an error.
    135         * We simply return a Boolean result of FALSE
    136         */
    137        PKIX_CHECK(PKIX_PL_Object_GetType
    138                    (secondObj, &secondType, plContext),
    139                    PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
    140        if (secondType != PKIX_OCSPREQUEST_TYPE) {
    141                goto cleanup;
    142        }
    143 
    144        firstReq = (PKIX_PL_OcspRequest *)firstObj;
    145        secondReq = (PKIX_PL_OcspRequest *)secondObj;
    146 
    147        if (firstReq->addServiceLocator != secondReq->addServiceLocator) {
    148                goto cleanup;
    149        }
    150 
    151        PKIX_EQUALS(firstReq->cert, secondReq->cert, &match, plContext,
    152                PKIX_CERTEQUALSFAILED);
    153 
    154        if (match == PKIX_FALSE) {
    155                goto cleanup;
    156        }
    157 
    158        PKIX_EQUALS(firstReq->validity, secondReq->validity, &match, plContext,
    159                PKIX_DATEEQUALSFAILED);
    160 
    161        if (match == PKIX_FALSE) {
    162                goto cleanup;
    163        }
    164 
    165        PKIX_EQUALS
    166                (firstReq->signerCert, secondReq->signerCert, &match, plContext,
    167                PKIX_CERTEQUALSFAILED);
    168 
    169 cleanup:
    170 
    171        *pResult = match;
    172 
    173        PKIX_RETURN(OCSPREQUEST);
    174 }
    175 
    176 /*
    177 * FUNCTION: pkix_pl_OcspRequest_RegisterSelf
    178 * DESCRIPTION:
    179 *  Registers PKIX_OCSPREQUEST_TYPE and its related functions with
    180 *  systemClasses[]
    181 * PARAMETERS:
    182 *  "plContext"
    183 *      Platform-specific context pointer.
    184 * THREAD SAFETY:
    185 *  Not Thread Safe - for performance and complexity reasons
    186 *
    187 *  Since this function is only called by PKIX_PL_Initialize, which should
    188 *  only be called once, it is acceptable that this function is not
    189 *  thread-safe.
    190 */
    191 PKIX_Error *
    192 pkix_pl_OcspRequest_RegisterSelf(void *plContext)
    193 {
    194        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
    195        pkix_ClassTable_Entry entry;
    196 
    197        PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_RegisterSelf");
    198 
    199        entry.description = "OcspRequest";
    200        entry.objCounter = 0;
    201        entry.typeObjectSize = sizeof(PKIX_PL_OcspRequest);
    202        entry.destructor = pkix_pl_OcspRequest_Destroy;
    203        entry.equalsFunction = pkix_pl_OcspRequest_Equals;
    204        entry.hashcodeFunction = pkix_pl_OcspRequest_Hashcode;
    205        entry.toStringFunction = NULL;
    206        entry.comparator = NULL;
    207        entry.duplicateFunction = pkix_duplicateImmutable;
    208 
    209        systemClasses[PKIX_OCSPREQUEST_TYPE] = entry;
    210 
    211        PKIX_RETURN(OCSPREQUEST);
    212 }
    213 
    214 /* --Public-Functions------------------------------------------------------- */
    215 
    216 /*
    217 * FUNCTION: pkix_pl_OcspRequest_Create
    218 * DESCRIPTION:
    219 *
    220 *  This function creates an OcspRequest to be used in validating the Cert
    221 *  pointed to by "cert" and storing the result at "pRequest". If a URI
    222 *  is found for an OCSP responder, PKIX_TRUE is stored at "pURIFound". If no
    223 *  URI is found, PKIX_FALSE is stored.
    224 *
    225 *  If a Date is provided in "validity" it may be used in the search for the
    226 *  issuer of "cert" but has no effect on the request itself. If
    227 *  "addServiceLocator" is TRUE, the AddServiceLocator extension will be
    228 *  included in the Request. If "signerCert" is provided it will be used to sign
    229 *  the Request. (Note: this signed request feature is not currently supported.)
    230 *
    231 * PARAMETERS:
    232 *  "cert"
    233 *     Address of the Cert for which an OcspRequest is to be created. Must be
    234 *     non-NULL.
    235 *  "validity"
    236 *     Address of the Date for which the Cert's validity is to be determined.
    237 *     May be NULL.
    238 *  "signerCert"
    239 *     Address of the Cert to be used, if present, in signing the request.
    240 *     May be NULL.
    241 *  "pRequest"
    242 *     Address at which the result is stored. Must be non-NULL.
    243 *  "plContext"
    244 *      Platform-specific context pointer.
    245 * THREAD SAFETY:
    246 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    247 * RETURNS:
    248 *  Returns NULL if the function succeeds.
    249 *  Returns an OcspRequest Error if the function fails in a non-fatal way.
    250 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    251 */
    252 PKIX_Error *
    253 pkix_pl_OcspRequest_Create(
    254        PKIX_PL_Cert *cert,
    255        PKIX_PL_OcspCertID *cid,
    256        PKIX_PL_Date *validity,
    257        PKIX_PL_Cert *signerCert,
    258        PKIX_UInt32 methodFlags,
    259        PKIX_Boolean *pURIFound,
    260        PKIX_PL_OcspRequest **pRequest,
    261        void *plContext)
    262 {
    263        PKIX_PL_OcspRequest *ocspRequest = NULL;
    264 
    265        CERTCertDBHandle *handle = NULL;
    266        SECStatus rv = SECFailure;
    267        SECItem *encoding = NULL;
    268        CERTOCSPRequest *certRequest = NULL;
    269        PRTime time = 0;
    270        PRBool addServiceLocatorExtension = PR_FALSE;
    271        CERTCertificate *nssCert = NULL;
    272        CERTCertificate *nssSignerCert = NULL;
    273        char *location = NULL;
    274        PRErrorCode locError = 0;
    275        PKIX_Boolean canUseDefaultSource = PKIX_FALSE;
    276 
    277        PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_Create");
    278        PKIX_NULLCHECK_TWO(cert, pRequest);
    279 
    280        /* create a PKIX_PL_OcspRequest object */
    281        PKIX_CHECK(PKIX_PL_Object_Alloc
    282                    (PKIX_OCSPREQUEST_TYPE,
    283                    sizeof (PKIX_PL_OcspRequest),
    284                    (PKIX_PL_Object **)&ocspRequest,
    285                    plContext),
    286                    PKIX_COULDNOTCREATEOBJECT);
    287 
    288        PKIX_INCREF(cert);
    289        ocspRequest->cert = cert;
    290 
    291        PKIX_INCREF(validity);
    292        ocspRequest->validity = validity;
    293 
    294        PKIX_INCREF(signerCert);
    295        ocspRequest->signerCert = signerCert;
    296 
    297        ocspRequest->decoded = NULL;
    298        ocspRequest->encoded = NULL;
    299 
    300        ocspRequest->location = NULL;
    301 
    302        nssCert = cert->nssCert;
    303 
    304        /*
    305         * Does this Cert have an Authority Information Access extension with
    306         * the URI of an OCSP responder?
    307         */
    308        handle = CERT_GetDefaultCertDB();
    309 
    310        if (!(methodFlags & PKIX_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE)) {
    311            canUseDefaultSource = PKIX_TRUE;
    312        }
    313        location = ocsp_GetResponderLocation(handle, nssCert,
    314                                             canUseDefaultSource,
    315                                             &addServiceLocatorExtension);
    316        if (location == NULL) {
    317                locError = PORT_GetError();
    318                if (locError == SEC_ERROR_EXTENSION_NOT_FOUND ||
    319                    locError == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) {
    320                    PORT_SetError(0);
    321                    *pURIFound = PKIX_FALSE;
    322                    goto cleanup;
    323                }
    324                PKIX_ERROR(PKIX_ERRORFINDINGORPROCESSINGURI);
    325        }
    326 
    327        ocspRequest->location = location;
    328        *pURIFound = PKIX_TRUE;
    329 
    330        if (signerCert != NULL) {
    331                nssSignerCert = signerCert->nssCert;
    332        }
    333 
    334        if (validity != NULL) {
    335 	PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext),
    336 		PKIX_DATEGETPRTIMEFAILED);
    337        } else {
    338                time = PR_Now();
    339 }
    340 
    341        certRequest = cert_CreateSingleCertOCSPRequest(
    342                cid->certID, cert->nssCert, time, 
    343                addServiceLocatorExtension, nssSignerCert);
    344 
    345        ocspRequest->decoded = certRequest;
    346 
    347        if (certRequest == NULL) {
    348                PKIX_ERROR(PKIX_UNABLETOCREATECERTOCSPREQUEST);
    349        }
    350 
    351        rv = CERT_AddOCSPAcceptableResponses(
    352                certRequest, SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
    353 
    354        if (rv == SECFailure) {
    355                PKIX_ERROR(PKIX_UNABLETOADDACCEPTABLERESPONSESTOREQUEST);
    356        }
    357 
    358        encoding = CERT_EncodeOCSPRequest(NULL, certRequest, NULL);
    359 
    360        ocspRequest->encoded = encoding;
    361 
    362        *pRequest = ocspRequest;
    363        ocspRequest = NULL;
    364 
    365 cleanup:
    366        PKIX_DECREF(ocspRequest);
    367 
    368        PKIX_RETURN(OCSPREQUEST);
    369 }
    370 
    371 /*
    372 * FUNCTION: pkix_pl_OcspRequest_GetEncoded
    373 * DESCRIPTION:
    374 *
    375 *  This function obtains the encoded message from the OcspRequest pointed to
    376 *  by "request", storing the result at "pRequest".
    377 *
    378 * PARAMETERS
    379 *  "request"
    380 *      The address of the OcspRequest whose encoded message is to be
    381 *      retrieved. Must be non-NULL.
    382 *  "pRequest"
    383 *      The address at which is stored the address of the encoded message. Must
    384 *      be non-NULL.
    385 *  "plContext"
    386 *      Platform-specific context pointer.
    387 * THREAD SAFETY:
    388 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    389 * RETURNS:
    390 *  Returns NULL if the function succeeds.
    391 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    392 */
    393 PKIX_Error *
    394 pkix_pl_OcspRequest_GetEncoded(
    395        PKIX_PL_OcspRequest *request,
    396        SECItem **pRequest,
    397        void *plContext)
    398 {
    399        PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetEncoded");
    400        PKIX_NULLCHECK_TWO(request, pRequest);
    401 
    402        *pRequest = request->encoded;
    403 
    404        PKIX_RETURN(OCSPREQUEST);
    405 }
    406 
    407 /*
    408 * FUNCTION: pkix_pl_OcspRequest_GetLocation
    409 * DESCRIPTION:
    410 *
    411 *  This function obtains the location from the OcspRequest pointed to
    412 *  by "request", storing the result at "pLocation".
    413 *
    414 * PARAMETERS
    415 *  "request"
    416 *      The address of the OcspRequest whose encoded message is to be
    417 *      retrieved. Must be non-NULL.
    418 *  "pLocation"
    419 *      The address at which is stored the address of the location. Must
    420 *      be non-NULL.
    421 *  "plContext"
    422 *      Platform-specific context pointer.
    423 * THREAD SAFETY:
    424 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    425 * RETURNS:
    426 *  Returns NULL if the function succeeds.
    427 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    428 */
    429 PKIX_Error *
    430 pkix_pl_OcspRequest_GetLocation(
    431        PKIX_PL_OcspRequest *request,
    432        char **pLocation,
    433        void *plContext)
    434 {
    435        PKIX_ENTER(OCSPREQUEST, "pkix_pl_OcspRequest_GetLocation");
    436        PKIX_NULLCHECK_TWO(request, pLocation);
    437 
    438        *pLocation = request->location;
    439 
    440        PKIX_RETURN(OCSPREQUEST);
    441 }