/* -*- Mode: C; tab-width: 8 -*-*/ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "cmmf.h" #include "cmmfi.h" #include "secitem.h" #include "secder.h" SECStatus cmmf_DestroyPKIStatusInfo(CMMFPKIStatusInfo *info, PRBool freeit) { if (info->status.data != NULL) { PORT_Free(info->status.data); info->status.data = NULL; } if (info->statusString.data != NULL) { PORT_Free(info->statusString.data); info->statusString.data = NULL; } if (info->failInfo.data != NULL) { PORT_Free(info->failInfo.data); info->failInfo.data = NULL; } if (freeit) { PORT_Free(info); } return SECSuccess; } SECStatus CMMF_DestroyCertResponse(CMMFCertResponse *inCertResp) { PORT_Assert(inCertResp != NULL); if (inCertResp != NULL) { if (inCertResp->certReqId.data != NULL) { PORT_Free(inCertResp->certReqId.data); } cmmf_DestroyPKIStatusInfo(&inCertResp->status, PR_FALSE); if (inCertResp->certifiedKeyPair != NULL) { CMMF_DestroyCertifiedKeyPair(inCertResp->certifiedKeyPair); } PORT_Free(inCertResp); } return SECSuccess; } SECStatus CMMF_DestroyCertRepContent(CMMFCertRepContent *inCertRepContent) { PORT_Assert(inCertRepContent != NULL); if (inCertRepContent != NULL) { CMMFCertResponse **pResponse = inCertRepContent->response; if (pResponse != NULL) { for (; *pResponse != NULL; pResponse++) { CMMFCertifiedKeyPair *certKeyPair = (*pResponse)->certifiedKeyPair; /* XXX Why not call CMMF_DestroyCertifiedKeyPair or ** XXX cmmf_DestroyCertOrEncCert ? */ if (certKeyPair != NULL && certKeyPair->certOrEncCert.choice == cmmfCertificate && certKeyPair->certOrEncCert.cert.certificate != NULL) { CERT_DestroyCertificate(certKeyPair->certOrEncCert.cert.certificate); certKeyPair->certOrEncCert.cert.certificate = NULL; } } } if (inCertRepContent->caPubs) { CERTCertificate **caPubs = inCertRepContent->caPubs; for (; *caPubs; ++caPubs) { CERT_DestroyCertificate(*caPubs); *caPubs = NULL; } } if (inCertRepContent->poolp != NULL) { PORT_FreeArena(inCertRepContent->poolp, PR_TRUE); } } return SECSuccess; } SECStatus CMMF_DestroyPOPODecKeyChallContent(CMMFPOPODecKeyChallContent *inDecKeyCont) { PORT_Assert(inDecKeyCont != NULL); if (inDecKeyCont != NULL && inDecKeyCont->poolp) { PORT_FreeArena(inDecKeyCont->poolp, PR_FALSE); } return SECSuccess; } SECStatus crmf_create_prtime(SECItem *src, PRTime **dest) { *dest = PORT_ZNew(PRTime); return DER_DecodeTimeChoice(*dest, src); } CRMFCertExtension * crmf_copy_cert_extension(PLArenaPool *poolp, CRMFCertExtension *inExtension) { PRBool isCritical; SECOidTag id; SECItem *data; CRMFCertExtension *newExt; PORT_Assert(inExtension != NULL); if (inExtension == NULL) { return NULL; } id = CRMF_CertExtensionGetOidTag(inExtension); isCritical = CRMF_CertExtensionGetIsCritical(inExtension); data = CRMF_CertExtensionGetValue(inExtension); newExt = crmf_create_cert_extension(poolp, id, isCritical, data); SECITEM_FreeItem(data, PR_TRUE); return newExt; } static SECItem * cmmf_encode_certificate(CERTCertificate *inCert) { return SEC_ASN1EncodeItem(NULL, NULL, inCert, SEC_ASN1_GET(SEC_SignedCertificateTemplate)); } CERTCertList * cmmf_MakeCertList(CERTCertificate **inCerts) { CERTCertList *certList; CERTCertificate *currCert; SECItem *derCert, *freeCert = NULL; SECStatus rv; int i; certList = CERT_NewCertList(); if (certList == NULL) { return NULL; } for (i = 0; inCerts[i] != NULL; i++) { derCert = &inCerts[i]->derCert; if (derCert->data == NULL) { derCert = freeCert = cmmf_encode_certificate(inCerts[i]); } currCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, NULL, PR_FALSE, PR_TRUE); if (freeCert != NULL) { SECITEM_FreeItem(freeCert, PR_TRUE); freeCert = NULL; } if (currCert == NULL) { goto loser; } rv = CERT_AddCertToListTail(certList, currCert); if (rv != SECSuccess) { goto loser; } } return certList; loser: CERT_DestroyCertList(certList); return NULL; } CMMFPKIStatus cmmf_PKIStatusInfoGetStatus(CMMFPKIStatusInfo *inStatus) { long derVal; derVal = DER_GetInteger(&inStatus->status); if (derVal == -1 || derVal < cmmfGranted || derVal >= cmmfNumPKIStatus) { return cmmfNoPKIStatus; } return (CMMFPKIStatus)derVal; } int CMMF_CertRepContentGetNumResponses(CMMFCertRepContent *inCertRepContent) { int numResponses = 0; PORT_Assert(inCertRepContent != NULL); if (inCertRepContent != NULL && inCertRepContent->response != NULL) { while (inCertRepContent->response[numResponses] != NULL) { numResponses++; } } return numResponses; } SECStatus cmmf_DestroyCertOrEncCert(CMMFCertOrEncCert *certOrEncCert, PRBool freeit) { switch (certOrEncCert->choice) { case cmmfCertificate: CERT_DestroyCertificate(certOrEncCert->cert.certificate); certOrEncCert->cert.certificate = NULL; break; case cmmfEncryptedCert: crmf_destroy_encrypted_value(certOrEncCert->cert.encryptedCert, PR_TRUE); certOrEncCert->cert.encryptedCert = NULL; break; default: break; } if (freeit) { PORT_Free(certOrEncCert); } return SECSuccess; } SECStatus cmmf_copy_secitem(PLArenaPool *poolp, SECItem *dest, SECItem *src) { SECStatus rv; if (src->data != NULL) { rv = SECITEM_CopyItem(poolp, dest, src); } else { dest->data = NULL; dest->len = 0; rv = SECSuccess; } return rv; } SECStatus CMMF_DestroyCertifiedKeyPair(CMMFCertifiedKeyPair *inCertKeyPair) { PORT_Assert(inCertKeyPair != NULL); if (inCertKeyPair != NULL) { cmmf_DestroyCertOrEncCert(&inCertKeyPair->certOrEncCert, PR_FALSE); if (inCertKeyPair->privateKey) { crmf_destroy_encrypted_value(inCertKeyPair->privateKey, PR_TRUE); } if (inCertKeyPair->derPublicationInfo.data) { PORT_Free(inCertKeyPair->derPublicationInfo.data); } PORT_Free(inCertKeyPair); } return SECSuccess; } SECStatus cmmf_CopyCertResponse(PLArenaPool *poolp, CMMFCertResponse *dest, CMMFCertResponse *src) { SECStatus rv; if (src->certReqId.data != NULL) { rv = SECITEM_CopyItem(poolp, &dest->certReqId, &src->certReqId); if (rv != SECSuccess) { return rv; } } rv = cmmf_CopyPKIStatusInfo(poolp, &dest->status, &src->status); if (rv != SECSuccess) { return rv; } if (src->certifiedKeyPair != NULL) { CMMFCertifiedKeyPair *destKeyPair; destKeyPair = (poolp == NULL) ? PORT_ZNew(CMMFCertifiedKeyPair) : PORT_ArenaZNew(poolp, CMMFCertifiedKeyPair); if (!destKeyPair) { return SECFailure; } rv = cmmf_CopyCertifiedKeyPair(poolp, destKeyPair, src->certifiedKeyPair); if (rv != SECSuccess) { if (!poolp) { CMMF_DestroyCertifiedKeyPair(destKeyPair); } return rv; } dest->certifiedKeyPair = destKeyPair; } return SECSuccess; } static SECStatus cmmf_CopyCertOrEncCert(PLArenaPool *poolp, CMMFCertOrEncCert *dest, CMMFCertOrEncCert *src) { SECStatus rv = SECSuccess; CRMFEncryptedValue *encVal; dest->choice = src->choice; rv = cmmf_copy_secitem(poolp, &dest->derValue, &src->derValue); switch (src->choice) { case cmmfCertificate: dest->cert.certificate = CERT_DupCertificate(src->cert.certificate); break; case cmmfEncryptedCert: encVal = (poolp == NULL) ? PORT_ZNew(CRMFEncryptedValue) : PORT_ArenaZNew(poolp, CRMFEncryptedValue); if (encVal == NULL) { return SECFailure; } rv = crmf_copy_encryptedvalue(poolp, src->cert.encryptedCert, encVal); if (rv != SECSuccess) { if (!poolp) { crmf_destroy_encrypted_value(encVal, PR_TRUE); } return rv; } dest->cert.encryptedCert = encVal; break; default: rv = SECFailure; } return rv; } SECStatus cmmf_CopyCertifiedKeyPair(PLArenaPool *poolp, CMMFCertifiedKeyPair *dest, CMMFCertifiedKeyPair *src) { SECStatus rv; rv = cmmf_CopyCertOrEncCert(poolp, &dest->certOrEncCert, &src->certOrEncCert); if (rv != SECSuccess) { return rv; } if (src->privateKey != NULL) { CRMFEncryptedValue *encVal; encVal = (poolp == NULL) ? PORT_ZNew(CRMFEncryptedValue) : PORT_ArenaZNew(poolp, CRMFEncryptedValue); if (encVal == NULL) { return SECFailure; } rv = crmf_copy_encryptedvalue(poolp, src->privateKey, encVal); if (rv != SECSuccess) { if (!poolp) { crmf_destroy_encrypted_value(encVal, PR_TRUE); } return rv; } dest->privateKey = encVal; } rv = cmmf_copy_secitem(poolp, &dest->derPublicationInfo, &src->derPublicationInfo); return rv; } SECStatus cmmf_CopyPKIStatusInfo(PLArenaPool *poolp, CMMFPKIStatusInfo *dest, CMMFPKIStatusInfo *src) { SECStatus rv; rv = cmmf_copy_secitem(poolp, &dest->status, &src->status); if (rv != SECSuccess) { return rv; } rv = cmmf_copy_secitem(poolp, &dest->statusString, &src->statusString); if (rv != SECSuccess) { return rv; } rv = cmmf_copy_secitem(poolp, &dest->failInfo, &src->failInfo); return rv; } CERTCertificate * cmmf_CertOrEncCertGetCertificate(CMMFCertOrEncCert *certOrEncCert, CERTCertDBHandle *certdb) { if (certOrEncCert->choice != cmmfCertificate || certOrEncCert->cert.certificate == NULL) { return NULL; } return CERT_NewTempCertificate(certdb, &certOrEncCert->cert.certificate->derCert, NULL, PR_FALSE, PR_TRUE); } SECStatus cmmf_PKIStatusInfoSetStatus(CMMFPKIStatusInfo *statusInfo, PLArenaPool *poolp, CMMFPKIStatus inStatus) { SECItem *dummy; if (inStatus < cmmfGranted || inStatus >= cmmfNumPKIStatus) { return SECFailure; } dummy = SEC_ASN1EncodeInteger(poolp, &statusInfo->status, inStatus); PORT_Assert(dummy == &statusInfo->status); if (dummy != &statusInfo->status) { SECITEM_FreeItem(dummy, PR_TRUE); return SECFailure; } return SECSuccess; }