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