diff options
Diffstat (limited to 'security/nss/cmd/ocspresp/ocspresp.c')
-rw-r--r-- | security/nss/cmd/ocspresp/ocspresp.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/security/nss/cmd/ocspresp/ocspresp.c b/security/nss/cmd/ocspresp/ocspresp.c new file mode 100644 index 0000000000..d18d32e18e --- /dev/null +++ b/security/nss/cmd/ocspresp/ocspresp.c @@ -0,0 +1,251 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * ocspresp - self test for OCSP response creation + */ + +#include "nspr.h" +#include "secutil.h" +#include "secpkcs7.h" +#include "cert.h" +#include "certdb.h" +#include "nss.h" +#include "pk11func.h" +#include "cryptohi.h" +#include "ocsp.h" + +#if defined(XP_UNIX) +#include <unistd.h> +#endif + +#include <stdio.h> +#include <string.h> + +secuPWData pwdata = { PW_NONE, 0 }; + +static PRBool +getCaAndSubjectCert(CERTCertDBHandle *certHandle, + const char *caNick, const char *eeNick, + CERTCertificate **outCA, CERTCertificate **outCert) +{ + *outCA = CERT_FindCertByNickname(certHandle, caNick); + *outCert = CERT_FindCertByNickname(certHandle, eeNick); + return *outCA && *outCert; +} + +static SECItem * +encode(PLArenaPool *arena, CERTOCSPCertID *cid, CERTCertificate *ca) +{ + SECItem *response; + PRTime now = PR_Now(); + PRTime nextUpdate; + CERTOCSPSingleResponse **responses; + CERTOCSPSingleResponse *sr; + + if (!arena) + return NULL; + + nextUpdate = now + 10 * PR_USEC_PER_SEC; /* in the future */ + + sr = CERT_CreateOCSPSingleResponseGood(arena, cid, now, &nextUpdate); + + /* meaning of value 2: one entry + one end marker */ + responses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2); + if (responses == NULL) + return NULL; + + responses[0] = sr; + responses[1] = NULL; + + response = CERT_CreateEncodedOCSPSuccessResponse( + arena, ca, ocspResponderID_byName, now, responses, &pwdata); + + return response; +} + +static SECItem * +encodeRevoked(PLArenaPool *arena, CERTOCSPCertID *cid, CERTCertificate *ca) +{ + SECItem *response; + PRTime now = PR_Now(); + PRTime revocationTime; + CERTOCSPSingleResponse **responses; + CERTOCSPSingleResponse *sr; + + if (!arena) + return NULL; + + revocationTime = now - 10 * PR_USEC_PER_SEC; /* in the past */ + + sr = CERT_CreateOCSPSingleResponseRevoked(arena, cid, now, NULL, + revocationTime, NULL); + + /* meaning of value 2: one entry + one end marker */ + responses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2); + if (responses == NULL) + return NULL; + + responses[0] = sr; + responses[1] = NULL; + + response = CERT_CreateEncodedOCSPSuccessResponse( + arena, ca, ocspResponderID_byName, now, responses, &pwdata); + + return response; +} + +int +Usage(void) +{ + PRFileDesc *pr_stderr = PR_STDERR; + PR_fprintf(pr_stderr, "ocspresp runs an internal selftest for OCSP response creation"); + PR_fprintf(pr_stderr, "Usage:"); + PR_fprintf(pr_stderr, + "\tocspresp <dbdir> <CA-nick> <EE-nick> [-p <pass>] [-f <file>]\n"); + PR_fprintf(pr_stderr, + "\tdbdir: Find security databases in \"dbdir\"\n"); + PR_fprintf(pr_stderr, + "\tCA-nick: nickname of a trusted CA certificate with private key\n"); + PR_fprintf(pr_stderr, + "\tEE-nick: nickname of a entity cert issued by CA\n"); + PR_fprintf(pr_stderr, + "\t-p: a password for db\n"); + PR_fprintf(pr_stderr, + "\t-f: a filename containing the password for db\n"); + return -1; +} + +int +main(int argc, char **argv) +{ + SECStatus rv; + int retval = -1; + CERTCertDBHandle *certHandle = NULL; + CERTCertificate *caCert = NULL, *cert = NULL; + CERTOCSPCertID *cid = NULL; + PLArenaPool *arena = NULL; + PRTime now = PR_Now(); + + SECItem *encoded = NULL; + CERTOCSPResponse *decoded = NULL; + + SECItem *encodedRev = NULL; + CERTOCSPResponse *decodedRev = NULL; + + SECItem *encodedFail = NULL; + CERTOCSPResponse *decodedFail = NULL; + + CERTCertificate *obtainedSignerCert = NULL; + + if (argc != 4 && argc != 6) { + return Usage(); + } + + if (argc == 6) { + if (!strcmp(argv[4], "-p")) { + pwdata.source = PW_PLAINTEXT; + pwdata.data = PORT_Strdup(argv[5]); + } else if (!strcmp(argv[4], "-f")) { + pwdata.source = PW_FROMFILE; + pwdata.data = PORT_Strdup(argv[5]); + } else + return Usage(); + } + + PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); + /*rv = NSS_Init(SECU_ConfigDirectory(NULL));*/ + rv = NSS_Init(argv[1]); + if (rv != SECSuccess) { + SECU_PrintPRandOSError(argv[0]); + goto loser; + } + + PK11_SetPasswordFunc(SECU_GetModulePassword); + + certHandle = CERT_GetDefaultCertDB(); + if (!certHandle) + goto loser; + + if (!getCaAndSubjectCert(certHandle, argv[2], argv[3], &caCert, &cert)) + goto loser; + + cid = CERT_CreateOCSPCertID(cert, now); + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + encoded = encode(arena, cid, caCert); + PORT_Assert(encoded); + decoded = CERT_DecodeOCSPResponse(encoded); + PORT_CheckSuccess(CERT_GetOCSPResponseStatus(decoded)); + + PORT_CheckSuccess(CERT_VerifyOCSPResponseSignature(decoded, certHandle, &pwdata, + &obtainedSignerCert, caCert)); + PORT_CheckSuccess(CERT_GetOCSPStatusForCertID(certHandle, decoded, cid, + obtainedSignerCert, now)); + CERT_DestroyCertificate(obtainedSignerCert); + + encodedRev = encodeRevoked(arena, cid, caCert); + PORT_Assert(encodedRev); + decodedRev = CERT_DecodeOCSPResponse(encodedRev); + PORT_CheckSuccess(CERT_GetOCSPResponseStatus(decodedRev)); + + PORT_CheckSuccess(CERT_VerifyOCSPResponseSignature(decodedRev, certHandle, &pwdata, + &obtainedSignerCert, caCert)); +#ifdef DEBUG + { + rv = CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid, + obtainedSignerCert, now); + PORT_Assert(rv == SECFailure); + PORT_Assert(PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE); + } +#else + (void)CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid, + obtainedSignerCert, now); +#endif + CERT_DestroyCertificate(obtainedSignerCert); + + encodedFail = CERT_CreateEncodedOCSPErrorResponse( + arena, SEC_ERROR_OCSP_TRY_SERVER_LATER); + PORT_Assert(encodedFail); + decodedFail = CERT_DecodeOCSPResponse(encodedFail); +#ifdef DEBUG + { + rv = CERT_GetOCSPResponseStatus(decodedFail); + PORT_Assert(rv == SECFailure); + PORT_Assert(PORT_GetError() == SEC_ERROR_OCSP_TRY_SERVER_LATER); + } +#else + (void)CERT_GetOCSPResponseStatus(decodedFail); +#endif + retval = 0; +loser: + if (retval != 0) + SECU_PrintError(argv[0], "tests failed"); + + if (cid) + CERT_DestroyOCSPCertID(cid); + if (cert) + CERT_DestroyCertificate(cert); + if (caCert) + CERT_DestroyCertificate(caCert); + if (arena) + PORT_FreeArena(arena, PR_FALSE); + if (decoded) + CERT_DestroyOCSPResponse(decoded); + if (decodedRev) + CERT_DestroyOCSPResponse(decodedRev); + if (decodedFail) + CERT_DestroyOCSPResponse(decodedFail); + if (pwdata.data) { + PORT_Free(pwdata.data); + } + + if (NSS_Shutdown() != SECSuccess) { + SECU_PrintError(argv[0], "NSS shutdown:"); + if (retval == 0) + retval = -2; + } + + return retval; +} |