|
1 /* -*- Mode: C; tab-width: 8 -*-*/ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /* |
|
7 * This file will implement the functions related to key recovery in |
|
8 * CMMF |
|
9 */ |
|
10 |
|
11 #include "cmmf.h" |
|
12 #include "cmmfi.h" |
|
13 #include "secitem.h" |
|
14 #include "keyhi.h" |
|
15 |
|
16 CMMFKeyRecRepContent* |
|
17 CMMF_CreateKeyRecRepContent(void) |
|
18 { |
|
19 PLArenaPool *poolp; |
|
20 CMMFKeyRecRepContent *keyRecContent; |
|
21 |
|
22 poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE); |
|
23 if (poolp == NULL) { |
|
24 return NULL; |
|
25 } |
|
26 keyRecContent = PORT_ArenaZNew(poolp, CMMFKeyRecRepContent); |
|
27 if (keyRecContent == NULL) { |
|
28 PORT_FreeArena(poolp, PR_FALSE); |
|
29 return NULL; |
|
30 } |
|
31 keyRecContent->poolp = poolp; |
|
32 return keyRecContent; |
|
33 } |
|
34 |
|
35 SECStatus |
|
36 CMMF_DestroyKeyRecRepContent(CMMFKeyRecRepContent *inKeyRecRep) |
|
37 { |
|
38 PORT_Assert(inKeyRecRep != NULL); |
|
39 if (inKeyRecRep != NULL && inKeyRecRep->poolp != NULL) { |
|
40 int i; |
|
41 |
|
42 if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert != NULL) { |
|
43 CERT_DestroyCertificate(inKeyRecRep->newSigCert); |
|
44 } |
|
45 if (inKeyRecRep->caCerts != NULL) { |
|
46 for (i=0; inKeyRecRep->caCerts[i] != NULL; i++) { |
|
47 CERT_DestroyCertificate(inKeyRecRep->caCerts[i]); |
|
48 } |
|
49 } |
|
50 if (inKeyRecRep->keyPairHist != NULL) { |
|
51 for (i=0; inKeyRecRep->keyPairHist[i] != NULL; i++) { |
|
52 if (inKeyRecRep->keyPairHist[i]->certOrEncCert.choice == |
|
53 cmmfCertificate) { |
|
54 CERT_DestroyCertificate(inKeyRecRep->keyPairHist[i]-> |
|
55 certOrEncCert.cert.certificate); |
|
56 } |
|
57 } |
|
58 } |
|
59 PORT_FreeArena(inKeyRecRep->poolp, PR_TRUE); |
|
60 } |
|
61 return SECSuccess; |
|
62 } |
|
63 |
|
64 SECStatus |
|
65 CMMF_KeyRecRepContentSetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep, |
|
66 CMMFPKIStatus inPKIStatus) |
|
67 { |
|
68 PORT_Assert(inKeyRecRep != NULL && inPKIStatus >= cmmfGranted && |
|
69 inPKIStatus < cmmfNumPKIStatus); |
|
70 if (inKeyRecRep == NULL) { |
|
71 return SECFailure; |
|
72 } |
|
73 |
|
74 return cmmf_PKIStatusInfoSetStatus(&inKeyRecRep->status, |
|
75 inKeyRecRep->poolp, |
|
76 inPKIStatus); |
|
77 } |
|
78 |
|
79 SECStatus |
|
80 CMMF_KeyRecRepContentSetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep, |
|
81 CERTCertificate *inNewSignCert) |
|
82 { |
|
83 PORT_Assert (inKeyRecRep != NULL && inNewSignCert != NULL); |
|
84 if (inKeyRecRep == NULL || inNewSignCert == NULL) { |
|
85 return SECFailure; |
|
86 } |
|
87 if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert) { |
|
88 CERT_DestroyCertificate(inKeyRecRep->newSigCert); |
|
89 } |
|
90 inKeyRecRep->isDecoded = PR_FALSE; |
|
91 inKeyRecRep->newSigCert = CERT_DupCertificate(inNewSignCert); |
|
92 return (inKeyRecRep->newSigCert == NULL) ? SECFailure : SECSuccess; |
|
93 } |
|
94 |
|
95 SECStatus |
|
96 CMMF_KeyRecRepContentSetCACerts(CMMFKeyRecRepContent *inKeyRecRep, |
|
97 CERTCertList *inCACerts) |
|
98 { |
|
99 SECStatus rv; |
|
100 void *mark; |
|
101 |
|
102 PORT_Assert (inKeyRecRep != NULL && inCACerts != NULL); |
|
103 if (inKeyRecRep == NULL || inCACerts == NULL) { |
|
104 return SECFailure; |
|
105 } |
|
106 mark = PORT_ArenaMark(inKeyRecRep->poolp); |
|
107 rv = cmmf_ExtractCertsFromList(inCACerts, inKeyRecRep->poolp, |
|
108 &inKeyRecRep->caCerts); |
|
109 if (rv != SECSuccess) { |
|
110 PORT_ArenaRelease(inKeyRecRep->poolp, mark); |
|
111 } else { |
|
112 PORT_ArenaUnmark(inKeyRecRep->poolp, mark); |
|
113 } |
|
114 return rv; |
|
115 } |
|
116 |
|
117 SECStatus |
|
118 CMMF_KeyRecRepContentSetCertifiedKeyPair(CMMFKeyRecRepContent *inKeyRecRep, |
|
119 CERTCertificate *inCert, |
|
120 SECKEYPrivateKey *inPrivKey, |
|
121 SECKEYPublicKey *inPubKey) |
|
122 { |
|
123 CMMFCertifiedKeyPair *keyPair; |
|
124 CRMFEncryptedValue *dummy; |
|
125 PLArenaPool *poolp; |
|
126 void *mark; |
|
127 SECStatus rv; |
|
128 |
|
129 PORT_Assert (inKeyRecRep != NULL && |
|
130 inCert != NULL && |
|
131 inPrivKey != NULL && |
|
132 inPubKey != NULL); |
|
133 if (inKeyRecRep == NULL || |
|
134 inCert == NULL || |
|
135 inPrivKey == NULL || |
|
136 inPubKey == NULL) { |
|
137 return SECFailure; |
|
138 } |
|
139 poolp = inKeyRecRep->poolp; |
|
140 mark = PORT_ArenaMark(poolp); |
|
141 if (inKeyRecRep->keyPairHist == NULL) { |
|
142 inKeyRecRep->keyPairHist = PORT_ArenaNewArray(poolp, |
|
143 CMMFCertifiedKeyPair*, |
|
144 (CMMF_MAX_KEY_PAIRS+1)); |
|
145 if (inKeyRecRep->keyPairHist == NULL) { |
|
146 goto loser; |
|
147 } |
|
148 inKeyRecRep->allocKeyPairs = CMMF_MAX_KEY_PAIRS; |
|
149 inKeyRecRep->numKeyPairs = 0; |
|
150 } |
|
151 |
|
152 if (inKeyRecRep->allocKeyPairs == inKeyRecRep->numKeyPairs) { |
|
153 goto loser; |
|
154 } |
|
155 |
|
156 keyPair = PORT_ArenaZNew(poolp, CMMFCertifiedKeyPair); |
|
157 if (keyPair == NULL) { |
|
158 goto loser; |
|
159 } |
|
160 rv = cmmf_CertOrEncCertSetCertificate(&keyPair->certOrEncCert, |
|
161 poolp, inCert); |
|
162 if (rv != SECSuccess) { |
|
163 goto loser; |
|
164 } |
|
165 keyPair->privateKey = PORT_ArenaZNew(poolp, CRMFEncryptedValue); |
|
166 if (keyPair->privateKey == NULL) { |
|
167 goto loser; |
|
168 } |
|
169 dummy = crmf_create_encrypted_value_wrapped_privkey(inPrivKey, inPubKey, |
|
170 keyPair->privateKey); |
|
171 PORT_Assert(dummy == keyPair->privateKey); |
|
172 if (dummy != keyPair->privateKey) { |
|
173 crmf_destroy_encrypted_value(dummy, PR_TRUE); |
|
174 goto loser; |
|
175 } |
|
176 inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = keyPair; |
|
177 inKeyRecRep->numKeyPairs++; |
|
178 inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = NULL; |
|
179 PORT_ArenaUnmark(poolp, mark); |
|
180 return SECSuccess; |
|
181 |
|
182 loser: |
|
183 PORT_ArenaRelease(poolp, mark); |
|
184 return SECFailure; |
|
185 } |
|
186 |
|
187 CMMFPKIStatus |
|
188 CMMF_KeyRecRepContentGetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep) |
|
189 { |
|
190 PORT_Assert(inKeyRecRep != NULL); |
|
191 if (inKeyRecRep == NULL) { |
|
192 return cmmfNoPKIStatus; |
|
193 } |
|
194 return cmmf_PKIStatusInfoGetStatus(&inKeyRecRep->status); |
|
195 } |
|
196 |
|
197 CERTCertificate* |
|
198 CMMF_KeyRecRepContentGetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep) |
|
199 { |
|
200 PORT_Assert(inKeyRecRep != NULL); |
|
201 if (inKeyRecRep == NULL || |
|
202 inKeyRecRep->newSigCert == NULL) { |
|
203 return NULL; |
|
204 } |
|
205 /* newSigCert may not be a real certificate, it may be a hand decoded |
|
206 * cert structure. This code makes sure we hand off a real, fully formed |
|
207 * CERTCertificate to the caller. TODO: This should move into the decode |
|
208 * portion so that we never wind up with a half formed CERTCertificate |
|
209 * here. In this case the call would be to CERT_DupCertificate. |
|
210 */ |
|
211 return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), |
|
212 &inKeyRecRep->newSigCert->signatureWrap.data, |
|
213 NULL, PR_FALSE, PR_TRUE); |
|
214 } |
|
215 |
|
216 CERTCertList* |
|
217 CMMF_KeyRecRepContentGetCACerts(CMMFKeyRecRepContent *inKeyRecRep) |
|
218 { |
|
219 PORT_Assert(inKeyRecRep != NULL); |
|
220 if (inKeyRecRep == NULL || inKeyRecRep->caCerts == NULL) { |
|
221 return NULL; |
|
222 } |
|
223 return cmmf_MakeCertList(inKeyRecRep->caCerts); |
|
224 } |
|
225 |
|
226 int |
|
227 CMMF_KeyRecRepContentGetNumKeyPairs(CMMFKeyRecRepContent *inKeyRecRep) |
|
228 { |
|
229 PORT_Assert(inKeyRecRep != NULL); |
|
230 return (inKeyRecRep == NULL) ? 0 : inKeyRecRep->numKeyPairs; |
|
231 } |
|
232 |
|
233 PRBool |
|
234 cmmf_KeyRecRepContentIsValidIndex(CMMFKeyRecRepContent *inKeyRecRep, |
|
235 int inIndex) |
|
236 { |
|
237 int numKeyPairs = CMMF_KeyRecRepContentGetNumKeyPairs(inKeyRecRep); |
|
238 |
|
239 return (PRBool)(inIndex >= 0 && inIndex < numKeyPairs); |
|
240 } |
|
241 |
|
242 CMMFCertifiedKeyPair* |
|
243 CMMF_KeyRecRepContentGetCertKeyAtIndex(CMMFKeyRecRepContent *inKeyRecRep, |
|
244 int inIndex) |
|
245 { |
|
246 CMMFCertifiedKeyPair *newKeyPair; |
|
247 SECStatus rv; |
|
248 |
|
249 PORT_Assert(inKeyRecRep != NULL && |
|
250 cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex)); |
|
251 if (inKeyRecRep == NULL || |
|
252 !cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex)) { |
|
253 return NULL; |
|
254 } |
|
255 newKeyPair = PORT_ZNew(CMMFCertifiedKeyPair); |
|
256 if (newKeyPair == NULL) { |
|
257 return NULL; |
|
258 } |
|
259 rv = cmmf_CopyCertifiedKeyPair(NULL, newKeyPair, |
|
260 inKeyRecRep->keyPairHist[inIndex]); |
|
261 if (rv != SECSuccess) { |
|
262 CMMF_DestroyCertifiedKeyPair(newKeyPair); |
|
263 newKeyPair = NULL; |
|
264 } |
|
265 return newKeyPair; |
|
266 } |
|
267 |
|
268 SECStatus |
|
269 CMMF_CertifiedKeyPairUnwrapPrivKey(CMMFCertifiedKeyPair *inKeyPair, |
|
270 SECKEYPrivateKey *inPrivKey, |
|
271 SECItem *inNickName, |
|
272 PK11SlotInfo *inSlot, |
|
273 CERTCertDBHandle *inCertdb, |
|
274 SECKEYPrivateKey **destPrivKey, |
|
275 void *wincx) |
|
276 { |
|
277 CERTCertificate *cert; |
|
278 SECItem keyUsageValue = {siBuffer, NULL, 0}; |
|
279 unsigned char keyUsage = 0x0; |
|
280 SECKEYPublicKey *pubKey; |
|
281 SECStatus rv; |
|
282 |
|
283 PORT_Assert(inKeyPair != NULL && |
|
284 inPrivKey != NULL && inCertdb != NULL); |
|
285 if (inKeyPair == NULL || |
|
286 inPrivKey == NULL || |
|
287 inKeyPair->privateKey == NULL || |
|
288 inCertdb == NULL) { |
|
289 return SECFailure; |
|
290 } |
|
291 |
|
292 cert = CMMF_CertifiedKeyPairGetCertificate(inKeyPair, inCertdb); |
|
293 CERT_FindKeyUsageExtension(cert, &keyUsageValue); |
|
294 if (keyUsageValue.data != NULL) { |
|
295 keyUsage = keyUsageValue.data[3]; |
|
296 PORT_Free(keyUsageValue.data); |
|
297 } |
|
298 pubKey = CERT_ExtractPublicKey(cert); |
|
299 rv = crmf_encrypted_value_unwrap_priv_key(NULL, inKeyPair->privateKey, |
|
300 inPrivKey, pubKey, |
|
301 inNickName, inSlot, keyUsage, |
|
302 destPrivKey, wincx); |
|
303 SECKEY_DestroyPublicKey(pubKey); |
|
304 CERT_DestroyCertificate(cert); |
|
305 return rv; |
|
306 } |
|
307 |
|
308 |
|
309 PRBool |
|
310 CMMF_KeyRecRepContentHasCACerts(CMMFKeyRecRepContent *inKeyRecRep) |
|
311 { |
|
312 PORT_Assert(inKeyRecRep != NULL); |
|
313 if (inKeyRecRep == NULL) { |
|
314 return PR_FALSE; |
|
315 } |
|
316 return (PRBool)(inKeyRecRep->caCerts != NULL && |
|
317 inKeyRecRep->caCerts[0] != NULL); |
|
318 } |