mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-11 02:10:17 +01:00
703 lines
19 KiB
C
703 lines
19 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 "crmf.h"
|
||
|
#include "crmfi.h"
|
||
|
#include "keyhi.h"
|
||
|
#include "secder.h"
|
||
|
|
||
|
/*
|
||
|
* Macro that returns PR_TRUE if the pointer is not NULL.
|
||
|
* If the pointer is NULL, then the macro will return PR_FALSE.
|
||
|
*/
|
||
|
#define IS_NOT_NULL(ptr) ((ptr) == NULL) ? PR_FALSE : PR_TRUE
|
||
|
|
||
|
const unsigned char hexTrue = 0xff;
|
||
|
const unsigned char hexFalse = 0x00;
|
||
|
|
||
|
|
||
|
SECStatus
|
||
|
crmf_encode_integer(PRArenaPool *poolp, SECItem *dest, long value)
|
||
|
{
|
||
|
SECItem *dummy;
|
||
|
|
||
|
dummy = SEC_ASN1EncodeInteger(poolp, dest, value);
|
||
|
PORT_Assert (dummy == dest);
|
||
|
if (dummy == NULL) {
|
||
|
return SECFailure;
|
||
|
}
|
||
|
return SECSuccess;
|
||
|
}
|
||
|
|
||
|
SECStatus
|
||
|
crmf_encode_unsigned_integer(PRArenaPool *poolp, SECItem *dest,
|
||
|
unsigned long value)
|
||
|
{
|
||
|
SECItem *dummy;
|
||
|
|
||
|
dummy = SEC_ASN1EncodeUnsignedInteger(poolp, dest, value);
|
||
|
PORT_Assert (dummy == dest);
|
||
|
if (dummy != dest) {
|
||
|
return SECFailure;
|
||
|
}
|
||
|
return SECSuccess;
|
||
|
}
|
||
|
|
||
|
static SECStatus
|
||
|
crmf_copy_secitem (PRArenaPool *poolp, SECItem *dest, SECItem *src)
|
||
|
{
|
||
|
return SECITEM_CopyItem (poolp, dest, src);
|
||
|
}
|
||
|
|
||
|
PRBool
|
||
|
CRMF_DoesRequestHaveField (CRMFCertRequest *inCertReq,
|
||
|
CRMFCertTemplateField inField)
|
||
|
{
|
||
|
|
||
|
PORT_Assert(inCertReq != NULL);
|
||
|
if (inCertReq == NULL) {
|
||
|
return PR_FALSE;
|
||
|
}
|
||
|
switch (inField) {
|
||
|
case crmfVersion:
|
||
|
return inCertReq->certTemplate.version.data != NULL;
|
||
|
case crmfSerialNumber:
|
||
|
return inCertReq->certTemplate.serialNumber.data != NULL;
|
||
|
case crmfSigningAlg:
|
||
|
return inCertReq->certTemplate.signingAlg != NULL;
|
||
|
case crmfIssuer:
|
||
|
return inCertReq->certTemplate.issuer != NULL;
|
||
|
case crmfValidity:
|
||
|
return inCertReq->certTemplate.validity != NULL;
|
||
|
case crmfSubject:
|
||
|
return inCertReq->certTemplate.subject != NULL;
|
||
|
case crmfPublicKey:
|
||
|
return inCertReq->certTemplate.publicKey != NULL;
|
||
|
case crmfIssuerUID:
|
||
|
return inCertReq->certTemplate.issuerUID.data != NULL;
|
||
|
case crmfSubjectUID:
|
||
|
return inCertReq->certTemplate.subjectUID.data != NULL;
|
||
|
case crmfExtension:
|
||
|
return CRMF_CertRequestGetNumberOfExtensions(inCertReq) != 0;
|
||
|
}
|
||
|
return PR_FALSE;
|
||
|
}
|
||
|
|
||
|
CRMFCertRequest *
|
||
|
CRMF_CreateCertRequest (PRUint32 inRequestID)
|
||
|
{
|
||
|
PRArenaPool *poolp;
|
||
|
CRMFCertRequest *certReq;
|
||
|
SECStatus rv;
|
||
|
|
||
|
poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
|
||
|
if (poolp == NULL) {
|
||
|
goto loser;
|
||
|
}
|
||
|
|
||
|
certReq=PORT_ArenaZNew(poolp,CRMFCertRequest);
|
||
|
if (certReq == NULL) {
|
||
|
goto loser;
|
||
|
}
|
||
|
|
||
|
certReq->poolp = poolp;
|
||
|
certReq->requestID = inRequestID;
|
||
|
|
||
|
rv = crmf_encode_unsigned_integer(poolp, &(certReq->certReqId),
|
||
|
inRequestID);
|
||
|
if (rv != SECSuccess) {
|
||
|
goto loser;
|
||
|
}
|
||
|
|
||
|
return certReq;
|
||
|
loser:
|
||
|
if (poolp) {
|
||
|
PORT_FreeArena(poolp, PR_FALSE);
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
SECStatus
|
||
|
CRMF_DestroyCertRequest(CRMFCertRequest *inCertReq)
|
||
|
{
|
||
|
PORT_Assert(inCertReq != NULL);
|
||
|
if (inCertReq != NULL) {
|
||
|
if (inCertReq->certTemplate.extensions) {
|
||
|
PORT_Free(inCertReq->certTemplate.extensions);
|
||
|
}
|
||
|
if (inCertReq->controls) {
|
||
|
/* Right now we don't support EnveloppedData option,
|
||
|
* so we won't go through and delete each occurrence of
|
||
|
* an EnveloppedData in the control.
|
||
|
*/
|
||
|
PORT_Free(inCertReq->controls);
|
||
|
}
|
||
|
if (inCertReq->poolp) {
|
||
|
PORT_FreeArena(inCertReq->poolp, PR_TRUE);
|
||
|
}
|
||
|
}
|
||
|
return SECSuccess;
|
||
|
}
|
||
|
|
||
|
static SECStatus
|
||
|
crmf_template_add_version(PRArenaPool *poolp, SECItem *dest, long version)
|
||
|
{
|
||
|
return (crmf_encode_integer(poolp, dest, version));
|
||
|
}
|
||
|
|
||
|
static SECStatus
|
||
|
crmf_template_add_serialnumber(PRArenaPool *poolp, SECItem *dest, long serial)
|
||
|
{
|
||
|
return (crmf_encode_integer(poolp, dest, serial));
|
||
|
}
|
||
|
|
||
|
SECStatus
|
||
|
crmf_template_copy_secalg (PRArenaPool *poolp, SECAlgorithmID **dest,
|
||
|
SECAlgorithmID* src)
|
||
|
{
|
||
|
SECStatus rv;
|
||
|
void *mark = NULL;
|
||
|
SECAlgorithmID *mySecAlg;
|
||
|
|
||
|
if (!poolp) {
|
||
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||
|
return SECFailure;
|
||
|
}
|
||
|
|
||
|
mark = PORT_ArenaMark(poolp);
|
||
|
*dest = mySecAlg = PORT_ArenaZNew(poolp, SECAlgorithmID);
|
||
|
if (mySecAlg == NULL) {
|
||
|
goto loser;
|
||
|
}
|
||
|
rv = SECOID_CopyAlgorithmID(poolp, mySecAlg, src);
|
||
|
if (rv != SECSuccess) {
|
||
|
goto loser;
|
||
|
}
|
||
|
if (mark) {
|
||
|
PORT_ArenaUnmark(poolp, mark);
|
||
|
}
|
||
|
return SECSuccess;
|
||
|
|
||
|
loser:
|
||
|
*dest = NULL;
|
||
|
if (mark) {
|
||
|
PORT_ArenaRelease(poolp, mark);
|
||
|
}
|
||
|
return SECFailure;
|
||
|
}
|
||
|
|
||
|
SECStatus
|
||
|
crmf_copy_cert_name(PRArenaPool *poolp, CERTName **dest,
|
||
|
CERTName *src)
|
||
|
{
|
||
|
CERTName *newName;
|
||
|
SECStatus rv;
|
||
|
void *mark;
|
||
|
|
||
|
mark = PORT_ArenaMark(poolp);
|
||
|
*dest = newName = PORT_ArenaZNew(poolp, CERTName);
|
||
|
if (newName == NULL) {
|
||
|
goto loser;
|
||
|
}
|
||
|
|
||
|
rv = CERT_CopyName(poolp, newName, src);
|
||
|
if (rv != SECSuccess) {
|
||
|
goto loser;
|
||
|
}
|
||
|
PORT_ArenaUnmark(poolp, mark);
|
||
|
return SECSuccess;
|
||
|
loser:
|
||
|
PORT_ArenaRelease(poolp, mark);
|
||
|
*dest = NULL;
|
||
|
return SECFailure;
|
||
|
}
|
||
|
|
||
|
static SECStatus
|
||
|
crmf_template_add_issuer (PRArenaPool *poolp, CERTName **dest,
|
||
|
CERTName* issuerName)
|
||
|
{
|
||
|
return crmf_copy_cert_name(poolp, dest, issuerName);
|
||
|
}
|
||
|
|
||
|
|
||
|
static SECStatus
|
||
|
crmf_template_add_validity (PRArenaPool *poolp, CRMFOptionalValidity **dest,
|
||
|
CRMFValidityCreationInfo *info)
|
||
|
{
|
||
|
SECStatus rv;
|
||
|
void *mark;
|
||
|
CRMFOptionalValidity *myValidity;
|
||
|
|
||
|
/*First off, let's make sure at least one of the two fields is present*/
|
||
|
if (!info || (!info->notBefore && !info->notAfter)) {
|
||
|
return SECFailure;
|
||
|
}
|
||
|
mark = PORT_ArenaMark (poolp);
|
||
|
*dest = myValidity = PORT_ArenaZNew(poolp, CRMFOptionalValidity);
|
||
|
if (myValidity == NULL) {
|
||
|
goto loser;
|
||
|
}
|
||
|
|
||
|
if (info->notBefore) {
|
||
|
rv = DER_EncodeTimeChoice (poolp, &myValidity->notBefore,
|
||
|
*info->notBefore);
|
||
|
if (rv != SECSuccess) {
|
||
|
goto loser;
|
||
|
}
|
||
|
}
|
||
|
if (info->notAfter) {
|
||
|
rv = DER_EncodeTimeChoice (poolp, &myValidity->notAfter,
|
||
|
*info->notAfter);
|
||
|
if (rv != SECSuccess) {
|
||
|
goto loser;
|
||
|
}
|
||
|
}
|
||
|
PORT_ArenaUnmark(poolp, mark);
|
||
|
return SECSuccess;
|
||
|
loser:
|
||
|
PORT_ArenaRelease(poolp, mark);
|
||
|
*dest = NULL;
|
||
|
return SECFailure;
|
||
|
}
|
||
|
|
||
|
static SECStatus
|
||
|
crmf_template_add_subject (PRArenaPool *poolp, CERTName **dest,
|
||
|
CERTName *subject)
|
||
|
{
|
||
|
return crmf_copy_cert_name(poolp, dest, subject);
|
||
|
}
|
||
|
|
||
|
SECStatus
|
||
|
crmf_template_add_public_key(PRArenaPool *poolp,
|
||
|
CERTSubjectPublicKeyInfo **dest,
|
||
|
CERTSubjectPublicKeyInfo *pubKey)
|
||
|
{
|
||
|
CERTSubjectPublicKeyInfo *spki;
|
||
|
SECStatus rv;
|
||
|
|
||
|
*dest = spki = (poolp == NULL) ?
|
||
|
PORT_ZNew(CERTSubjectPublicKeyInfo) :
|
||
|
PORT_ArenaZNew (poolp, CERTSubjectPublicKeyInfo);
|
||
|
if (spki == NULL) {
|
||
|
goto loser;
|
||
|
}
|
||
|
rv = SECKEY_CopySubjectPublicKeyInfo (poolp, spki, pubKey);
|
||
|
if (rv != SECSuccess) {
|
||
|
goto loser;
|
||
|
}
|
||
|
return SECSuccess;
|
||
|
loser:
|
||
|
if (poolp == NULL && spki != NULL) {
|
||
|
SECKEY_DestroySubjectPublicKeyInfo(spki);
|
||
|
}
|
||
|
*dest = NULL;
|
||
|
return SECFailure;
|
||
|
}
|
||
|
|
||
|
static SECStatus
|
||
|
crmf_copy_bitstring (PRArenaPool *poolp, SECItem *dest, const SECItem *src)
|
||
|
{
|
||
|
SECStatus rv;
|
||
|
SECItem byteSrc;
|
||
|
|
||
|
byteSrc = *src;
|
||
|
byteSrc.len = CRMF_BITS_TO_BYTES(byteSrc.len);
|
||
|
rv = crmf_copy_secitem(poolp, dest, &byteSrc);
|
||
|
dest->len = src->len;
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
static SECStatus
|
||
|
crmf_template_add_issuer_uid(PRArenaPool *poolp, SECItem *dest,
|
||
|
const SECItem *issuerUID)
|
||
|
{
|
||
|
return crmf_copy_bitstring (poolp, dest, issuerUID);
|
||
|
}
|
||
|
|
||
|
static SECStatus
|
||
|
crmf_template_add_subject_uid(PRArenaPool *poolp, SECItem *dest,
|
||
|
const SECItem *subjectUID)
|
||
|
{
|
||
|
return crmf_copy_bitstring (poolp, dest, subjectUID);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
crmf_zeroize_new_extensions (CRMFCertExtension **extensions,
|
||
|
int numToZeroize)
|
||
|
{
|
||
|
PORT_Memset((void*)extensions, 0, sizeof(CERTCertExtension*)*numToZeroize);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* The strategy for adding templates will differ from all the other
|
||
|
* attributes in the template. First, we want to allow the client
|
||
|
* of this API to set extensions more than just once. So we will
|
||
|
* need the ability grow the array of extensions. Since arenas don't
|
||
|
* give us the realloc function, we'll use the generic PORT_* functions
|
||
|
* to allocate the array of pointers *ONLY*. Then we will allocate each
|
||
|
* individual extension from the arena that comes along with the certReq
|
||
|
* structure that owns this template.
|
||
|
*/
|
||
|
static SECStatus
|
||
|
crmf_template_add_extensions(PRArenaPool *poolp, CRMFCertTemplate *inTemplate,
|
||
|
CRMFCertExtCreationInfo *extensions)
|
||
|
{
|
||
|
void *mark;
|
||
|
int newSize, oldSize, i;
|
||
|
SECStatus rv;
|
||
|
CRMFCertExtension **extArray;
|
||
|
CRMFCertExtension *newExt, *currExt;
|
||
|
|
||
|
mark = PORT_ArenaMark(poolp);
|
||
|
if (inTemplate->extensions == NULL) {
|
||
|
newSize = extensions->numExtensions;
|
||
|
extArray = PORT_ZNewArray(CRMFCertExtension*,newSize+1);
|
||
|
} else {
|
||
|
newSize = inTemplate->numExtensions + extensions->numExtensions;
|
||
|
extArray = PORT_Realloc(inTemplate->extensions,
|
||
|
sizeof(CRMFCertExtension*)*(newSize+1));
|
||
|
}
|
||
|
if (extArray == NULL) {
|
||
|
goto loser;
|
||
|
}
|
||
|
oldSize = inTemplate->numExtensions;
|
||
|
inTemplate->extensions = extArray;
|
||
|
inTemplate->numExtensions = newSize;
|
||
|
for (i=oldSize; i < newSize; i++) {
|
||
|
newExt = PORT_ArenaZNew(poolp, CRMFCertExtension);
|
||
|
if (newExt == NULL) {
|
||
|
goto loser2;
|
||
|
}
|
||
|
currExt = extensions->extensions[i-oldSize];
|
||
|
rv = crmf_copy_secitem(poolp, &(newExt->id), &(currExt->id));
|
||
|
if (rv != SECSuccess) {
|
||
|
goto loser2;
|
||
|
}
|
||
|
rv = crmf_copy_secitem(poolp, &(newExt->critical),
|
||
|
&(currExt->critical));
|
||
|
if (rv != SECSuccess) {
|
||
|
goto loser2;
|
||
|
}
|
||
|
rv = crmf_copy_secitem(poolp, &(newExt->value), &(currExt->value));
|
||
|
if (rv != SECSuccess) {
|
||
|
goto loser2;
|
||
|
}
|
||
|
extArray[i] = newExt;
|
||
|
}
|
||
|
extArray[newSize] = NULL;
|
||
|
PORT_ArenaUnmark(poolp, mark);
|
||
|
return SECSuccess;
|
||
|
loser2:
|
||
|
crmf_zeroize_new_extensions (&(inTemplate->extensions[oldSize]),
|
||
|
extensions->numExtensions);
|
||
|
inTemplate->numExtensions = oldSize;
|
||
|
loser:
|
||
|
PORT_ArenaRelease(poolp, mark);
|
||
|
return SECFailure;
|
||
|
}
|
||
|
|
||
|
SECStatus
|
||
|
CRMF_CertRequestSetTemplateField(CRMFCertRequest *inCertReq,
|
||
|
CRMFCertTemplateField inTemplateField,
|
||
|
void *data)
|
||
|
{
|
||
|
CRMFCertTemplate *certTemplate;
|
||
|
PRArenaPool *poolp;
|
||
|
SECStatus rv = SECFailure;
|
||
|
void *mark;
|
||
|
|
||
|
|
||
|
if (inCertReq == NULL) {
|
||
|
return SECFailure;
|
||
|
}
|
||
|
|
||
|
certTemplate = &(inCertReq->certTemplate);
|
||
|
|
||
|
poolp = inCertReq->poolp;
|
||
|
mark = PORT_ArenaMark(poolp);
|
||
|
switch (inTemplateField) {
|
||
|
case crmfVersion:
|
||
|
rv = crmf_template_add_version(poolp,&(certTemplate->version),
|
||
|
*(long*)data);
|
||
|
break;
|
||
|
case crmfSerialNumber:
|
||
|
rv = crmf_template_add_serialnumber(poolp,
|
||
|
&(certTemplate->serialNumber),
|
||
|
*(long*)data);
|
||
|
break;
|
||
|
case crmfSigningAlg:
|
||
|
rv = crmf_template_copy_secalg (poolp, &(certTemplate->signingAlg),
|
||
|
(SECAlgorithmID*)data);
|
||
|
break;
|
||
|
case crmfIssuer:
|
||
|
rv = crmf_template_add_issuer (poolp, &(certTemplate->issuer),
|
||
|
(CERTName*)data);
|
||
|
break;
|
||
|
case crmfValidity:
|
||
|
rv = crmf_template_add_validity (poolp, &(certTemplate->validity),
|
||
|
(CRMFValidityCreationInfo*)data);
|
||
|
break;
|
||
|
case crmfSubject:
|
||
|
rv = crmf_template_add_subject (poolp, &(certTemplate->subject),
|
||
|
(CERTName*)data);
|
||
|
break;
|
||
|
case crmfPublicKey:
|
||
|
rv = crmf_template_add_public_key(poolp, &(certTemplate->publicKey),
|
||
|
(CERTSubjectPublicKeyInfo*)data);
|
||
|
break;
|
||
|
case crmfIssuerUID:
|
||
|
rv = crmf_template_add_issuer_uid(poolp, &(certTemplate->issuerUID),
|
||
|
(SECItem*)data);
|
||
|
break;
|
||
|
case crmfSubjectUID:
|
||
|
rv = crmf_template_add_subject_uid(poolp, &(certTemplate->subjectUID),
|
||
|
(SECItem*)data);
|
||
|
break;
|
||
|
case crmfExtension:
|
||
|
rv = crmf_template_add_extensions(poolp, certTemplate,
|
||
|
(CRMFCertExtCreationInfo*)data);
|
||
|
break;
|
||
|
}
|
||
|
if (rv != SECSuccess) {
|
||
|
PORT_ArenaRelease(poolp, mark);
|
||
|
} else {
|
||
|
PORT_ArenaUnmark(poolp, mark);
|
||
|
}
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
SECStatus
|
||
|
CRMF_CertReqMsgSetCertRequest (CRMFCertReqMsg *inCertReqMsg,
|
||
|
CRMFCertRequest *inCertReq)
|
||
|
{
|
||
|
PORT_Assert (inCertReqMsg != NULL && inCertReq != NULL);
|
||
|
if (inCertReqMsg == NULL || inCertReq == NULL) {
|
||
|
return SECFailure;
|
||
|
}
|
||
|
inCertReqMsg->certReq = crmf_copy_cert_request(inCertReqMsg->poolp,
|
||
|
inCertReq);
|
||
|
return (inCertReqMsg->certReq == NULL) ? SECFailure : SECSuccess;
|
||
|
}
|
||
|
|
||
|
CRMFCertReqMsg*
|
||
|
CRMF_CreateCertReqMsg(void)
|
||
|
{
|
||
|
PRArenaPool *poolp;
|
||
|
CRMFCertReqMsg *reqMsg;
|
||
|
|
||
|
poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
|
||
|
if (poolp == NULL) {
|
||
|
goto loser;
|
||
|
}
|
||
|
reqMsg = PORT_ArenaZNew(poolp, CRMFCertReqMsg);
|
||
|
if (reqMsg == NULL) {
|
||
|
goto loser;
|
||
|
}
|
||
|
reqMsg->poolp = poolp;
|
||
|
return reqMsg;
|
||
|
|
||
|
loser:
|
||
|
if (poolp) {
|
||
|
PORT_FreeArena(poolp, PR_FALSE);
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
SECStatus
|
||
|
CRMF_DestroyCertReqMsg(CRMFCertReqMsg *inCertReqMsg)
|
||
|
{
|
||
|
PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->poolp != NULL);
|
||
|
if (!inCertReqMsg->isDecoded) {
|
||
|
if (inCertReqMsg->certReq->certTemplate.extensions != NULL) {
|
||
|
PORT_Free(inCertReqMsg->certReq->certTemplate.extensions);
|
||
|
}
|
||
|
if (inCertReqMsg->certReq->controls != NULL) {
|
||
|
PORT_Free(inCertReqMsg->certReq->controls);
|
||
|
}
|
||
|
}
|
||
|
PORT_FreeArena(inCertReqMsg->poolp, PR_TRUE);
|
||
|
return SECSuccess;
|
||
|
}
|
||
|
|
||
|
CRMFCertExtension*
|
||
|
crmf_create_cert_extension(PRArenaPool *poolp,
|
||
|
SECOidTag id,
|
||
|
PRBool isCritical,
|
||
|
SECItem *data)
|
||
|
{
|
||
|
CRMFCertExtension *newExt;
|
||
|
SECOidData *oidData;
|
||
|
SECStatus rv;
|
||
|
|
||
|
newExt = (poolp == NULL) ? PORT_ZNew(CRMFCertExtension) :
|
||
|
PORT_ArenaZNew(poolp, CRMFCertExtension);
|
||
|
if (newExt == NULL) {
|
||
|
goto loser;
|
||
|
}
|
||
|
oidData = SECOID_FindOIDByTag(id);
|
||
|
if (oidData == NULL ||
|
||
|
oidData->supportedExtension != SUPPORTED_CERT_EXTENSION) {
|
||
|
goto loser;
|
||
|
}
|
||
|
|
||
|
rv = SECITEM_CopyItem(poolp, &(newExt->id), &(oidData->oid));
|
||
|
if (rv != SECSuccess) {
|
||
|
goto loser;
|
||
|
}
|
||
|
|
||
|
rv = SECITEM_CopyItem(poolp, &(newExt->value), data);
|
||
|
if (rv != SECSuccess) {
|
||
|
goto loser;
|
||
|
}
|
||
|
|
||
|
if (isCritical) {
|
||
|
newExt->critical.data = (poolp == NULL) ?
|
||
|
PORT_New(unsigned char) :
|
||
|
PORT_ArenaNew(poolp, unsigned char);
|
||
|
if (newExt->critical.data == NULL) {
|
||
|
goto loser;
|
||
|
}
|
||
|
newExt->critical.data[0] = hexTrue;
|
||
|
newExt->critical.len = 1;
|
||
|
}
|
||
|
return newExt;
|
||
|
loser:
|
||
|
if (newExt != NULL && poolp == NULL) {
|
||
|
CRMF_DestroyCertExtension(newExt);
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
CRMFCertExtension *
|
||
|
CRMF_CreateCertExtension(SECOidTag id,
|
||
|
PRBool isCritical,
|
||
|
SECItem *data)
|
||
|
{
|
||
|
return crmf_create_cert_extension(NULL, id, isCritical, data);
|
||
|
}
|
||
|
|
||
|
static SECStatus
|
||
|
crmf_destroy_cert_extension(CRMFCertExtension *inExtension, PRBool freeit)
|
||
|
{
|
||
|
if (inExtension != NULL) {
|
||
|
SECITEM_FreeItem (&(inExtension->id), PR_FALSE);
|
||
|
SECITEM_FreeItem (&(inExtension->value), PR_FALSE);
|
||
|
SECITEM_FreeItem (&(inExtension->critical), PR_FALSE);
|
||
|
if (freeit) {
|
||
|
PORT_Free(inExtension);
|
||
|
}
|
||
|
}
|
||
|
return SECSuccess;
|
||
|
}
|
||
|
|
||
|
SECStatus
|
||
|
CRMF_DestroyCertExtension(CRMFCertExtension *inExtension)
|
||
|
{
|
||
|
return crmf_destroy_cert_extension(inExtension, PR_TRUE);
|
||
|
}
|
||
|
|
||
|
SECStatus
|
||
|
CRMF_DestroyCertReqMessages(CRMFCertReqMessages *inCertReqMsgs)
|
||
|
{
|
||
|
PORT_Assert (inCertReqMsgs != NULL);
|
||
|
if (inCertReqMsgs != NULL) {
|
||
|
PORT_FreeArena(inCertReqMsgs->poolp, PR_TRUE);
|
||
|
}
|
||
|
return SECSuccess;
|
||
|
}
|
||
|
|
||
|
static PRBool
|
||
|
crmf_item_has_data(SECItem *item)
|
||
|
{
|
||
|
if (item != NULL && item->data != NULL) {
|
||
|
return PR_TRUE;
|
||
|
}
|
||
|
return PR_FALSE;
|
||
|
}
|
||
|
|
||
|
PRBool
|
||
|
CRMF_CertRequestIsFieldPresent(CRMFCertRequest *inCertReq,
|
||
|
CRMFCertTemplateField inTemplateField)
|
||
|
{
|
||
|
PRBool retVal;
|
||
|
CRMFCertTemplate *certTemplate;
|
||
|
|
||
|
PORT_Assert(inCertReq != NULL);
|
||
|
if (inCertReq == NULL) {
|
||
|
/* This is probably some kind of error, but this is
|
||
|
* the safest return value for this function.
|
||
|
*/
|
||
|
return PR_FALSE;
|
||
|
}
|
||
|
certTemplate = &inCertReq->certTemplate;
|
||
|
switch (inTemplateField) {
|
||
|
case crmfVersion:
|
||
|
retVal = crmf_item_has_data(&certTemplate->version);
|
||
|
break;
|
||
|
case crmfSerialNumber:
|
||
|
retVal = crmf_item_has_data(&certTemplate->serialNumber);
|
||
|
break;
|
||
|
case crmfSigningAlg:
|
||
|
retVal = IS_NOT_NULL(certTemplate->signingAlg);
|
||
|
break;
|
||
|
case crmfIssuer:
|
||
|
retVal = IS_NOT_NULL(certTemplate->issuer);
|
||
|
break;
|
||
|
case crmfValidity:
|
||
|
retVal = IS_NOT_NULL(certTemplate->validity);
|
||
|
break;
|
||
|
case crmfSubject:
|
||
|
retVal = IS_NOT_NULL(certTemplate->subject);
|
||
|
break;
|
||
|
case crmfPublicKey:
|
||
|
retVal = IS_NOT_NULL(certTemplate->publicKey);
|
||
|
break;
|
||
|
case crmfIssuerUID:
|
||
|
retVal = crmf_item_has_data(&certTemplate->issuerUID);
|
||
|
break;
|
||
|
case crmfSubjectUID:
|
||
|
retVal = crmf_item_has_data(&certTemplate->subjectUID);
|
||
|
break;
|
||
|
case crmfExtension:
|
||
|
retVal = IS_NOT_NULL(certTemplate->extensions);
|
||
|
break;
|
||
|
default:
|
||
|
retVal = PR_FALSE;
|
||
|
}
|
||
|
return retVal;
|
||
|
}
|