1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
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_ */
|