diff options
Diffstat (limited to 'security/nss/lib/crmf/respcmn.c')
-rw-r--r-- | security/nss/lib/crmf/respcmn.c | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/security/nss/lib/crmf/respcmn.c b/security/nss/lib/crmf/respcmn.c new file mode 100644 index 000000000..f9e4155a3 --- /dev/null +++ b/security/nss/lib/crmf/respcmn.c @@ -0,0 +1,399 @@ +/* -*- 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; +} |