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/
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.
12 * The Original Code is the Netscape security libraries.
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
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
37 #include "SecAsn1Item.h"
40 #include <security_asn1/secasn1.h>
41 #include <security_asn1/secerr.h>
42 #include <security_asn1/secport.h>
44 #include <Security/SecIdentity.h>
47 nss_cms_recipients_traverse(SecCmsRecipientInfoRef
*recipientinfos
, SecCmsRecipient
**recipient_list
)
53 SecCmsRecipientInfoRef ri
;
54 SecCmsRecipientEncryptedKey
*rek
;
56 for (i
= 0; recipientinfos
[i
] != NULL
; i
++) {
57 ri
= recipientinfos
[i
];
58 switch (ri
->recipientInfoType
) {
59 case SecCmsRecipientInfoIDKeyTrans
:
61 /* alloc one & fill it out */
62 rle
= (SecCmsRecipient
*)PORT_ZAlloc(sizeof(SecCmsRecipient
));
68 switch (ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.identifierType
) {
69 case SecCmsRecipientIDIssuerSN
:
70 rle
->kind
= RLIssuerSN
;
71 rle
->id
.issuerAndSN
= ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.issuerAndSN
;
73 case SecCmsRecipientIDSubjectKeyID
:
74 rle
->kind
= RLSubjKeyID
;
75 rle
->id
.subjectKeyID
= ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.subjectKeyID
;
78 recipient_list
[rlindex
++] = rle
;
83 case SecCmsRecipientInfoIDKeyAgree
:
84 if (ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
== NULL
)
86 for (j
=0; ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[j
] != NULL
; j
++) {
88 rek
= ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[j
];
89 /* alloc one & fill it out */
90 rle
= (SecCmsRecipient
*)PORT_ZAlloc(sizeof(SecCmsRecipient
));
96 switch (rek
->recipientIdentifier
.identifierType
) {
97 case SecCmsKeyAgreeRecipientIDIssuerSN
:
98 rle
->kind
= RLIssuerSN
;
99 rle
->id
.issuerAndSN
= rek
->recipientIdentifier
.id
.issuerAndSN
;
101 case SecCmsKeyAgreeRecipientIDRKeyID
:
102 rle
->kind
= RLSubjKeyID
;
103 rle
->id
.subjectKeyID
= rek
->recipientIdentifier
.id
.recipientKeyIdentifier
.subjectKeyIdentifier
;
106 recipient_list
[rlindex
++] = rle
;
112 case SecCmsRecipientInfoIDKEK
:
113 /* KEK is not implemented */
117 /* if we have a recipient list, we return on success (-1, above, on failure) */
118 /* otherwise, we return the count. */
119 if (recipient_list
) {
120 recipient_list
[rlindex
] = NULL
;
128 nss_cms_recipient_list_create(SecCmsRecipientInfoRef
*recipientinfos
)
131 SecCmsRecipient
**recipient_list
;
133 /* count the number of recipient identifiers */
134 count
= nss_cms_recipients_traverse(recipientinfos
, NULL
);
135 if (count
<= 0 || count
>=(int)((INT_MAX
/sizeof(SecCmsRecipient
*))-1)) {
136 /* no recipients? or risk of underallocation 20130783 */
137 PORT_SetError(SEC_ERROR_BAD_DATA
);
139 PORT_SetErrorString("Cannot find recipient data in envelope.");
144 /* allocate an array of pointers */
145 recipient_list
= (SecCmsRecipient
**)
146 PORT_ZAlloc((count
+ 1) * sizeof(SecCmsRecipient
*));
147 if (recipient_list
== NULL
)
150 /* now fill in the recipient_list */
151 rv
= nss_cms_recipients_traverse(recipientinfos
, recipient_list
);
153 nss_cms_recipient_list_destroy(recipient_list
);
156 return recipient_list
;
160 nss_cms_recipient_list_destroy(SecCmsRecipient
**recipient_list
)
163 SecCmsRecipient
*recipient
;
165 for (i
=0; recipient_list
[i
] != NULL
; i
++) {
166 recipient
= recipient_list
[i
];
168 CFRelease(recipient
->cert
);
169 if (recipient
->privkey
)
170 CFRelease(recipient
->privkey
);
172 // @@@ Eliminate slot stuff.
174 PK11_FreeSlot(recipient
->slot
);
176 PORT_Free(recipient
);
178 PORT_Free(recipient_list
);
181 SecCmsRecipientEncryptedKey
*
182 SecCmsRecipientEncryptedKeyCreate(PLArenaPool
*poolp
)
184 return (SecCmsRecipientEncryptedKey
*)PORT_ArenaZAlloc(poolp
, sizeof(SecCmsRecipientEncryptedKey
));
189 nss_cms_FindCertAndKeyByRecipientList(SecCmsRecipient
**recipient_list
, void *wincx
)
191 SecCmsRecipient
*recipient
= NULL
;
192 SecCertificateRef cert
= NULL
;
193 SecPrivateKeyRef privKey
= NULL
;
194 SecIdentityRef identity
= NULL
;
196 CFTypeRef keychainOrArray
= NULL
; // @@@ The caller should be able to pass this in somehow.
198 for (ix
= 0; recipient_list
[ix
] != NULL
; ++ix
)
200 recipient
= recipient_list
[ix
];
202 switch (recipient
->kind
)
205 identity
= CERT_FindIdentityByIssuerAndSN(keychainOrArray
, recipient
->id
.issuerAndSN
);
208 identity
= CERT_FindIdentityBySubjectKeyID(keychainOrArray
, recipient
->id
.subjectKeyID
);
222 if (SecIdentityCopyCertificate(identity
, &cert
))
224 if (SecIdentityCopyPrivateKey(identity
, &privKey
))
228 recipient
->cert
= cert
;
229 recipient
->privkey
= privKey
;