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
40 #include <security_asn1/secasn1.h>
41 #include <security_asn1/secerr.h>
42 #include <Security/SecIdentity.h>
45 nss_cms_recipients_traverse(SecCmsRecipientInfoRef
*recipientinfos
, SecCmsRecipient
**recipient_list
)
51 SecCmsRecipientInfoRef ri
;
52 SecCmsRecipientEncryptedKey
*rek
;
54 for (i
= 0; recipientinfos
[i
] != NULL
; i
++) {
55 ri
= recipientinfos
[i
];
56 switch (ri
->recipientInfoType
) {
57 case SecCmsRecipientInfoIDKeyTrans
:
59 /* alloc one & fill it out */
60 rle
= (SecCmsRecipient
*)PORT_ZAlloc(sizeof(SecCmsRecipient
));
66 switch (ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.identifierType
) {
67 case SecCmsRecipientIDIssuerSN
:
68 rle
->kind
= RLIssuerSN
;
69 rle
->id
.issuerAndSN
= ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.issuerAndSN
;
71 case SecCmsRecipientIDSubjectKeyID
:
72 rle
->kind
= RLSubjKeyID
;
73 rle
->id
.subjectKeyID
= ri
->ri
.keyTransRecipientInfo
.recipientIdentifier
.id
.subjectKeyID
;
76 recipient_list
[rlindex
++] = rle
;
81 case SecCmsRecipientInfoIDKeyAgree
:
82 if (ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
== NULL
)
84 for (j
=0; ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[j
] != NULL
; j
++) {
86 rek
= ri
->ri
.keyAgreeRecipientInfo
.recipientEncryptedKeys
[j
];
87 /* alloc one & fill it out */
88 rle
= (SecCmsRecipient
*)PORT_ZAlloc(sizeof(SecCmsRecipient
));
94 switch (rek
->recipientIdentifier
.identifierType
) {
95 case SecCmsKeyAgreeRecipientIDIssuerSN
:
96 rle
->kind
= RLIssuerSN
;
97 rle
->id
.issuerAndSN
= rek
->recipientIdentifier
.id
.issuerAndSN
;
99 case SecCmsKeyAgreeRecipientIDRKeyID
:
100 rle
->kind
= RLSubjKeyID
;
101 rle
->id
.subjectKeyID
= rek
->recipientIdentifier
.id
.recipientKeyIdentifier
.subjectKeyIdentifier
;
104 recipient_list
[rlindex
++] = rle
;
110 case SecCmsRecipientInfoIDKEK
:
111 /* KEK is not implemented */
115 /* if we have a recipient list, we return on success (-1, above, on failure) */
116 /* otherwise, we return the count. */
117 if (recipient_list
) {
118 recipient_list
[rlindex
] = NULL
;
126 nss_cms_recipient_list_create(SecCmsRecipientInfoRef
*recipientinfos
)
129 SecCmsRecipient
**recipient_list
;
131 /* count the number of recipient identifiers */
132 count
= nss_cms_recipients_traverse(recipientinfos
, NULL
);
133 if (count
<= 0 || count
>=(int)((INT_MAX
/sizeof(SecCmsRecipient
*))-1)) {
134 /* no recipients? or risk of underallocation 20130783 */
135 PORT_SetError(SEC_ERROR_BAD_DATA
);
137 PORT_SetErrorString("Cannot find recipient data in envelope.");
142 /* allocate an array of pointers */
143 recipient_list
= (SecCmsRecipient
**)
144 PORT_ZAlloc((count
+ 1) * sizeof(SecCmsRecipient
*));
145 if (recipient_list
== NULL
)
148 /* now fill in the recipient_list */
149 rv
= nss_cms_recipients_traverse(recipientinfos
, recipient_list
);
151 nss_cms_recipient_list_destroy(recipient_list
);
154 return recipient_list
;
158 nss_cms_recipient_list_destroy(SecCmsRecipient
**recipient_list
)
161 SecCmsRecipient
*recipient
;
163 for (i
=0; recipient_list
[i
] != NULL
; i
++) {
164 recipient
= recipient_list
[i
];
166 CFRelease(recipient
->cert
);
167 if (recipient
->privkey
)
168 CFRelease(recipient
->privkey
);
170 // @@@ Eliminate slot stuff.
172 PK11_FreeSlot(recipient
->slot
);
174 PORT_Free(recipient
);
176 PORT_Free(recipient_list
);
179 SecCmsRecipientEncryptedKey
*
180 SecCmsRecipientEncryptedKeyCreate(PLArenaPool
*poolp
)
182 return (SecCmsRecipientEncryptedKey
*)PORT_ArenaZAlloc(poolp
, sizeof(SecCmsRecipientEncryptedKey
));
187 nss_cms_FindCertAndKeyByRecipientList(SecCmsRecipient
**recipient_list
, void *wincx
)
189 SecCmsRecipient
*recipient
= NULL
;
190 SecCertificateRef cert
= NULL
;
191 SecPrivateKeyRef privKey
= NULL
;
192 SecIdentityRef identity
= NULL
;
193 CFTypeRef keychainOrArray
= NULL
; // @@@ The caller should be able to pass this in somehow.
196 for (index
= 0; recipient_list
[index
] != NULL
; ++index
)
198 recipient
= recipient_list
[index
];
200 switch (recipient
->kind
)
203 identity
= CERT_FindIdentityByIssuerAndSN(keychainOrArray
, recipient
->id
.issuerAndSN
);
206 identity
= CERT_FindIdentityBySubjectKeyID(keychainOrArray
, recipient
->id
.subjectKeyID
);
217 if (SecIdentityCopyCertificate(identity
, &cert
))
219 if (SecIdentityCopyPrivateKey(identity
, &privKey
))
223 recipient
->cert
= cert
;
224 recipient
->privkey
= privKey
;