Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 #include "cmmf.h"
7 #include "cmmfi.h"
8 #include "secitem.h"
9 #include "secder.h"
11 SECStatus
12 cmmf_DestroyPKIStatusInfo (CMMFPKIStatusInfo *info, PRBool freeit)
13 {
14 if (info->status.data != NULL) {
15 PORT_Free(info->status.data);
16 info->status.data = NULL;
17 }
18 if (info->statusString.data != NULL) {
19 PORT_Free(info->statusString.data);
20 info->statusString.data = NULL;
21 }
22 if (info->failInfo.data != NULL) {
23 PORT_Free(info->failInfo.data);
24 info->failInfo.data = NULL;
25 }
26 if (freeit) {
27 PORT_Free(info);
28 }
29 return SECSuccess;
30 }
32 SECStatus
33 CMMF_DestroyCertResponse(CMMFCertResponse *inCertResp)
34 {
35 PORT_Assert(inCertResp != NULL);
36 if (inCertResp != NULL) {
37 if (inCertResp->certReqId.data != NULL) {
38 PORT_Free(inCertResp->certReqId.data);
39 }
40 cmmf_DestroyPKIStatusInfo(&inCertResp->status, PR_FALSE);
41 if (inCertResp->certifiedKeyPair != NULL) {
42 CMMF_DestroyCertifiedKeyPair(inCertResp->certifiedKeyPair);
43 }
44 PORT_Free(inCertResp);
45 }
46 return SECSuccess;
47 }
49 SECStatus
50 CMMF_DestroyCertRepContent(CMMFCertRepContent *inCertRepContent)
51 {
52 PORT_Assert(inCertRepContent != NULL);
53 if (inCertRepContent != NULL) {
54 CMMFCertResponse **pResponse = inCertRepContent->response;
55 if (pResponse != NULL) {
56 for (; *pResponse != NULL; pResponse++) {
57 CMMFCertifiedKeyPair *certKeyPair = (*pResponse)->certifiedKeyPair;
58 /* XXX Why not call CMMF_DestroyCertifiedKeyPair or
59 ** XXX cmmf_DestroyCertOrEncCert ?
60 */
61 if (certKeyPair != NULL &&
62 certKeyPair->certOrEncCert.choice == cmmfCertificate &&
63 certKeyPair->certOrEncCert.cert.certificate != NULL) {
64 CERT_DestroyCertificate
65 (certKeyPair->certOrEncCert.cert.certificate);
66 certKeyPair->certOrEncCert.cert.certificate = NULL;
67 }
68 }
69 }
70 if (inCertRepContent->caPubs) {
71 CERTCertificate **caPubs = inCertRepContent->caPubs;
72 for (; *caPubs; ++caPubs) {
73 CERT_DestroyCertificate(*caPubs);
74 *caPubs = NULL;
75 }
76 }
77 if (inCertRepContent->poolp != NULL) {
78 PORT_FreeArena(inCertRepContent->poolp, PR_TRUE);
79 }
80 }
81 return SECSuccess;
82 }
84 SECStatus
85 CMMF_DestroyPOPODecKeyChallContent(CMMFPOPODecKeyChallContent *inDecKeyCont)
86 {
87 PORT_Assert(inDecKeyCont != NULL);
88 if (inDecKeyCont != NULL && inDecKeyCont->poolp) {
89 PORT_FreeArena(inDecKeyCont->poolp, PR_FALSE);
90 }
91 return SECSuccess;
92 }
94 SECStatus
95 crmf_create_prtime(SECItem *src, PRTime **dest)
96 {
97 *dest = PORT_ZNew(PRTime);
98 return DER_DecodeTimeChoice(*dest, src);
99 }
101 CRMFCertExtension*
102 crmf_copy_cert_extension(PLArenaPool *poolp, CRMFCertExtension *inExtension)
103 {
104 PRBool isCritical;
105 SECOidTag id;
106 SECItem *data;
107 CRMFCertExtension *newExt;
109 PORT_Assert(inExtension != NULL);
110 if (inExtension == NULL) {
111 return NULL;
112 }
113 id = CRMF_CertExtensionGetOidTag(inExtension);
114 isCritical = CRMF_CertExtensionGetIsCritical(inExtension);
115 data = CRMF_CertExtensionGetValue(inExtension);
116 newExt = crmf_create_cert_extension(poolp, id,
117 isCritical,
118 data);
119 SECITEM_FreeItem(data, PR_TRUE);
120 return newExt;
121 }
123 static SECItem*
124 cmmf_encode_certificate(CERTCertificate *inCert)
125 {
126 return SEC_ASN1EncodeItem(NULL, NULL, inCert,
127 SEC_ASN1_GET(SEC_SignedCertificateTemplate));
128 }
130 CERTCertList*
131 cmmf_MakeCertList(CERTCertificate **inCerts)
132 {
133 CERTCertList *certList;
134 CERTCertificate *currCert;
135 SECItem *derCert, *freeCert = NULL;
136 SECStatus rv;
137 int i;
139 certList = CERT_NewCertList();
140 if (certList == NULL) {
141 return NULL;
142 }
143 for (i=0; inCerts[i] != NULL; i++) {
144 derCert = &inCerts[i]->derCert;
145 if (derCert->data == NULL) {
146 derCert = freeCert = cmmf_encode_certificate(inCerts[i]);
147 }
148 currCert=CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
149 derCert, NULL, PR_FALSE, PR_TRUE);
150 if (freeCert != NULL) {
151 SECITEM_FreeItem(freeCert, PR_TRUE);
152 freeCert = NULL;
153 }
154 if (currCert == NULL) {
155 goto loser;
156 }
157 rv = CERT_AddCertToListTail(certList, currCert);
158 if (rv != SECSuccess) {
159 goto loser;
160 }
161 }
162 return certList;
163 loser:
164 CERT_DestroyCertList(certList);
165 return NULL;
166 }
168 CMMFPKIStatus
169 cmmf_PKIStatusInfoGetStatus(CMMFPKIStatusInfo *inStatus)
170 {
171 long derVal;
173 derVal = DER_GetInteger(&inStatus->status);
174 if (derVal == -1 || derVal < cmmfGranted || derVal >= cmmfNumPKIStatus) {
175 return cmmfNoPKIStatus;
176 }
177 return (CMMFPKIStatus)derVal;
178 }
180 int
181 CMMF_CertRepContentGetNumResponses(CMMFCertRepContent *inCertRepContent)
182 {
183 int numResponses = 0;
184 PORT_Assert (inCertRepContent != NULL);
185 if (inCertRepContent != NULL && inCertRepContent->response != NULL) {
186 while (inCertRepContent->response[numResponses] != NULL) {
187 numResponses++;
188 }
189 }
190 return numResponses;
191 }
194 SECStatus
195 cmmf_DestroyCertOrEncCert(CMMFCertOrEncCert *certOrEncCert, PRBool freeit)
196 {
197 switch (certOrEncCert->choice) {
198 case cmmfCertificate:
199 CERT_DestroyCertificate(certOrEncCert->cert.certificate);
200 certOrEncCert->cert.certificate = NULL;
201 break;
202 case cmmfEncryptedCert:
203 crmf_destroy_encrypted_value(certOrEncCert->cert.encryptedCert,
204 PR_TRUE);
205 certOrEncCert->cert.encryptedCert = NULL;
206 break;
207 default:
208 break;
209 }
210 if (freeit) {
211 PORT_Free(certOrEncCert);
212 }
213 return SECSuccess;
214 }
216 SECStatus
217 cmmf_copy_secitem (PLArenaPool *poolp, SECItem *dest, SECItem *src)
218 {
219 SECStatus rv;
221 if (src->data != NULL) {
222 rv = SECITEM_CopyItem(poolp, dest, src);
223 } else {
224 dest->data = NULL;
225 dest->len = 0;
226 rv = SECSuccess;
227 }
228 return rv;
229 }
231 SECStatus
232 CMMF_DestroyCertifiedKeyPair(CMMFCertifiedKeyPair *inCertKeyPair)
233 {
234 PORT_Assert(inCertKeyPair != NULL);
235 if (inCertKeyPair != NULL) {
236 cmmf_DestroyCertOrEncCert(&inCertKeyPair->certOrEncCert, PR_FALSE);
237 if (inCertKeyPair->privateKey) {
238 crmf_destroy_encrypted_value(inCertKeyPair->privateKey, PR_TRUE);
239 }
240 if (inCertKeyPair->derPublicationInfo.data) {
241 PORT_Free(inCertKeyPair->derPublicationInfo.data);
242 }
243 PORT_Free(inCertKeyPair);
244 }
245 return SECSuccess;
246 }
248 SECStatus
249 cmmf_CopyCertResponse(PLArenaPool *poolp,
250 CMMFCertResponse *dest,
251 CMMFCertResponse *src)
252 {
253 SECStatus rv;
255 if (src->certReqId.data != NULL) {
256 rv = SECITEM_CopyItem(poolp, &dest->certReqId, &src->certReqId);
257 if (rv != SECSuccess) {
258 return rv;
259 }
260 }
261 rv = cmmf_CopyPKIStatusInfo(poolp, &dest->status, &src->status);
262 if (rv != SECSuccess) {
263 return rv;
264 }
265 if (src->certifiedKeyPair != NULL) {
266 CMMFCertifiedKeyPair *destKeyPair;
268 destKeyPair = (poolp == NULL) ? PORT_ZNew(CMMFCertifiedKeyPair) :
269 PORT_ArenaZNew(poolp, CMMFCertifiedKeyPair);
270 if (!destKeyPair) {
271 return SECFailure;
272 }
273 rv = cmmf_CopyCertifiedKeyPair(poolp, destKeyPair,
274 src->certifiedKeyPair);
275 if (rv != SECSuccess) {
276 if (!poolp) {
277 CMMF_DestroyCertifiedKeyPair(destKeyPair);
278 }
279 return rv;
280 }
281 dest->certifiedKeyPair = destKeyPair;
282 }
283 return SECSuccess;
284 }
286 static SECStatus
287 cmmf_CopyCertOrEncCert(PLArenaPool *poolp, CMMFCertOrEncCert *dest,
288 CMMFCertOrEncCert *src)
289 {
290 SECStatus rv = SECSuccess;
291 CRMFEncryptedValue *encVal;
293 dest->choice = src->choice;
294 rv = cmmf_copy_secitem(poolp, &dest->derValue, &src->derValue);
295 switch (src->choice) {
296 case cmmfCertificate:
297 dest->cert.certificate = CERT_DupCertificate(src->cert.certificate);
298 break;
299 case cmmfEncryptedCert:
300 encVal = (poolp == NULL) ? PORT_ZNew(CRMFEncryptedValue) :
301 PORT_ArenaZNew(poolp, CRMFEncryptedValue);
302 if (encVal == NULL) {
303 return SECFailure;
304 }
305 rv = crmf_copy_encryptedvalue(poolp, src->cert.encryptedCert, encVal);
306 if (rv != SECSuccess) {
307 if (!poolp) {
308 crmf_destroy_encrypted_value(encVal, PR_TRUE);
309 }
310 return rv;
311 }
312 dest->cert.encryptedCert = encVal;
313 break;
314 default:
315 rv = SECFailure;
316 }
317 return rv;
318 }
320 SECStatus
321 cmmf_CopyCertifiedKeyPair(PLArenaPool *poolp, CMMFCertifiedKeyPair *dest,
322 CMMFCertifiedKeyPair *src)
323 {
324 SECStatus rv;
326 rv = cmmf_CopyCertOrEncCert(poolp, &dest->certOrEncCert,
327 &src->certOrEncCert);
328 if (rv != SECSuccess) {
329 return rv;
330 }
332 if (src->privateKey != NULL) {
333 CRMFEncryptedValue *encVal;
335 encVal = (poolp == NULL) ? PORT_ZNew(CRMFEncryptedValue) :
336 PORT_ArenaZNew(poolp, CRMFEncryptedValue);
337 if (encVal == NULL) {
338 return SECFailure;
339 }
340 rv = crmf_copy_encryptedvalue(poolp, src->privateKey,
341 encVal);
342 if (rv != SECSuccess) {
343 if (!poolp) {
344 crmf_destroy_encrypted_value(encVal, PR_TRUE);
345 }
346 return rv;
347 }
348 dest->privateKey = encVal;
349 }
350 rv = cmmf_copy_secitem(poolp, &dest->derPublicationInfo,
351 &src->derPublicationInfo);
352 return rv;
353 }
355 SECStatus
356 cmmf_CopyPKIStatusInfo(PLArenaPool *poolp, CMMFPKIStatusInfo *dest,
357 CMMFPKIStatusInfo *src)
358 {
359 SECStatus rv;
361 rv = cmmf_copy_secitem (poolp, &dest->status, &src->status);
362 if (rv != SECSuccess) {
363 return rv;
364 }
365 rv = cmmf_copy_secitem (poolp, &dest->statusString, &src->statusString);
366 if (rv != SECSuccess) {
367 return rv;
368 }
369 rv = cmmf_copy_secitem (poolp, &dest->failInfo, &src->failInfo);
370 return rv;
371 }
373 CERTCertificate*
374 cmmf_CertOrEncCertGetCertificate(CMMFCertOrEncCert *certOrEncCert,
375 CERTCertDBHandle *certdb)
376 {
377 if (certOrEncCert->choice != cmmfCertificate ||
378 certOrEncCert->cert.certificate == NULL) {
379 return NULL;
380 }
381 return CERT_NewTempCertificate(certdb,
382 &certOrEncCert->cert.certificate->derCert,
383 NULL, PR_FALSE, PR_TRUE);
384 }
386 SECStatus
387 cmmf_PKIStatusInfoSetStatus(CMMFPKIStatusInfo *statusInfo,
388 PLArenaPool *poolp,
389 CMMFPKIStatus inStatus)
390 {
391 SECItem *dummy;
393 if (inStatus <cmmfGranted || inStatus >= cmmfNumPKIStatus) {
394 return SECFailure;
395 }
397 dummy = SEC_ASN1EncodeInteger(poolp, &statusInfo->status, inStatus);
398 PORT_Assert(dummy == &statusInfo->status);
399 if (dummy != &statusInfo->status) {
400 SECITEM_FreeItem(dummy, PR_TRUE);
401 return SECFailure;
402 }
403 return SECSuccess;
404 }