security/nss/lib/certhigh/ocspti.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 /*
michael@0 6 * Private header defining OCSP types.
michael@0 7 */
michael@0 8
michael@0 9 #ifndef _OCSPTI_H_
michael@0 10 #define _OCSPTI_H_
michael@0 11
michael@0 12 #include "ocspt.h"
michael@0 13
michael@0 14 #include "certt.h"
michael@0 15 #include "plarena.h"
michael@0 16 #include "seccomon.h"
michael@0 17 #include "secoidt.h"
michael@0 18
michael@0 19
michael@0 20 /*
michael@0 21 * Some notes about naming conventions...
michael@0 22 *
michael@0 23 * The public data types all start with "CERTOCSP" (e.g. CERTOCSPRequest).
michael@0 24 * (Even the public types are opaque, however. Only their names are
michael@0 25 * "exported".)
michael@0 26 *
michael@0 27 * Internal-only data types drop the "CERT" prefix and use only the
michael@0 28 * lower-case "ocsp" (e.g. ocspTBSRequest), for brevity sake.
michael@0 29 *
michael@0 30 * In either case, the base/suffix of the type name usually matches the
michael@0 31 * name as defined in the OCSP specification. The exceptions to this are:
michael@0 32 * - When there is overlap between the "OCSP" or "ocsp" prefix and
michael@0 33 * the name used in the standard. That is, you cannot strip off the
michael@0 34 * "CERTOCSP" or "ocsp" prefix and necessarily get the name of the
michael@0 35 * type as it is defined in the standard; the "real" name will be
michael@0 36 * *either* "OCSPSuffix" or just "Suffix".
michael@0 37 * - When the name in the standard was a little too generic. (e.g. The
michael@0 38 * standard defines "Request" but we call it a "SingleRequest".)
michael@0 39 * In this case a comment above the type definition calls attention
michael@0 40 * to the difference.
michael@0 41 *
michael@0 42 * The definitions laid out in this header file are intended to follow
michael@0 43 * the same order as the definitions in the OCSP specification itself.
michael@0 44 * With the OCSP standard in hand, you should be able to move through
michael@0 45 * this file and follow along. To future modifiers of this file: please
michael@0 46 * try to keep it that way. The only exceptions are the few cases where
michael@0 47 * we need to define a type before it is referenced (e.g. enumerations),
michael@0 48 * whereas in the OCSP specification these are usually defined the other
michael@0 49 * way around (reference before definition).
michael@0 50 */
michael@0 51
michael@0 52
michael@0 53 /*
michael@0 54 * Forward-declarations of internal-only data structures.
michael@0 55 *
michael@0 56 * These are in alphabetical order (case-insensitive); please keep it that way!
michael@0 57 */
michael@0 58 typedef struct ocspBasicOCSPResponseStr ocspBasicOCSPResponse;
michael@0 59 typedef struct ocspCertStatusStr ocspCertStatus;
michael@0 60 typedef struct ocspResponderIDStr ocspResponderID;
michael@0 61 typedef struct ocspResponseBytesStr ocspResponseBytes;
michael@0 62 typedef struct ocspResponseDataStr ocspResponseData;
michael@0 63 typedef struct ocspRevokedInfoStr ocspRevokedInfo;
michael@0 64 typedef struct ocspServiceLocatorStr ocspServiceLocator;
michael@0 65 typedef struct ocspSignatureStr ocspSignature;
michael@0 66 typedef struct ocspSingleRequestStr ocspSingleRequest;
michael@0 67 typedef struct ocspSingleResponseStr ocspSingleResponse;
michael@0 68 typedef struct ocspTBSRequestStr ocspTBSRequest;
michael@0 69
michael@0 70
michael@0 71 /*
michael@0 72 * An OCSPRequest; this is what is sent (encoded) to an OCSP responder.
michael@0 73 */
michael@0 74 struct CERTOCSPRequestStr {
michael@0 75 PLArenaPool *arena; /* local; not part of encoding */
michael@0 76 ocspTBSRequest *tbsRequest;
michael@0 77 ocspSignature *optionalSignature;
michael@0 78 };
michael@0 79
michael@0 80 /*
michael@0 81 * A TBSRequest; when an OCSPRequest is signed, the encoding of this
michael@0 82 * is what the signature is actually applied to. ("TBS" == To Be Signed)
michael@0 83 * Whether signed or not, however, this structure will be present, and
michael@0 84 * is the "meat" of the OCSPRequest.
michael@0 85 *
michael@0 86 * Note that the "requestorName" field cannot be encoded/decoded in the
michael@0 87 * same pass as the entire request -- it needs to be handled with a special
michael@0 88 * call to convert to/from our internal form of a GeneralName. Thus the
michael@0 89 * "derRequestorName" field, which is the actual DER-encoded bytes.
michael@0 90 *
michael@0 91 * The "extensionHandle" field is used on creation only; it holds
michael@0 92 * in-progress extensions as they are optionally added to the request.
michael@0 93 */
michael@0 94 struct ocspTBSRequestStr {
michael@0 95 SECItem version; /* an INTEGER */
michael@0 96 SECItem *derRequestorName; /* encoded GeneralName; see above */
michael@0 97 CERTGeneralNameList *requestorName; /* local; not part of encoding */
michael@0 98 ocspSingleRequest **requestList;
michael@0 99 CERTCertExtension **requestExtensions;
michael@0 100 void *extensionHandle; /* local; not part of encoding */
michael@0 101 };
michael@0 102
michael@0 103 /*
michael@0 104 * This is the actual signature information for an OCSPRequest (applied to
michael@0 105 * the TBSRequest structure) or for a BasicOCSPResponse (applied to a
michael@0 106 * ResponseData structure).
michael@0 107 *
michael@0 108 * Note that the "signature" field itself is a BIT STRING; operations on
michael@0 109 * it need to keep that in mind, converting the length to bytes as needed
michael@0 110 * and back again afterward (so that the length is usually expressing bits).
michael@0 111 *
michael@0 112 * The "cert" field is the signer's certificate. In the case of a received
michael@0 113 * signature, it will be filled in when the signature is verified. In the
michael@0 114 * case of a created signature, it is filled in on creation and will be the
michael@0 115 * cert used to create the signature when the signing-and-encoding occurs,
michael@0 116 * as well as the cert (and its chain) to fill in derCerts if requested.
michael@0 117 *
michael@0 118 * The extra fields cache information about the signature after we have
michael@0 119 * attempted a verification. "wasChecked", if true, means the signature
michael@0 120 * has been checked against the appropriate data and thus that "status"
michael@0 121 * contains the result of that verification. If "status" is not SECSuccess,
michael@0 122 * "failureReason" is a copy of the error code that was set at the time;
michael@0 123 * presumably it tells why the signature verification failed.
michael@0 124 */
michael@0 125 struct ocspSignatureStr {
michael@0 126 SECAlgorithmID signatureAlgorithm;
michael@0 127 SECItem signature; /* a BIT STRING */
michael@0 128 SECItem **derCerts; /* a SEQUENCE OF Certificate */
michael@0 129 CERTCertificate *cert; /* local; not part of encoding */
michael@0 130 PRBool wasChecked; /* local; not part of encoding */
michael@0 131 SECStatus status; /* local; not part of encoding */
michael@0 132 int failureReason; /* local; not part of encoding */
michael@0 133 };
michael@0 134
michael@0 135 /*
michael@0 136 * An OCSPRequest contains a SEQUENCE OF these, one for each certificate
michael@0 137 * whose status is being checked.
michael@0 138 *
michael@0 139 * Note that in the OCSP specification this is just called "Request",
michael@0 140 * but since that seemed confusing (vs. an OCSPRequest) and to be more
michael@0 141 * consistent with the parallel type "SingleResponse", I called it a
michael@0 142 * "SingleRequest".
michael@0 143 *
michael@0 144 * XXX figure out how to get rid of that arena -- there must be a way
michael@0 145 */
michael@0 146 struct ocspSingleRequestStr {
michael@0 147 PLArenaPool *arena; /* just a copy of the response arena,
michael@0 148 * needed here for extension handling
michael@0 149 * routines, on creation only */
michael@0 150 CERTOCSPCertID *reqCert;
michael@0 151 CERTCertExtension **singleRequestExtensions;
michael@0 152 };
michael@0 153
michael@0 154 /*
michael@0 155 * A CertID is the means of identifying a certificate, used both in requests
michael@0 156 * and in responses.
michael@0 157 *
michael@0 158 * When in a SingleRequest it specifies the certificate to be checked.
michael@0 159 * When in a SingleResponse it is the cert whose status is being given.
michael@0 160 */
michael@0 161 struct CERTOCSPCertIDStr {
michael@0 162 SECAlgorithmID hashAlgorithm;
michael@0 163 SECItem issuerNameHash; /* an OCTET STRING */
michael@0 164 SECItem issuerKeyHash; /* an OCTET STRING */
michael@0 165 SECItem serialNumber; /* an INTEGER */
michael@0 166 SECItem issuerSHA1NameHash; /* keep other hashes around when */
michael@0 167 SECItem issuerMD5NameHash; /* we have them */
michael@0 168 SECItem issuerMD2NameHash;
michael@0 169 SECItem issuerSHA1KeyHash; /* keep other hashes around when */
michael@0 170 SECItem issuerMD5KeyHash; /* we have them */
michael@0 171 SECItem issuerMD2KeyHash;
michael@0 172 PLArenaPool *poolp;
michael@0 173 };
michael@0 174
michael@0 175 /*
michael@0 176 * This describes the value of the responseStatus field in an OCSPResponse.
michael@0 177 * The corresponding ASN.1 definition is:
michael@0 178 *
michael@0 179 * OCSPResponseStatus ::= ENUMERATED {
michael@0 180 * successful (0), --Response has valid confirmations
michael@0 181 * malformedRequest (1), --Illegal confirmation request
michael@0 182 * internalError (2), --Internal error in issuer
michael@0 183 * tryLater (3), --Try again later
michael@0 184 * --(4) is not used
michael@0 185 * sigRequired (5), --Must sign the request
michael@0 186 * unauthorized (6), --Request unauthorized
michael@0 187 * }
michael@0 188 */
michael@0 189 typedef enum {
michael@0 190 ocspResponse_min = 0,
michael@0 191 ocspResponse_successful = 0,
michael@0 192 ocspResponse_malformedRequest = 1,
michael@0 193 ocspResponse_internalError = 2,
michael@0 194 ocspResponse_tryLater = 3,
michael@0 195 ocspResponse_unused = 4,
michael@0 196 ocspResponse_sigRequired = 5,
michael@0 197 ocspResponse_unauthorized = 6,
michael@0 198 ocspResponse_max = 6 /* Please update max when adding values.
michael@0 199 * Remember to also update arrays, e.g.
michael@0 200 * "responseStatusNames" in ocspclnt.c
michael@0 201 * and potentially other places. */
michael@0 202 } ocspResponseStatus;
michael@0 203
michael@0 204 /*
michael@0 205 * An OCSPResponse is what is sent (encoded) by an OCSP responder.
michael@0 206 *
michael@0 207 * The field "responseStatus" is the ASN.1 encoded value; the field
michael@0 208 * "statusValue" is simply that same value translated into our local
michael@0 209 * type ocspResponseStatus.
michael@0 210 */
michael@0 211 struct CERTOCSPResponseStr {
michael@0 212 PLArenaPool *arena; /* local; not part of encoding */
michael@0 213 SECItem responseStatus; /* an ENUMERATED, see above */
michael@0 214 ocspResponseStatus statusValue; /* local; not part of encoding */
michael@0 215 ocspResponseBytes *responseBytes; /* only when status is successful */
michael@0 216 };
michael@0 217
michael@0 218 /*
michael@0 219 * A ResponseBytes (despite appearances) is what contains the meat
michael@0 220 * of a successful response -- but still in encoded form. The type
michael@0 221 * given as "responseType" tells you how to decode the string.
michael@0 222 *
michael@0 223 * We look at the OID and translate it into our local OID representation
michael@0 224 * "responseTypeTag", and use that value to tell us how to decode the
michael@0 225 * actual response itself. For now the only kind of OCSP response we
michael@0 226 * know about is a BasicOCSPResponse. However, the intention in the
michael@0 227 * OCSP specification is to allow for other response types, so we are
michael@0 228 * building in that flexibility from the start and thus put a pointer
michael@0 229 * to that data structure inside of a union. Whenever OCSP adds more
michael@0 230 * response types, just add them to the union.
michael@0 231 */
michael@0 232 struct ocspResponseBytesStr {
michael@0 233 SECItem responseType; /* an OBJECT IDENTIFIER */
michael@0 234 SECOidTag responseTypeTag; /* local; not part of encoding */
michael@0 235 SECItem response; /* an OCTET STRING */
michael@0 236 union {
michael@0 237 ocspBasicOCSPResponse *basic; /* when type is id-pkix-ocsp-basic */
michael@0 238 } decodedResponse; /* local; not part of encoding */
michael@0 239 };
michael@0 240
michael@0 241 /*
michael@0 242 * A BasicOCSPResponse -- when the responseType in a ResponseBytes is
michael@0 243 * id-pkix-ocsp-basic, the "response" OCTET STRING above is the DER
michael@0 244 * encoding of one of these.
michael@0 245 *
michael@0 246 * Note that in the OCSP specification, the signature fields are not
michael@0 247 * part of a separate sub-structure. But since they are the same fields
michael@0 248 * as we define for the signature in a request, it made sense to share
michael@0 249 * the C data structure here and in some shared code to operate on them.
michael@0 250 */
michael@0 251 struct ocspBasicOCSPResponseStr {
michael@0 252 SECItem tbsResponseDataDER;
michael@0 253 ocspResponseData *tbsResponseData; /* "tbs" == To Be Signed */
michael@0 254 ocspSignature responseSignature;
michael@0 255 };
michael@0 256
michael@0 257 /*
michael@0 258 * A ResponseData is the part of a BasicOCSPResponse that is signed
michael@0 259 * (after it is DER encoded). It contains the real details of the response
michael@0 260 * (a per-certificate status).
michael@0 261 */
michael@0 262 struct ocspResponseDataStr {
michael@0 263 SECItem version; /* an INTEGER */
michael@0 264 SECItem derResponderID;
michael@0 265 ocspResponderID *responderID; /* local; not part of encoding */
michael@0 266 SECItem producedAt; /* a GeneralizedTime */
michael@0 267 CERTOCSPSingleResponse **responses;
michael@0 268 CERTCertExtension **responseExtensions;
michael@0 269 };
michael@0 270
michael@0 271 struct ocspResponderIDStr {
michael@0 272 CERTOCSPResponderIDType responderIDType;/* local; not part of encoding */
michael@0 273 union {
michael@0 274 CERTName name; /* when ocspResponderID_byName */
michael@0 275 SECItem keyHash; /* when ocspResponderID_byKey */
michael@0 276 SECItem other; /* when ocspResponderID_other */
michael@0 277 } responderIDValue;
michael@0 278 };
michael@0 279
michael@0 280 /*
michael@0 281 * The ResponseData in a BasicOCSPResponse contains a SEQUENCE OF
michael@0 282 * SingleResponse -- one for each certificate whose status is being supplied.
michael@0 283 *
michael@0 284 * XXX figure out how to get rid of that arena -- there must be a way
michael@0 285 */
michael@0 286 struct CERTOCSPSingleResponseStr {
michael@0 287 PLArenaPool *arena; /* just a copy of the response arena,
michael@0 288 * needed here for extension handling
michael@0 289 * routines, on creation only */
michael@0 290 CERTOCSPCertID *certID;
michael@0 291 SECItem derCertStatus;
michael@0 292 ocspCertStatus *certStatus; /* local; not part of encoding */
michael@0 293 SECItem thisUpdate; /* a GeneralizedTime */
michael@0 294 SECItem *nextUpdate; /* a GeneralizedTime */
michael@0 295 CERTCertExtension **singleExtensions;
michael@0 296 };
michael@0 297
michael@0 298 /*
michael@0 299 * A CertStatus is the actual per-certificate status. Its ASN.1 definition:
michael@0 300 *
michael@0 301 * CertStatus ::= CHOICE {
michael@0 302 * good [0] IMPLICIT NULL,
michael@0 303 * revoked [1] IMPLICIT RevokedInfo,
michael@0 304 * unknown [2] IMPLICIT UnknownInfo }
michael@0 305 *
michael@0 306 * (where for now UnknownInfo is defined to be NULL but in the
michael@0 307 * future may be replaced with an enumeration).
michael@0 308 *
michael@0 309 * Because it is CHOICE, the status value and its associated information
michael@0 310 * (if any) are actually encoded together. To represent this same
michael@0 311 * information internally, we explicitly define a type and save it,
michael@0 312 * along with the value, into a data structure.
michael@0 313 */
michael@0 314
michael@0 315 typedef enum {
michael@0 316 ocspCertStatus_good, /* cert is not revoked */
michael@0 317 ocspCertStatus_revoked, /* cert is revoked */
michael@0 318 ocspCertStatus_unknown, /* cert was unknown to the responder */
michael@0 319 ocspCertStatus_other /* status was not an expected value */
michael@0 320 } ocspCertStatusType;
michael@0 321
michael@0 322 /*
michael@0 323 * This is the actual per-certificate status.
michael@0 324 *
michael@0 325 * The "goodInfo" and "unknownInfo" items are only place-holders for a NULL.
michael@0 326 * (Though someday OCSP may replace UnknownInfo with an enumeration that
michael@0 327 * gives more detailed information.)
michael@0 328 */
michael@0 329 struct ocspCertStatusStr {
michael@0 330 ocspCertStatusType certStatusType; /* local; not part of encoding */
michael@0 331 union {
michael@0 332 SECItem *goodInfo; /* when ocspCertStatus_good */
michael@0 333 ocspRevokedInfo *revokedInfo; /* when ocspCertStatus_revoked */
michael@0 334 SECItem *unknownInfo; /* when ocspCertStatus_unknown */
michael@0 335 SECItem *otherInfo; /* when ocspCertStatus_other */
michael@0 336 } certStatusInfo;
michael@0 337 };
michael@0 338
michael@0 339 /*
michael@0 340 * A RevokedInfo gives information about a revoked certificate -- when it
michael@0 341 * was revoked and why.
michael@0 342 */
michael@0 343 struct ocspRevokedInfoStr {
michael@0 344 SECItem revocationTime; /* a GeneralizedTime */
michael@0 345 SECItem *revocationReason; /* a CRLReason; ignored for now */
michael@0 346 };
michael@0 347
michael@0 348 /*
michael@0 349 * ServiceLocator can be included as one of the singleRequestExtensions.
michael@0 350 * When added, it specifies the (name of the) issuer of the cert being
michael@0 351 * checked, and optionally the value of the AuthorityInfoAccess extension
michael@0 352 * if the cert has one.
michael@0 353 */
michael@0 354 struct ocspServiceLocatorStr {
michael@0 355 CERTName *issuer;
michael@0 356 SECItem locator; /* DER encoded authInfoAccess extension from cert */
michael@0 357 };
michael@0 358
michael@0 359 #endif /* _OCSPTI_H_ */

mercurial