diff options
Diffstat (limited to '')
-rw-r--r-- | security/nss/lib/certhigh/ocspti.h | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/security/nss/lib/certhigh/ocspti.h b/security/nss/lib/certhigh/ocspti.h new file mode 100644 index 0000000000..d9297dba6a --- /dev/null +++ b/security/nss/lib/certhigh/ocspti.h @@ -0,0 +1,356 @@ +/* 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_ */ |