1/*
2 * Copyright (c) 2003-2004,2011,2013-2014 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/*
24 * pkcs12Templates.cpp
25 */
26
27#include "pkcs12Templates.h"
28#include "pkcs12Utils.h"
29#include <security_asn1/nssUtils.h>
30#include <Security/SecAsn1Templates.h>
31#include <Security/oidsattr.h>
32
33#pragma clang diagnostic push
34#pragma clang diagnostic ignored "-Wunused-const-variable"
35
36
37const SecAsn1Template NSS_P12_MacDataTemplate[] = {
38    { SEC_ASN1_SEQUENCE,
39      0, NULL, sizeof(NSS_P12_MacData) },
40	{ SEC_ASN1_INLINE,
41	  offsetof(NSS_P12_MacData,mac),
42	  NSS_P7_DigestInfoTemplate },
43    { SEC_ASN1_OCTET_STRING,
44	  offsetof(NSS_P12_MacData,macSalt) },
45	/* iterations is unsigned - right? */
46	{ SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL,
47	  offsetof(NSS_P12_MacData,iterations) },
48    { 0, }
49};
50
51const SecAsn1Template pointerToMacDataTemplate[] = {
52    { SEC_ASN1_POINTER, 0, NSS_P12_MacDataTemplate }
53};
54
55/* raw PFX with unprocessed authSafe */
56const SecAsn1Template NSS_P12_RawPFXTemplate[] = {
57    { SEC_ASN1_SEQUENCE,
58      0, NULL, sizeof(NSS_P12_RawPFX) },
59	{ SEC_ASN1_INTEGER,
60	  offsetof(NSS_P12_RawPFX,version) },
61	{ SEC_ASN1_INLINE,
62	  offsetof(NSS_P12_RawPFX, authSafe),
63	  NSS_P7_RawContentInfoTemplate },
64	{ SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL,
65	  offsetof(NSS_P12_RawPFX, macData),
66	  NSS_P12_MacDataTemplate },
67    { 0, }
68};
69
70/* PFX with decoded authSafe */
71extern const SecAsn1Template NSS_P12_DecodedPFXTemplate[] = {
72    { SEC_ASN1_SEQUENCE,
73      0, NULL, sizeof(NSS_P12_DecodedPFX) },
74	{ SEC_ASN1_INTEGER,
75	  offsetof(NSS_P12_DecodedPFX,version) },
76	{ SEC_ASN1_INLINE,
77	  offsetof(NSS_P12_DecodedPFX, authSafe),
78	  NSS_P7_DecodedContentInfoTemplate },
79	{ SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL,
80	  offsetof(NSS_P12_DecodedPFX, macData),
81	  NSS_P12_MacDataTemplate },
82    { 0, }
83};
84
85/* AuthenticatedSafe */
86const SecAsn1Template NSS_P12_AuthenticatedSafeTemplate[] = {
87	{ SEC_ASN1_SEQUENCE_OF,
88	  offsetof(NSS_P12_AuthenticatedSafe, info),
89	  NSS_P7_DecodedContentInfoTemplate,
90	  sizeof(NSS_P12_AuthenticatedSafe) }
91};
92
93/*
94 * Individual SafeBag type-specific templates here when we write 'em
95 */
96const SecAsn1Template NSS_P12_PtrToShroudedKeyBagTemplate[] = {
97	{ SEC_ASN1_POINTER, 0, kSecAsn1EncryptedPrivateKeyInfoTemplate }
98};
99
100/*
101 * CertBag via SEC_ASN1_DYNAMIC
102 */
103static const SecAsn1Template * NSS_P12_CertBagChooser(
104	void *arg, 			// --> NSS_P12_CertBag
105	Boolean enc,
106	const char *buf,	// on decode, tag byte
107	void *dest)			// --> NSS_P12_CertBag.bagValue
108{
109	NSS_P12_CertBag *bag = (NSS_P12_CertBag *)arg;
110	const SecAsn1Template *templ = NULL;
111	NSS_P12_CertBagType type = CT_Unknown;
112	CSSM_OID *oid = &bag->bagType;
113
114	if(nssCompareCssmData(oid, &CSSMOID_PKCS9_X509Certificate)) {
115		templ = kSecAsn1OctetStringTemplate;
116		type = CT_X509;
117	}
118	else if(nssCompareCssmData(oid, &CSSMOID_PKCS9_SdsiCertificate)) {
119		templ = kSecAsn1IA5StringTemplate;
120		type = CT_SDSI;
121	}
122	else {
123		/* punt */
124		templ = kSecAsn1AnyTemplate;
125	}
126	if(!enc) {
127		bag->type = type;
128	}
129	return templ;
130}
131
132static const SecAsn1TemplateChooserPtr NSS_P12_CertBagChooserPtr =
133	NSS_P12_CertBagChooser;
134
135const SecAsn1Template NSS_P12_CertBagTemplate[] = {
136    { SEC_ASN1_SEQUENCE,
137      0, NULL, sizeof(NSS_P12_CertBag) },
138	{ SEC_ASN1_OBJECT_ID,
139	  offsetof(NSS_P12_CertBag,bagType) },
140	  /* these come in with a tag of 0xA0, context/constructed,
141	   * though I don't know why they are flagged as constructed */
142	{ SEC_ASN1_DYNAMIC | SEC_ASN1_CONTEXT_SPECIFIC |
143	  SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | 0,
144	  offsetof(NSS_P12_CertBag, certValue),
145	  &NSS_P12_CertBagChooserPtr },
146    { 0, }
147};
148
149const SecAsn1Template NSS_P12_PtrToCertBagTemplate[] = {
150	{ SEC_ASN1_POINTER, 0, NSS_P12_CertBagTemplate }
151};
152
153/*
154 * CrlBag via SEC_ASN1_DYNAMIC
155 */
156static const SecAsn1Template * NSS_P12_CrlBagChooser(
157	void *arg, 			// --> NSS_P12_CrlBag
158	Boolean enc,
159	const char *buf,	// on decode, tag byte
160	void *dest)			// --> NSS_P12_CertBag.bagValue
161{
162	NSS_P12_CrlBag *bag = (NSS_P12_CrlBag *)arg;
163	const SecAsn1Template *templ = NULL;
164	NSS_P12_CrlBagType type = CRT_Unknown;
165	CSSM_OID *oid = &bag->bagType;
166
167	if(nssCompareCssmData(oid, &CSSMOID_PKCS9_X509Crl)) {
168		templ = kSecAsn1OctetStringTemplate;
169		type = CRT_X509;
170	}
171	else {
172		/* punt */
173		templ = kSecAsn1AnyTemplate;
174	}
175	if(!enc) {
176		bag->type = type;
177	}
178	return templ;
179}
180
181static const SecAsn1TemplateChooserPtr NSS_P12_CrlBagChooserPtr =
182	NSS_P12_CrlBagChooser;
183
184const SecAsn1Template NSS_P12_CrlBagTemplate[] = {
185    { SEC_ASN1_SEQUENCE,
186      0, NULL, sizeof(NSS_P12_CrlBag) },
187	{ SEC_ASN1_OBJECT_ID,
188	  offsetof(NSS_P12_CrlBag,bagType) },
189	  /* these come in with a tag of 0xA0, context/constructed,
190	   * though I don't know why they are flagged as constructed */
191	{ SEC_ASN1_DYNAMIC | SEC_ASN1_CONTEXT_SPECIFIC |
192	  SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | 0,
193	  offsetof(NSS_P12_CrlBag, crlValue),
194	  &NSS_P12_CrlBagChooserPtr },
195    { 0, }
196};
197
198const SecAsn1Template NSS_P12_PtrToCrlBagTemplate[] = {
199	{ SEC_ASN1_POINTER, 0, NSS_P12_CrlBagTemplate }
200};
201
202
203/* the stub templates for unimplemented BagTypes */
204#define NSS_P12_PtrToKeyBagTemplate				kSecAsn1PointerToAnyTemplate
205#define NSS_P12_PtrToSecretBagTemplate			kSecAsn1PointerToAnyTemplate
206#define NSS_P12_PtrToSafeContentsBagTemplate	kSecAsn1PointerToAnyTemplate
207
208
209/*
210 * SafeBag via SEC_ASN1_DYNAMIC
211 */
212static const SecAsn1Template * NSS_P12_SafeBagChooser(
213	void *arg, 			// --> NSS_P12_SafeBag
214	Boolean enc,
215	const char *buf,	// on decode, tag byte
216	void *dest)			// --> NSS_P12_SafeBag.bagValue
217{
218	NSS_P12_SafeBag *bag = (NSS_P12_SafeBag *)arg;
219	const SecAsn1Template *templ = NULL;
220	NSS_P12_SB_Type type = BT_None;
221	CSSM_OID *oid = &bag->bagId;
222
223	if(nssCompareCssmData(oid, &CSSMOID_PKCS12_keyBag)) {
224		templ = NSS_P12_PtrToKeyBagTemplate;
225		type = BT_KeyBag;
226	}
227	else if(nssCompareCssmData(oid, &CSSMOID_PKCS12_shroudedKeyBag)) {
228		templ = NSS_P12_PtrToShroudedKeyBagTemplate;
229		type = BT_ShroudedKeyBag;
230	}
231	else if(nssCompareCssmData(oid, &CSSMOID_PKCS12_certBag)) {
232		templ = NSS_P12_PtrToCertBagTemplate;
233		type = BT_CertBag;
234	}
235	else if(nssCompareCssmData(oid, &CSSMOID_PKCS12_crlBag)) {
236		templ = NSS_P12_PtrToCrlBagTemplate;
237		type = BT_CrlBag;
238	}
239	else if(nssCompareCssmData(oid, &CSSMOID_PKCS12_secretBag)) {
240		templ = NSS_P12_PtrToSecretBagTemplate;
241		type = BT_SecretBag;
242	}
243	else if(nssCompareCssmData(oid, &CSSMOID_PKCS12_safeContentsBag)) {
244		templ = NSS_P12_PtrToSafeContentsBagTemplate;
245		type = BT_SafeContentsBag;
246	}
247	/* add more here when we implement them */
248	else {
249		templ = kSecAsn1PointerToAnyTemplate;
250	}
251	if(!enc) {
252		bag->type = type;
253	}
254	return templ;
255}
256
257static const SecAsn1TemplateChooserPtr NSS_P12_SafeBagChooserPtr =
258	NSS_P12_SafeBagChooser;
259
260const SecAsn1Template NSS_P12_SafeBagTemplate[] = {
261    { SEC_ASN1_SEQUENCE,
262      0, NULL, sizeof(NSS_P12_SafeBag) },
263    { SEC_ASN1_OBJECT_ID,
264	  offsetof(NSS_P12_SafeBag,bagId) },
265    { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED |
266		SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0,
267	  offsetof(NSS_P12_SafeBag,bagValue),
268	  &NSS_P12_SafeBagChooserPtr },
269    { SEC_ASN1_OPTIONAL | SEC_ASN1_SET_OF,
270        offsetof(NSS_P12_SafeBag,bagAttrs),
271        kSecAsn1AttributeTemplate },
272   { 0 }
273};
274
275const SecAsn1Template NSS_P12_SafeContentsTemplate[] = {
276	{ SEC_ASN1_SEQUENCE_OF,
277	  offsetof(NSS_P12_SafeContents, bags),
278	  NSS_P12_SafeBagTemplate,
279	  sizeof(NSS_P12_SafeContents) }
280};
281
282const SecAsn1Template NSS_P12_PBE_ParamsTemplate[] = {
283	{ SEC_ASN1_SEQUENCE,
284      0, NULL, sizeof(NSS_P12_PBE_Params) },
285    { SEC_ASN1_OCTET_STRING,
286	  offsetof(NSS_P12_PBE_Params,salt) },
287	/* iterations is unsigned - right? */
288	{ SEC_ASN1_INTEGER,
289	  offsetof(NSS_P12_PBE_Params,iterations) },
290	{ 0 }
291};
292
293#pragma clang diagnostic pop
294