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