1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/certhigh/ocspsig.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,600 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "plarena.h" 1.9 + 1.10 +#include "seccomon.h" 1.11 +#include "secitem.h" 1.12 +#include "secasn1.h" 1.13 +#include "secder.h" 1.14 +#include "cert.h" 1.15 +#include "secerr.h" 1.16 +#include "secoid.h" 1.17 +#include "sechash.h" 1.18 +#include "keyhi.h" 1.19 +#include "cryptohi.h" 1.20 +#include "ocsp.h" 1.21 +#include "ocspti.h" 1.22 +#include "ocspi.h" 1.23 +#include "pk11pub.h" 1.24 + 1.25 + 1.26 +extern const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[]; 1.27 +extern const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[]; 1.28 +extern const SEC_ASN1Template ocsp_OCSPResponseTemplate[]; 1.29 + 1.30 +ocspCertStatus* 1.31 +ocsp_CreateCertStatus(PLArenaPool *arena, 1.32 + ocspCertStatusType status, 1.33 + PRTime revocationTime) 1.34 +{ 1.35 + ocspCertStatus *cs; 1.36 + 1.37 + if (!arena) { 1.38 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.39 + return NULL; 1.40 + } 1.41 + 1.42 + switch (status) { 1.43 + case ocspCertStatus_good: 1.44 + case ocspCertStatus_unknown: 1.45 + case ocspCertStatus_revoked: 1.46 + break; 1.47 + default: 1.48 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.49 + return NULL; 1.50 + } 1.51 + 1.52 + cs = PORT_ArenaZNew(arena, ocspCertStatus); 1.53 + if (!cs) 1.54 + return NULL; 1.55 + cs->certStatusType = status; 1.56 + switch (status) { 1.57 + case ocspCertStatus_good: 1.58 + cs->certStatusInfo.goodInfo = SECITEM_AllocItem(arena, NULL, 0); 1.59 + if (!cs->certStatusInfo.goodInfo) 1.60 + return NULL; 1.61 + break; 1.62 + case ocspCertStatus_unknown: 1.63 + cs->certStatusInfo.unknownInfo = SECITEM_AllocItem(arena, NULL, 0); 1.64 + if (!cs->certStatusInfo.unknownInfo) 1.65 + return NULL; 1.66 + break; 1.67 + case ocspCertStatus_revoked: 1.68 + cs->certStatusInfo.revokedInfo = 1.69 + PORT_ArenaZNew(arena, ocspRevokedInfo); 1.70 + if (!cs->certStatusInfo.revokedInfo) 1.71 + return NULL; 1.72 + cs->certStatusInfo.revokedInfo->revocationReason = 1.73 + SECITEM_AllocItem(arena, NULL, 0); 1.74 + if (!cs->certStatusInfo.revokedInfo->revocationReason) 1.75 + return NULL; 1.76 + if (DER_TimeToGeneralizedTimeArena(arena, 1.77 + &cs->certStatusInfo.revokedInfo->revocationTime, 1.78 + revocationTime) != SECSuccess) 1.79 + return NULL; 1.80 + break; 1.81 + default: 1.82 + PORT_Assert(PR_FALSE); 1.83 + } 1.84 + return cs; 1.85 +} 1.86 + 1.87 +static const SEC_ASN1Template mySEC_EnumeratedTemplate[] = { 1.88 + { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) } 1.89 +}; 1.90 + 1.91 +static const SEC_ASN1Template mySEC_PointerToEnumeratedTemplate[] = { 1.92 + { SEC_ASN1_POINTER, 0, mySEC_EnumeratedTemplate } 1.93 +}; 1.94 + 1.95 +static const SEC_ASN1Template ocsp_EncodeRevokedInfoTemplate[] = { 1.96 + { SEC_ASN1_GENERALIZED_TIME, 1.97 + offsetof(ocspRevokedInfo, revocationTime) }, 1.98 + { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1.99 + SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC| 0, 1.100 + offsetof(ocspRevokedInfo, revocationReason), 1.101 + mySEC_PointerToEnumeratedTemplate }, 1.102 + { 0 } 1.103 +}; 1.104 + 1.105 +static const SEC_ASN1Template ocsp_PointerToEncodeRevokedInfoTemplate[] = { 1.106 + { SEC_ASN1_POINTER, 0, 1.107 + ocsp_EncodeRevokedInfoTemplate } 1.108 +}; 1.109 + 1.110 +static const SEC_ASN1Template mySEC_NullTemplate[] = { 1.111 + { SEC_ASN1_NULL, 0, NULL, sizeof(SECItem) } 1.112 +}; 1.113 + 1.114 +static const SEC_ASN1Template ocsp_CertStatusTemplate[] = { 1.115 + { SEC_ASN1_CHOICE, offsetof(ocspCertStatus, certStatusType), 1.116 + 0, sizeof(ocspCertStatus) }, 1.117 + { SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.118 + 0, mySEC_NullTemplate, ocspCertStatus_good }, 1.119 + { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | 1.120 + SEC_ASN1_CONTEXT_SPECIFIC | 1, 1.121 + offsetof(ocspCertStatus, certStatusInfo.revokedInfo), 1.122 + ocsp_PointerToEncodeRevokedInfoTemplate, ocspCertStatus_revoked }, 1.123 + { SEC_ASN1_CONTEXT_SPECIFIC | 2, 1.124 + 0, mySEC_NullTemplate, ocspCertStatus_unknown }, 1.125 + { 0 } 1.126 +}; 1.127 + 1.128 +static const SEC_ASN1Template mySECOID_AlgorithmIDTemplate[] = { 1.129 + { SEC_ASN1_SEQUENCE, 1.130 + 0, NULL, sizeof(SECAlgorithmID) }, 1.131 + { SEC_ASN1_OBJECT_ID, 1.132 + offsetof(SECAlgorithmID,algorithm), }, 1.133 + { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, 1.134 + offsetof(SECAlgorithmID,parameters), }, 1.135 + { 0, } 1.136 +}; 1.137 + 1.138 +static const SEC_ASN1Template mySEC_AnyTemplate[] = { 1.139 + { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) } 1.140 +}; 1.141 + 1.142 +static const SEC_ASN1Template mySEC_SequenceOfAnyTemplate[] = { 1.143 + { SEC_ASN1_SEQUENCE_OF, 0, mySEC_AnyTemplate } 1.144 +}; 1.145 + 1.146 +static const SEC_ASN1Template mySEC_PointerToSequenceOfAnyTemplate[] = { 1.147 + { SEC_ASN1_POINTER, 0, mySEC_SequenceOfAnyTemplate } 1.148 +}; 1.149 + 1.150 +static const SEC_ASN1Template mySEC_IntegerTemplate[] = { 1.151 + { SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) } 1.152 +}; 1.153 + 1.154 +static const SEC_ASN1Template mySEC_PointerToIntegerTemplate[] = { 1.155 + { SEC_ASN1_POINTER, 0, mySEC_IntegerTemplate } 1.156 +}; 1.157 + 1.158 +static const SEC_ASN1Template mySEC_GeneralizedTimeTemplate[] = { 1.159 + { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)} 1.160 +}; 1.161 + 1.162 +static const SEC_ASN1Template mySEC_PointerToGeneralizedTimeTemplate[] = { 1.163 + { SEC_ASN1_POINTER, 0, mySEC_GeneralizedTimeTemplate } 1.164 +}; 1.165 + 1.166 +static const SEC_ASN1Template ocsp_myCertIDTemplate[] = { 1.167 + { SEC_ASN1_SEQUENCE, 1.168 + 0, NULL, sizeof(CERTOCSPCertID) }, 1.169 + { SEC_ASN1_INLINE, 1.170 + offsetof(CERTOCSPCertID, hashAlgorithm), 1.171 + mySECOID_AlgorithmIDTemplate }, 1.172 + { SEC_ASN1_OCTET_STRING, 1.173 + offsetof(CERTOCSPCertID, issuerNameHash) }, 1.174 + { SEC_ASN1_OCTET_STRING, 1.175 + offsetof(CERTOCSPCertID, issuerKeyHash) }, 1.176 + { SEC_ASN1_INTEGER, 1.177 + offsetof(CERTOCSPCertID, serialNumber) }, 1.178 + { 0 } 1.179 +}; 1.180 + 1.181 +static const SEC_ASN1Template myCERT_CertExtensionTemplate[] = { 1.182 + { SEC_ASN1_SEQUENCE, 1.183 + 0, NULL, sizeof(CERTCertExtension) }, 1.184 + { SEC_ASN1_OBJECT_ID, 1.185 + offsetof(CERTCertExtension,id) }, 1.186 + { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */ 1.187 + offsetof(CERTCertExtension,critical) }, 1.188 + { SEC_ASN1_OCTET_STRING, 1.189 + offsetof(CERTCertExtension,value) }, 1.190 + { 0, } 1.191 +}; 1.192 + 1.193 +static const SEC_ASN1Template myCERT_SequenceOfCertExtensionTemplate[] = { 1.194 + { SEC_ASN1_SEQUENCE_OF, 0, myCERT_CertExtensionTemplate } 1.195 +}; 1.196 + 1.197 +static const SEC_ASN1Template myCERT_PointerToSequenceOfCertExtensionTemplate[] = { 1.198 + { SEC_ASN1_POINTER, 0, myCERT_SequenceOfCertExtensionTemplate } 1.199 +}; 1.200 + 1.201 +static const SEC_ASN1Template ocsp_mySingleResponseTemplate[] = { 1.202 + { SEC_ASN1_SEQUENCE, 1.203 + 0, NULL, sizeof(CERTOCSPSingleResponse) }, 1.204 + { SEC_ASN1_POINTER, 1.205 + offsetof(CERTOCSPSingleResponse, certID), 1.206 + ocsp_myCertIDTemplate }, 1.207 + { SEC_ASN1_ANY, 1.208 + offsetof(CERTOCSPSingleResponse, derCertStatus) }, 1.209 + { SEC_ASN1_GENERALIZED_TIME, 1.210 + offsetof(CERTOCSPSingleResponse, thisUpdate) }, 1.211 + { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1.212 + SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.213 + offsetof(CERTOCSPSingleResponse, nextUpdate), 1.214 + mySEC_PointerToGeneralizedTimeTemplate }, 1.215 + { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1.216 + SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 1.217 + offsetof(CERTOCSPSingleResponse, singleExtensions), 1.218 + myCERT_PointerToSequenceOfCertExtensionTemplate }, 1.219 + { 0 } 1.220 +}; 1.221 + 1.222 +static const SEC_ASN1Template ocsp_myResponseDataTemplate[] = { 1.223 + { SEC_ASN1_SEQUENCE, 1.224 + 0, NULL, sizeof(ocspResponseData) }, 1.225 + { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */ 1.226 + SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.227 + offsetof(ocspResponseData, version), 1.228 + mySEC_PointerToIntegerTemplate }, 1.229 + { SEC_ASN1_ANY, 1.230 + offsetof(ocspResponseData, derResponderID) }, 1.231 + { SEC_ASN1_GENERALIZED_TIME, 1.232 + offsetof(ocspResponseData, producedAt) }, 1.233 + { SEC_ASN1_SEQUENCE_OF, 1.234 + offsetof(ocspResponseData, responses), 1.235 + ocsp_mySingleResponseTemplate }, 1.236 + { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1.237 + SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 1.238 + offsetof(ocspResponseData, responseExtensions), 1.239 + myCERT_PointerToSequenceOfCertExtensionTemplate }, 1.240 + { 0 } 1.241 +}; 1.242 + 1.243 + 1.244 +static const SEC_ASN1Template ocsp_EncodeBasicOCSPResponseTemplate[] = { 1.245 + { SEC_ASN1_SEQUENCE, 1.246 + 0, NULL, sizeof(ocspBasicOCSPResponse) }, 1.247 + { SEC_ASN1_POINTER, 1.248 + offsetof(ocspBasicOCSPResponse, tbsResponseData), 1.249 + ocsp_myResponseDataTemplate }, 1.250 + { SEC_ASN1_INLINE, 1.251 + offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm), 1.252 + mySECOID_AlgorithmIDTemplate }, 1.253 + { SEC_ASN1_BIT_STRING, 1.254 + offsetof(ocspBasicOCSPResponse, responseSignature.signature) }, 1.255 + { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | 1.256 + SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 1.257 + offsetof(ocspBasicOCSPResponse, responseSignature.derCerts), 1.258 + mySEC_PointerToSequenceOfAnyTemplate }, 1.259 + { 0 } 1.260 +}; 1.261 + 1.262 +static CERTOCSPSingleResponse* 1.263 +ocsp_CreateSingleResponse(PLArenaPool *arena, 1.264 + CERTOCSPCertID *id, ocspCertStatus *status, 1.265 + PRTime thisUpdate, const PRTime *nextUpdate) 1.266 +{ 1.267 + CERTOCSPSingleResponse *sr; 1.268 + 1.269 + if (!arena || !id || !status) { 1.270 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.271 + return NULL; 1.272 + } 1.273 + 1.274 + sr = PORT_ArenaZNew(arena, CERTOCSPSingleResponse); 1.275 + if (!sr) 1.276 + return NULL; 1.277 + sr->arena = arena; 1.278 + sr->certID = id; 1.279 + sr->certStatus = status; 1.280 + if (DER_TimeToGeneralizedTimeArena(arena, &sr->thisUpdate, thisUpdate) 1.281 + != SECSuccess) 1.282 + return NULL; 1.283 + sr->nextUpdate = NULL; 1.284 + if (nextUpdate) { 1.285 + sr->nextUpdate = SECITEM_AllocItem(arena, NULL, 0); 1.286 + if (!sr->nextUpdate) 1.287 + return NULL; 1.288 + if (DER_TimeToGeneralizedTimeArena(arena, sr->nextUpdate, *nextUpdate) 1.289 + != SECSuccess) 1.290 + return NULL; 1.291 + } 1.292 + 1.293 + sr->singleExtensions = PORT_ArenaNewArray(arena, CERTCertExtension*, 1); 1.294 + if (!sr->singleExtensions) 1.295 + return NULL; 1.296 + 1.297 + sr->singleExtensions[0] = NULL; 1.298 + 1.299 + if (!SEC_ASN1EncodeItem(arena, &sr->derCertStatus, 1.300 + status, ocsp_CertStatusTemplate)) 1.301 + return NULL; 1.302 + 1.303 + return sr; 1.304 +} 1.305 + 1.306 +CERTOCSPSingleResponse* 1.307 +CERT_CreateOCSPSingleResponseGood(PLArenaPool *arena, 1.308 + CERTOCSPCertID *id, 1.309 + PRTime thisUpdate, 1.310 + const PRTime *nextUpdate) 1.311 +{ 1.312 + ocspCertStatus * cs; 1.313 + if (!arena) { 1.314 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.315 + return NULL; 1.316 + } 1.317 + cs = ocsp_CreateCertStatus(arena, ocspCertStatus_good, 0); 1.318 + if (!cs) 1.319 + return NULL; 1.320 + return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); 1.321 +} 1.322 + 1.323 +CERTOCSPSingleResponse* 1.324 +CERT_CreateOCSPSingleResponseUnknown(PLArenaPool *arena, 1.325 + CERTOCSPCertID *id, 1.326 + PRTime thisUpdate, 1.327 + const PRTime *nextUpdate) 1.328 +{ 1.329 + ocspCertStatus * cs; 1.330 + if (!arena) { 1.331 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.332 + return NULL; 1.333 + } 1.334 + cs = ocsp_CreateCertStatus(arena, ocspCertStatus_unknown, 0); 1.335 + if (!cs) 1.336 + return NULL; 1.337 + return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); 1.338 +} 1.339 + 1.340 +CERTOCSPSingleResponse* 1.341 +CERT_CreateOCSPSingleResponseRevoked( 1.342 + PLArenaPool *arena, 1.343 + CERTOCSPCertID *id, 1.344 + PRTime thisUpdate, 1.345 + const PRTime *nextUpdate, 1.346 + PRTime revocationTime, 1.347 + const CERTCRLEntryReasonCode* revocationReason) 1.348 +{ 1.349 + ocspCertStatus * cs; 1.350 + /* revocationReason is not yet supported, so it must be NULL. */ 1.351 + if (!arena || revocationReason) { 1.352 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.353 + return NULL; 1.354 + } 1.355 + cs = ocsp_CreateCertStatus(arena, ocspCertStatus_revoked, revocationTime); 1.356 + if (!cs) 1.357 + return NULL; 1.358 + return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); 1.359 +} 1.360 + 1.361 +/* responderCert == 0 means: 1.362 + * create a response with an invalid signature (for testing purposes) */ 1.363 +SECItem* 1.364 +CERT_CreateEncodedOCSPSuccessResponse( 1.365 + PLArenaPool *arena, 1.366 + CERTCertificate *responderCert, 1.367 + CERTOCSPResponderIDType responderIDType, 1.368 + PRTime producedAt, 1.369 + CERTOCSPSingleResponse **responses, 1.370 + void *wincx) 1.371 +{ 1.372 + PLArenaPool *tmpArena; 1.373 + ocspResponseData *rd = NULL; 1.374 + ocspResponderID *rid = NULL; 1.375 + const SEC_ASN1Template *responderIDTemplate = NULL; 1.376 + ocspBasicOCSPResponse *br = NULL; 1.377 + ocspResponseBytes *rb = NULL; 1.378 + CERTOCSPResponse *response = NULL; 1.379 + 1.380 + SECOidTag algID; 1.381 + SECOidData *od = NULL; 1.382 + SECKEYPrivateKey *privKey = NULL; 1.383 + SECItem *result = NULL; 1.384 + 1.385 + if (!arena || !responses) { 1.386 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.387 + return NULL; 1.388 + } 1.389 + if (responderIDType != ocspResponderID_byName && 1.390 + responderIDType != ocspResponderID_byKey) { 1.391 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.392 + return NULL; 1.393 + } 1.394 + 1.395 + tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.396 + if (!tmpArena) 1.397 + return NULL; 1.398 + 1.399 + rd = PORT_ArenaZNew(tmpArena, ocspResponseData); 1.400 + if (!rd) 1.401 + goto done; 1.402 + rid = PORT_ArenaZNew(tmpArena, ocspResponderID); 1.403 + if (!rid) 1.404 + goto done; 1.405 + br = PORT_ArenaZNew(tmpArena, ocspBasicOCSPResponse); 1.406 + if (!br) 1.407 + goto done; 1.408 + rb = PORT_ArenaZNew(tmpArena, ocspResponseBytes); 1.409 + if (!rb) 1.410 + goto done; 1.411 + response = PORT_ArenaZNew(tmpArena, CERTOCSPResponse); 1.412 + if (!response) 1.413 + goto done; 1.414 + 1.415 + rd->version.data=NULL; 1.416 + rd->version.len=0; 1.417 + rd->responseExtensions = NULL; 1.418 + rd->responses = responses; 1.419 + if (DER_TimeToGeneralizedTimeArena(tmpArena, &rd->producedAt, producedAt) 1.420 + != SECSuccess) 1.421 + goto done; 1.422 + 1.423 + if (!responderCert) { 1.424 + /* use invalid signature for testing purposes */ 1.425 + unsigned char dummyChar = 'd'; 1.426 + SECItem dummy; 1.427 + 1.428 + dummy.len = 1; 1.429 + dummy.data = &dummyChar; 1.430 + 1.431 + /* it's easier to produdce a keyHash out of nowhere, 1.432 + * than to produce an encoded subject, 1.433 + * so for our dummy response we always use byKey 1.434 + */ 1.435 + 1.436 + rid->responderIDType = ocspResponderID_byKey; 1.437 + if (!ocsp_DigestValue(tmpArena, SEC_OID_SHA1, &rid->responderIDValue.keyHash, 1.438 + &dummy)) 1.439 + goto done; 1.440 + 1.441 + if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid, 1.442 + ocsp_ResponderIDByKeyTemplate)) 1.443 + goto done; 1.444 + 1.445 + br->tbsResponseData = rd; 1.446 + 1.447 + if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData, 1.448 + ocsp_myResponseDataTemplate)) 1.449 + goto done; 1.450 + 1.451 + br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem*, 1); 1.452 + if (!br->responseSignature.derCerts) 1.453 + goto done; 1.454 + br->responseSignature.derCerts[0] = NULL; 1.455 + 1.456 + algID = SEC_GetSignatureAlgorithmOidTag(rsaKey, SEC_OID_SHA1); 1.457 + if (algID == SEC_OID_UNKNOWN) 1.458 + goto done; 1.459 + 1.460 + /* match the regular signature code, which doesn't use the arena */ 1.461 + if (!SECITEM_AllocItem(NULL, &br->responseSignature.signature, 1)) 1.462 + goto done; 1.463 + PORT_Memcpy(br->responseSignature.signature.data, &dummyChar, 1); 1.464 + 1.465 + /* convert len-in-bytes to len-in-bits */ 1.466 + br->responseSignature.signature.len = br->responseSignature.signature.len << 3; 1.467 + } 1.468 + else { 1.469 + rid->responderIDType = responderIDType; 1.470 + if (responderIDType == ocspResponderID_byName) { 1.471 + responderIDTemplate = ocsp_ResponderIDByNameTemplate; 1.472 + if (CERT_CopyName(tmpArena, &rid->responderIDValue.name, 1.473 + &responderCert->subject) != SECSuccess) 1.474 + goto done; 1.475 + } 1.476 + else { 1.477 + responderIDTemplate = ocsp_ResponderIDByKeyTemplate; 1.478 + if (!CERT_GetSubjectPublicKeyDigest(tmpArena, responderCert, 1.479 + SEC_OID_SHA1, &rid->responderIDValue.keyHash)) 1.480 + goto done; 1.481 + } 1.482 + 1.483 + if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid, 1.484 + responderIDTemplate)) 1.485 + goto done; 1.486 + 1.487 + br->tbsResponseData = rd; 1.488 + 1.489 + if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData, 1.490 + ocsp_myResponseDataTemplate)) 1.491 + goto done; 1.492 + 1.493 + br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem*, 1); 1.494 + if (!br->responseSignature.derCerts) 1.495 + goto done; 1.496 + br->responseSignature.derCerts[0] = NULL; 1.497 + 1.498 + privKey = PK11_FindKeyByAnyCert(responderCert, wincx); 1.499 + if (!privKey) 1.500 + goto done; 1.501 + 1.502 + algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1); 1.503 + if (algID == SEC_OID_UNKNOWN) 1.504 + goto done; 1.505 + 1.506 + if (SEC_SignData(&br->responseSignature.signature, 1.507 + br->tbsResponseDataDER.data, br->tbsResponseDataDER.len, 1.508 + privKey, algID) 1.509 + != SECSuccess) 1.510 + goto done; 1.511 + 1.512 + /* convert len-in-bytes to len-in-bits */ 1.513 + br->responseSignature.signature.len = br->responseSignature.signature.len << 3; 1.514 + 1.515 + /* br->responseSignature.signature wasn't allocated from arena, 1.516 + * we must free it when done. */ 1.517 + } 1.518 + 1.519 + if (SECOID_SetAlgorithmID(tmpArena, &br->responseSignature.signatureAlgorithm, algID, 0) 1.520 + != SECSuccess) 1.521 + goto done; 1.522 + 1.523 + if (!SEC_ASN1EncodeItem(tmpArena, &rb->response, br, 1.524 + ocsp_EncodeBasicOCSPResponseTemplate)) 1.525 + goto done; 1.526 + 1.527 + rb->responseTypeTag = SEC_OID_PKIX_OCSP_BASIC_RESPONSE; 1.528 + 1.529 + od = SECOID_FindOIDByTag(rb->responseTypeTag); 1.530 + if (!od) 1.531 + goto done; 1.532 + 1.533 + rb->responseType = od->oid; 1.534 + rb->decodedResponse.basic = br; 1.535 + 1.536 + response->arena = tmpArena; 1.537 + response->responseBytes = rb; 1.538 + response->statusValue = ocspResponse_successful; 1.539 + 1.540 + if (!SEC_ASN1EncodeInteger(tmpArena, &response->responseStatus, 1.541 + response->statusValue)) 1.542 + goto done; 1.543 + 1.544 + result = SEC_ASN1EncodeItem(arena, NULL, response, ocsp_OCSPResponseTemplate); 1.545 + 1.546 +done: 1.547 + if (privKey) 1.548 + SECKEY_DestroyPrivateKey(privKey); 1.549 + if (br->responseSignature.signature.data) 1.550 + SECITEM_FreeItem(&br->responseSignature.signature, PR_FALSE); 1.551 + PORT_FreeArena(tmpArena, PR_FALSE); 1.552 + 1.553 + return result; 1.554 +} 1.555 + 1.556 +static const SEC_ASN1Template ocsp_OCSPErrorResponseTemplate[] = { 1.557 + { SEC_ASN1_SEQUENCE, 1.558 + 0, NULL, sizeof(CERTOCSPResponse) }, 1.559 + { SEC_ASN1_ENUMERATED, 1.560 + offsetof(CERTOCSPResponse, responseStatus) }, 1.561 + { 0, 0, 1.562 + mySEC_NullTemplate }, 1.563 + { 0 } 1.564 +}; 1.565 + 1.566 +SECItem* 1.567 +CERT_CreateEncodedOCSPErrorResponse(PLArenaPool *arena, int error) 1.568 +{ 1.569 + CERTOCSPResponse response; 1.570 + SECItem *result = NULL; 1.571 + 1.572 + switch (error) { 1.573 + case SEC_ERROR_OCSP_MALFORMED_REQUEST: 1.574 + response.statusValue = ocspResponse_malformedRequest; 1.575 + break; 1.576 + case SEC_ERROR_OCSP_SERVER_ERROR: 1.577 + response.statusValue = ocspResponse_internalError; 1.578 + break; 1.579 + case SEC_ERROR_OCSP_TRY_SERVER_LATER: 1.580 + response.statusValue = ocspResponse_tryLater; 1.581 + break; 1.582 + case SEC_ERROR_OCSP_REQUEST_NEEDS_SIG: 1.583 + response.statusValue = ocspResponse_sigRequired; 1.584 + break; 1.585 + case SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST: 1.586 + response.statusValue = ocspResponse_unauthorized; 1.587 + break; 1.588 + default: 1.589 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.590 + return NULL; 1.591 + } 1.592 + 1.593 + if (!SEC_ASN1EncodeInteger(NULL, &response.responseStatus, 1.594 + response.statusValue)) 1.595 + return NULL; 1.596 + 1.597 + result = SEC_ASN1EncodeItem(arena, NULL, &response, 1.598 + ocsp_OCSPErrorResponseTemplate); 1.599 + 1.600 + SECITEM_FreeItem(&response.responseStatus, PR_FALSE); 1.601 + 1.602 + return result; 1.603 +}