mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
1011 lines
26 KiB
C
1011 lines
26 KiB
C
/* -*- Mode: C; tab-width: 8 -*-*/
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is the Netscape security libraries.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
#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(PRArenaPool *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);
|
|
}
|
|
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(PRArenaPool *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(PRArenaPool *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;
|
|
PRArenaPool *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:
|
|
if (newReqMsg != NULL) {
|
|
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)
|
|
{
|
|
PRArenaPool *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)
|
|
{
|
|
PRArenaPool *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:
|
|
if (newControl != NULL) {
|
|
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]);
|
|
}
|
|
|