| OLD | NEW |
| (Empty) |
| 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 #include "plarena.h" | |
| 6 | |
| 7 #include "seccomon.h" | |
| 8 #include "secitem.h" | |
| 9 #include "secasn1.h" | |
| 10 #include "secder.h" | |
| 11 #include "cert.h" | |
| 12 #include "secerr.h" | |
| 13 #include "secoid.h" | |
| 14 #include "sechash.h" | |
| 15 #include "keyhi.h" | |
| 16 #include "cryptohi.h" | |
| 17 #include "ocsp.h" | |
| 18 #include "ocspti.h" | |
| 19 #include "ocspi.h" | |
| 20 #include "pk11pub.h" | |
| 21 | |
| 22 | |
| 23 extern const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[]; | |
| 24 extern const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[]; | |
| 25 extern const SEC_ASN1Template ocsp_OCSPResponseTemplate[]; | |
| 26 | |
| 27 ocspCertStatus* | |
| 28 ocsp_CreateCertStatus(PLArenaPool *arena, | |
| 29 ocspCertStatusType status, | |
| 30 PRTime revocationTime) | |
| 31 { | |
| 32 ocspCertStatus *cs; | |
| 33 | |
| 34 if (!arena) { | |
| 35 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 36 return NULL; | |
| 37 } | |
| 38 | |
| 39 switch (status) { | |
| 40 case ocspCertStatus_good: | |
| 41 case ocspCertStatus_unknown: | |
| 42 case ocspCertStatus_revoked: | |
| 43 break; | |
| 44 default: | |
| 45 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 46 return NULL; | |
| 47 } | |
| 48 | |
| 49 cs = PORT_ArenaZNew(arena, ocspCertStatus); | |
| 50 if (!cs) | |
| 51 return NULL; | |
| 52 cs->certStatusType = status; | |
| 53 switch (status) { | |
| 54 case ocspCertStatus_good: | |
| 55 cs->certStatusInfo.goodInfo = SECITEM_AllocItem(arena, NULL, 0); | |
| 56 if (!cs->certStatusInfo.goodInfo) | |
| 57 return NULL; | |
| 58 break; | |
| 59 case ocspCertStatus_unknown: | |
| 60 cs->certStatusInfo.unknownInfo = SECITEM_AllocItem(arena, NULL, 0); | |
| 61 if (!cs->certStatusInfo.unknownInfo) | |
| 62 return NULL; | |
| 63 break; | |
| 64 case ocspCertStatus_revoked: | |
| 65 cs->certStatusInfo.revokedInfo = | |
| 66 PORT_ArenaZNew(arena, ocspRevokedInfo); | |
| 67 if (!cs->certStatusInfo.revokedInfo) | |
| 68 return NULL; | |
| 69 cs->certStatusInfo.revokedInfo->revocationReason = | |
| 70 SECITEM_AllocItem(arena, NULL, 0); | |
| 71 if (!cs->certStatusInfo.revokedInfo->revocationReason) | |
| 72 return NULL; | |
| 73 if (DER_TimeToGeneralizedTimeArena(arena, | |
| 74 &cs->certStatusInfo.revokedInfo->revocationTime, | |
| 75 revocationTime) != SECSuccess) | |
| 76 return NULL; | |
| 77 break; | |
| 78 default: | |
| 79 PORT_Assert(PR_FALSE); | |
| 80 } | |
| 81 return cs; | |
| 82 } | |
| 83 | |
| 84 static const SEC_ASN1Template mySEC_EnumeratedTemplate[] = { | |
| 85 { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) } | |
| 86 }; | |
| 87 | |
| 88 static const SEC_ASN1Template mySEC_PointerToEnumeratedTemplate[] = { | |
| 89 { SEC_ASN1_POINTER, 0, mySEC_EnumeratedTemplate } | |
| 90 }; | |
| 91 | |
| 92 static const SEC_ASN1Template ocsp_EncodeRevokedInfoTemplate[] = { | |
| 93 { SEC_ASN1_GENERALIZED_TIME, | |
| 94 offsetof(ocspRevokedInfo, revocationTime) }, | |
| 95 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | |
| 96 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC| 0, | |
| 97 offsetof(ocspRevokedInfo, revocationReason), | |
| 98 mySEC_PointerToEnumeratedTemplate }, | |
| 99 { 0 } | |
| 100 }; | |
| 101 | |
| 102 static const SEC_ASN1Template ocsp_PointerToEncodeRevokedInfoTemplate[] = { | |
| 103 { SEC_ASN1_POINTER, 0, | |
| 104 ocsp_EncodeRevokedInfoTemplate } | |
| 105 }; | |
| 106 | |
| 107 static const SEC_ASN1Template mySEC_NullTemplate[] = { | |
| 108 { SEC_ASN1_NULL, 0, NULL, sizeof(SECItem) } | |
| 109 }; | |
| 110 | |
| 111 static const SEC_ASN1Template ocsp_CertStatusTemplate[] = { | |
| 112 { SEC_ASN1_CHOICE, offsetof(ocspCertStatus, certStatusType), | |
| 113 0, sizeof(ocspCertStatus) }, | |
| 114 { SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
| 115 0, mySEC_NullTemplate, ocspCertStatus_good }, | |
| 116 { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | | |
| 117 SEC_ASN1_CONTEXT_SPECIFIC | 1, | |
| 118 offsetof(ocspCertStatus, certStatusInfo.revokedInfo), | |
| 119 ocsp_PointerToEncodeRevokedInfoTemplate, ocspCertStatus_revoked }, | |
| 120 { SEC_ASN1_CONTEXT_SPECIFIC | 2, | |
| 121 0, mySEC_NullTemplate, ocspCertStatus_unknown }, | |
| 122 { 0 } | |
| 123 }; | |
| 124 | |
| 125 static const SEC_ASN1Template mySECOID_AlgorithmIDTemplate[] = { | |
| 126 { SEC_ASN1_SEQUENCE, | |
| 127 0, NULL, sizeof(SECAlgorithmID) }, | |
| 128 { SEC_ASN1_OBJECT_ID, | |
| 129 offsetof(SECAlgorithmID,algorithm), }, | |
| 130 { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, | |
| 131 offsetof(SECAlgorithmID,parameters), }, | |
| 132 { 0, } | |
| 133 }; | |
| 134 | |
| 135 static const SEC_ASN1Template mySEC_AnyTemplate[] = { | |
| 136 { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) } | |
| 137 }; | |
| 138 | |
| 139 static const SEC_ASN1Template mySEC_SequenceOfAnyTemplate[] = { | |
| 140 { SEC_ASN1_SEQUENCE_OF, 0, mySEC_AnyTemplate } | |
| 141 }; | |
| 142 | |
| 143 static const SEC_ASN1Template mySEC_PointerToSequenceOfAnyTemplate[] = { | |
| 144 { SEC_ASN1_POINTER, 0, mySEC_SequenceOfAnyTemplate } | |
| 145 }; | |
| 146 | |
| 147 static const SEC_ASN1Template mySEC_IntegerTemplate[] = { | |
| 148 { SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) } | |
| 149 }; | |
| 150 | |
| 151 static const SEC_ASN1Template mySEC_PointerToIntegerTemplate[] = { | |
| 152 { SEC_ASN1_POINTER, 0, mySEC_IntegerTemplate } | |
| 153 }; | |
| 154 | |
| 155 static const SEC_ASN1Template mySEC_GeneralizedTimeTemplate[] = { | |
| 156 { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)} | |
| 157 }; | |
| 158 | |
| 159 static const SEC_ASN1Template mySEC_PointerToGeneralizedTimeTemplate[] = { | |
| 160 { SEC_ASN1_POINTER, 0, mySEC_GeneralizedTimeTemplate } | |
| 161 }; | |
| 162 | |
| 163 static const SEC_ASN1Template ocsp_myCertIDTemplate[] = { | |
| 164 { SEC_ASN1_SEQUENCE, | |
| 165 0, NULL, sizeof(CERTOCSPCertID) }, | |
| 166 { SEC_ASN1_INLINE, | |
| 167 offsetof(CERTOCSPCertID, hashAlgorithm), | |
| 168 mySECOID_AlgorithmIDTemplate }, | |
| 169 { SEC_ASN1_OCTET_STRING, | |
| 170 offsetof(CERTOCSPCertID, issuerNameHash) }, | |
| 171 { SEC_ASN1_OCTET_STRING, | |
| 172 offsetof(CERTOCSPCertID, issuerKeyHash) }, | |
| 173 { SEC_ASN1_INTEGER, | |
| 174 offsetof(CERTOCSPCertID, serialNumber) }, | |
| 175 { 0 } | |
| 176 }; | |
| 177 | |
| 178 static const SEC_ASN1Template myCERT_CertExtensionTemplate[] = { | |
| 179 { SEC_ASN1_SEQUENCE, | |
| 180 0, NULL, sizeof(CERTCertExtension) }, | |
| 181 { SEC_ASN1_OBJECT_ID, | |
| 182 offsetof(CERTCertExtension,id) }, | |
| 183 { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */ | |
| 184 offsetof(CERTCertExtension,critical) }, | |
| 185 { SEC_ASN1_OCTET_STRING, | |
| 186 offsetof(CERTCertExtension,value) }, | |
| 187 { 0, } | |
| 188 }; | |
| 189 | |
| 190 static const SEC_ASN1Template myCERT_SequenceOfCertExtensionTemplate[] = { | |
| 191 { SEC_ASN1_SEQUENCE_OF, 0, myCERT_CertExtensionTemplate } | |
| 192 }; | |
| 193 | |
| 194 static const SEC_ASN1Template myCERT_PointerToSequenceOfCertExtensionTemplate[]
= { | |
| 195 { SEC_ASN1_POINTER, 0, myCERT_SequenceOfCertExtensionTemplate } | |
| 196 }; | |
| 197 | |
| 198 static const SEC_ASN1Template ocsp_mySingleResponseTemplate[] = { | |
| 199 { SEC_ASN1_SEQUENCE, | |
| 200 0, NULL, sizeof(CERTOCSPSingleResponse) }, | |
| 201 { SEC_ASN1_POINTER, | |
| 202 offsetof(CERTOCSPSingleResponse, certID), | |
| 203 ocsp_myCertIDTemplate }, | |
| 204 { SEC_ASN1_ANY, | |
| 205 offsetof(CERTOCSPSingleResponse, derCertStatus) }, | |
| 206 { SEC_ASN1_GENERALIZED_TIME, | |
| 207 offsetof(CERTOCSPSingleResponse, thisUpdate) }, | |
| 208 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | |
| 209 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
| 210 offsetof(CERTOCSPSingleResponse, nextUpdate), | |
| 211 mySEC_PointerToGeneralizedTimeTemplate }, | |
| 212 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | |
| 213 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, | |
| 214 offsetof(CERTOCSPSingleResponse, singleExtensions), | |
| 215 myCERT_PointerToSequenceOfCertExtensionTemplate }, | |
| 216 { 0 } | |
| 217 }; | |
| 218 | |
| 219 static const SEC_ASN1Template ocsp_myResponseDataTemplate[] = { | |
| 220 { SEC_ASN1_SEQUENCE, | |
| 221 0, NULL, sizeof(ocspResponseData) }, | |
| 222 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */ | |
| 223 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
| 224 offsetof(ocspResponseData, version), | |
| 225 mySEC_PointerToIntegerTemplate }, | |
| 226 { SEC_ASN1_ANY, | |
| 227 offsetof(ocspResponseData, derResponderID) }, | |
| 228 { SEC_ASN1_GENERALIZED_TIME, | |
| 229 offsetof(ocspResponseData, producedAt) }, | |
| 230 { SEC_ASN1_SEQUENCE_OF, | |
| 231 offsetof(ocspResponseData, responses), | |
| 232 ocsp_mySingleResponseTemplate }, | |
| 233 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | |
| 234 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, | |
| 235 offsetof(ocspResponseData, responseExtensions), | |
| 236 myCERT_PointerToSequenceOfCertExtensionTemplate }, | |
| 237 { 0 } | |
| 238 }; | |
| 239 | |
| 240 | |
| 241 static const SEC_ASN1Template ocsp_EncodeBasicOCSPResponseTemplate[] = { | |
| 242 { SEC_ASN1_SEQUENCE, | |
| 243 0, NULL, sizeof(ocspBasicOCSPResponse) }, | |
| 244 { SEC_ASN1_POINTER, | |
| 245 offsetof(ocspBasicOCSPResponse, tbsResponseData), | |
| 246 ocsp_myResponseDataTemplate }, | |
| 247 { SEC_ASN1_INLINE, | |
| 248 offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm), | |
| 249 mySECOID_AlgorithmIDTemplate }, | |
| 250 { SEC_ASN1_BIT_STRING, | |
| 251 offsetof(ocspBasicOCSPResponse, responseSignature.signature) }, | |
| 252 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | |
| 253 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
| 254 offsetof(ocspBasicOCSPResponse, responseSignature.derCerts), | |
| 255 mySEC_PointerToSequenceOfAnyTemplate }, | |
| 256 { 0 } | |
| 257 }; | |
| 258 | |
| 259 static CERTOCSPSingleResponse* | |
| 260 ocsp_CreateSingleResponse(PLArenaPool *arena, | |
| 261 CERTOCSPCertID *id, ocspCertStatus *status, | |
| 262 PRTime thisUpdate, const PRTime *nextUpdate) | |
| 263 { | |
| 264 CERTOCSPSingleResponse *sr; | |
| 265 | |
| 266 if (!arena || !id || !status) { | |
| 267 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 268 return NULL; | |
| 269 } | |
| 270 | |
| 271 sr = PORT_ArenaZNew(arena, CERTOCSPSingleResponse); | |
| 272 if (!sr) | |
| 273 return NULL; | |
| 274 sr->arena = arena; | |
| 275 sr->certID = id; | |
| 276 sr->certStatus = status; | |
| 277 if (DER_TimeToGeneralizedTimeArena(arena, &sr->thisUpdate, thisUpdate) | |
| 278 != SECSuccess) | |
| 279 return NULL; | |
| 280 sr->nextUpdate = NULL; | |
| 281 if (nextUpdate) { | |
| 282 sr->nextUpdate = SECITEM_AllocItem(arena, NULL, 0); | |
| 283 if (!sr->nextUpdate) | |
| 284 return NULL; | |
| 285 if (DER_TimeToGeneralizedTimeArena(arena, sr->nextUpdate, *nextUpdate) | |
| 286 != SECSuccess) | |
| 287 return NULL; | |
| 288 } | |
| 289 | |
| 290 sr->singleExtensions = PORT_ArenaNewArray(arena, CERTCertExtension*, 1); | |
| 291 if (!sr->singleExtensions) | |
| 292 return NULL; | |
| 293 | |
| 294 sr->singleExtensions[0] = NULL; | |
| 295 | |
| 296 if (!SEC_ASN1EncodeItem(arena, &sr->derCertStatus, | |
| 297 status, ocsp_CertStatusTemplate)) | |
| 298 return NULL; | |
| 299 | |
| 300 return sr; | |
| 301 } | |
| 302 | |
| 303 CERTOCSPSingleResponse* | |
| 304 CERT_CreateOCSPSingleResponseGood(PLArenaPool *arena, | |
| 305 CERTOCSPCertID *id, | |
| 306 PRTime thisUpdate, | |
| 307 const PRTime *nextUpdate) | |
| 308 { | |
| 309 ocspCertStatus * cs; | |
| 310 if (!arena) { | |
| 311 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 312 return NULL; | |
| 313 } | |
| 314 cs = ocsp_CreateCertStatus(arena, ocspCertStatus_good, 0); | |
| 315 if (!cs) | |
| 316 return NULL; | |
| 317 return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); | |
| 318 } | |
| 319 | |
| 320 CERTOCSPSingleResponse* | |
| 321 CERT_CreateOCSPSingleResponseUnknown(PLArenaPool *arena, | |
| 322 CERTOCSPCertID *id, | |
| 323 PRTime thisUpdate, | |
| 324 const PRTime *nextUpdate) | |
| 325 { | |
| 326 ocspCertStatus * cs; | |
| 327 if (!arena) { | |
| 328 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 329 return NULL; | |
| 330 } | |
| 331 cs = ocsp_CreateCertStatus(arena, ocspCertStatus_unknown, 0); | |
| 332 if (!cs) | |
| 333 return NULL; | |
| 334 return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); | |
| 335 } | |
| 336 | |
| 337 CERTOCSPSingleResponse* | |
| 338 CERT_CreateOCSPSingleResponseRevoked( | |
| 339 PLArenaPool *arena, | |
| 340 CERTOCSPCertID *id, | |
| 341 PRTime thisUpdate, | |
| 342 const PRTime *nextUpdate, | |
| 343 PRTime revocationTime, | |
| 344 const CERTCRLEntryReasonCode* revocationReason) | |
| 345 { | |
| 346 ocspCertStatus * cs; | |
| 347 /* revocationReason is not yet supported, so it must be NULL. */ | |
| 348 if (!arena || revocationReason) { | |
| 349 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 350 return NULL; | |
| 351 } | |
| 352 cs = ocsp_CreateCertStatus(arena, ocspCertStatus_revoked, revocationTime); | |
| 353 if (!cs) | |
| 354 return NULL; | |
| 355 return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); | |
| 356 } | |
| 357 | |
| 358 SECItem* | |
| 359 CERT_CreateEncodedOCSPSuccessResponse( | |
| 360 PLArenaPool *arena, | |
| 361 CERTCertificate *responderCert, | |
| 362 CERTOCSPResponderIDType responderIDType, | |
| 363 PRTime producedAt, | |
| 364 CERTOCSPSingleResponse **responses, | |
| 365 void *wincx) | |
| 366 { | |
| 367 PLArenaPool *tmpArena; | |
| 368 ocspResponseData *rd = NULL; | |
| 369 ocspResponderID *rid = NULL; | |
| 370 const SEC_ASN1Template *responderIDTemplate = NULL; | |
| 371 ocspBasicOCSPResponse *br = NULL; | |
| 372 ocspResponseBytes *rb = NULL; | |
| 373 CERTOCSPResponse *response = NULL; | |
| 374 | |
| 375 SECOidTag algID; | |
| 376 SECOidData *od = NULL; | |
| 377 SECKEYPrivateKey *privKey = NULL; | |
| 378 SECItem *result = NULL; | |
| 379 | |
| 380 if (!arena || !responderCert || !responses) { | |
| 381 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 382 return NULL; | |
| 383 } | |
| 384 if (responderIDType != ocspResponderID_byName && | |
| 385 responderIDType != ocspResponderID_byKey) { | |
| 386 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 387 return NULL; | |
| 388 } | |
| 389 | |
| 390 tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
| 391 if (!tmpArena) | |
| 392 return NULL; | |
| 393 | |
| 394 rd = PORT_ArenaZNew(tmpArena, ocspResponseData); | |
| 395 if (!rd) | |
| 396 goto done; | |
| 397 rid = PORT_ArenaZNew(tmpArena, ocspResponderID); | |
| 398 if (!rid) | |
| 399 goto done; | |
| 400 br = PORT_ArenaZNew(tmpArena, ocspBasicOCSPResponse); | |
| 401 if (!br) | |
| 402 goto done; | |
| 403 rb = PORT_ArenaZNew(tmpArena, ocspResponseBytes); | |
| 404 if (!rb) | |
| 405 goto done; | |
| 406 response = PORT_ArenaZNew(tmpArena, CERTOCSPResponse); | |
| 407 if (!response) | |
| 408 goto done; | |
| 409 | |
| 410 rd->version.data=NULL; | |
| 411 rd->version.len=0; | |
| 412 rd->responseExtensions = NULL; | |
| 413 rd->responses = responses; | |
| 414 if (DER_TimeToGeneralizedTimeArena(tmpArena, &rd->producedAt, producedAt) | |
| 415 != SECSuccess) | |
| 416 goto done; | |
| 417 rid->responderIDType = responderIDType; | |
| 418 if (responderIDType == ocspResponderID_byName) { | |
| 419 responderIDTemplate = ocsp_ResponderIDByNameTemplate; | |
| 420 if (CERT_CopyName(tmpArena, &rid->responderIDValue.name, | |
| 421 &responderCert->subject) != SECSuccess) | |
| 422 goto done; | |
| 423 } | |
| 424 else { | |
| 425 responderIDTemplate = ocsp_ResponderIDByKeyTemplate; | |
| 426 if (!CERT_GetSPKIDigest(tmpArena, responderCert, SEC_OID_SHA1, | |
| 427 &rid->responderIDValue.keyHash)) | |
| 428 goto done; | |
| 429 } | |
| 430 | |
| 431 if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid, | |
| 432 responderIDTemplate)) | |
| 433 goto done; | |
| 434 | |
| 435 br->tbsResponseData = rd; | |
| 436 | |
| 437 if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseDa
ta, | |
| 438 ocsp_myResponseDataTemplate)) | |
| 439 goto done; | |
| 440 | |
| 441 br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem*, 1); | |
| 442 if (!br->responseSignature.derCerts) | |
| 443 goto done; | |
| 444 br->responseSignature.derCerts[0] = NULL; | |
| 445 | |
| 446 privKey = PK11_FindKeyByAnyCert(responderCert, wincx); | |
| 447 if (!privKey) | |
| 448 goto done; | |
| 449 | |
| 450 algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1); | |
| 451 if (algID == SEC_OID_UNKNOWN) | |
| 452 goto done; | |
| 453 | |
| 454 if (SEC_SignData(&br->responseSignature.signature, | |
| 455 br->tbsResponseDataDER.data, br->tbsResponseDataDER.len, | |
| 456 privKey, algID) | |
| 457 != SECSuccess) | |
| 458 goto done; | |
| 459 | |
| 460 /* convert len-in-bytes to len-in-bits */ | |
| 461 br->responseSignature.signature.len = br->responseSignature.signature.len <<
3; | |
| 462 | |
| 463 /* br->responseSignature.signature wasn't allocated from arena, | |
| 464 * we must free it when done. */ | |
| 465 | |
| 466 if (SECOID_SetAlgorithmID(tmpArena, &br->responseSignature.signatureAlgorith
m, algID, 0) | |
| 467 != SECSuccess) | |
| 468 goto done; | |
| 469 | |
| 470 if (!SEC_ASN1EncodeItem(tmpArena, &rb->response, br, | |
| 471 ocsp_EncodeBasicOCSPResponseTemplate)) | |
| 472 goto done; | |
| 473 | |
| 474 rb->responseTypeTag = SEC_OID_PKIX_OCSP_BASIC_RESPONSE; | |
| 475 | |
| 476 od = SECOID_FindOIDByTag(rb->responseTypeTag); | |
| 477 if (!od) | |
| 478 goto done; | |
| 479 | |
| 480 rb->responseType = od->oid; | |
| 481 rb->decodedResponse.basic = br; | |
| 482 | |
| 483 response->arena = tmpArena; | |
| 484 response->responseBytes = rb; | |
| 485 response->statusValue = ocspResponse_successful; | |
| 486 | |
| 487 if (!SEC_ASN1EncodeInteger(tmpArena, &response->responseStatus, | |
| 488 response->statusValue)) | |
| 489 goto done; | |
| 490 | |
| 491 result = SEC_ASN1EncodeItem(arena, NULL, response, ocsp_OCSPResponseTemplate
); | |
| 492 | |
| 493 done: | |
| 494 if (privKey) | |
| 495 SECKEY_DestroyPrivateKey(privKey); | |
| 496 if (br->responseSignature.signature.data) | |
| 497 SECITEM_FreeItem(&br->responseSignature.signature, PR_FALSE); | |
| 498 PORT_FreeArena(tmpArena, PR_FALSE); | |
| 499 | |
| 500 return result; | |
| 501 } | |
| 502 | |
| 503 static const SEC_ASN1Template ocsp_OCSPErrorResponseTemplate[] = { | |
| 504 { SEC_ASN1_SEQUENCE, | |
| 505 0, NULL, sizeof(CERTOCSPResponse) }, | |
| 506 { SEC_ASN1_ENUMERATED, | |
| 507 offsetof(CERTOCSPResponse, responseStatus) }, | |
| 508 { 0, 0, | |
| 509 mySEC_NullTemplate }, | |
| 510 { 0 } | |
| 511 }; | |
| 512 | |
| 513 SECItem* | |
| 514 CERT_CreateEncodedOCSPErrorResponse(PLArenaPool *arena, int error) | |
| 515 { | |
| 516 CERTOCSPResponse response; | |
| 517 SECItem *result = NULL; | |
| 518 | |
| 519 switch (error) { | |
| 520 case SEC_ERROR_OCSP_MALFORMED_REQUEST: | |
| 521 response.statusValue = ocspResponse_malformedRequest; | |
| 522 break; | |
| 523 case SEC_ERROR_OCSP_SERVER_ERROR: | |
| 524 response.statusValue = ocspResponse_internalError; | |
| 525 break; | |
| 526 case SEC_ERROR_OCSP_TRY_SERVER_LATER: | |
| 527 response.statusValue = ocspResponse_tryLater; | |
| 528 break; | |
| 529 case SEC_ERROR_OCSP_REQUEST_NEEDS_SIG: | |
| 530 response.statusValue = ocspResponse_sigRequired; | |
| 531 break; | |
| 532 case SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST: | |
| 533 response.statusValue = ocspResponse_unauthorized; | |
| 534 break; | |
| 535 default: | |
| 536 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 537 return NULL; | |
| 538 } | |
| 539 | |
| 540 if (!SEC_ASN1EncodeInteger(NULL, &response.responseStatus, | |
| 541 response.statusValue)) | |
| 542 return NULL; | |
| 543 | |
| 544 result = SEC_ASN1EncodeItem(arena, NULL, &response, | |
| 545 ocsp_OCSPErrorResponseTemplate); | |
| 546 | |
| 547 SECITEM_FreeItem(&response.responseStatus, PR_FALSE); | |
| 548 | |
| 549 return result; | |
| 550 } | |
| OLD | NEW |