| /* -*- 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; |
| } |