1/*
2 * The contents of this file are subject to the Mozilla Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/MPL/
6 *
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
11 *
12 * The Original Code is the Netscape security libraries.
13 *
14 * The Initial Developer of the Original Code is Netscape
15 * Communications Corporation.  Portions created by Netscape are
16 * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
17 * Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * Alternatively, the contents of this file may be used under the
22 * terms of the GNU General Public License Version 2 or later (the
23 * "GPL"), in which case the provisions of the GPL are applicable
24 * instead of those above.  If you wish to allow use of your
25 * version of this file only under the terms of the GPL and not to
26 * allow others to use your version of this file under the MPL,
27 * indicate your decision by deleting the provisions above and
28 * replace them with the notice and other provisions required by
29 * the GPL.  If you do not delete the provisions above, a recipient
30 * may use your version of this file under either the MPL or the
31 * GPL.
32 */
33
34/*
35 * CMS ASN.1 templates
36 */
37
38#include <Security/SecCmsContentInfo.h>
39
40#include "cmslocal.h"
41
42#include "secoid.h"
43#include <security_asn1/secasn1.h>
44#include <security_asn1/secerr.h>
45
46
47extern const SecAsn1Template nss_cms_set_of_attribute_template[];
48
49//SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate)
50//SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate)
51SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
52SEC_ASN1_MKSUB(kSecAsn1BitStringTemplate)
53SEC_ASN1_MKSUB(kSecAsn1OctetStringTemplate)
54SEC_ASN1_MKSUB(kSecAsn1PointerToOctetStringTemplate)
55SEC_ASN1_MKSUB(kSecAsn1SetOfAnyTemplate)
56
57/* -----------------------------------------------------------------------------
58 * MESSAGE
59 * (uses SecCmsContentInfo)
60 */
61
62/* forward declaration */
63static const SecAsn1Template *
64nss_cms_choose_content_template(void *src_or_dest, Boolean encoding, const char *buf, void *dest);
65
66static const SecAsn1TemplateChooserPtr nss_cms_chooser
67	= nss_cms_choose_content_template;
68
69const SecAsn1Template SecCmsMessageTemplate[] = {
70    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
71	  0, NULL, sizeof(SecCmsMessage) },
72    { SEC_ASN1_OBJECT_ID,
73	  offsetof(SecCmsMessage,contentInfo.contentType) },
74    { SEC_ASN1_OPTIONAL | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM
75     | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
76	  offsetof(SecCmsMessage,contentInfo.content),
77	  &nss_cms_chooser },
78    { 0 }
79};
80
81#if 0
82static const SecAsn1Template NSS_PointerToCMSMessageTemplate[] = {
83    { SEC_ASN1_POINTER, 0, SecCmsMessageTemplate }
84};
85#endif
86
87/* -----------------------------------------------------------------------------
88 * ENCAPSULATED & ENCRYPTED CONTENTINFO
89 * (both use a SecCmsContentInfo)
90 */
91static const SecAsn1Template SecCmsEncapsulatedContentInfoTemplate[] = {
92    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
93	  0, NULL, sizeof(SecCmsContentInfo) },
94    { SEC_ASN1_OBJECT_ID,
95	  offsetof(SecCmsContentInfo,contentType) },
96    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_MAY_STREAM |
97	SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
98	  offsetof(SecCmsContentInfo,rawContent),
99	  SEC_ASN1_SUB(kSecAsn1PointerToOctetStringTemplate) },
100    { 0 }
101};
102
103static const SecAsn1Template SecCmsEncryptedContentInfoTemplate[] = {
104    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
105	  0, NULL, sizeof(SecCmsContentInfo) },
106    { SEC_ASN1_OBJECT_ID,
107	  offsetof(SecCmsContentInfo,contentType) },
108    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
109	  offsetof(SecCmsContentInfo,contentEncAlg),
110	  SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
111    { SEC_ASN1_OPTIONAL | SEC_ASN1_POINTER | SEC_ASN1_MAY_STREAM |
112      SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
113	  offsetof(SecCmsContentInfo,rawContent),
114	  SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) },
115    { 0 }
116};
117
118/* -----------------------------------------------------------------------------
119 * SIGNED DATA
120 */
121
122const SecAsn1Template SecCmsSignerInfoTemplate[];
123
124
125const SecAsn1Template SecCmsSignedDataTemplate[] = {
126    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
127	  0, NULL, sizeof(SecCmsSignedData) },
128    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
129	  offsetof(SecCmsSignedData,version) },
130    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
131	  offsetof(SecCmsSignedData,digestAlgorithms),
132	  SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
133    { SEC_ASN1_INLINE,
134	  offsetof(SecCmsSignedData,contentInfo),
135	  SecCmsEncapsulatedContentInfoTemplate },
136    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
137      SEC_ASN1_XTRN | 0,
138	  offsetof(SecCmsSignedData,rawCerts),
139	  SEC_ASN1_SUB(kSecAsn1SetOfAnyTemplate) },
140    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
141      SEC_ASN1_XTRN | 1,
142	  offsetof(SecCmsSignedData,rawCrls),
143	  SEC_ASN1_SUB(kSecAsn1SetOfAnyTemplate) },
144    { SEC_ASN1_SET_OF,
145	  offsetof(SecCmsSignedData,signerInfos),
146	  SecCmsSignerInfoTemplate },
147    { 0 }
148};
149
150const SecAsn1Template NSS_PointerToCMSSignedDataTemplate[] = {
151    { SEC_ASN1_POINTER, 0, SecCmsSignedDataTemplate }
152};
153
154/* -----------------------------------------------------------------------------
155 * signeridentifier
156 */
157
158static const SecAsn1Template SecCmsSignerIdentifierTemplate[] = {
159    { SEC_ASN1_CHOICE,
160	  offsetof(SecCmsSignerIdentifier,identifierType), NULL,
161	  sizeof(SecCmsSignerIdentifier) },
162    { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
163	  offsetof(SecCmsSignerIdentifier,id.subjectKeyID),
164	  SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) ,
165	  SecCmsRecipientIDSubjectKeyID },
166    { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
167	  offsetof(SecCmsSignerIdentifier,id.issuerAndSN),
168	  SEC_ASN1_SUB(SecCmsIssuerAndSNTemplate),
169	  SecCmsRecipientIDIssuerSN },
170    { 0 }
171};
172
173/* -----------------------------------------------------------------------------
174 * signerinfo
175 */
176
177const SecAsn1Template SecCmsSignerInfoTemplate[] = {
178    { SEC_ASN1_SEQUENCE,
179	  0, NULL, sizeof(SecCmsSignerInfo) },
180    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
181	  offsetof(SecCmsSignerInfo,version) },
182    { SEC_ASN1_INLINE,
183	  offsetof(SecCmsSignerInfo,signerIdentifier),
184	  SecCmsSignerIdentifierTemplate },
185    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
186	  offsetof(SecCmsSignerInfo,digestAlg),
187	  SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
188    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
189	  offsetof(SecCmsSignerInfo,authAttr),
190	  nss_cms_set_of_attribute_template },
191    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
192	  offsetof(SecCmsSignerInfo,digestEncAlg),
193	  SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
194    { SEC_ASN1_OCTET_STRING,
195	  offsetof(SecCmsSignerInfo,encDigest) },
196    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
197	  offsetof(SecCmsSignerInfo,unAuthAttr),
198	  nss_cms_set_of_attribute_template },
199    { 0 }
200};
201
202/* -----------------------------------------------------------------------------
203 * ENVELOPED DATA
204 */
205
206static const SecAsn1Template SecCmsOriginatorInfoTemplate[] = {
207    { SEC_ASN1_SEQUENCE,
208	  0, NULL, sizeof(SecCmsOriginatorInfo) },
209    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
210      SEC_ASN1_XTRN | 0,
211	  offsetof(SecCmsOriginatorInfo,rawCerts),
212	  SEC_ASN1_SUB(kSecAsn1SetOfAnyTemplate) },
213    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
214      SEC_ASN1_XTRN | 1,
215	  offsetof(SecCmsOriginatorInfo,rawCrls),
216	  SEC_ASN1_SUB(kSecAsn1SetOfAnyTemplate) },
217    { 0 }
218};
219
220const SecAsn1Template SecCmsRecipientInfoTemplate[];
221
222const SecAsn1Template SecCmsEnvelopedDataTemplate[] = {
223    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
224	  0, NULL, sizeof(SecCmsEnvelopedData) },
225    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
226	  offsetof(SecCmsEnvelopedData,version) },
227    { SEC_ASN1_OPTIONAL | SEC_ASN1_POINTER | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
228	  offsetof(SecCmsEnvelopedData,originatorInfo),
229	  SecCmsOriginatorInfoTemplate },
230    { SEC_ASN1_SET_OF,
231	  offsetof(SecCmsEnvelopedData,recipientInfos),
232	  SecCmsRecipientInfoTemplate },
233    { SEC_ASN1_INLINE,
234	  offsetof(SecCmsEnvelopedData,contentInfo),
235	  SecCmsEncryptedContentInfoTemplate },
236    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
237	  offsetof(SecCmsEnvelopedData,unprotectedAttr),
238	  nss_cms_set_of_attribute_template },
239    { 0 }
240};
241
242const SecAsn1Template NSS_PointerToCMSEnvelopedDataTemplate[] = {
243    { SEC_ASN1_POINTER, 0, SecCmsEnvelopedDataTemplate }
244};
245
246/* here come the 15 gazillion templates for all the v3 varieties of RecipientInfo */
247
248/* -----------------------------------------------------------------------------
249 * key transport recipient info
250 */
251
252static const SecAsn1Template SecCmsRecipientIdentifierTemplate[] = {
253    { SEC_ASN1_CHOICE,
254	  offsetof(SecCmsRecipientIdentifier,identifierType), NULL,
255	  sizeof(SecCmsRecipientIdentifier) },
256    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
257      SEC_ASN1_XTRN | 0,
258	  offsetof(SecCmsRecipientIdentifier,id.subjectKeyID),
259	  SEC_ASN1_SUB(kSecAsn1PointerToOctetStringTemplate) ,
260	  SecCmsRecipientIDSubjectKeyID },
261    { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
262	  offsetof(SecCmsRecipientIdentifier,id.issuerAndSN),
263	  SEC_ASN1_SUB(SecCmsIssuerAndSNTemplate),
264	  SecCmsRecipientIDIssuerSN },
265    { 0 }
266};
267
268
269static const SecAsn1Template SecCmsKeyTransRecipientInfoTemplate[] = {
270    { SEC_ASN1_SEQUENCE,
271	  0, NULL, sizeof(SecCmsKeyTransRecipientInfo) },
272    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
273	  offsetof(SecCmsKeyTransRecipientInfo,version) },
274    { SEC_ASN1_INLINE,
275	  offsetof(SecCmsKeyTransRecipientInfo,recipientIdentifier),
276	  SecCmsRecipientIdentifierTemplate },
277    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
278	  offsetof(SecCmsKeyTransRecipientInfo,keyEncAlg),
279	  SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
280    { SEC_ASN1_OCTET_STRING,
281	  offsetof(SecCmsKeyTransRecipientInfo,encKey) },
282    { 0 }
283};
284
285/* -----------------------------------------------------------------------------
286 * key agreement recipient info
287 */
288
289static const SecAsn1Template SecCmsOriginatorPublicKeyTemplate[] = {
290    { SEC_ASN1_SEQUENCE,
291	  0, NULL, sizeof(SecCmsOriginatorPublicKey) },
292    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
293	  offsetof(SecCmsOriginatorPublicKey,algorithmIdentifier),
294	  SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
295    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
296	  offsetof(SecCmsOriginatorPublicKey,publicKey),
297	  SEC_ASN1_SUB(kSecAsn1BitStringTemplate) },
298    { 0 }
299};
300
301
302static const SecAsn1Template SecCmsOriginatorIdentifierOrKeyTemplate[] = {
303    { SEC_ASN1_CHOICE,
304	  offsetof(SecCmsOriginatorIdentifierOrKey,identifierType), NULL,
305	  sizeof(SecCmsOriginatorIdentifierOrKey) },
306    { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
307	  offsetof(SecCmsOriginatorIdentifierOrKey,id.issuerAndSN),
308	  SEC_ASN1_SUB(SecCmsIssuerAndSNTemplate),
309	  SecCmsOriginatorIDOrKeyIssuerSN },
310    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
311      /* this was tag 1 here, 2 for the next; RFC 3852 says they are 0 and 1 */
312      SEC_ASN1_XTRN | 0,
313	  offsetof(SecCmsOriginatorIdentifierOrKey,id.subjectKeyID),
314	  kSecAsn1OctetStringTemplate,
315	  SecCmsOriginatorIDOrKeySubjectKeyID },
316    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
317	  offsetof(SecCmsOriginatorIdentifierOrKey,id.originatorPublicKey),
318	  SecCmsOriginatorPublicKeyTemplate,
319	  SecCmsOriginatorIDOrKeyOriginatorPublicKey },
320    { 0 }
321};
322
323const SecAsn1Template SecCmsRecipientKeyIdentifierTemplate[] = {
324    { SEC_ASN1_SEQUENCE,
325	  0, NULL, sizeof(SecCmsRecipientKeyIdentifier) },
326    { SEC_ASN1_OCTET_STRING,
327	  offsetof(SecCmsRecipientKeyIdentifier,subjectKeyIdentifier) },
328    { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING,
329	  offsetof(SecCmsRecipientKeyIdentifier,date) },
330    { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING,
331	  offsetof(SecCmsRecipientKeyIdentifier,other) },
332    { 0 }
333};
334
335
336static const SecAsn1Template SecCmsKeyAgreeRecipientIdentifierTemplate[] = {
337    { SEC_ASN1_CHOICE,
338	  offsetof(SecCmsKeyAgreeRecipientIdentifier,identifierType), NULL,
339	  sizeof(SecCmsKeyAgreeRecipientIdentifier) },
340    { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
341	  offsetof(SecCmsKeyAgreeRecipientIdentifier,id.issuerAndSN),
342	  SEC_ASN1_SUB(SecCmsIssuerAndSNTemplate),
343	  SecCmsKeyAgreeRecipientIDIssuerSN },
344    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
345	  offsetof(SecCmsKeyAgreeRecipientIdentifier,id.recipientKeyIdentifier),
346	  SecCmsRecipientKeyIdentifierTemplate,
347	  SecCmsKeyAgreeRecipientIDRKeyID },
348    { 0 }
349};
350
351static const SecAsn1Template SecCmsRecipientEncryptedKeyTemplate[] = {
352    { SEC_ASN1_SEQUENCE,
353	  0, NULL, sizeof(SecCmsRecipientEncryptedKey) },
354    { SEC_ASN1_INLINE,
355	  offsetof(SecCmsRecipientEncryptedKey,recipientIdentifier),
356	  SecCmsKeyAgreeRecipientIdentifierTemplate },
357    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
358	  offsetof(SecCmsRecipientEncryptedKey,encKey),
359	  SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) },
360    { 0 }
361};
362
363static const SecAsn1Template SecCmsKeyAgreeRecipientInfoTemplate[] = {
364    { SEC_ASN1_SEQUENCE,
365	  0, NULL, sizeof(SecCmsKeyAgreeRecipientInfo) },
366    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
367	  offsetof(SecCmsKeyAgreeRecipientInfo,version) },
368    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
369	  offsetof(SecCmsKeyAgreeRecipientInfo,originatorIdentifierOrKey),
370	  SecCmsOriginatorIdentifierOrKeyTemplate },
371    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
372      SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
373	  offsetof(SecCmsKeyAgreeRecipientInfo,ukm),
374	  SEC_ASN1_SUB(kSecAsn1OctetStringTemplate) },
375    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
376	  offsetof(SecCmsKeyAgreeRecipientInfo,keyEncAlg),
377	  SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
378    { SEC_ASN1_SEQUENCE_OF,
379	  offsetof(SecCmsKeyAgreeRecipientInfo,recipientEncryptedKeys),
380	  SecCmsRecipientEncryptedKeyTemplate },
381    { 0 }
382};
383
384/* -----------------------------------------------------------------------------
385 * KEK recipient info
386 */
387
388static const SecAsn1Template SecCmsKEKIdentifierTemplate[] = {
389    { SEC_ASN1_SEQUENCE,
390	  0, NULL, sizeof(SecCmsKEKIdentifier) },
391    { SEC_ASN1_OCTET_STRING,
392	  offsetof(SecCmsKEKIdentifier,keyIdentifier) },
393    { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING,
394	  offsetof(SecCmsKEKIdentifier,date) },
395    { SEC_ASN1_OPTIONAL | SEC_ASN1_OCTET_STRING,
396	  offsetof(SecCmsKEKIdentifier,other) },
397    { 0 }
398};
399
400static const SecAsn1Template SecCmsKEKRecipientInfoTemplate[] = {
401    { SEC_ASN1_SEQUENCE,
402	  0, NULL, sizeof(SecCmsKEKRecipientInfo) },
403    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
404	  offsetof(SecCmsKEKRecipientInfo,version) },
405    { SEC_ASN1_INLINE,
406	  offsetof(SecCmsKEKRecipientInfo,kekIdentifier),
407	  SecCmsKEKIdentifierTemplate },
408    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
409	  offsetof(SecCmsKEKRecipientInfo,keyEncAlg),
410	  SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
411    { SEC_ASN1_OCTET_STRING,
412	  offsetof(SecCmsKEKRecipientInfo,encKey) },
413    { 0 }
414};
415
416/* -----------------------------------------------------------------------------
417 * recipient info
418 */
419const SecAsn1Template SecCmsRecipientInfoTemplate[] = {
420    { SEC_ASN1_CHOICE,
421	  offsetof(SecCmsRecipientInfo,recipientInfoType), NULL,
422	  sizeof(SecCmsRecipientInfo) },
423    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
424	  offsetof(SecCmsRecipientInfo,ri.keyAgreeRecipientInfo),
425	  SecCmsKeyAgreeRecipientInfoTemplate,
426	  SecCmsRecipientInfoIDKeyAgree },
427    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2,
428	  offsetof(SecCmsRecipientInfo,ri.kekRecipientInfo),
429	  SecCmsKEKRecipientInfoTemplate,
430	  SecCmsRecipientInfoIDKEK },
431    { SEC_ASN1_INLINE,
432	  offsetof(SecCmsRecipientInfo,ri.keyTransRecipientInfo),
433	  SecCmsKeyTransRecipientInfoTemplate,
434	  SecCmsRecipientInfoIDKeyTrans },
435    { 0 }
436};
437
438/* -----------------------------------------------------------------------------
439 *
440 */
441
442const SecAsn1Template SecCmsDigestedDataTemplate[] = {
443    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
444	  0, NULL, sizeof(SecCmsDigestedData) },
445    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
446	  offsetof(SecCmsDigestedData,version) },
447    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
448	  offsetof(SecCmsDigestedData,digestAlg),
449	  SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
450    { SEC_ASN1_INLINE,
451	  offsetof(SecCmsDigestedData,contentInfo),
452	  SecCmsEncapsulatedContentInfoTemplate },
453    { SEC_ASN1_OCTET_STRING,
454	  offsetof(SecCmsDigestedData,digest) },
455    { 0 }
456};
457
458const SecAsn1Template NSS_PointerToCMSDigestedDataTemplate[] = {
459    { SEC_ASN1_POINTER, 0, SecCmsDigestedDataTemplate }
460};
461
462const SecAsn1Template SecCmsEncryptedDataTemplate[] = {
463    { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM,
464	  0, NULL, sizeof(SecCmsEncryptedData) },
465    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
466	  offsetof(SecCmsEncryptedData,version) },
467    { SEC_ASN1_INLINE,
468	  offsetof(SecCmsEncryptedData,contentInfo),
469	  SecCmsEncryptedContentInfoTemplate },
470    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
471	  offsetof(SecCmsEncryptedData,unprotectedAttr),
472	  nss_cms_set_of_attribute_template },
473    { 0 }
474};
475
476const SecAsn1Template NSS_PointerToCMSEncryptedDataTemplate[] = {
477    { SEC_ASN1_POINTER, 0, SecCmsEncryptedDataTemplate }
478};
479
480/* -----------------------------------------------------------------------------
481 * SetOfSignedCrlTemplate
482 */
483const SecAsn1Template SecCmsIssuerAndSNTemplate[] = {
484    { SEC_ASN1_SEQUENCE,
485          0, NULL, sizeof(SecCmsIssuerAndSN) },
486#if 1 // @@@ Switch to using NSS_NameTemplate
487    { SEC_ASN1_ANY,
488          offsetof(SecCmsIssuerAndSN,derIssuer) },
489#else
490    { SEC_ASN1_INLINE,
491	  offsetof(SecCmsIssuerAndSN,issuer),
492	  NSS_NameTemplate },
493#endif
494    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
495          offsetof(SecCmsIssuerAndSN,serialNumber) },
496    { 0 }
497};
498
499
500/* -----------------------------------------------------------------------------
501 * FORTEZZA KEA
502 */
503const SecAsn1Template NSS_SMIMEKEAParamTemplateSkipjack[] = {
504	{ SEC_ASN1_SEQUENCE,
505	  0, NULL, sizeof(SecCmsSMIMEKEAParameters) },
506	{ SEC_ASN1_OCTET_STRING /* | SEC_ASN1_OPTIONAL */,
507	  offsetof(SecCmsSMIMEKEAParameters,originatorKEAKey) },
508	{ SEC_ASN1_OCTET_STRING,
509	  offsetof(SecCmsSMIMEKEAParameters,originatorRA) },
510	{ 0 }
511};
512
513const SecAsn1Template NSS_SMIMEKEAParamTemplateNoSkipjack[] = {
514	{ SEC_ASN1_SEQUENCE,
515	  0, NULL, sizeof(SecCmsSMIMEKEAParameters) },
516	{ SEC_ASN1_OCTET_STRING /* | SEC_ASN1_OPTIONAL */,
517	  offsetof(SecCmsSMIMEKEAParameters,originatorKEAKey) },
518	{ SEC_ASN1_OCTET_STRING,
519	  offsetof(SecCmsSMIMEKEAParameters,originatorRA) },
520	{ SEC_ASN1_OCTET_STRING  | SEC_ASN1_OPTIONAL ,
521	  offsetof(SecCmsSMIMEKEAParameters,nonSkipjackIV) },
522	{ 0 }
523};
524
525const SecAsn1Template NSS_SMIMEKEAParamTemplateAllParams[] = {
526	{ SEC_ASN1_SEQUENCE,
527	  0, NULL, sizeof(SecCmsSMIMEKEAParameters) },
528	{ SEC_ASN1_OCTET_STRING /* | SEC_ASN1_OPTIONAL */,
529	  offsetof(SecCmsSMIMEKEAParameters,originatorKEAKey) },
530	{ SEC_ASN1_OCTET_STRING,
531	  offsetof(SecCmsSMIMEKEAParameters,originatorRA) },
532	{ SEC_ASN1_OCTET_STRING  | SEC_ASN1_OPTIONAL ,
533	  offsetof(SecCmsSMIMEKEAParameters,nonSkipjackIV) },
534	{ SEC_ASN1_OCTET_STRING  | SEC_ASN1_OPTIONAL ,
535	  offsetof(SecCmsSMIMEKEAParameters,bulkKeySize) },
536	{ 0 }
537};
538
539/*TODO: this should be in some header */
540const SecAsn1Template *
541nss_cms_get_kea_template(SecCmsKEATemplateSelector whichTemplate);
542const SecAsn1Template *
543nss_cms_get_kea_template(SecCmsKEATemplateSelector whichTemplate)
544{
545	const SecAsn1Template *returnVal = NULL;
546
547	switch(whichTemplate)
548	{
549	case SecCmsKEAUsesNonSkipjack:
550		returnVal = NSS_SMIMEKEAParamTemplateNoSkipjack;
551		break;
552	case SecCmsKEAUsesSkipjack:
553		returnVal = NSS_SMIMEKEAParamTemplateSkipjack;
554		break;
555	case SecCmsKEAUsesNonSkipjackWithPaddedEncKey:
556	default:
557		returnVal = NSS_SMIMEKEAParamTemplateAllParams;
558		break;
559	}
560	return returnVal;
561}
562
563/* -----------------------------------------------------------------------------
564 *
565 */
566static const SecAsn1Template *
567nss_cms_choose_content_template(void *src_or_dest, Boolean encoding, const char *buf, void *dest)
568{
569    const SecAsn1Template *theTemplate;
570    SecCmsContentInfoRef cinfo;
571
572    PORT_Assert (src_or_dest != NULL);
573    if (src_or_dest == NULL)
574	return NULL;
575
576    cinfo = (SecCmsContentInfoRef)src_or_dest;
577    switch (SecCmsContentInfoGetContentTypeTag(cinfo)) {
578    default:
579	theTemplate = SEC_ASN1_GET(kSecAsn1PointerToAnyTemplate);
580	break;
581    case SEC_OID_PKCS7_DATA:
582    case SEC_OID_OTHER:
583	theTemplate = SEC_ASN1_GET(kSecAsn1PointerToOctetStringTemplate);
584	break;
585    case SEC_OID_PKCS7_SIGNED_DATA:
586	theTemplate = NSS_PointerToCMSSignedDataTemplate;
587	break;
588    case SEC_OID_PKCS7_ENVELOPED_DATA:
589	theTemplate = NSS_PointerToCMSEnvelopedDataTemplate;
590	break;
591    case SEC_OID_PKCS7_DIGESTED_DATA:
592	theTemplate = NSS_PointerToCMSDigestedDataTemplate;
593	break;
594    case SEC_OID_PKCS7_ENCRYPTED_DATA:
595	theTemplate = NSS_PointerToCMSEncryptedDataTemplate;
596	break;
597    }
598    return theTemplate;
599}
600