/* 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_ */
