]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_smime/lib/cmsreclist.c
Security-57336.1.9.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 }
176 PORT_Free(recipient_list);
177 }
178
179 SecCmsRecipientEncryptedKey *
180 SecCmsRecipientEncryptedKeyCreate(PLArenaPool *poolp)
181 {
182 return (SecCmsRecipientEncryptedKey *)PORT_ArenaZAlloc(poolp, sizeof(SecCmsRecipientEncryptedKey));
183 }
184
185
186 int
187 nss_cms_FindCertAndKeyByRecipientList(SecCmsRecipient **recipient_list, void *wincx)
188 {
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.
194 int index;
195
196 for (index = 0; recipient_list[index] != NULL; ++index)
197 {
198 recipient = recipient_list[index];
199
200 switch (recipient->kind)
201 {
202 case RLIssuerSN:
203 identity = CERT_FindIdentityByIssuerAndSN(keychainOrArray, recipient->id.issuerAndSN);
204 break;
205 case RLSubjKeyID:
206 identity = CERT_FindIdentityBySubjectKeyID(keychainOrArray, recipient->id.subjectKeyID);
207 break;
208 }
209
210 if (identity)
211 break;
212 }
213
214 if (!recipient)
215 goto loser;
216
217 if (SecIdentityCopyCertificate(identity, &cert))
218 goto loser;
219 if (SecIdentityCopyPrivateKey(identity, &privKey))
220 goto loser;
221 CFRelease(identity);
222
223 recipient->cert = cert;
224 recipient->privkey = privKey;
225
226 return index;
227
228 loser:
229 if (identity)
230 CFRelease(identity);
231 if (cert)
232 CFRelease(cert);
233 if (privKey)
234 CFRelease(privKey);
235
236 return -1;
237 }