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