1/*
2 * Copyright (c) 2003-2006,2008-2010 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 *
23 * ocspTemplates.cpp -  ASN1 templates OCSP requests and responses.
24 */
25
26#include "ocspTemplates.h"
27#include "keyTemplates.h"		/* for kSecAsn1AlgorithmIDTemplate */
28#include "SecAsn1Templates.h"
29#include <stddef.h>
30#include <assert.h>
31
32// MARK: ----- OCSP Request -----
33
34const SecAsn1Template kSecAsn1OCSPCertIDTemplate[] = {
35    { SEC_ASN1_SEQUENCE,
36	  0, NULL, sizeof(SecAsn1OCSPCertID) },
37    { SEC_ASN1_INLINE,
38	  offsetof(SecAsn1OCSPCertID, algId),
39	  kSecAsn1AlgorithmIDTemplate },
40    { SEC_ASN1_OCTET_STRING, offsetof(SecAsn1OCSPCertID, issuerNameHash) },
41    { SEC_ASN1_OCTET_STRING, offsetof(SecAsn1OCSPCertID, issuerPubKeyHash) },
42	/* serial number is SIGNED integer */
43    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
44	  offsetof(SecAsn1OCSPCertID, serialNumber) },
45    { 0 }
46};
47
48const SecAsn1Template kSecAsn1OCSPRequestTemplate[] = {
49    { SEC_ASN1_SEQUENCE,
50	  0, NULL, sizeof(SecAsn1OCSPRequest) },
51    { SEC_ASN1_INLINE,
52	  offsetof(SecAsn1OCSPRequest, reqCert),
53	  kSecAsn1OCSPCertIDTemplate },
54    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
55			SEC_ASN1_EXPLICIT | 0,
56	  offsetof(SecAsn1OCSPRequest, extensions),
57	  kSecAsn1SequenceOfCertExtensionTemplate },
58    { 0 }
59};
60
61const SecAsn1Template kSecAsn1OCSPSignatureTemplate[] = {
62    { SEC_ASN1_SEQUENCE,
63	  0, NULL, sizeof(SecAsn1OCSPSignature) },
64    { SEC_ASN1_INLINE,
65	  offsetof(SecAsn1OCSPSignature, algId),
66	  kSecAsn1AlgorithmIDTemplate },
67    { SEC_ASN1_BIT_STRING, offsetof(SecAsn1OCSPSignature, sig) },
68    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
69			SEC_ASN1_EXPLICIT | 0,
70	  offsetof(SecAsn1OCSPSignature, certs),
71	  kSecAsn1SequenceOfAnyTemplate },
72    { 0 }
73};
74
75const SecAsn1Template kSecAsn1OCSPTbsRequestTemplate[] = {
76    { SEC_ASN1_SEQUENCE,
77	  0, NULL, sizeof(SecAsn1OCSPTbsRequest) },
78	/* optional version, explicit tag 0, default 0 */
79    { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
80	  SEC_ASN1_CONTEXT_SPECIFIC | 0,
81	  offsetof(SecAsn1OCSPTbsRequest, version),
82	  kSecAsn1PointerToIntegerTemplate },
83    { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
84	  SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 1,
85	  offsetof(SecAsn1OCSPTbsRequest, requestorName),
86	  kSecAsn1GeneralNameTemplate },
87	{ SEC_ASN1_SEQUENCE_OF,
88	  offsetof(SecAsn1OCSPTbsRequest, requestList),
89	  kSecAsn1OCSPRequestTemplate },
90    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
91			SEC_ASN1_EXPLICIT | 2,
92	  offsetof(SecAsn1OCSPTbsRequest, requestExtensions),
93	  kSecAsn1SequenceOfCertExtensionTemplate },
94    { 0 }
95};
96
97const SecAsn1Template kSecAsn1OCSPSignedRequestTemplate[] = {
98    { SEC_ASN1_SEQUENCE,
99	  0, NULL, sizeof(SecAsn1OCSPSignedRequest) },
100    { SEC_ASN1_INLINE,
101	  offsetof(SecAsn1OCSPSignedRequest, tbsRequest),
102	  kSecAsn1OCSPTbsRequestTemplate },
103	{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
104			SEC_ASN1_POINTER | SEC_ASN1_EXPLICIT | 0,
105	  offsetof(SecAsn1OCSPSignedRequest, signature),
106	  kSecAsn1OCSPSignatureTemplate },
107    { 0 }
108};
109
110// MARK: ----- OCSP Response -----
111
112const SecAsn1Template kSecAsn1OCSPRevokedInfoTemplate[] = {
113    { SEC_ASN1_SEQUENCE,
114	  0, NULL, sizeof(SecAsn1OCSPRevokedInfo) },
115	{ SEC_ASN1_GENERALIZED_TIME, offsetof(SecAsn1OCSPRevokedInfo, revocationTime) },
116    { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
117	  SEC_ASN1_CONTEXT_SPECIFIC | 0,
118	  offsetof(SecAsn1OCSPRevokedInfo, revocationReason) ,
119	  kSecAsn1PointerToEnumeratedTemplate },
120    { 0 }
121};
122
123/* three context-specific templates, app picks one of these */
124
125/*
126 * Encode/decode CertStatus separately using one of these †hree templates.
127 * The result goes into SecAsn1OCSPSingleResponse.certStatus on encode.
128 */
129const SecAsn1Template kSecAsn1OCSPCertStatusGoodTemplate[] = {
130	{ SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 0,
131	  offsetof(SecAsn1OCSPCertStatus, nullData),
132	  kSecAsn1NullTemplate }
133};
134
135const SecAsn1Template kSecAsn1OCSPCertStatusRevokedTemplate[] = {
136	{ SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 1,
137	  offsetof(SecAsn1OCSPCertStatus, revokedInfo) ,
138	  kSecAsn1OCSPRevokedInfoTemplate }
139};
140
141const SecAsn1Template kSecAsn1OCSPCertStatusUnknownTemplate[] = {
142	{ SEC_ASN1_CONTEXT_SPECIFIC | 2,
143	  offsetof(SecAsn1OCSPCertStatus, nullData),
144	  kSecAsn1NullTemplate }
145};
146
147const SecAsn1Template kSecAsn1OCSPSingleResponseTemplate[] = {
148    { SEC_ASN1_SEQUENCE,
149	  0, NULL, sizeof(SecAsn1OCSPSingleResponse) },
150    { SEC_ASN1_INLINE,
151	  offsetof(SecAsn1OCSPSingleResponse, certID),
152	  kSecAsn1OCSPCertIDTemplate },
153    { SEC_ASN1_ANY,
154	  offsetof(SecAsn1OCSPSingleResponse, certStatus),
155	  kSecAsn1AnyTemplate },
156	{ SEC_ASN1_GENERALIZED_TIME, offsetof(SecAsn1OCSPSingleResponse, thisUpdate) },
157    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
158	  SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT | 0,
159	  offsetof(SecAsn1OCSPSingleResponse, nextUpdate),
160	  kSecAsn1PointerToGeneralizedTimeTemplate },
161    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
162	  SEC_ASN1_EXPLICIT | 1,
163	  offsetof(SecAsn1OCSPSingleResponse, singleExtensions),
164	  kSecAsn1SequenceOfCertExtensionTemplate },
165    { 0 }
166};
167
168/*
169 * support for ResponderID CHOICE
170 */
171const SecAsn1Template kSecAsn1OCSPResponderIDAsNameTemplate[] = {
172    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
173	offsetof(SecAsn1OCSPResponderID, byName),
174	kSecAsn1AnyTemplate }
175};
176
177const SecAsn1Template kSecAsn1OCSPResponderIDAsKeyTemplate[] = {
178    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2,
179	offsetof(SecAsn1OCSPResponderID, byKey),
180	kSecAsn1OctetStringTemplate }
181};
182
183const SecAsn1Template kSecAsn1OCSPResponseDataTemplate[] = {
184    { SEC_ASN1_SEQUENCE,
185	  0, NULL, sizeof(SecAsn1OCSPResponseData) },
186	/* optional version, explicit tag 0, default 0 */
187    { SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
188	  SEC_ASN1_CONTEXT_SPECIFIC | 0,
189	  offsetof(SecAsn1OCSPResponseData, version),
190	  kSecAsn1PointerToIntegerTemplate },
191	{ SEC_ASN1_ANY,
192	  offsetof(SecAsn1OCSPResponseData, responderID),
193	  kSecAsn1AnyTemplate },
194	{ SEC_ASN1_GENERALIZED_TIME, offsetof(SecAsn1OCSPResponseData, producedAt) },
195    { SEC_ASN1_SEQUENCE_OF,
196	  offsetof(SecAsn1OCSPResponseData, responses),
197	  kSecAsn1OCSPSingleResponseTemplate },
198    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
199			SEC_ASN1_EXPLICIT | 1,
200	  offsetof(SecAsn1OCSPResponseData, responseExtensions),
201	  kSecAsn1SequenceOfCertExtensionTemplate },
202    { 0 }
203};
204
205const SecAsn1Template kSecAsn1OCSPBasicResponseTemplate[] = {
206    { SEC_ASN1_SEQUENCE,
207	  0, NULL, sizeof(SecAsn1OCSPBasicResponse) },
208    { SEC_ASN1_ANY,  offsetof(SecAsn1OCSPBasicResponse, tbsResponseData) },
209    { SEC_ASN1_INLINE,
210	  offsetof(SecAsn1OCSPBasicResponse, algId),
211	  kSecAsn1AlgorithmIDTemplate },
212    { SEC_ASN1_BIT_STRING, offsetof(SecAsn1OCSPBasicResponse, sig) },
213    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
214			SEC_ASN1_EXPLICIT | 0,
215	  offsetof(SecAsn1OCSPBasicResponse, certs),
216	  kSecAsn1SequenceOfAnyTemplate },
217    { 0 }
218};
219
220const SecAsn1Template kSecAsn1OCSPResponseBytesTemplate[] = {
221    { SEC_ASN1_SEQUENCE,
222	  0, NULL, sizeof(SecAsn1OCSPResponseBytes) },
223	{ SEC_ASN1_OBJECT_ID, offsetof(SecAsn1OCSPResponseBytes, responseType) },
224	{ SEC_ASN1_OCTET_STRING, offsetof(SecAsn1OCSPResponseBytes, response) },
225    { 0 }
226};
227
228const SecAsn1Template kSecAsn1OCSPPtrToResponseBytesTemplate[] = {
229	{ SEC_ASN1_POINTER, 0, kSecAsn1OCSPResponseBytesTemplate }
230};
231
232const SecAsn1Template kSecAsn1OCSPResponseTemplate[] = {
233    { SEC_ASN1_SEQUENCE,
234	  0, NULL, sizeof(SecAsn1OCSPResponse) },
235	{ SEC_ASN1_ENUMERATED, offsetof(SecAsn1OCSPResponse, responseStatus) },
236    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
237			SEC_ASN1_EXPLICIT | 0,
238	  offsetof(SecAsn1OCSPResponse, responseBytes),
239	  kSecAsn1OCSPPtrToResponseBytesTemplate },
240    { 0 }
241};
242
243// MARK: ---- OCSPD RPC ----
244
245const SecAsn1Template kSecAsn1OCSPDRequestTemplate[] = {
246    { SEC_ASN1_SEQUENCE,
247	  0, NULL, sizeof(SecAsn1OCSPDRequest) },
248    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
249			SEC_ASN1_EXPLICIT | 0,
250	  offsetof(SecAsn1OCSPDRequest, cacheWriteDisable),
251	  kSecAsn1PointerToBooleanTemplate },
252    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
253			SEC_ASN1_EXPLICIT | 1,
254	  offsetof(SecAsn1OCSPDRequest, cacheReadDisable),
255	  kSecAsn1PointerToBooleanTemplate },
256    { SEC_ASN1_OCTET_STRING,  offsetof(SecAsn1OCSPDRequest, certID) },
257    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
258			SEC_ASN1_EXPLICIT | 2,
259	  offsetof(SecAsn1OCSPDRequest, ocspReq),
260	  kSecAsn1PointerToOctetStringTemplate },
261    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
262			SEC_ASN1_EXPLICIT | 3,
263	  offsetof(SecAsn1OCSPDRequest, localRespURI),
264	  kSecAsn1PointerToIA5StringTemplate },
265    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
266			SEC_ASN1_EXPLICIT | 4,
267	  offsetof(SecAsn1OCSPDRequest, urls),
268	  kSecAsn1SequenceOfIA5StringTemplate },
269    { 0 }
270};
271
272const SecAsn1Template kSecAsn1OCSPDRequestsTemplate[] = {
273    { SEC_ASN1_SEQUENCE,
274	  0, NULL, sizeof(SecAsn1OCSPDRequests) },
275	{ SEC_ASN1_INTEGER, offsetof(SecAsn1OCSPDRequests, version) },
276    { SEC_ASN1_SEQUENCE_OF,
277	  offsetof(SecAsn1OCSPDRequests, requests),
278	  kSecAsn1OCSPDRequestTemplate },
279    { 0 }
280};
281
282const SecAsn1Template kSecAsn1OCSPDReplyTemplate[] = {
283    { SEC_ASN1_SEQUENCE,
284	  0, NULL, sizeof(SecAsn1OCSPDReply) },
285	{ SEC_ASN1_ANY, offsetof(SecAsn1OCSPDReply, certID) },
286	{ SEC_ASN1_ANY, offsetof(SecAsn1OCSPDReply, ocspResp) },
287    { 0 }
288};
289
290const SecAsn1Template kSecAsn1OCSPDRepliesTemplate[] = {
291    { SEC_ASN1_SEQUENCE,
292	  0, NULL, sizeof(SecAsn1OCSPReplies) },
293	{ SEC_ASN1_INTEGER, offsetof(SecAsn1OCSPReplies, version) },
294    { SEC_ASN1_SEQUENCE_OF,
295	  offsetof(SecAsn1OCSPReplies, replies),
296	  kSecAsn1OCSPDReplyTemplate },
297    { 0 }
298};
299