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