Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
6 /*
7 * This file will implement the functions related to key recovery in
8 * CMMF
9 */
11 #include "cmmf.h"
12 #include "cmmfi.h"
13 #include "secitem.h"
14 #include "keyhi.h"
16 CMMFKeyRecRepContent*
17 CMMF_CreateKeyRecRepContent(void)
18 {
19 PLArenaPool *poolp;
20 CMMFKeyRecRepContent *keyRecContent;
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 }
35 SECStatus
36 CMMF_DestroyKeyRecRepContent(CMMFKeyRecRepContent *inKeyRecRep)
37 {
38 PORT_Assert(inKeyRecRep != NULL);
39 if (inKeyRecRep != NULL && inKeyRecRep->poolp != NULL) {
40 int i;
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 }
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 }
74 return cmmf_PKIStatusInfoSetStatus(&inKeyRecRep->status,
75 inKeyRecRep->poolp,
76 inPKIStatus);
77 }
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 }
95 SECStatus
96 CMMF_KeyRecRepContentSetCACerts(CMMFKeyRecRepContent *inKeyRecRep,
97 CERTCertList *inCACerts)
98 {
99 SECStatus rv;
100 void *mark;
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 }
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;
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 }
152 if (inKeyRecRep->allocKeyPairs == inKeyRecRep->numKeyPairs) {
153 goto loser;
154 }
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;
182 loser:
183 PORT_ArenaRelease(poolp, mark);
184 return SECFailure;
185 }
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 }
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 }
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 }
226 int
227 CMMF_KeyRecRepContentGetNumKeyPairs(CMMFKeyRecRepContent *inKeyRecRep)
228 {
229 PORT_Assert(inKeyRecRep != NULL);
230 return (inKeyRecRep == NULL) ? 0 : inKeyRecRep->numKeyPairs;
231 }
233 PRBool
234 cmmf_KeyRecRepContentIsValidIndex(CMMFKeyRecRepContent *inKeyRecRep,
235 int inIndex)
236 {
237 int numKeyPairs = CMMF_KeyRecRepContentGetNumKeyPairs(inKeyRecRep);
239 return (PRBool)(inIndex >= 0 && inIndex < numKeyPairs);
240 }
242 CMMFCertifiedKeyPair*
243 CMMF_KeyRecRepContentGetCertKeyAtIndex(CMMFKeyRecRepContent *inKeyRecRep,
244 int inIndex)
245 {
246 CMMFCertifiedKeyPair *newKeyPair;
247 SECStatus rv;
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 }
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;
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 }
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 }
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 }