security/nss/lib/certhigh/ocspsig.c

changeset 0
6474c204b198
     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 +}

mercurial