tor-browser

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

ocspresp.c (7414B)


      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 /*
      6 * ocspresp - self test for OCSP response creation
      7 */
      8 
      9 #include "nspr.h"
     10 #include "secutil.h"
     11 #include "secpkcs7.h"
     12 #include "cert.h"
     13 #include "certdb.h"
     14 #include "nss.h"
     15 #include "pk11func.h"
     16 #include "cryptohi.h"
     17 #include "ocsp.h"
     18 
     19 #if defined(XP_UNIX)
     20 #include <unistd.h>
     21 #endif
     22 
     23 #include <stdio.h>
     24 #include <string.h>
     25 
     26 secuPWData pwdata = { PW_NONE, 0 };
     27 
     28 static PRBool
     29 getCaAndSubjectCert(CERTCertDBHandle *certHandle,
     30                    const char *caNick, const char *eeNick,
     31                    CERTCertificate **outCA, CERTCertificate **outCert)
     32 {
     33    *outCA = CERT_FindCertByNickname(certHandle, caNick);
     34    *outCert = CERT_FindCertByNickname(certHandle, eeNick);
     35    return *outCA && *outCert;
     36 }
     37 
     38 static SECItem *
     39 encode(PLArenaPool *arena, CERTOCSPCertID *cid, CERTCertificate *ca)
     40 {
     41    SECItem *response;
     42    PRTime now = PR_Now();
     43    PRTime nextUpdate;
     44    CERTOCSPSingleResponse **responses;
     45    CERTOCSPSingleResponse *sr;
     46 
     47    if (!arena)
     48        return NULL;
     49 
     50    nextUpdate = now + 10 * PR_USEC_PER_SEC; /* in the future */
     51 
     52    sr = CERT_CreateOCSPSingleResponseGood(arena, cid, now, &nextUpdate);
     53 
     54    /* meaning of value 2: one entry + one end marker */
     55    responses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2);
     56    if (responses == NULL)
     57        return NULL;
     58 
     59    responses[0] = sr;
     60    responses[1] = NULL;
     61 
     62    response = CERT_CreateEncodedOCSPSuccessResponse(
     63        arena, ca, ocspResponderID_byName, now, responses, &pwdata);
     64 
     65    return response;
     66 }
     67 
     68 static SECItem *
     69 encodeRevoked(PLArenaPool *arena, CERTOCSPCertID *cid, CERTCertificate *ca)
     70 {
     71    SECItem *response;
     72    PRTime now = PR_Now();
     73    PRTime revocationTime;
     74    CERTOCSPSingleResponse **responses;
     75    CERTOCSPSingleResponse *sr;
     76 
     77    if (!arena)
     78        return NULL;
     79 
     80    revocationTime = now - 10 * PR_USEC_PER_SEC; /* in the past */
     81 
     82    sr = CERT_CreateOCSPSingleResponseRevoked(arena, cid, now, NULL,
     83                                              revocationTime, NULL);
     84 
     85    /* meaning of value 2: one entry + one end marker */
     86    responses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2);
     87    if (responses == NULL)
     88        return NULL;
     89 
     90    responses[0] = sr;
     91    responses[1] = NULL;
     92 
     93    response = CERT_CreateEncodedOCSPSuccessResponse(
     94        arena, ca, ocspResponderID_byName, now, responses, &pwdata);
     95 
     96    return response;
     97 }
     98 
     99 int
    100 Usage(void)
    101 {
    102    PRFileDesc *pr_stderr = PR_STDERR;
    103    PR_fprintf(pr_stderr, "ocspresp runs an internal selftest for OCSP response creation");
    104    PR_fprintf(pr_stderr, "Usage:");
    105    PR_fprintf(pr_stderr,
    106               "\tocspresp <dbdir> <CA-nick> <EE-nick> [-p <pass>] [-f <file>]\n");
    107    PR_fprintf(pr_stderr,
    108               "\tdbdir:   Find security databases in \"dbdir\"\n");
    109    PR_fprintf(pr_stderr,
    110               "\tCA-nick: nickname of a trusted CA certificate with private key\n");
    111    PR_fprintf(pr_stderr,
    112               "\tEE-nick: nickname of a entity cert issued by CA\n");
    113    PR_fprintf(pr_stderr,
    114               "\t-p:      a password for db\n");
    115    PR_fprintf(pr_stderr,
    116               "\t-f:      a filename containing the password for db\n");
    117    return -1;
    118 }
    119 
    120 int
    121 main(int argc, char **argv)
    122 {
    123    SECStatus rv;
    124    int retval = -1;
    125    CERTCertDBHandle *certHandle = NULL;
    126    CERTCertificate *caCert = NULL, *cert = NULL;
    127    CERTOCSPCertID *cid = NULL;
    128    PLArenaPool *arena = NULL;
    129    PRTime now = PR_Now();
    130 
    131    SECItem *encoded = NULL;
    132    CERTOCSPResponse *decoded = NULL;
    133 
    134    SECItem *encodedRev = NULL;
    135    CERTOCSPResponse *decodedRev = NULL;
    136 
    137    SECItem *encodedFail = NULL;
    138    CERTOCSPResponse *decodedFail = NULL;
    139 
    140    CERTCertificate *obtainedSignerCert = NULL;
    141 
    142    if (argc != 4 && argc != 6) {
    143        return Usage();
    144    }
    145 
    146    if (argc == 6) {
    147        if (!strcmp(argv[4], "-p")) {
    148            pwdata.source = PW_PLAINTEXT;
    149            pwdata.data = PORT_Strdup(argv[5]);
    150        } else if (!strcmp(argv[4], "-f")) {
    151            pwdata.source = PW_FROMFILE;
    152            pwdata.data = PORT_Strdup(argv[5]);
    153        } else
    154            return Usage();
    155    }
    156 
    157    PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
    158    /*rv = NSS_Init(SECU_ConfigDirectory(NULL));*/
    159    rv = NSS_Init(argv[1]);
    160    if (rv != SECSuccess) {
    161        SECU_PrintPRandOSError(argv[0]);
    162        goto loser;
    163    }
    164 
    165    PK11_SetPasswordFunc(SECU_GetModulePassword);
    166 
    167    certHandle = CERT_GetDefaultCertDB();
    168    if (!certHandle)
    169        goto loser;
    170 
    171    if (!getCaAndSubjectCert(certHandle, argv[2], argv[3], &caCert, &cert))
    172        goto loser;
    173 
    174    cid = CERT_CreateOCSPCertID(cert, now);
    175 
    176    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    177    encoded = encode(arena, cid, caCert);
    178    PORT_Assert(encoded);
    179    decoded = CERT_DecodeOCSPResponse(encoded);
    180    PORT_CheckSuccess(CERT_GetOCSPResponseStatus(decoded));
    181 
    182    PORT_CheckSuccess(CERT_VerifyOCSPResponseSignature(decoded, certHandle, &pwdata,
    183                                                       &obtainedSignerCert, caCert));
    184    PORT_CheckSuccess(CERT_GetOCSPStatusForCertID(certHandle, decoded, cid,
    185                                                  obtainedSignerCert, now));
    186    CERT_DestroyCertificate(obtainedSignerCert);
    187 
    188    encodedRev = encodeRevoked(arena, cid, caCert);
    189    PORT_Assert(encodedRev);
    190    decodedRev = CERT_DecodeOCSPResponse(encodedRev);
    191    PORT_CheckSuccess(CERT_GetOCSPResponseStatus(decodedRev));
    192 
    193    PORT_CheckSuccess(CERT_VerifyOCSPResponseSignature(decodedRev, certHandle, &pwdata,
    194                                                       &obtainedSignerCert, caCert));
    195 #ifdef DEBUG
    196    {
    197        rv = CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid,
    198                                         obtainedSignerCert, now);
    199        PORT_Assert(rv == SECFailure);
    200        PORT_Assert(PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE);
    201    }
    202 #else
    203    (void)CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid,
    204                                      obtainedSignerCert, now);
    205 #endif
    206    CERT_DestroyCertificate(obtainedSignerCert);
    207 
    208    encodedFail = CERT_CreateEncodedOCSPErrorResponse(
    209        arena, SEC_ERROR_OCSP_TRY_SERVER_LATER);
    210    PORT_Assert(encodedFail);
    211    decodedFail = CERT_DecodeOCSPResponse(encodedFail);
    212 #ifdef DEBUG
    213    {
    214        rv = CERT_GetOCSPResponseStatus(decodedFail);
    215        PORT_Assert(rv == SECFailure);
    216        PORT_Assert(PORT_GetError() == SEC_ERROR_OCSP_TRY_SERVER_LATER);
    217    }
    218 #else
    219    (void)CERT_GetOCSPResponseStatus(decodedFail);
    220 #endif
    221    retval = 0;
    222 loser:
    223    if (retval != 0)
    224        SECU_PrintError(argv[0], "tests failed");
    225 
    226    if (cid)
    227        CERT_DestroyOCSPCertID(cid);
    228    if (cert)
    229        CERT_DestroyCertificate(cert);
    230    if (caCert)
    231        CERT_DestroyCertificate(caCert);
    232    if (arena)
    233        PORT_FreeArena(arena, PR_FALSE);
    234    if (decoded)
    235        CERT_DestroyOCSPResponse(decoded);
    236    if (decodedRev)
    237        CERT_DestroyOCSPResponse(decodedRev);
    238    if (decodedFail)
    239        CERT_DestroyOCSPResponse(decodedFail);
    240    if (pwdata.data) {
    241        PORT_Free(pwdata.data);
    242    }
    243 
    244    if (NSS_Shutdown() != SECSuccess) {
    245        SECU_PrintError(argv[0], "NSS shutdown:");
    246        if (retval == 0)
    247            retval = -2;
    248    }
    249 
    250    return retval;
    251 }