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