]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_smime/lib/cmsreclist.c
Security-59306.101.1.tar.gz
[apple/security.git] / OSX / libsecurity_smime / lib / cmsreclist.c
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 #include "cmslocal.h"
35
36 #include "cert.h"
37 #include "secitem.h"
38 #include "secoid.h"
39
40 #include <security_asn1/secasn1.h>
41 #include <security_asn1/secerr.h>
42 #include <Security/SecIdentity.h>
43
44 static int
45 nss_cms_recipients_traverse(SecCmsRecipientInfoRef *recipientinfos, SecCmsRecipient **recipient_list)
46 {
47 int count = 0;
48 int rlindex = 0;
49 int i, j;
50 SecCmsRecipient *rle;
51 SecCmsRecipientInfoRef ri;
52 SecCmsRecipientEncryptedKey *rek;
53
54 for (i = 0; recipientinfos[i] != NULL; i++) {
55 ri = recipientinfos[i];
56 switch (ri->recipientInfoType) {
57 case SecCmsRecipientInfoIDKeyTrans:
58 if (recipient_list) {
59 /* alloc one & fill it out */
60 rle = (SecCmsRecipient *)PORT_ZAlloc(sizeof(SecCmsRecipient));
61 if (rle == NULL)
62 return -1;
63
64 rle->riIndex = i;
65 rle->subIndex = -1;
66 switch (ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType) {
67 case SecCmsRecipientIDIssuerSN:
68 rle->kind = RLIssuerSN;
69 rle->id.issuerAndSN = ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN;
70 break;
71 case SecCmsRecipientIDSubjectKeyID:
72 rle->kind = RLSubjKeyID;
73 rle->id.subjectKeyID = ri->ri.keyTransRecipientInfo.recipientIdentifier.id.subjectKeyID;
74 break;
75 }
76 recipient_list[rlindex++] = rle;
77 } else {
78 count++;
79 }
80 break;
81 case SecCmsRecipientInfoIDKeyAgree:
82 if (ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys == NULL)
83 break;
84 for (j=0; ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[j] != NULL; j++) {
85 if (recipient_list) {
86 rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[j];
87 /* alloc one & fill it out */
88 rle = (SecCmsRecipient *)PORT_ZAlloc(sizeof(SecCmsRecipient));
89 if (rle == NULL)
90 return -1;
91
92 rle->riIndex = i;
93 rle->subIndex = j;
94 switch (rek->recipientIdentifier.identifierType) {
95 case SecCmsKeyAgreeRecipientIDIssuerSN:
96 rle->kind = RLIssuerSN;
97 rle->id.issuerAndSN = rek->recipientIdentifier.id.issuerAndSN;
98 break;
99 case SecCmsKeyAgreeRecipientIDRKeyID:
100 rle->kind = RLSubjKeyID;
101 rle->id.subjectKeyID = &rek->recipientIdentifier.id.recipientKeyIdentifier.subjectKeyIdentifier;
102 break;
103 }
104 recipient_list[rlindex++] = rle;
105 } else {
106 count++;
107 }
108 }
109 break;
110 case SecCmsRecipientInfoIDKEK:
111 /* KEK is not implemented */
112 break;
113 }
114 }
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;
119 return 0;
120 } else {
121 return count;
122 }
123 }
124
125 SecCmsRecipient **
126 nss_cms_recipient_list_create(SecCmsRecipientInfoRef *recipientinfos)
127 {
128 int count, rv;
129 SecCmsRecipient **recipient_list;
130
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);
136 #if 0
137 PORT_SetErrorString("Cannot find recipient data in envelope.");
138 #endif
139 return NULL;
140 }
141
142 /* allocate an array of pointers */
143 recipient_list = (SecCmsRecipient **)
144 PORT_ZAlloc((count + 1) * sizeof(SecCmsRecipient *));
145 if (recipient_list == NULL)
146 return NULL;
147
148 /* now fill in the recipient_list */
149 rv = nss_cms_recipients_traverse(recipientinfos, recipient_list);
150 if (rv < 0) {
151 nss_cms_recipient_list_destroy(recipient_list);
152 return NULL;
153 }
154 return recipient_list;
155 }
156
157 void
158 nss_cms_recipient_list_destroy(SecCmsRecipient **recipient_list)
159 {
160 int i;
161 SecCmsRecipient *recipient;
162
163 for (i=0; recipient_list[i] != NULL; i++) {
164 recipient = recipient_list[i];
165 if (recipient->cert)
166 CFRelease(recipient->cert);
167 if (recipient->privkey)
168 CFRelease(recipient->privkey);
169 #if 0
170 // @@@ Eliminate slot stuff.
171 if (recipient->slot)
172 PK11_FreeSlot(recipient->slot);
173 #endif
174 PORT_Free(recipient);
175 recipient_list[i] = NULL;
176 }
177 PORT_Free(recipient_list);
178 }
179
180 SecCmsRecipientEncryptedKey *
181 SecCmsRecipientEncryptedKeyCreate(PLArenaPool *poolp)
182 {
183 return (SecCmsRecipientEncryptedKey *)PORT_ArenaZAlloc(poolp, sizeof(SecCmsRecipientEncryptedKey));
184 }
185
186
187 int
188 nss_cms_FindCertAndKeyByRecipientList(SecCmsRecipient **recipient_list, void *wincx)
189 {
190 SecCmsRecipient *recipient = NULL;
191 SecCertificateRef cert = NULL;
192 SecPrivateKeyRef privKey = NULL;
193 SecIdentityRef identity = NULL;
194 CFTypeRef keychainOrArray = NULL; // @@@ The caller should be able to pass this in somehow.
195 int index;
196
197 for (index = 0; recipient_list[index] != NULL; ++index)
198 {
199 recipient = recipient_list[index];
200
201 switch (recipient->kind)
202 {
203 case RLIssuerSN:
204 identity = CERT_FindIdentityByIssuerAndSN(keychainOrArray, recipient->id.issuerAndSN);
205 break;
206 case RLSubjKeyID:
207 identity = CERT_FindIdentityBySubjectKeyID(keychainOrArray, recipient->id.subjectKeyID);
208 break;
209 }
210
211 if (identity)
212 break;
213 }
214
215 if (!recipient)
216 goto loser;
217
218 if (!identity || SecIdentityCopyCertificate(identity, &cert))
219 goto loser;
220 if (!identity || SecIdentityCopyPrivateKey(identity, &privKey))
221 goto loser;
222 CFRelease(identity);
223
224 recipient->cert = cert;
225 recipient->privkey = privKey;
226
227 return index;
228
229 loser:
230 if (identity)
231 CFRelease(identity);
232 if (cert)
233 CFRelease(cert);
234 if (privKey)
235 CFRelease(privKey);
236
237 return -1;
238 }