Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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 "keyhi.h"
#include "secder.h"
CRMFEncryptedKeyChoice
CRMF_EncryptedKeyGetChoice(CRMFEncryptedKey *inEncrKey)
{
PORT_Assert(inEncrKey != NULL);
if (inEncrKey == NULL) {
return crmfNoEncryptedKeyChoice;
}
return inEncrKey->encKeyChoice;
}
CRMFEncryptedValue *
CRMF_EncryptedKeyGetEncryptedValue(CRMFEncryptedKey *inEncrKey)
{
CRMFEncryptedValue *newEncrValue = NULL;
SECStatus rv;
PORT_Assert(inEncrKey != NULL);
if (inEncrKey == NULL ||
CRMF_EncryptedKeyGetChoice(inEncrKey) != crmfEncryptedValueChoice) {
goto loser;
}
newEncrValue = PORT_ZNew(CRMFEncryptedValue);
if (newEncrValue == NULL) {
goto loser;
}
rv = crmf_copy_encryptedvalue(NULL, &inEncrKey->value.encryptedValue,
newEncrValue);
if (rv != SECSuccess) {
goto loser;
}
return newEncrValue;
loser:
if (newEncrValue != NULL) {
CRMF_DestroyEncryptedValue(newEncrValue);
}
return NULL;
}
static SECItem *
crmf_get_encvalue_bitstring(SECItem *srcItem)
{
SECItem *newItem = NULL;
SECStatus rv;
if (srcItem->data == NULL) {
return NULL;
}
newItem = PORT_ZNew(SECItem);
if (newItem == NULL) {
goto loser;
}
rv = crmf_make_bitstring_copy(NULL, newItem, srcItem);
if (rv != SECSuccess) {
goto loser;
}
return newItem;
loser:
if (newItem != NULL) {
SECITEM_FreeItem(newItem, PR_TRUE);
}
return NULL;
}
SECItem *
CRMF_EncryptedValueGetEncSymmKey(CRMFEncryptedValue *inEncValue)
{
if (inEncValue == NULL) {
return NULL;
}
return crmf_get_encvalue_bitstring(&inEncValue->encSymmKey);
}
SECItem *
CRMF_EncryptedValueGetEncValue(CRMFEncryptedValue *inEncrValue)
{
if (inEncrValue == NULL || inEncrValue->encValue.data == NULL) {
return NULL;
}
return crmf_get_encvalue_bitstring(&inEncrValue->encValue);
}
static SECAlgorithmID *
crmf_get_encvalue_algid(SECAlgorithmID *srcAlg)
{
SECStatus rv;
SECAlgorithmID *newAlgID;
if (srcAlg == NULL) {
return NULL;
}
rv = crmf_copy_encryptedvalue_secalg(NULL, srcAlg, &newAlgID);
if (rv != SECSuccess) {
return NULL;
}
return newAlgID;
}
SECAlgorithmID *
CRMF_EncryptedValueGetIntendedAlg(CRMFEncryptedValue *inEncValue)
{
if (inEncValue == NULL) {
return NULL;
}
return crmf_get_encvalue_algid(inEncValue->intendedAlg);
}
SECAlgorithmID *
CRMF_EncryptedValueGetKeyAlg(CRMFEncryptedValue *inEncValue)
{
if (inEncValue == NULL) {
return NULL;
}
return crmf_get_encvalue_algid(inEncValue->keyAlg);
}
SECAlgorithmID *
CRMF_EncryptedValueGetSymmAlg(CRMFEncryptedValue *inEncValue)
{
if (inEncValue == NULL) {
return NULL;
}
return crmf_get_encvalue_algid(inEncValue->symmAlg);
}
SECItem *
CRMF_EncryptedValueGetValueHint(CRMFEncryptedValue *inEncValue)
{
if (inEncValue == NULL || inEncValue->valueHint.data == NULL) {
return NULL;
}
return SECITEM_DupItem(&inEncValue->valueHint);
}
SECStatus
CRMF_PKIArchiveOptionsGetArchiveRemGenPrivKey(CRMFPKIArchiveOptions *inOpt,
PRBool *destVal)
{
if (inOpt == NULL || destVal == NULL ||
CRMF_PKIArchiveOptionsGetOptionType(inOpt) != crmfArchiveRemGenPrivKey) {
return SECFailure;
}
*destVal = (inOpt->option.archiveRemGenPrivKey.data[0] == hexFalse)
? PR_FALSE
: PR_TRUE;
return SECSuccess;
}
CRMFEncryptedKey *
CRMF_PKIArchiveOptionsGetEncryptedPrivKey(CRMFPKIArchiveOptions *inOpts)
{
CRMFEncryptedKey *newEncrKey = NULL;
SECStatus rv;
PORT_Assert(inOpts != NULL);
if (inOpts == NULL ||
CRMF_PKIArchiveOptionsGetOptionType(inOpts) != crmfEncryptedPrivateKey) {
return NULL;
}
newEncrKey = PORT_ZNew(CRMFEncryptedKey);
if (newEncrKey == NULL) {
goto loser;
}
rv = crmf_copy_encryptedkey(NULL, &inOpts->option.encryptedKey,
newEncrKey);
if (rv != SECSuccess) {
goto loser;
}
return newEncrKey;
loser:
if (newEncrKey != NULL) {
CRMF_DestroyEncryptedKey(newEncrKey);
}
return NULL;
}
SECItem *
CRMF_PKIArchiveOptionsGetKeyGenParameters(CRMFPKIArchiveOptions *inOptions)
{
if (inOptions == NULL ||
CRMF_PKIArchiveOptionsGetOptionType(inOptions) != crmfKeyGenParameters ||
inOptions->option.keyGenParameters.data == NULL) {
return NULL;
}
return SECITEM_DupItem(&inOptions->option.keyGenParameters);
}
CRMFPKIArchiveOptionsType
CRMF_PKIArchiveOptionsGetOptionType(CRMFPKIArchiveOptions *inOptions)
{
PORT_Assert(inOptions != NULL);
if (inOptions == NULL) {
return crmfNoArchiveOptions;
}
return inOptions->archOption;
}
static SECStatus
crmf_extract_long_from_item(SECItem *intItem, long *destLong)
{
*destLong = DER_GetInteger(intItem);
return (*destLong == -1) ? SECFailure : SECSuccess;
}
SECStatus
CRMF_POPOPrivGetKeySubseqMess(CRMFPOPOPrivKey *inKey,
CRMFSubseqMessOptions *destOpt)
{
long value;
SECStatus rv;
PORT_Assert(inKey != NULL);
if (inKey == NULL ||
inKey->messageChoice != crmfSubsequentMessage) {
return SECFailure;
}
rv = crmf_extract_long_from_item(&inKey->message.subsequentMessage, &value);
if (rv != SECSuccess) {
return SECFailure;
}
switch (value) {
case 0:
*destOpt = crmfEncrCert;
break;
case 1:
*destOpt = crmfChallengeResp;
break;
default:
rv = SECFailure;
}
if (rv != SECSuccess) {
return rv;
}
return SECSuccess;
}
CRMFPOPOPrivKeyChoice
CRMF_POPOPrivKeyGetChoice(CRMFPOPOPrivKey *inPrivKey)
{
PORT_Assert(inPrivKey != NULL);
if (inPrivKey != NULL) {
return inPrivKey->messageChoice;
}
return crmfNoMessage;
}
SECStatus
CRMF_POPOPrivKeyGetDHMAC(CRMFPOPOPrivKey *inKey, SECItem *destMAC)
{
PORT_Assert(inKey != NULL);
if (inKey == NULL || inKey->message.dhMAC.data == NULL) {
return SECFailure;
}
return crmf_make_bitstring_copy(NULL, destMAC, &inKey->message.dhMAC);
}
SECStatus
CRMF_POPOPrivKeyGetThisMessage(CRMFPOPOPrivKey *inKey,
SECItem *destString)
{
PORT_Assert(inKey != NULL);
if (inKey == NULL ||
inKey->messageChoice != crmfThisMessage) {
return SECFailure;
}
return crmf_make_bitstring_copy(NULL, destString,
&inKey->message.thisMessage);
}
SECAlgorithmID *
CRMF_POPOSigningKeyGetAlgID(CRMFPOPOSigningKey *inSignKey)
{
SECAlgorithmID *newAlgId = NULL;
SECStatus rv;
PORT_Assert(inSignKey != NULL);
if (inSignKey == NULL) {
return NULL;
}
newAlgId = PORT_ZNew(SECAlgorithmID);
if (newAlgId == NULL) {
goto loser;
}
rv = SECOID_CopyAlgorithmID(NULL, newAlgId,
inSignKey->algorithmIdentifier);
if (rv != SECSuccess) {
goto loser;
}
return newAlgId;
loser:
if (newAlgId != NULL) {
SECOID_DestroyAlgorithmID(newAlgId, PR_TRUE);
}
return NULL;
}
SECItem *
CRMF_POPOSigningKeyGetInput(CRMFPOPOSigningKey *inSignKey)
{
PORT_Assert(inSignKey != NULL);
if (inSignKey == NULL || inSignKey->derInput.data == NULL) {
return NULL;
}
return SECITEM_DupItem(&inSignKey->derInput);
}
SECItem *
CRMF_POPOSigningKeyGetSignature(CRMFPOPOSigningKey *inSignKey)
{
SECItem *newSig = NULL;
SECStatus rv;
PORT_Assert(inSignKey != NULL);
if (inSignKey == NULL) {
return NULL;
}
newSig = PORT_ZNew(SECItem);
if (newSig == NULL) {
goto loser;
}
rv = crmf_make_bitstring_copy(NULL, newSig, &inSignKey->signature);
if (rv != SECSuccess) {
goto loser;
}
return newSig;
loser:
if (newSig != NULL) {
SECITEM_FreeItem(newSig, PR_TRUE);
}
return NULL;
}
static SECStatus
crmf_copy_poposigningkey(PLArenaPool *poolp,
CRMFPOPOSigningKey *inPopoSignKey,
CRMFPOPOSigningKey *destPopoSignKey)
{
SECStatus rv;
/* We don't support use of the POPOSigningKeyInput, so we'll only
* store away the DER encoding.
*/
if (inPopoSignKey->derInput.data != NULL) {
rv = SECITEM_CopyItem(poolp, &destPopoSignKey->derInput,
&inPopoSignKey->derInput);
if (rv != SECSuccess) {
goto loser;
}
}
destPopoSignKey->algorithmIdentifier = (poolp == NULL) ? PORT_ZNew(SECAlgorithmID)
: PORT_ArenaZNew(poolp, SECAlgorithmID);
if (destPopoSignKey->algorithmIdentifier == NULL) {
goto loser;
}
rv = SECOID_CopyAlgorithmID(poolp, destPopoSignKey->algorithmIdentifier,
inPopoSignKey->algorithmIdentifier);
if (rv != SECSuccess) {
goto loser;
}
rv = crmf_make_bitstring_copy(poolp, &destPopoSignKey->signature,
&inPopoSignKey->signature);
if (rv != SECSuccess) {
goto loser;
}
return SECSuccess;
loser:
if (poolp == NULL) {
CRMF_DestroyPOPOSigningKey(destPopoSignKey);
}
return SECFailure;
}
static SECStatus
crmf_copy_popoprivkey(PLArenaPool *poolp,
CRMFPOPOPrivKey *srcPrivKey,
CRMFPOPOPrivKey *destPrivKey)
{
SECStatus rv;
destPrivKey->messageChoice = srcPrivKey->messageChoice;
switch (destPrivKey->messageChoice) {
case crmfThisMessage:
case crmfDHMAC:
/* I've got a union, so taking the address of one, will also give
* me a pointer to the other (eg, message.dhMAC)
*/
rv = crmf_make_bitstring_copy(poolp, &destPrivKey->message.thisMessage,
&srcPrivKey->message.thisMessage);
break;
case crmfSubsequentMessage:
rv = SECITEM_CopyItem(poolp, &destPrivKey->message.subsequentMessage,
&srcPrivKey->message.subsequentMessage);
break;
default:
rv = SECFailure;
}
if (rv != SECSuccess && poolp == NULL) {
CRMF_DestroyPOPOPrivKey(destPrivKey);
}
return rv;
}
static CRMFProofOfPossession *
crmf_copy_pop(PLArenaPool *poolp, CRMFProofOfPossession *srcPOP)
{
CRMFProofOfPossession *newPOP;
SECStatus rv;
/*
* Proof Of Possession structures are always part of the Request
* message, so there will always be an arena for allocating memory.
*/
if (poolp == NULL) {
return NULL;
}
newPOP = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
if (newPOP == NULL) {
return NULL;
}
switch (srcPOP->popUsed) {
case crmfRAVerified:
newPOP->popChoice.raVerified.data = NULL;
newPOP->popChoice.raVerified.len = 0;
break;
case crmfSignature:
rv = crmf_copy_poposigningkey(poolp, &srcPOP->popChoice.signature,
&newPOP->popChoice.signature);
if (rv != SECSuccess) {
goto loser;
}
break;
case crmfKeyEncipherment:
case crmfKeyAgreement:
/* We've got a union, so a pointer to one, is a pointer to the
* other one.
*/
rv = crmf_copy_popoprivkey(poolp, &srcPOP->popChoice.keyEncipherment,
&newPOP->popChoice.keyEncipherment);
if (rv != SECSuccess) {
goto loser;
}
break;
default:
goto loser;
}
newPOP->popUsed = srcPOP->popUsed;
return newPOP;
loser:
return NULL;
}
static CRMFCertReqMsg *
crmf_copy_cert_req_msg(CRMFCertReqMsg *srcReqMsg)
{
CRMFCertReqMsg *newReqMsg;
PLArenaPool *poolp;
poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
if (poolp == NULL) {
return NULL;
}
newReqMsg = PORT_ArenaZNew(poolp, CRMFCertReqMsg);
if (newReqMsg == NULL) {
PORT_FreeArena(poolp, PR_TRUE);
return NULL;
}
newReqMsg->poolp = poolp;
newReqMsg->certReq = crmf_copy_cert_request(poolp, srcReqMsg->certReq);
if (newReqMsg->certReq == NULL) {
goto loser;
}
newReqMsg->pop = crmf_copy_pop(poolp, srcReqMsg->pop);
if (newReqMsg->pop == NULL) {
goto loser;
}
/* None of my set/get routines operate on the regInfo field, so
* for now, that won't get copied over.
*/
return newReqMsg;
loser:
CRMF_DestroyCertReqMsg(newReqMsg);
return NULL;
}
CRMFCertReqMsg *
CRMF_CertReqMessagesGetCertReqMsgAtIndex(CRMFCertReqMessages *inReqMsgs,
int index)
{
int numMsgs;
PORT_Assert(inReqMsgs != NULL && index >= 0);
if (inReqMsgs == NULL) {
return NULL;
}
numMsgs = CRMF_CertReqMessagesGetNumMessages(inReqMsgs);
if (index < 0 || index >= numMsgs) {
return NULL;
}
return crmf_copy_cert_req_msg(inReqMsgs->messages[index]);
}
int
CRMF_CertReqMessagesGetNumMessages(CRMFCertReqMessages *inCertReqMsgs)
{
int numMessages = 0;
PORT_Assert(inCertReqMsgs != NULL);
if (inCertReqMsgs == NULL) {
return 0;
}
while (inCertReqMsgs->messages[numMessages] != NULL) {
numMessages++;
}
return numMessages;
}
CRMFCertRequest *
CRMF_CertReqMsgGetCertRequest(CRMFCertReqMsg *inCertReqMsg)
{
PLArenaPool *poolp = NULL;
CRMFCertRequest *newCertReq = NULL;
PORT_Assert(inCertReqMsg != NULL);
poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
if (poolp == NULL) {
goto loser;
}
newCertReq = crmf_copy_cert_request(poolp, inCertReqMsg->certReq);
if (newCertReq == NULL) {
goto loser;
}
newCertReq->poolp = poolp;
return newCertReq;
loser:
if (poolp != NULL) {
PORT_FreeArena(poolp, PR_FALSE);
}
return NULL;
}
SECStatus
CRMF_CertReqMsgGetID(CRMFCertReqMsg *inCertReqMsg, long *destID)
{
PORT_Assert(inCertReqMsg != NULL && destID != NULL);
if (inCertReqMsg == NULL || inCertReqMsg->certReq == NULL) {
return SECFailure;
}
return crmf_extract_long_from_item(&inCertReqMsg->certReq->certReqId,
destID);
}
SECStatus
CRMF_CertReqMsgGetPOPKeyAgreement(CRMFCertReqMsg *inCertReqMsg,
CRMFPOPOPrivKey **destKey)
{
PORT_Assert(inCertReqMsg != NULL && destKey != NULL);
if (inCertReqMsg == NULL || destKey == NULL ||
CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfKeyAgreement) {
return SECFailure;
}
*destKey = PORT_ZNew(CRMFPOPOPrivKey);
if (*destKey == NULL) {
return SECFailure;
}
return crmf_copy_popoprivkey(NULL,
&inCertReqMsg->pop->popChoice.keyAgreement,
*destKey);
}
SECStatus
CRMF_CertReqMsgGetPOPKeyEncipherment(CRMFCertReqMsg *inCertReqMsg,
CRMFPOPOPrivKey **destKey)
{
PORT_Assert(inCertReqMsg != NULL && destKey != NULL);
if (inCertReqMsg == NULL || destKey == NULL ||
CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfKeyEncipherment) {
return SECFailure;
}
*destKey = PORT_ZNew(CRMFPOPOPrivKey);
if (*destKey == NULL) {
return SECFailure;
}
return crmf_copy_popoprivkey(NULL,
&inCertReqMsg->pop->popChoice.keyEncipherment,
*destKey);
}
SECStatus
CRMF_CertReqMsgGetPOPOSigningKey(CRMFCertReqMsg *inCertReqMsg,
CRMFPOPOSigningKey **destKey)
{
CRMFProofOfPossession *pop;
PORT_Assert(inCertReqMsg != NULL);
if (inCertReqMsg == NULL) {
return SECFailure;
}
pop = inCertReqMsg->pop;
;
if (pop->popUsed != crmfSignature) {
return SECFailure;
}
*destKey = PORT_ZNew(CRMFPOPOSigningKey);
if (*destKey == NULL) {
return SECFailure;
}
return crmf_copy_poposigningkey(NULL, &pop->popChoice.signature, *destKey);
}
static SECStatus
crmf_copy_name(CERTName *destName, CERTName *srcName)
{
PLArenaPool *poolp = NULL;
SECStatus rv;
if (destName->arena != NULL) {
poolp = destName->arena;
} else {
poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
}
if (poolp == NULL) {
return SECFailure;
}
/* Need to do this so that CERT_CopyName doesn't free out
* the arena from underneath us.
*/
destName->arena = NULL;
rv = CERT_CopyName(poolp, destName, srcName);
destName->arena = poolp;
return rv;
}
SECStatus
CRMF_CertRequestGetCertTemplateIssuer(CRMFCertRequest *inCertReq,
CERTName *destIssuer)
{
PORT_Assert(inCertReq != NULL);
if (inCertReq == NULL) {
return SECFailure;
}
if (CRMF_DoesRequestHaveField(inCertReq, crmfIssuer)) {
return crmf_copy_name(destIssuer,
inCertReq->certTemplate.issuer);
}
return SECFailure;
}
SECStatus
CRMF_CertRequestGetCertTemplateIssuerUID(CRMFCertRequest *inCertReq,
SECItem *destIssuerUID)
{
PORT_Assert(inCertReq != NULL);
if (inCertReq == NULL) {
return SECFailure;
}
if (CRMF_DoesRequestHaveField(inCertReq, crmfIssuerUID)) {
return crmf_make_bitstring_copy(NULL, destIssuerUID,
&inCertReq->certTemplate.issuerUID);
}
return SECFailure;
}
SECStatus
CRMF_CertRequestGetCertTemplatePublicKey(CRMFCertRequest *inCertReq,
CERTSubjectPublicKeyInfo *destPublicKey)
{
PORT_Assert(inCertReq != NULL);
if (inCertReq == NULL) {
return SECFailure;
}
if (CRMF_DoesRequestHaveField(inCertReq, crmfPublicKey)) {
return SECKEY_CopySubjectPublicKeyInfo(NULL, destPublicKey,
inCertReq->certTemplate.publicKey);
}
return SECFailure;
}
SECStatus
CRMF_CertRequestGetCertTemplateSerialNumber(CRMFCertRequest *inCertReq,
long *serialNumber)
{
PORT_Assert(inCertReq != NULL);
if (inCertReq == NULL) {
return SECFailure;
}
if (CRMF_DoesRequestHaveField(inCertReq, crmfSerialNumber)) {
return crmf_extract_long_from_item(&inCertReq->certTemplate.serialNumber,
serialNumber);
}
return SECFailure;
}
SECStatus
CRMF_CertRequestGetCertTemplateSigningAlg(CRMFCertRequest *inCertReq,
SECAlgorithmID *destAlg)
{
PORT_Assert(inCertReq != NULL);
if (inCertReq == NULL) {
return SECFailure;
}
if (CRMF_DoesRequestHaveField(inCertReq, crmfSigningAlg)) {
return SECOID_CopyAlgorithmID(NULL, destAlg,
inCertReq->certTemplate.signingAlg);
}
return SECFailure;
}
SECStatus
CRMF_CertRequestGetCertTemplateSubject(CRMFCertRequest *inCertReq,
CERTName *destSubject)
{
PORT_Assert(inCertReq != NULL);
if (inCertReq == NULL) {
return SECFailure;
}
if (CRMF_DoesRequestHaveField(inCertReq, crmfSubject)) {
return crmf_copy_name(destSubject, inCertReq->certTemplate.subject);
}
return SECFailure;
}
SECStatus
CRMF_CertRequestGetCertTemplateSubjectUID(CRMFCertRequest *inCertReq,
SECItem *destSubjectUID)
{
PORT_Assert(inCertReq != NULL);
if (inCertReq == NULL) {
return SECFailure;
}
if (CRMF_DoesRequestHaveField(inCertReq, crmfSubjectUID)) {
return crmf_make_bitstring_copy(NULL, destSubjectUID,
&inCertReq->certTemplate.subjectUID);
}
return SECFailure;
}
SECStatus
CRMF_CertRequestGetCertTemplateVersion(CRMFCertRequest *inCertReq,
long *version)
{
PORT_Assert(inCertReq != NULL);
if (inCertReq == NULL) {
return SECFailure;
}
if (CRMF_DoesRequestHaveField(inCertReq, crmfVersion)) {
return crmf_extract_long_from_item(&inCertReq->certTemplate.version,
version);
}
return SECFailure;
}
static SECStatus
crmf_copy_validity(CRMFGetValidity *destValidity,
CRMFOptionalValidity *src)
{
SECStatus rv;
destValidity->notBefore = destValidity->notAfter = NULL;
if (src->notBefore.data != NULL) {
rv = crmf_create_prtime(&src->notBefore,
&destValidity->notBefore);
if (rv != SECSuccess) {
return rv;
}
}
if (src->notAfter.data != NULL) {
rv = crmf_create_prtime(&src->notAfter,
&destValidity->notAfter);
if (rv != SECSuccess) {
return rv;
}
}
return SECSuccess;
}
SECStatus
CRMF_CertRequestGetCertTemplateValidity(CRMFCertRequest *inCertReq,
CRMFGetValidity *destValidity)
{
PORT_Assert(inCertReq != NULL);
if (inCertReq == NULL) {
return SECFailure;
}
if (CRMF_DoesRequestHaveField(inCertReq, crmfValidity)) {
return crmf_copy_validity(destValidity,
inCertReq->certTemplate.validity);
}
return SECFailure;
}
CRMFControl *
CRMF_CertRequestGetControlAtIndex(CRMFCertRequest *inCertReq, int index)
{
CRMFControl *newControl, *srcControl;
int numControls;
SECStatus rv;
PORT_Assert(inCertReq != NULL);
if (inCertReq == NULL) {
return NULL;
}
numControls = CRMF_CertRequestGetNumControls(inCertReq);
if (index >= numControls || index < 0) {
return NULL;
}
newControl = PORT_ZNew(CRMFControl);
if (newControl == NULL) {
return NULL;
}
srcControl = inCertReq->controls[index];
newControl->tag = srcControl->tag;
rv = SECITEM_CopyItem(NULL, &newControl->derTag, &srcControl->derTag);
if (rv != SECSuccess) {
goto loser;
}
rv = SECITEM_CopyItem(NULL, &newControl->derValue,
&srcControl->derValue);
if (rv != SECSuccess) {
goto loser;
}
/* Copy over the PKIArchiveOptions stuff */
switch (srcControl->tag) {
case SEC_OID_PKIX_REGCTRL_REGTOKEN:
case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
/* No further processing necessary for these types. */
rv = SECSuccess;
break;
case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
/* These aren't supported yet, so no post-processing will
* be done at this time. But we don't want to fail in case
* we read in DER that has one of these options.
*/
rv = SECSuccess;
break;
case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
rv = crmf_copy_pkiarchiveoptions(NULL,
&newControl->value.archiveOptions,
&srcControl->value.archiveOptions);
break;
default:
rv = SECFailure;
}
if (rv != SECSuccess) {
goto loser;
}
return newControl;
loser:
CRMF_DestroyControl(newControl);
return NULL;
}
static SECItem *
crmf_copy_control_value(CRMFControl *inControl)
{
return SECITEM_DupItem(&inControl->derValue);
}
SECItem *
CRMF_ControlGetAuthenticatorControlValue(CRMFControl *inControl)
{
PORT_Assert(inControl != NULL);
if (inControl == NULL ||
CRMF_ControlGetControlType(inControl) != crmfAuthenticatorControl) {
return NULL;
}
return crmf_copy_control_value(inControl);
}
CRMFControlType
CRMF_ControlGetControlType(CRMFControl *inControl)
{
CRMFControlType retType;
PORT_Assert(inControl != NULL);
switch (inControl->tag) {
case SEC_OID_PKIX_REGCTRL_REGTOKEN:
retType = crmfRegTokenControl;
break;
case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
retType = crmfAuthenticatorControl;
break;
case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
retType = crmfPKIPublicationInfoControl;
break;
case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
retType = crmfPKIArchiveOptionsControl;
break;
case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
retType = crmfOldCertIDControl;
break;
case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
retType = crmfProtocolEncrKeyControl;
break;
default:
retType = crmfNoControl;
}
return retType;
}
CRMFPKIArchiveOptions *
CRMF_ControlGetPKIArchiveOptions(CRMFControl *inControl)
{
CRMFPKIArchiveOptions *newOpt = NULL;
SECStatus rv;
PORT_Assert(inControl != NULL);
if (inControl == NULL ||
CRMF_ControlGetControlType(inControl) != crmfPKIArchiveOptionsControl) {
goto loser;
}
newOpt = PORT_ZNew(CRMFPKIArchiveOptions);
if (newOpt == NULL) {
goto loser;
}
rv = crmf_copy_pkiarchiveoptions(NULL, newOpt,
&inControl->value.archiveOptions);
if (rv != SECSuccess) {
goto loser;
}
loser:
if (newOpt != NULL) {
CRMF_DestroyPKIArchiveOptions(newOpt);
}
return NULL;
}
SECItem *
CRMF_ControlGetRegTokenControlValue(CRMFControl *inControl)
{
PORT_Assert(inControl != NULL);
if (inControl == NULL ||
CRMF_ControlGetControlType(inControl) != crmfRegTokenControl) {
return NULL;
}
return crmf_copy_control_value(inControl);
;
}
CRMFCertExtension *
CRMF_CertRequestGetExtensionAtIndex(CRMFCertRequest *inCertReq,
int index)
{
int numExtensions;
PORT_Assert(inCertReq != NULL);
numExtensions = CRMF_CertRequestGetNumberOfExtensions(inCertReq);
if (index >= numExtensions || index < 0) {
return NULL;
}
return crmf_copy_cert_extension(NULL,
inCertReq->certTemplate.extensions[index]);
}