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