diff nss/lib/certhigh/ocspsig.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nss/lib/certhigh/ocspsig.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,600 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "plarena.h"
+
+#include "seccomon.h"
+#include "secitem.h"
+#include "secasn1.h"
+#include "secder.h"
+#include "cert.h"
+#include "secerr.h"
+#include "secoid.h"
+#include "sechash.h"
+#include "keyhi.h"
+#include "cryptohi.h"
+#include "ocsp.h"
+#include "ocspti.h"
+#include "ocspi.h"
+#include "pk11pub.h"
+
+
+extern const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[];
+extern const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[];
+extern const SEC_ASN1Template ocsp_OCSPResponseTemplate[];
+
+ocspCertStatus*
+ocsp_CreateCertStatus(PLArenaPool *arena,
+                      ocspCertStatusType status,
+                      PRTime revocationTime)
+{
+    ocspCertStatus *cs;
+
+    if (!arena) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return NULL;
+    }
+
+    switch (status) {
+        case ocspCertStatus_good:
+        case ocspCertStatus_unknown:
+        case ocspCertStatus_revoked:
+            break;
+        default:
+            PORT_SetError(SEC_ERROR_INVALID_ARGS);
+            return NULL;
+    }
+    
+    cs = PORT_ArenaZNew(arena, ocspCertStatus);
+    if (!cs)
+        return NULL;
+    cs->certStatusType = status;
+    switch (status) {
+        case ocspCertStatus_good:
+            cs->certStatusInfo.goodInfo = SECITEM_AllocItem(arena, NULL, 0);
+            if (!cs->certStatusInfo.goodInfo)
+                return NULL;
+            break;
+        case ocspCertStatus_unknown:
+            cs->certStatusInfo.unknownInfo = SECITEM_AllocItem(arena, NULL, 0);
+            if (!cs->certStatusInfo.unknownInfo)
+                return NULL;
+            break;
+        case ocspCertStatus_revoked:
+            cs->certStatusInfo.revokedInfo =
+                PORT_ArenaZNew(arena, ocspRevokedInfo);
+            if (!cs->certStatusInfo.revokedInfo)
+                return NULL;
+            cs->certStatusInfo.revokedInfo->revocationReason =
+                SECITEM_AllocItem(arena, NULL, 0);
+            if (!cs->certStatusInfo.revokedInfo->revocationReason)
+                return NULL;
+            if (DER_TimeToGeneralizedTimeArena(arena,
+                    &cs->certStatusInfo.revokedInfo->revocationTime,
+                    revocationTime) != SECSuccess)
+                return NULL;
+            break;
+        default:
+            PORT_Assert(PR_FALSE);
+    }
+    return cs;
+}
+
+static const SEC_ASN1Template mySEC_EnumeratedTemplate[] = {
+    { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) }
+};
+
+static const SEC_ASN1Template mySEC_PointerToEnumeratedTemplate[] = {
+    { SEC_ASN1_POINTER, 0, mySEC_EnumeratedTemplate }
+};
+
+static const SEC_ASN1Template ocsp_EncodeRevokedInfoTemplate[] = {
+    { SEC_ASN1_GENERALIZED_TIME,
+        offsetof(ocspRevokedInfo, revocationTime) },
+    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
+      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC| 0,
+        offsetof(ocspRevokedInfo, revocationReason),
+        mySEC_PointerToEnumeratedTemplate },
+    { 0 }
+};
+
+static const SEC_ASN1Template ocsp_PointerToEncodeRevokedInfoTemplate[] = {
+    { SEC_ASN1_POINTER, 0,
+      ocsp_EncodeRevokedInfoTemplate }
+};
+
+static const SEC_ASN1Template mySEC_NullTemplate[] = {
+    { SEC_ASN1_NULL, 0, NULL, sizeof(SECItem) }
+};
+
+static const SEC_ASN1Template ocsp_CertStatusTemplate[] = {
+    { SEC_ASN1_CHOICE, offsetof(ocspCertStatus, certStatusType),
+        0, sizeof(ocspCertStatus) },
+    { SEC_ASN1_CONTEXT_SPECIFIC | 0,
+        0, mySEC_NullTemplate, ocspCertStatus_good },
+    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
+      SEC_ASN1_CONTEXT_SPECIFIC | 1,
+        offsetof(ocspCertStatus, certStatusInfo.revokedInfo),
+        ocsp_PointerToEncodeRevokedInfoTemplate, ocspCertStatus_revoked },
+    { SEC_ASN1_CONTEXT_SPECIFIC | 2,
+        0, mySEC_NullTemplate, ocspCertStatus_unknown },
+    { 0 }
+};
+
+static const SEC_ASN1Template mySECOID_AlgorithmIDTemplate[] = {
+    { SEC_ASN1_SEQUENCE,
+          0, NULL, sizeof(SECAlgorithmID) },
+    { SEC_ASN1_OBJECT_ID,
+          offsetof(SECAlgorithmID,algorithm), },
+    { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
+          offsetof(SECAlgorithmID,parameters), },
+    { 0, }
+};
+
+static const SEC_ASN1Template mySEC_AnyTemplate[] = {
+    { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
+};
+
+static const SEC_ASN1Template mySEC_SequenceOfAnyTemplate[] = {
+    { SEC_ASN1_SEQUENCE_OF, 0, mySEC_AnyTemplate }
+};
+
+static const SEC_ASN1Template mySEC_PointerToSequenceOfAnyTemplate[] = {
+    { SEC_ASN1_POINTER, 0, mySEC_SequenceOfAnyTemplate }
+};
+
+static const SEC_ASN1Template mySEC_IntegerTemplate[] = {
+    { SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) }
+};
+
+static const SEC_ASN1Template mySEC_PointerToIntegerTemplate[] = {
+    { SEC_ASN1_POINTER, 0, mySEC_IntegerTemplate }
+};
+
+static const SEC_ASN1Template mySEC_GeneralizedTimeTemplate[] = {
+    { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
+};
+
+static const SEC_ASN1Template mySEC_PointerToGeneralizedTimeTemplate[] = {
+    { SEC_ASN1_POINTER, 0, mySEC_GeneralizedTimeTemplate }
+};
+
+static const SEC_ASN1Template ocsp_myCertIDTemplate[] = {
+    { SEC_ASN1_SEQUENCE,
+        0, NULL, sizeof(CERTOCSPCertID) },
+    { SEC_ASN1_INLINE,
+        offsetof(CERTOCSPCertID, hashAlgorithm),
+        mySECOID_AlgorithmIDTemplate },
+    { SEC_ASN1_OCTET_STRING,
+        offsetof(CERTOCSPCertID, issuerNameHash) },
+    { SEC_ASN1_OCTET_STRING,
+        offsetof(CERTOCSPCertID, issuerKeyHash) },
+    { SEC_ASN1_INTEGER,
+        offsetof(CERTOCSPCertID, serialNumber) },
+    { 0 }
+};
+
+static const SEC_ASN1Template myCERT_CertExtensionTemplate[] = {
+    { SEC_ASN1_SEQUENCE,
+          0, NULL, sizeof(CERTCertExtension) },
+    { SEC_ASN1_OBJECT_ID,
+          offsetof(CERTCertExtension,id) },
+    { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN,             /* XXX DER_DEFAULT */
+          offsetof(CERTCertExtension,critical) },
+    { SEC_ASN1_OCTET_STRING,
+          offsetof(CERTCertExtension,value) },
+    { 0, }
+};
+
+static const SEC_ASN1Template myCERT_SequenceOfCertExtensionTemplate[] = {
+    { SEC_ASN1_SEQUENCE_OF, 0, myCERT_CertExtensionTemplate }
+};
+
+static const SEC_ASN1Template myCERT_PointerToSequenceOfCertExtensionTemplate[] = {
+    { SEC_ASN1_POINTER, 0, myCERT_SequenceOfCertExtensionTemplate }
+};
+
+static const SEC_ASN1Template ocsp_mySingleResponseTemplate[] = {
+    { SEC_ASN1_SEQUENCE,
+        0, NULL, sizeof(CERTOCSPSingleResponse) },
+    { SEC_ASN1_POINTER,
+        offsetof(CERTOCSPSingleResponse, certID),
+        ocsp_myCertIDTemplate },
+    { SEC_ASN1_ANY,
+        offsetof(CERTOCSPSingleResponse, derCertStatus) },
+    { SEC_ASN1_GENERALIZED_TIME,
+        offsetof(CERTOCSPSingleResponse, thisUpdate) },
+    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
+      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+        offsetof(CERTOCSPSingleResponse, nextUpdate),
+        mySEC_PointerToGeneralizedTimeTemplate },
+    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
+      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
+        offsetof(CERTOCSPSingleResponse, singleExtensions),
+        myCERT_PointerToSequenceOfCertExtensionTemplate },
+    { 0 }
+};
+
+static const SEC_ASN1Template ocsp_myResponseDataTemplate[] = {
+    { SEC_ASN1_SEQUENCE,
+        0, NULL, sizeof(ocspResponseData) },
+    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |           /* XXX DER_DEFAULT */
+      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+        offsetof(ocspResponseData, version),
+        mySEC_PointerToIntegerTemplate },
+    { SEC_ASN1_ANY,
+        offsetof(ocspResponseData, derResponderID) },
+    { SEC_ASN1_GENERALIZED_TIME,
+        offsetof(ocspResponseData, producedAt) },
+    { SEC_ASN1_SEQUENCE_OF,
+        offsetof(ocspResponseData, responses),
+        ocsp_mySingleResponseTemplate },
+    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
+      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
+        offsetof(ocspResponseData, responseExtensions),
+        myCERT_PointerToSequenceOfCertExtensionTemplate },
+    { 0 }
+};
+
+
+static const SEC_ASN1Template ocsp_EncodeBasicOCSPResponseTemplate[] = {
+    { SEC_ASN1_SEQUENCE,
+        0, NULL, sizeof(ocspBasicOCSPResponse) },
+    { SEC_ASN1_POINTER,
+        offsetof(ocspBasicOCSPResponse, tbsResponseData),
+        ocsp_myResponseDataTemplate },
+    { SEC_ASN1_INLINE,
+        offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm),
+        mySECOID_AlgorithmIDTemplate },
+    { SEC_ASN1_BIT_STRING,
+        offsetof(ocspBasicOCSPResponse, responseSignature.signature) },
+    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
+      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+        offsetof(ocspBasicOCSPResponse, responseSignature.derCerts),
+        mySEC_PointerToSequenceOfAnyTemplate },
+    { 0 }
+};
+
+static CERTOCSPSingleResponse*
+ocsp_CreateSingleResponse(PLArenaPool *arena,
+                          CERTOCSPCertID *id, ocspCertStatus *status,
+                          PRTime thisUpdate, const PRTime *nextUpdate)
+{
+    CERTOCSPSingleResponse *sr;
+
+    if (!arena || !id || !status) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return NULL;
+    }
+
+    sr = PORT_ArenaZNew(arena, CERTOCSPSingleResponse);
+    if (!sr)
+        return NULL;
+    sr->arena = arena;
+    sr->certID = id;
+    sr->certStatus = status;
+    if (DER_TimeToGeneralizedTimeArena(arena, &sr->thisUpdate, thisUpdate)
+             != SECSuccess)
+        return NULL;
+    sr->nextUpdate = NULL;
+    if (nextUpdate) {
+        sr->nextUpdate = SECITEM_AllocItem(arena, NULL, 0);
+        if (!sr->nextUpdate)
+            return NULL;
+        if (DER_TimeToGeneralizedTimeArena(arena, sr->nextUpdate, *nextUpdate)
+             != SECSuccess)
+            return NULL;
+    }
+
+    sr->singleExtensions = PORT_ArenaNewArray(arena, CERTCertExtension*, 1);
+    if (!sr->singleExtensions)
+        return NULL;
+
+    sr->singleExtensions[0] = NULL;
+    
+    if (!SEC_ASN1EncodeItem(arena, &sr->derCertStatus,
+                            status, ocsp_CertStatusTemplate))
+        return NULL;
+
+    return sr;
+}
+
+CERTOCSPSingleResponse*
+CERT_CreateOCSPSingleResponseGood(PLArenaPool *arena,
+                                  CERTOCSPCertID *id,
+                                  PRTime thisUpdate,
+                                  const PRTime *nextUpdate)
+{
+    ocspCertStatus * cs;
+    if (!arena) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return NULL;
+    }
+    cs = ocsp_CreateCertStatus(arena, ocspCertStatus_good, 0);
+    if (!cs)
+        return NULL;
+    return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
+}
+
+CERTOCSPSingleResponse*
+CERT_CreateOCSPSingleResponseUnknown(PLArenaPool *arena,
+                                     CERTOCSPCertID *id,
+                                     PRTime thisUpdate,
+                                     const PRTime *nextUpdate)
+{
+    ocspCertStatus * cs;
+    if (!arena) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return NULL;
+    }
+    cs = ocsp_CreateCertStatus(arena, ocspCertStatus_unknown, 0);
+    if (!cs)
+        return NULL;
+    return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
+}
+
+CERTOCSPSingleResponse*
+CERT_CreateOCSPSingleResponseRevoked(
+    PLArenaPool *arena,
+    CERTOCSPCertID *id,
+    PRTime thisUpdate,
+    const PRTime *nextUpdate,
+    PRTime revocationTime,
+    const CERTCRLEntryReasonCode* revocationReason)
+{
+    ocspCertStatus * cs;
+    /* revocationReason is not yet supported, so it must be NULL. */
+    if (!arena || revocationReason) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return NULL;
+    }
+    cs = ocsp_CreateCertStatus(arena, ocspCertStatus_revoked, revocationTime);
+    if (!cs)
+        return NULL;
+    return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
+}
+
+/* responderCert == 0 means:
+ * create a response with an invalid signature (for testing purposes) */
+SECItem*
+CERT_CreateEncodedOCSPSuccessResponse(
+    PLArenaPool *arena,
+    CERTCertificate *responderCert,
+    CERTOCSPResponderIDType responderIDType,
+    PRTime producedAt,
+    CERTOCSPSingleResponse **responses,
+    void *wincx)
+{
+    PLArenaPool *tmpArena;
+    ocspResponseData *rd = NULL;
+    ocspResponderID *rid = NULL;
+    const SEC_ASN1Template *responderIDTemplate = NULL;
+    ocspBasicOCSPResponse *br = NULL;
+    ocspResponseBytes *rb = NULL;
+    CERTOCSPResponse *response = NULL;
+    
+    SECOidTag algID;
+    SECOidData *od = NULL;
+    SECKEYPrivateKey *privKey = NULL;
+    SECItem *result = NULL;
+  
+    if (!arena || !responses) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return NULL;
+    }
+    if (responderIDType != ocspResponderID_byName &&
+        responderIDType != ocspResponderID_byKey) {
+        PORT_SetError(SEC_ERROR_INVALID_ARGS);
+        return NULL;
+    }
+
+    tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    if (!tmpArena)
+        return NULL;
+
+    rd = PORT_ArenaZNew(tmpArena, ocspResponseData);
+    if (!rd)
+        goto done;
+    rid = PORT_ArenaZNew(tmpArena, ocspResponderID);
+    if (!rid)
+        goto done;
+    br = PORT_ArenaZNew(tmpArena, ocspBasicOCSPResponse);
+    if (!br)
+        goto done;
+    rb = PORT_ArenaZNew(tmpArena, ocspResponseBytes);
+    if (!rb)
+        goto done;
+    response = PORT_ArenaZNew(tmpArena, CERTOCSPResponse);
+    if (!response)
+        goto done;
+    
+    rd->version.data=NULL;
+    rd->version.len=0;
+    rd->responseExtensions = NULL;
+    rd->responses = responses;
+    if (DER_TimeToGeneralizedTimeArena(tmpArena, &rd->producedAt, producedAt)
+            != SECSuccess)
+        goto done;
+
+    if (!responderCert) {
+	/* use invalid signature for testing purposes */
+	unsigned char dummyChar = 'd';
+	SECItem dummy;
+
+	dummy.len = 1;
+	dummy.data = &dummyChar;
+
+	/* it's easier to produdce a keyHash out of nowhere,
+	 * than to produce an encoded subject,
+	 * so for our dummy response we always use byKey
+	 */
+	
+	rid->responderIDType = ocspResponderID_byKey;
+	if (!ocsp_DigestValue(tmpArena, SEC_OID_SHA1, &rid->responderIDValue.keyHash,
+			      &dummy))
+	    goto done;
+
+	if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid,
+				ocsp_ResponderIDByKeyTemplate))
+	    goto done;
+
+	br->tbsResponseData = rd;
+
+	if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData,
+				ocsp_myResponseDataTemplate))
+	    goto done;
+
+	br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem*, 1);
+	if (!br->responseSignature.derCerts)
+	    goto done;
+	br->responseSignature.derCerts[0] = NULL;
+
+	algID = SEC_GetSignatureAlgorithmOidTag(rsaKey, SEC_OID_SHA1);
+	if (algID == SEC_OID_UNKNOWN)
+	    goto done;
+
+	/* match the regular signature code, which doesn't use the arena */
+	if (!SECITEM_AllocItem(NULL, &br->responseSignature.signature, 1))
+	    goto done;
+	PORT_Memcpy(br->responseSignature.signature.data, &dummyChar, 1);
+
+	/* convert len-in-bytes to len-in-bits */
+	br->responseSignature.signature.len = br->responseSignature.signature.len << 3;
+    }
+    else {
+	rid->responderIDType = responderIDType;
+	if (responderIDType == ocspResponderID_byName) {
+	    responderIDTemplate = ocsp_ResponderIDByNameTemplate;
+	    if (CERT_CopyName(tmpArena, &rid->responderIDValue.name,
+			    &responderCert->subject) != SECSuccess)
+		goto done;
+	}
+	else {
+	    responderIDTemplate = ocsp_ResponderIDByKeyTemplate;
+	    if (!CERT_GetSubjectPublicKeyDigest(tmpArena, responderCert,
+				SEC_OID_SHA1, &rid->responderIDValue.keyHash))
+		goto done;
+	}
+
+	if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid,
+		responderIDTemplate))
+	    goto done;
+
+	br->tbsResponseData = rd;
+
+	if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData,
+		ocsp_myResponseDataTemplate))
+	    goto done;
+
+	br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem*, 1);
+	if (!br->responseSignature.derCerts)
+	    goto done;
+	br->responseSignature.derCerts[0] = NULL;
+
+	privKey = PK11_FindKeyByAnyCert(responderCert, wincx);
+	if (!privKey)
+	    goto done;
+
+	algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1);
+	if (algID == SEC_OID_UNKNOWN)
+	    goto done;
+
+	if (SEC_SignData(&br->responseSignature.signature,
+			    br->tbsResponseDataDER.data, br->tbsResponseDataDER.len,
+			    privKey, algID)
+		!= SECSuccess)
+	    goto done;
+
+	/* convert len-in-bytes to len-in-bits */
+	br->responseSignature.signature.len = br->responseSignature.signature.len << 3;
+
+	/* br->responseSignature.signature wasn't allocated from arena,
+	* we must free it when done. */
+    }
+
+    if (SECOID_SetAlgorithmID(tmpArena, &br->responseSignature.signatureAlgorithm, algID, 0)
+	    != SECSuccess)
+	goto done;
+
+    if (!SEC_ASN1EncodeItem(tmpArena, &rb->response, br,
+                            ocsp_EncodeBasicOCSPResponseTemplate))
+        goto done;
+
+    rb->responseTypeTag = SEC_OID_PKIX_OCSP_BASIC_RESPONSE;
+
+    od = SECOID_FindOIDByTag(rb->responseTypeTag);
+    if (!od)
+        goto done;
+
+    rb->responseType = od->oid;
+    rb->decodedResponse.basic = br;
+
+    response->arena = tmpArena;
+    response->responseBytes = rb;
+    response->statusValue = ocspResponse_successful;
+
+    if (!SEC_ASN1EncodeInteger(tmpArena, &response->responseStatus,
+                               response->statusValue))
+        goto done;
+
+    result = SEC_ASN1EncodeItem(arena, NULL, response, ocsp_OCSPResponseTemplate);
+
+done:
+    if (privKey)
+        SECKEY_DestroyPrivateKey(privKey);
+    if (br->responseSignature.signature.data)
+        SECITEM_FreeItem(&br->responseSignature.signature, PR_FALSE);
+    PORT_FreeArena(tmpArena, PR_FALSE);
+
+    return result;
+}
+
+static const SEC_ASN1Template ocsp_OCSPErrorResponseTemplate[] = {
+    { SEC_ASN1_SEQUENCE,
+        0, NULL, sizeof(CERTOCSPResponse) },
+    { SEC_ASN1_ENUMERATED,
+        offsetof(CERTOCSPResponse, responseStatus) },
+    { 0, 0,
+        mySEC_NullTemplate },
+    { 0 }
+};
+
+SECItem*
+CERT_CreateEncodedOCSPErrorResponse(PLArenaPool *arena, int error)
+{
+    CERTOCSPResponse response;
+    SECItem *result = NULL;
+
+    switch (error) {
+        case SEC_ERROR_OCSP_MALFORMED_REQUEST:
+            response.statusValue = ocspResponse_malformedRequest;
+            break;
+        case SEC_ERROR_OCSP_SERVER_ERROR:
+            response.statusValue = ocspResponse_internalError;
+            break;
+        case SEC_ERROR_OCSP_TRY_SERVER_LATER:
+            response.statusValue = ocspResponse_tryLater;
+            break;
+        case SEC_ERROR_OCSP_REQUEST_NEEDS_SIG:
+            response.statusValue = ocspResponse_sigRequired;
+            break;
+        case SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST:
+            response.statusValue = ocspResponse_unauthorized;
+            break;
+        default:
+            PORT_SetError(SEC_ERROR_INVALID_ARGS);
+            return NULL;
+    }
+
+    if (!SEC_ASN1EncodeInteger(NULL, &response.responseStatus,
+                               response.statusValue))
+        return NULL;
+
+    result = SEC_ASN1EncodeItem(arena, NULL, &response,
+                                ocsp_OCSPErrorResponseTemplate);
+
+    SECITEM_FreeItem(&response.responseStatus, PR_FALSE);
+
+    return result;
+}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)