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