Source code

Revision control

Copy as Markdown

Other Tools

/* 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/. */
/*
* Private header defining OCSP types.
*/
#ifndef _OCSPTI_H_
#define _OCSPTI_H_
#include "ocspt.h"
#include "certt.h"
#include "plarena.h"
#include "seccomon.h"
#include "secoidt.h"
/*
* Some notes about naming conventions...
*
* The public data types all start with "CERTOCSP" (e.g. CERTOCSPRequest).
* (Even the public types are opaque, however. Only their names are
* "exported".)
*
* Internal-only data types drop the "CERT" prefix and use only the
* lower-case "ocsp" (e.g. ocspTBSRequest), for brevity sake.
*
* In either case, the base/suffix of the type name usually matches the
* name as defined in the OCSP specification. The exceptions to this are:
* - When there is overlap between the "OCSP" or "ocsp" prefix and
* the name used in the standard. That is, you cannot strip off the
* "CERTOCSP" or "ocsp" prefix and necessarily get the name of the
* type as it is defined in the standard; the "real" name will be
* *either* "OCSPSuffix" or just "Suffix".
* - When the name in the standard was a little too generic. (e.g. The
* standard defines "Request" but we call it a "SingleRequest".)
* In this case a comment above the type definition calls attention
* to the difference.
*
* The definitions laid out in this header file are intended to follow
* the same order as the definitions in the OCSP specification itself.
* With the OCSP standard in hand, you should be able to move through
* this file and follow along. To future modifiers of this file: please
* try to keep it that way. The only exceptions are the few cases where
* we need to define a type before it is referenced (e.g. enumerations),
* whereas in the OCSP specification these are usually defined the other
* way around (reference before definition).
*/
/*
* Forward-declarations of internal-only data structures.
*
* These are in alphabetical order (case-insensitive); please keep it that way!
*/
typedef struct ocspBasicOCSPResponseStr ocspBasicOCSPResponse;
typedef struct ocspCertStatusStr ocspCertStatus;
typedef struct ocspResponderIDStr ocspResponderID;
typedef struct ocspResponseBytesStr ocspResponseBytes;
typedef struct ocspResponseDataStr ocspResponseData;
typedef struct ocspRevokedInfoStr ocspRevokedInfo;
typedef struct ocspServiceLocatorStr ocspServiceLocator;
typedef struct ocspSignatureStr ocspSignature;
typedef struct ocspSingleRequestStr ocspSingleRequest;
typedef struct ocspSingleResponseStr ocspSingleResponse;
typedef struct ocspTBSRequestStr ocspTBSRequest;
/*
* An OCSPRequest; this is what is sent (encoded) to an OCSP responder.
*/
struct CERTOCSPRequestStr {
PLArenaPool *arena; /* local; not part of encoding */
ocspTBSRequest *tbsRequest;
ocspSignature *optionalSignature;
};
/*
* A TBSRequest; when an OCSPRequest is signed, the encoding of this
* is what the signature is actually applied to. ("TBS" == To Be Signed)
* Whether signed or not, however, this structure will be present, and
* is the "meat" of the OCSPRequest.
*
* Note that the "requestorName" field cannot be encoded/decoded in the
* same pass as the entire request -- it needs to be handled with a special
* call to convert to/from our internal form of a GeneralName. Thus the
* "derRequestorName" field, which is the actual DER-encoded bytes.
*
* The "extensionHandle" field is used on creation only; it holds
* in-progress extensions as they are optionally added to the request.
*/
struct ocspTBSRequestStr {
SECItem version; /* an INTEGER */
SECItem *derRequestorName; /* encoded GeneralName; see above */
CERTGeneralNameList *requestorName; /* local; not part of encoding */
ocspSingleRequest **requestList;
CERTCertExtension **requestExtensions;
void *extensionHandle; /* local; not part of encoding */
};
/*
* This is the actual signature information for an OCSPRequest (applied to
* the TBSRequest structure) or for a BasicOCSPResponse (applied to a
* ResponseData structure).
*
* Note that the "signature" field itself is a BIT STRING; operations on
* it need to keep that in mind, converting the length to bytes as needed
* and back again afterward (so that the length is usually expressing bits).
*
* The "cert" field is the signer's certificate. In the case of a received
* signature, it will be filled in when the signature is verified. In the
* case of a created signature, it is filled in on creation and will be the
* cert used to create the signature when the signing-and-encoding occurs,
* as well as the cert (and its chain) to fill in derCerts if requested.
*
* The extra fields cache information about the signature after we have
* attempted a verification. "wasChecked", if true, means the signature
* has been checked against the appropriate data and thus that "status"
* contains the result of that verification. If "status" is not SECSuccess,
* "failureReason" is a copy of the error code that was set at the time;
* presumably it tells why the signature verification failed.
*/
struct ocspSignatureStr {
SECAlgorithmID signatureAlgorithm;
SECItem signature; /* a BIT STRING */
SECItem **derCerts; /* a SEQUENCE OF Certificate */
CERTCertificate *cert; /* local; not part of encoding */
PRBool wasChecked; /* local; not part of encoding */
SECStatus status; /* local; not part of encoding */
int failureReason; /* local; not part of encoding */
};
/*
* An OCSPRequest contains a SEQUENCE OF these, one for each certificate
* whose status is being checked.
*
* Note that in the OCSP specification this is just called "Request",
* but since that seemed confusing (vs. an OCSPRequest) and to be more
* consistent with the parallel type "SingleResponse", I called it a
* "SingleRequest".
*
* XXX figure out how to get rid of that arena -- there must be a way
*/
struct ocspSingleRequestStr {
PLArenaPool *arena; /* just a copy of the response arena,
* needed here for extension handling
* routines, on creation only */
CERTOCSPCertID *reqCert;
CERTCertExtension **singleRequestExtensions;
};
/*
* A CertID is the means of identifying a certificate, used both in requests
* and in responses.
*
* When in a SingleRequest it specifies the certificate to be checked.
* When in a SingleResponse it is the cert whose status is being given.
*/
struct CERTOCSPCertIDStr {
SECAlgorithmID hashAlgorithm;
SECItem issuerNameHash; /* an OCTET STRING */
SECItem issuerKeyHash; /* an OCTET STRING */
SECItem serialNumber; /* an INTEGER */
SECItem issuerSHA1NameHash; /* keep other hashes around when */
SECItem issuerMD5NameHash; /* we have them */
SECItem issuerMD2NameHash;
SECItem issuerSHA1KeyHash; /* keep other hashes around when */
SECItem issuerMD5KeyHash; /* we have them */
SECItem issuerMD2KeyHash;
PLArenaPool *poolp;
};
/*
* This describes the value of the responseStatus field in an OCSPResponse.
* The corresponding ASN.1 definition is:
*
* OCSPResponseStatus ::= ENUMERATED {
* successful (0), --Response has valid confirmations
* malformedRequest (1), --Illegal confirmation request
* internalError (2), --Internal error in issuer
* tryLater (3), --Try again later
* --(4) is not used
* sigRequired (5), --Must sign the request
* unauthorized (6), --Request unauthorized
* }
*/
typedef enum {
ocspResponse_min = 0,
ocspResponse_successful = 0,
ocspResponse_malformedRequest = 1,
ocspResponse_internalError = 2,
ocspResponse_tryLater = 3,
ocspResponse_unused = 4,
ocspResponse_sigRequired = 5,
ocspResponse_unauthorized = 6,
ocspResponse_max = 6 /* Please update max when adding values.
* Remember to also update arrays, e.g.
* "responseStatusNames" in ocspclnt.c
* and potentially other places. */
} ocspResponseStatus;
/*
* An OCSPResponse is what is sent (encoded) by an OCSP responder.
*
* The field "responseStatus" is the ASN.1 encoded value; the field
* "statusValue" is simply that same value translated into our local
* type ocspResponseStatus.
*/
struct CERTOCSPResponseStr {
PLArenaPool *arena; /* local; not part of encoding */
SECItem responseStatus; /* an ENUMERATED, see above */
ocspResponseStatus statusValue; /* local; not part of encoding */
ocspResponseBytes *responseBytes; /* only when status is successful */
};
/*
* A ResponseBytes (despite appearances) is what contains the meat
* of a successful response -- but still in encoded form. The type
* given as "responseType" tells you how to decode the string.
*
* We look at the OID and translate it into our local OID representation
* "responseTypeTag", and use that value to tell us how to decode the
* actual response itself. For now the only kind of OCSP response we
* know about is a BasicOCSPResponse. However, the intention in the
* OCSP specification is to allow for other response types, so we are
* building in that flexibility from the start and thus put a pointer
* to that data structure inside of a union. Whenever OCSP adds more
* response types, just add them to the union.
*/
struct ocspResponseBytesStr {
SECItem responseType; /* an OBJECT IDENTIFIER */
SECOidTag responseTypeTag; /* local; not part of encoding */
SECItem response; /* an OCTET STRING */
union {
ocspBasicOCSPResponse *basic; /* when type is id-pkix-ocsp-basic */
} decodedResponse; /* local; not part of encoding */
};
/*
* A BasicOCSPResponse -- when the responseType in a ResponseBytes is
* id-pkix-ocsp-basic, the "response" OCTET STRING above is the DER
* encoding of one of these.
*
* Note that in the OCSP specification, the signature fields are not
* part of a separate sub-structure. But since they are the same fields
* as we define for the signature in a request, it made sense to share
* the C data structure here and in some shared code to operate on them.
*/
struct ocspBasicOCSPResponseStr {
SECItem tbsResponseDataDER;
ocspResponseData *tbsResponseData; /* "tbs" == To Be Signed */
ocspSignature responseSignature;
};
/*
* A ResponseData is the part of a BasicOCSPResponse that is signed
* (after it is DER encoded). It contains the real details of the response
* (a per-certificate status).
*/
struct ocspResponseDataStr {
SECItem version; /* an INTEGER */
SECItem derResponderID;
ocspResponderID *responderID; /* local; not part of encoding */
SECItem producedAt; /* a GeneralizedTime */
CERTOCSPSingleResponse **responses;
CERTCertExtension **responseExtensions;
};
struct ocspResponderIDStr {
CERTOCSPResponderIDType responderIDType; /* local; not part of encoding */
union {
CERTName name; /* when ocspResponderID_byName */
SECItem keyHash; /* when ocspResponderID_byKey */
SECItem other; /* when ocspResponderID_other */
} responderIDValue;
};
/*
* The ResponseData in a BasicOCSPResponse contains a SEQUENCE OF
* SingleResponse -- one for each certificate whose status is being supplied.
*
* XXX figure out how to get rid of that arena -- there must be a way
*/
struct CERTOCSPSingleResponseStr {
PLArenaPool *arena; /* just a copy of the response arena,
* needed here for extension handling
* routines, on creation only */
CERTOCSPCertID *certID;
SECItem derCertStatus;
ocspCertStatus *certStatus; /* local; not part of encoding */
SECItem thisUpdate; /* a GeneralizedTime */
SECItem *nextUpdate; /* a GeneralizedTime */
CERTCertExtension **singleExtensions;
};
/*
* A CertStatus is the actual per-certificate status. Its ASN.1 definition:
*
* CertStatus ::= CHOICE {
* good [0] IMPLICIT NULL,
* revoked [1] IMPLICIT RevokedInfo,
* unknown [2] IMPLICIT UnknownInfo }
*
* (where for now UnknownInfo is defined to be NULL but in the
* future may be replaced with an enumeration).
*
* Because it is CHOICE, the status value and its associated information
* (if any) are actually encoded together. To represent this same
* information internally, we explicitly define a type and save it,
* along with the value, into a data structure.
*/
typedef enum {
ocspCertStatus_good, /* cert is not revoked */
ocspCertStatus_revoked, /* cert is revoked */
ocspCertStatus_unknown, /* cert was unknown to the responder */
ocspCertStatus_other /* status was not an expected value */
} ocspCertStatusType;
/*
* This is the actual per-certificate status.
*
* The "goodInfo" and "unknownInfo" items are only place-holders for a NULL.
* (Though someday OCSP may replace UnknownInfo with an enumeration that
* gives more detailed information.)
*/
struct ocspCertStatusStr {
ocspCertStatusType certStatusType; /* local; not part of encoding */
union {
SECItem *goodInfo; /* when ocspCertStatus_good */
ocspRevokedInfo *revokedInfo; /* when ocspCertStatus_revoked */
SECItem *unknownInfo; /* when ocspCertStatus_unknown */
SECItem *otherInfo; /* when ocspCertStatus_other */
} certStatusInfo;
};
/*
* A RevokedInfo gives information about a revoked certificate -- when it
* was revoked and why.
*/
struct ocspRevokedInfoStr {
SECItem revocationTime; /* a GeneralizedTime */
SECItem *revocationReason; /* a CRLReason; ignored for now */
};
/*
* ServiceLocator can be included as one of the singleRequestExtensions.
* When added, it specifies the (name of the) issuer of the cert being
* checked, and optionally the value of the AuthorityInfoAccess extension
* if the cert has one.
*/
struct ocspServiceLocatorStr {
CERTName *issuer;
SECItem locator; /* DER encoded authInfoAccess extension from cert */
};
#endif /* _OCSPTI_H_ */