|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 /* |
|
6 * CMS recipient list functions |
|
7 */ |
|
8 |
|
9 #include "cmslocal.h" |
|
10 |
|
11 #include "cert.h" |
|
12 #include "key.h" |
|
13 #include "secasn1.h" |
|
14 #include "secitem.h" |
|
15 #include "secoid.h" |
|
16 #include "pk11func.h" |
|
17 #include "prtime.h" |
|
18 #include "secerr.h" |
|
19 |
|
20 static int |
|
21 nss_cms_recipients_traverse(NSSCMSRecipientInfo **recipientinfos, NSSCMSRecipient **recipient_list) |
|
22 { |
|
23 int count = 0; |
|
24 int rlindex = 0; |
|
25 int i, j; |
|
26 NSSCMSRecipient *rle; |
|
27 NSSCMSRecipientInfo *ri; |
|
28 NSSCMSRecipientEncryptedKey *rek; |
|
29 |
|
30 for (i = 0; recipientinfos[i] != NULL; i++) { |
|
31 ri = recipientinfos[i]; |
|
32 switch (ri->recipientInfoType) { |
|
33 case NSSCMSRecipientInfoID_KeyTrans: |
|
34 if (recipient_list) { |
|
35 NSSCMSRecipientIdentifier *recipId = |
|
36 &ri->ri.keyTransRecipientInfo.recipientIdentifier; |
|
37 |
|
38 if (recipId->identifierType != NSSCMSRecipientID_IssuerSN && |
|
39 recipId->identifierType != NSSCMSRecipientID_SubjectKeyID) { |
|
40 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
|
41 return -1; |
|
42 } |
|
43 /* alloc one & fill it out */ |
|
44 rle = (NSSCMSRecipient *)PORT_ZAlloc(sizeof(NSSCMSRecipient)); |
|
45 if (!rle) |
|
46 return -1; |
|
47 |
|
48 rle->riIndex = i; |
|
49 rle->subIndex = -1; |
|
50 switch (recipId->identifierType) { |
|
51 case NSSCMSRecipientID_IssuerSN: |
|
52 rle->kind = RLIssuerSN; |
|
53 rle->id.issuerAndSN = recipId->id.issuerAndSN; |
|
54 break; |
|
55 case NSSCMSRecipientID_SubjectKeyID: |
|
56 rle->kind = RLSubjKeyID; |
|
57 rle->id.subjectKeyID = recipId->id.subjectKeyID; |
|
58 break; |
|
59 default: /* we never get here because of identifierType check |
|
60 we done before. Leaving it to kill compiler warning */ |
|
61 break; |
|
62 } |
|
63 recipient_list[rlindex++] = rle; |
|
64 } else { |
|
65 count++; |
|
66 } |
|
67 break; |
|
68 case NSSCMSRecipientInfoID_KeyAgree: |
|
69 if (ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys == NULL) |
|
70 break; |
|
71 for (j=0; ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[j] != NULL; j++) { |
|
72 if (recipient_list) { |
|
73 rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[j]; |
|
74 /* alloc one & fill it out */ |
|
75 rle = (NSSCMSRecipient *)PORT_ZAlloc(sizeof(NSSCMSRecipient)); |
|
76 if (!rle) |
|
77 return -1; |
|
78 |
|
79 rle->riIndex = i; |
|
80 rle->subIndex = j; |
|
81 switch (rek->recipientIdentifier.identifierType) { |
|
82 case NSSCMSKeyAgreeRecipientID_IssuerSN: |
|
83 rle->kind = RLIssuerSN; |
|
84 rle->id.issuerAndSN = rek->recipientIdentifier.id.issuerAndSN; |
|
85 break; |
|
86 case NSSCMSKeyAgreeRecipientID_RKeyID: |
|
87 rle->kind = RLSubjKeyID; |
|
88 rle->id.subjectKeyID = rek->recipientIdentifier.id.recipientKeyIdentifier.subjectKeyIdentifier; |
|
89 break; |
|
90 } |
|
91 recipient_list[rlindex++] = rle; |
|
92 } else { |
|
93 count++; |
|
94 } |
|
95 } |
|
96 break; |
|
97 case NSSCMSRecipientInfoID_KEK: |
|
98 /* KEK is not implemented */ |
|
99 break; |
|
100 } |
|
101 } |
|
102 /* if we have a recipient list, we return on success (-1, above, on failure) */ |
|
103 /* otherwise, we return the count. */ |
|
104 if (recipient_list) { |
|
105 recipient_list[rlindex] = NULL; |
|
106 return 0; |
|
107 } else { |
|
108 return count; |
|
109 } |
|
110 } |
|
111 |
|
112 NSSCMSRecipient ** |
|
113 nss_cms_recipient_list_create(NSSCMSRecipientInfo **recipientinfos) |
|
114 { |
|
115 int count, rv; |
|
116 NSSCMSRecipient **recipient_list; |
|
117 |
|
118 /* count the number of recipient identifiers */ |
|
119 count = nss_cms_recipients_traverse(recipientinfos, NULL); |
|
120 if (count <= 0) { |
|
121 /* no recipients? */ |
|
122 PORT_SetError(SEC_ERROR_BAD_DATA); |
|
123 #if 0 |
|
124 PORT_SetErrorString("Cannot find recipient data in envelope."); |
|
125 #endif |
|
126 return NULL; |
|
127 } |
|
128 |
|
129 /* allocate an array of pointers */ |
|
130 recipient_list = (NSSCMSRecipient **) |
|
131 PORT_ZAlloc((count + 1) * sizeof(NSSCMSRecipient *)); |
|
132 if (recipient_list == NULL) |
|
133 return NULL; |
|
134 |
|
135 /* now fill in the recipient_list */ |
|
136 rv = nss_cms_recipients_traverse(recipientinfos, recipient_list); |
|
137 if (rv < 0) { |
|
138 nss_cms_recipient_list_destroy(recipient_list); |
|
139 return NULL; |
|
140 } |
|
141 return recipient_list; |
|
142 } |
|
143 |
|
144 void |
|
145 nss_cms_recipient_list_destroy(NSSCMSRecipient **recipient_list) |
|
146 { |
|
147 int i; |
|
148 NSSCMSRecipient *recipient; |
|
149 |
|
150 for (i=0; recipient_list[i] != NULL; i++) { |
|
151 recipient = recipient_list[i]; |
|
152 if (recipient->cert) |
|
153 CERT_DestroyCertificate(recipient->cert); |
|
154 if (recipient->privkey) |
|
155 SECKEY_DestroyPrivateKey(recipient->privkey); |
|
156 if (recipient->slot) |
|
157 PK11_FreeSlot(recipient->slot); |
|
158 PORT_Free(recipient); |
|
159 } |
|
160 PORT_Free(recipient_list); |
|
161 } |
|
162 |
|
163 NSSCMSRecipientEncryptedKey * |
|
164 NSS_CMSRecipientEncryptedKey_Create(PLArenaPool *poolp) |
|
165 { |
|
166 return (NSSCMSRecipientEncryptedKey *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSRecipientEncryptedKey)); |
|
167 } |