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 }