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