security/nss/lib/certhigh/ocspsig.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial