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 44static int 45nss_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 125SecCmsRecipient ** 126nss_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) { 134 /* no recipients? */ 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 157void 158nss_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 179SecCmsRecipientEncryptedKey * 180SecCmsRecipientEncryptedKeyCreate(PLArenaPool *poolp) 181{ 182 return (SecCmsRecipientEncryptedKey *)PORT_ArenaZAlloc(poolp, sizeof(SecCmsRecipientEncryptedKey)); 183} 184 185 186int 187nss_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 228loser: 229 if (identity) 230 CFRelease(identity); 231 if (cert) 232 CFRelease(cert); 233 if (privKey) 234 CFRelease(privKey); 235 236 return -1; 237} 238