/* * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ * * ocspTemplates.h - ASN1 templates OCSP requests and responses. */ #ifndef _OCSP_TEMPLATES_H_ #define _OCSP_TEMPLATES_H_ #include <Security/secasn1t.h> #include <Security/x509defs.h> /* CSSM_X509_ALGORITHM_IDENTIFIER */ #include <Security/X509Templates.h> /* NSS_CertExtension */ #include <Security/nameTemplates.h> /* NSS_GeneralName and support */ #ifdef __cplusplus extern "C" { #endif #pragma mark ----- OCSP Request ----- /* * CertID ::= SEQUENCE { * hashAlgorithm AlgorithmIdentifier, * issuerNameHash OCTET STRING, -- Hash of Issuer's DN * issuerKeyHash OCTET STRING, -- Hash of Issuers public key * serialNumber CertificateSerialNumber } -- i.e., INTEGER */ typedef struct { CSSM_X509_ALGORITHM_IDENTIFIER algId; CSSM_DATA issuerNameHash; CSSM_DATA issuerPubKeyHash; CSSM_DATA serialNumber; } SecAsn1OCSPCertID; extern const SecAsn1Template kSecAsn1OCSPCertIDTemplate[]; /* * Request ::= SEQUENCE { * reqCert CertID, * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } */ typedef struct { SecAsn1OCSPCertID reqCert; NSS_CertExtension **extensions; // optional } SecAsn1OCSPRequest; extern const SecAsn1Template kSecAsn1OCSPRequestTemplate[]; /* * Signature ::= SEQUENCE { * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING, * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL} * * Since we wish to avoid knowing anything about the details of the certs, * we declare them here as ASN_ANY, get/set as raw data, and leave it to * the CL to parse them. */ typedef struct { CSSM_X509_ALGORITHM_IDENTIFIER algId; CSSM_DATA sig; // length in BITS CSSM_DATA **certs; // OPTIONAL } SecAsn1OCSPSignature; extern const SecAsn1Template kSecAsn1OCSPSignatureTemplate[]; /* * TBSRequest ::= SEQUENCE { * version [0] EXPLICIT Version DEFAULT v1, * requestorName [1] EXPLICIT GeneralName OPTIONAL, * requestList SEQUENCE OF Request, * requestExtensions [2] EXPLICIT Extensions OPTIONAL } */ typedef struct { CSSM_DATA *version; // OPTIONAL NSS_GeneralName *requestorName; // OPTIONAL SecAsn1OCSPRequest **requestList; NSS_CertExtension **requestExtensions; // OPTIONAL } SecAsn1OCSPTbsRequest; extern const SecAsn1Template kSecAsn1OCSPTbsRequestTemplate[]; /* * OCSPRequest ::= SEQUENCE { * tbsRequest TBSRequest, * optionalSignature [0] EXPLICIT Signature OPTIONAL } */ typedef struct { SecAsn1OCSPTbsRequest tbsRequest; SecAsn1OCSPSignature *signature; // OPTIONAL } SecAsn1OCSPSignedRequest; extern const SecAsn1Template kSecAsn1OCSPSignedRequestTemplate[]; #pragma mark ----- OCSP Response ----- /* * CertStatus ::= CHOICE { * good [0] IMPLICIT NULL, * revoked [1] IMPLICIT RevokedInfo, * unknown [2] IMPLICIT UnknownInfo } * * RevokedInfo ::= SEQUENCE { * revocationTime GeneralizedTime, * revocationReason [0] EXPLICIT CRLReason OPTIONAL } * * UnknownInfo ::= NULL -- this can be replaced with an enumeration * * See <Security/certextensions.h> for enum values of CE_CrlReason. */ typedef struct { CSSM_DATA revocationTime; CSSM_DATA *revocationReason; // OPTIONAL, CE_CrlReason } SecAsn1OCSPRevokedInfo; typedef union { SecAsn1OCSPRevokedInfo *revokedInfo; CSSM_DATA *nullData; } SecAsn1OCSPCertStatus; typedef enum { CS_Good = 0, CS_Revoked = 1, CS_Unknown = 2, CS_NotParsed = 0xff /* Not in protocol: means value not parsed or seen */ } SecAsn1OCSPCertStatusTag; extern const SecAsn1Template kSecAsn1OCSPRevokedInfoTemplate[]; /* * Encode/decode CertStatus separately using one of these hree templates. * The result goes into SecAsn1OCSPSingleResponse.certStatus on encode. */ extern const SecAsn1Template kSecAsn1OCSPCertStatusGoodTemplate[]; extern const SecAsn1Template kSecAsn1OCSPCertStatusRevokedTemplate[]; extern const SecAsn1Template kSecAsn1OCSPCertStatusUnknownTemplate[]; /* * SingleResponse ::= SEQUENCE { * certID CertID, * certStatus CertStatus, * thisUpdate GeneralizedTime, * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, * singleExtensions [1] EXPLICIT Extensions OPTIONAL } */ typedef struct { SecAsn1OCSPCertID certID; CSSM_DATA certStatus; // ASN_ANY here CSSM_DATA thisUpdate; // GeneralizedTime CSSM_DATA *nextUpdate; // GeneralizedTime, OPTIONAL NSS_CertExtension **singleExtensions; // OPTIONAL } SecAsn1OCSPSingleResponse; extern const SecAsn1Template kSecAsn1OCSPSingleResponseTemplate[]; /* * ResponderID ::= CHOICE { * byName EXPLICIT [1] Name, * byKey EXPLICIT [2] KeyHash } * * Since our ASN.1 encoder/decoder can't handle CHOICEs very well, we encode * this separately using one of the following two templates. On encode the * result if this step of the encode goes into SecAsn1OCSPResponseData.responderID, * where it's treated as an ANY_ANY when encoding that struct. The reverse happens * on decode. */ typedef union { NSS_Name byName; CSSM_DATA byKey; // key hash in OCTET STRING } SecAsn1OCSPResponderID; typedef enum { RIT_Name = 1, RIT_Key = 2 } SecAsn1OCSPResponderIDTag; extern const SecAsn1Template kSecAsn1OCSPResponderIDAsNameTemplate[]; extern const SecAsn1Template kSecAsn1OCSPResponderIDAsKeyTemplate[]; /* * ResponseData ::= SEQUENCE { * version [0] EXPLICIT Version DEFAULT v1, * responderID ResponderID, * producedAt GeneralizedTime, * responses SEQUENCE OF SingleResponse, * responseExtensions [1] EXPLICIT Extensions OPTIONAL } */ typedef struct { CSSM_DATA *version; // OPTIONAL CSSM_DATA responderID; // ASN_ANY here, decode/encode separately CSSM_DATA producedAt; // GeneralizedTime SecAsn1OCSPSingleResponse **responses; NSS_CertExtension **responseExtensions; // OPTIONAL } SecAsn1OCSPResponseData; extern const SecAsn1Template kSecAsn1OCSPResponseDataTemplate[]; /* * BasicOCSPResponse ::= SEQUENCE { * tbsResponseData ResponseData, * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING, * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } * * Since we ALWAYS encode the tbsResponseData in preparation for signing, * we declare it as a raw ASN_ANY in the BasicOCSPResponse. * * Certs are likewise ASN_ANY since we use the CL to parse and create them. */ typedef struct { CSSM_DATA tbsResponseData; CSSM_X509_ALGORITHM_IDENTIFIER algId; CSSM_DATA sig; // length in BITS CSSM_DATA **certs; // optional } SecAsn1OCSPBasicResponse; extern const SecAsn1Template kSecAsn1OCSPBasicResponseTemplate[]; /* * ResponseBytes ::= SEQUENCE { * responseType OBJECT IDENTIFIER, * response OCTET STRING } * * The contents of response are actually an encoded SecAsn1OCSPBasicResponse (at * least until another response type is defined). */ typedef struct { CSSM_OID responseType; CSSM_DATA response; } SecAsn1OCSPResponseBytes; extern const SecAsn1Template kSecAsn1OCSPResponseBytesTemplate[]; /* * OCSPResponse ::= SEQUENCE { * responseStatus OCSPResponseStatus, -- an ENUM * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } */ typedef struct { CSSM_DATA responseStatus; // see enum below SecAsn1OCSPResponseBytes *responseBytes; // optional } SecAsn1OCSPResponse; extern const SecAsn1Template kSecAsn1OCSPResponseTemplate[]; typedef enum { RS_Success = 0, RS_MalformedRequest = 1, RS_InternalError = 2, RS_TryLater = 3, RS_Unused = 4, RS_SigRequired = 5, RS_Unauthorized = 6 } SecAsn1OCSPResponseStatus; /* * This is not part of the OCSP protocol; it's used in the communication between * the Apple X.509 TP module and the ocspd server. * * OCSPDRequest ::= SEQUENCE { * cacheWriteDisable :: = EXPLICIT [0] BOOL OPTIONAL; -- cache write disable * -- default FALSE * cacheWriteDisable :: = EXPLICIT [1] BOOL OPTIONAL; -- cache read disable * -- default FALSE * certID ::= OCTET STRING; -- for cache lookup * ocspReq ::= EXPLICIT [2] OCTET STRING OPTIONAL; -- for net fetch * localResp ::= EXPLICIT [3] IA5String OPTIONAL; -- for local responder * urls ::= EXPLICIT [4] SEQUENCE of IA5String OPTIONAL; * -- for normal net fetch * }; */ #define OCSPD_REQUEST_VERS 0 typedef struct { CSSM_DATA *cacheWriteDisable; CSSM_DATA *cacheReadDisable; CSSM_DATA certID; // DER encoded SecAsn1OCSPCertID CSSM_DATA *ocspReq; // DER encoded SecAsn1OCSPSignedRequest CSSM_DATA *localRespURI; // local responder URI CSSM_DATA **urls; // normal URIs } SecAsn1OCSPDRequest; /* * And this is a sequence of them, packaged up and sent to ocspd in one RPC. */ typedef struct { CSSM_DATA version; // OCSPD_REQUEST_VERS SecAsn1OCSPDRequest **requests; } SecAsn1OCSPDRequests; extern const SecAsn1Template kSecAsn1OCSPDRequestTemplate[]; extern const SecAsn1Template kSecAsn1OCSPDRequestsTemplate[]; /* * Unordered set of replies from ocsdp; they map back to individual * SecAsn1OCSPDRequests by the encoded certID (which is obtained from the * SecAsn1OCSPDRequest, NOT from the OCSP response). */ typedef struct { CSSM_DATA certID; // DER encoded SecAsn1OCSPCertID CSSM_DATA ocspResp; // DER encoded SecAsn1OCSPResponse } SecAsn1OCSPDReply; #define OCSPD_REPLY_VERS 0 typedef struct { CSSM_DATA version; // OCSPD_REPLY_VERS SecAsn1OCSPDReply **replies; } SecAsn1OCSPReplies; extern const SecAsn1Template kSecAsn1OCSPDReplyTemplate[]; extern const SecAsn1Template kSecAsn1OCSPDRepliesTemplate[]; #ifdef __cplusplus } #endif #endif /* _OCSP_TEMPLATES_H_ */