/* -*- 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 "crmf.h" #include "crmfi.h" #include "keyhi.h" #include "secder.h" CRMFPOPChoice CRMF_CertReqMsgGetPOPType(CRMFCertReqMsg *inCertReqMsg) { PORT_Assert(inCertReqMsg != NULL); if (inCertReqMsg != NULL && inCertReqMsg->pop != NULL) { return inCertReqMsg->pop->popUsed; } return crmfNoPOPChoice; } static SECStatus crmf_destroy_validity(CRMFOptionalValidity *inValidity, PRBool freeit) { if (inValidity != NULL) { if (inValidity->notBefore.data != NULL) { PORT_Free(inValidity->notBefore.data); } if (inValidity->notAfter.data != NULL) { PORT_Free(inValidity->notAfter.data); } if (freeit) { PORT_Free(inValidity); } } return SECSuccess; } static SECStatus crmf_copy_cert_request_validity(PLArenaPool *poolp, CRMFOptionalValidity **destValidity, CRMFOptionalValidity *srcValidity) { CRMFOptionalValidity *myValidity = NULL; SECStatus rv; *destValidity = myValidity = (poolp == NULL) ? PORT_ZNew(CRMFOptionalValidity) : PORT_ArenaZNew(poolp, CRMFOptionalValidity); if (myValidity == NULL) { goto loser; } if (srcValidity->notBefore.data != NULL) { rv = SECITEM_CopyItem(poolp, &myValidity->notBefore, &srcValidity->notBefore); if (rv != SECSuccess) { goto loser; } } if (srcValidity->notAfter.data != NULL) { rv = SECITEM_CopyItem(poolp, &myValidity->notAfter, &srcValidity->notAfter); if (rv != SECSuccess) { goto loser; } } return SECSuccess; loser: if (myValidity != NULL && poolp == NULL) { crmf_destroy_validity(myValidity, PR_TRUE); } return SECFailure; } static SECStatus crmf_copy_extensions(PLArenaPool *poolp, CRMFCertTemplate *destTemplate, CRMFCertExtension **srcExt) { int numExt = 0, i; CRMFCertExtension **myExtArray = NULL; while (srcExt[numExt] != NULL) { numExt++; } if (numExt == 0) { /*No extensions to copy.*/ destTemplate->extensions = NULL; destTemplate->numExtensions = 0; return SECSuccess; } destTemplate->extensions = myExtArray = PORT_NewArray(CRMFCertExtension *, numExt + 1); if (myExtArray == NULL) { goto loser; } for (i = 0; i < numExt; i++) { myExtArray[i] = crmf_copy_cert_extension(poolp, srcExt[i]); if (myExtArray[i] == NULL) { goto loser; } } destTemplate->numExtensions = numExt; myExtArray[numExt] = NULL; return SECSuccess; loser: if (myExtArray != NULL) { if (poolp == NULL) { for (i = 0; myExtArray[i] != NULL; i++) { CRMF_DestroyCertExtension(myExtArray[i]); } } PORT_Free(myExtArray); } destTemplate->extensions = NULL; destTemplate->numExtensions = 0; return SECFailure; } static SECStatus crmf_copy_cert_request_template(PLArenaPool *poolp, CRMFCertTemplate *destTemplate, CRMFCertTemplate *srcTemplate) { SECStatus rv; if (srcTemplate->version.data != NULL) { rv = SECITEM_CopyItem(poolp, &destTemplate->version, &srcTemplate->version); if (rv != SECSuccess) { goto loser; } } if (srcTemplate->serialNumber.data != NULL) { rv = SECITEM_CopyItem(poolp, &destTemplate->serialNumber, &srcTemplate->serialNumber); if (rv != SECSuccess) { goto loser; } } if (srcTemplate->signingAlg != NULL) { rv = crmf_template_copy_secalg(poolp, &destTemplate->signingAlg, srcTemplate->signingAlg); if (rv != SECSuccess) { goto loser; } } if (srcTemplate->issuer != NULL) { rv = crmf_copy_cert_name(poolp, &destTemplate->issuer, srcTemplate->issuer); if (rv != SECSuccess) { goto loser; } } if (srcTemplate->validity != NULL) { rv = crmf_copy_cert_request_validity(poolp, &destTemplate->validity, srcTemplate->validity); if (rv != SECSuccess) { goto loser; } } if (srcTemplate->subject != NULL) { rv = crmf_copy_cert_name(poolp, &destTemplate->subject, srcTemplate->subject); if (rv != SECSuccess) { goto loser; } } if (srcTemplate->publicKey != NULL) { rv = crmf_template_add_public_key(poolp, &destTemplate->publicKey, srcTemplate->publicKey); if (rv != SECSuccess) { goto loser; } } if (srcTemplate->issuerUID.data != NULL) { rv = crmf_make_bitstring_copy(poolp, &destTemplate->issuerUID, &srcTemplate->issuerUID); if (rv != SECSuccess) { goto loser; } } if (srcTemplate->subjectUID.data != NULL) { rv = crmf_make_bitstring_copy(poolp, &destTemplate->subjectUID, &srcTemplate->subjectUID); if (rv != SECSuccess) { goto loser; } } if (srcTemplate->extensions != NULL) { rv = crmf_copy_extensions(poolp, destTemplate, srcTemplate->extensions); if (rv != SECSuccess) { goto loser; } } return SECSuccess; loser: return SECFailure; } static CRMFControl * crmf_copy_control(PLArenaPool *poolp, CRMFControl *srcControl) { CRMFControl *newControl; SECStatus rv; newControl = (poolp == NULL) ? PORT_ZNew(CRMFControl) : PORT_ArenaZNew(poolp, CRMFControl); if (newControl == NULL) { goto loser; } newControl->tag = srcControl->tag; rv = SECITEM_CopyItem(poolp, &newControl->derTag, &srcControl->derTag); if (rv != SECSuccess) { goto loser; } rv = SECITEM_CopyItem(poolp, &newControl->derValue, &srcControl->derValue); if (rv != SECSuccess) { goto loser; } /* We only handle PKIArchiveOptions Control right now. But if in * the future, more controls that are part of the union are added, * then they need to be handled here as well. */ switch (newControl->tag) { case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS: rv = crmf_copy_pkiarchiveoptions(poolp, &newControl->value.archiveOptions, &srcControl->value.archiveOptions); break; default: rv = SECSuccess; } if (rv != SECSuccess) { goto loser; } return newControl; loser: if (poolp == NULL && newControl != NULL) { CRMF_DestroyControl(newControl); } return NULL; } static SECStatus crmf_copy_cert_request_controls(PLArenaPool *poolp, CRMFCertRequest *destReq, CRMFCertRequest *srcReq) { int numControls, i; CRMFControl **myControls = NULL; numControls = CRMF_CertRequestGetNumControls(srcReq); if (numControls == 0) { /* No Controls To Copy*/ return SECSuccess; } myControls = destReq->controls = PORT_NewArray(CRMFControl *, numControls + 1); if (myControls == NULL) { goto loser; } for (i = 0; i < numControls; i++) { myControls[i] = crmf_copy_control(poolp, srcReq->controls[i]); if (myControls[i] == NULL) { goto loser; } } myControls[numControls] = NULL; return SECSuccess; loser: if (myControls != NULL) { if (poolp == NULL) { for (i = 0; myControls[i] != NULL; i++) { CRMF_DestroyControl(myControls[i]); } } PORT_Free(myControls); } return SECFailure; } CRMFCertRequest * crmf_copy_cert_request(PLArenaPool *poolp, CRMFCertRequest *srcReq) { CRMFCertRequest *newReq = NULL; SECStatus rv; if (srcReq == NULL) { return NULL; } newReq = (poolp == NULL) ? PORT_ZNew(CRMFCertRequest) : PORT_ArenaZNew(poolp, CRMFCertRequest); if (newReq == NULL) { goto loser; } rv = SECITEM_CopyItem(poolp, &newReq->certReqId, &srcReq->certReqId); if (rv != SECSuccess) { goto loser; } rv = crmf_copy_cert_request_template(poolp, &newReq->certTemplate, &srcReq->certTemplate); if (rv != SECSuccess) { goto loser; } rv = crmf_copy_cert_request_controls(poolp, newReq, srcReq); if (rv != SECSuccess) { goto loser; } return newReq; loser: if (newReq != NULL && poolp == NULL) { CRMF_DestroyCertRequest(newReq); PORT_Free(newReq); } return NULL; } SECStatus CRMF_DestroyGetValidity(CRMFGetValidity *inValidity) { PORT_Assert(inValidity != NULL); if (inValidity != NULL) { if (inValidity->notAfter) { PORT_Free(inValidity->notAfter); inValidity->notAfter = NULL; } if (inValidity->notBefore) { PORT_Free(inValidity->notBefore); inValidity->notBefore = NULL; } } return SECSuccess; } SECStatus crmf_make_bitstring_copy(PLArenaPool *arena, SECItem *dest, SECItem *src) { int origLenBits; int bytesToCopy; SECStatus rv; origLenBits = src->len; bytesToCopy = CRMF_BITS_TO_BYTES(origLenBits); src->len = bytesToCopy; rv = SECITEM_CopyItem(arena, dest, src); src->len = origLenBits; if (rv != SECSuccess) { return rv; } dest->len = origLenBits; return SECSuccess; } int CRMF_CertRequestGetNumberOfExtensions(CRMFCertRequest *inCertReq) { CRMFCertTemplate *certTemplate; int count = 0; certTemplate = &inCertReq->certTemplate; if (certTemplate->extensions) { while (certTemplate->extensions[count] != NULL) count++; } return count; } SECOidTag CRMF_CertExtensionGetOidTag(CRMFCertExtension *inExtension) { PORT_Assert(inExtension != NULL); if (inExtension == NULL) { return SEC_OID_UNKNOWN; } return SECOID_FindOIDTag(&inExtension->id); } PRBool CRMF_CertExtensionGetIsCritical(CRMFCertExtension *inExt) { PORT_Assert(inExt != NULL); if (inExt == NULL) { return PR_FALSE; } return inExt->critical.data != NULL; } SECItem * CRMF_CertExtensionGetValue(CRMFCertExtension *inExtension) { PORT_Assert(inExtension != NULL); if (inExtension == NULL) { return NULL; } return SECITEM_DupItem(&inExtension->value); } SECStatus CRMF_DestroyPOPOSigningKey(CRMFPOPOSigningKey *inKey) { PORT_Assert(inKey != NULL); if (inKey != NULL) { if (inKey->derInput.data != NULL) { SECITEM_FreeItem(&inKey->derInput, PR_FALSE); } if (inKey->algorithmIdentifier != NULL) { SECOID_DestroyAlgorithmID(inKey->algorithmIdentifier, PR_TRUE); } if (inKey->signature.data != NULL) { SECITEM_FreeItem(&inKey->signature, PR_FALSE); } PORT_Free(inKey); } return SECSuccess; } SECStatus CRMF_DestroyPOPOPrivKey(CRMFPOPOPrivKey *inPrivKey) { PORT_Assert(inPrivKey != NULL); if (inPrivKey != NULL) { SECITEM_FreeItem(&inPrivKey->message.thisMessage, PR_FALSE); PORT_Free(inPrivKey); } return SECSuccess; } int CRMF_CertRequestGetNumControls(CRMFCertRequest *inCertReq) { int count = 0; PORT_Assert(inCertReq != NULL); if (inCertReq == NULL) { return 0; } if (inCertReq->controls) { while (inCertReq->controls[count] != NULL) count++; } return count; }