r=nelson Bug=263779

This commit is contained in:
neil.williams%sun.com 2005-03-09 23:02:48 +00:00
parent 22e4705847
commit 5431bc6445
5 changed files with 293 additions and 59 deletions

View File

@ -398,10 +398,21 @@ getSignatureOidTag(KeyType keyType, SECOidTag hashAlgTag)
return sigTag;
}
static SECStatus
AddExtensions(void *, const char *, const char *, PRBool, PRBool, PRBool, PRBool,
PRBool, PRBool);
static SECStatus
CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
SECOidTag hashAlgTag, CERTName *subject, char *phone, int ascii,
const char *emailAddrs, const char *dnsNames, PRFileDesc *outFile)
const char *emailAddrs, const char *dnsNames,
PRBool keyUsage,
PRBool extKeyUsage,
PRBool basicConstraint,
PRBool authKeyID,
PRBool crlDistPoints,
PRBool nscpCertType,
PRFileDesc *outFile)
{
CERTSubjectPublicKeyInfo *spki;
CERTCertificateRequest *cr;
@ -411,6 +422,7 @@ CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
SECStatus rv;
PRArenaPool *arena;
PRInt32 numBytes;
void *extHandle;
/* Create info about public key */
spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
@ -418,9 +430,9 @@ CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
SECU_PrintError(progName, "unable to create subject public key");
return SECFailure;
}
/* Generate certificate request */
cr = CERT_CreateCertificateRequest(subject, spki, 0);
cr = CERT_CreateCertificateRequest(subject, spki, NULL);
if (!cr) {
SECU_PrintError(progName, "unable to make certificate request");
return SECFailure;
@ -432,6 +444,20 @@ CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
return SECFailure;
}
extHandle = CERT_StartCertificateRequestAttributes(cr);
if (extHandle == NULL) {
PORT_FreeArena (arena, PR_FALSE);
return SECFailure;
}
if (AddExtensions(extHandle, emailAddrs, PR_FALSE, PR_FALSE, PR_FALSE,
PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE)
!= SECSuccess) {
PORT_FreeArena (arena, PR_FALSE);
return SECFailure;
}
CERT_FinishExtensions(extHandle);
CERT_FinishCertificateRequestAttributes(cr);
/* Der encode the request */
encoding = SEC_ASN1EncodeItem(arena, NULL, cr,
SEC_ASN1_GET(CERT_CertificateRequestTemplate));
@ -2080,6 +2106,71 @@ AddCrlDistPoint(void *extHandle)
return (rv);
}
static SECStatus
AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
PRBool keyUsage,
PRBool extKeyUsage,
PRBool basicConstraint,
PRBool authKeyID,
PRBool crlDistPoints,
PRBool nscpCertType)
{
SECStatus rv = SECSuccess;
do {
/* Add key usage extension */
if (keyUsage) {
rv = AddKeyUsage(extHandle);
if (rv)
break;
}
/* Add extended key usage extension */
if (extKeyUsage) {
rv = AddExtKeyUsage(extHandle);
if (rv)
break;
}
/* Add basic constraint extension */
if (basicConstraint) {
rv = AddBasicConstraint(extHandle);
if (rv)
break;
}
if (authKeyID) {
rv = AddAuthKeyID (extHandle);
if (rv)
break;
}
if (crlDistPoints) {
rv = AddCrlDistPoint (extHandle);
if (rv)
break;
}
if (nscpCertType) {
rv = AddNscpCertType(extHandle);
if (rv)
break;
}
if (emailAddrs != NULL) {
rv = AddEmailSubjectAlt(extHandle,emailAddrs);
if (rv)
break;
}
if (dnsNames != NULL) {
rv = AddDNSSubjectAlt(extHandle,dnsNames);
if (rv)
break;
}
} while (0);
return rv;
}
static SECStatus
CreateCert(
CERTCertDBHandle *handle,
@ -2110,6 +2201,7 @@ CreateCert(
CERTCertificateRequest *certReq = NULL;
SECStatus rv = SECSuccess;
SECItem reqDER;
CERTCertExtension **CRexts;
reqDER.data = NULL;
do {
@ -2129,63 +2221,29 @@ CreateCert(
if (subjectCert == NULL) {
GEN_BREAK (SECFailure)
}
extHandle = CERT_StartCertExtensions (subjectCert);
if (extHandle == NULL) {
GEN_BREAK (SECFailure)
}
/* Add key usage extension */
if (keyUsage) {
rv = AddKeyUsage(extHandle);
if (rv)
break;
}
/* Add extended key usage extension */
if (extKeyUsage) {
rv = AddExtKeyUsage(extHandle);
if (rv)
break;
}
/* Add basic constraint extension */
if (basicConstraint) {
rv = AddBasicConstraint(extHandle);
if (rv)
break;
}
if (authKeyID) {
rv = AddAuthKeyID (extHandle);
if (rv)
break;
}
if (crlDistPoints) {
rv = AddCrlDistPoint (extHandle);
if (rv)
break;
}
if (nscpCertType) {
rv = AddNscpCertType(extHandle);
if (rv)
break;
}
if (emailAddrs != NULL) {
rv = AddEmailSubjectAlt(extHandle,emailAddrs);
if (rv)
break;
}
if (dnsNames != NULL) {
rv = AddDNSSubjectAlt(extHandle,dnsNames);
if (rv)
break;
rv = AddExtensions(extHandle, emailAddrs, dnsNames, keyUsage, extKeyUsage,
basicConstraint, authKeyID, crlDistPoints, nscpCertType);
if (rv != SECSuccess) {
GEN_BREAK (SECFailure)
}
if (certReq->attributes != NULL &&
SECOID_FindOIDTag(&(*certReq->attributes)->attrType)
== SEC_OID_PKCS9_EXTENSION_REQUEST) {
rv = CERT_GetCertificateRequestExtensions(certReq, &CRexts);
if (rv != SECSuccess)
break;
rv = CERT_MergeExtensions(extHandle, CRexts);
if (rv != SECSuccess)
break;
}
CERT_FinishExtensions(extHandle);
@ -2877,7 +2935,13 @@ secuCommandFlag certutil_options[] =
certutil.options[opt_ASCIIForIO].activated,
certutil.options[opt_ExtendedEmailAddrs].arg,
certutil.options[opt_ExtendedDNSNames].arg,
outFile ? outFile : PR_STDOUT);
certutil.options[opt_AddKeyUsageExt].activated,
certutil.options[opt_AddExtKeyUsageExt].activated,
certutil.options[opt_AddBasicConstraintExt].activated,
certutil.options[opt_AddAuthorityKeyIDExt].activated,
certutil.options[opt_AddCRLDistPtsExt].activated,
certutil.options[opt_AddNSCertTypeExt].activated,
outFile ? outFile : PR_STDOUT);
if (rv)
goto shutdown;
privkey->wincx = &pwdata;

View File

@ -37,7 +37,7 @@
/*
* cert.h - public data structures and prototypes for the certificate library
*
* $Id: cert.h,v 1.52 2005/03/08 07:08:43 julien.pierre.bugs%sun.com Exp $
* $Id: cert.h,v 1.53 2005/03/09 23:02:47 neil.williams%sun.com Exp $
*/
#ifndef _CERT_H_
@ -250,6 +250,26 @@ CERT_CreateCertificateRequest (CERTName *name, CERTSubjectPublicKeyInfo *spki,
*/
extern void CERT_DestroyCertificateRequest(CERTCertificateRequest *r);
/*
** Start adding extensions to a certificate request.
*/
void *
CERT_StartCertificateRequestAttributes(CERTCertificateRequest *req);
/*
** Reformat the certifcate extension list into a CertificateRequest
** attribute list.
*/
SECStatus
CERT_FinishCertificateRequestAttributes(CERTCertificateRequest *req);
/*
** Extract the Extension Requests from a DER CertRequest attribute list.
*/
SECStatus
CERT_GetCertificateRequestExtensions(CERTCertificateRequest *req,
CERTCertExtension ***exts);
/*
** Extract a public key object from a certificate
*/
@ -823,6 +843,13 @@ CERT_EncodeAltNameExtension(PRArenaPool *arena, CERTGeneralName *value, SECIte
*/
extern SECStatus CERT_FinishExtensions(void *exthandle);
/*
** Merge an external list of extensions into a cert's extension list, adding one
** only when its OID matches none of the cert's existing extensions. Call this
** immediately before calling CERT_FinishExtensions().
*/
SECStatus
CERT_MergeExtensions(void *exthandle, CERTCertExtension **exts);
/* If the extension is found, return its criticality and value.
** This allocate storage for the returning extension value.

View File

@ -375,6 +375,51 @@ loser:
return rv;
}
SECStatus
CERT_MergeExtensions(void *exthandle, CERTCertExtension **extensions)
{
CERTCertExtension *ext;
SECStatus rv = SECSuccess;
SECOidTag tag;
extNode *node;
extRec *handle = exthandle;
PRBool critical;
if (!exthandle || !extensions) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
while ((ext = *extensions++) != NULL) {
tag = SECOID_FindOIDTag(&ext->id);
for (node=handle->head; node != NULL; node=node->next) {
if (tag == 0) {
if (SECITEM_ItemsAreEqual(&ext->id, &node->ext->id))
break;
}
else {
if (SECOID_FindOIDTag(&node->ext->id) == tag) {
break;
}
}
}
if (node == NULL) {
PRBool critical = (ext->critical.len != 0 &&
ext->critical.data[ext->critical.len - 1] != 0);
if (critical && tag == SEC_OID_UNKNOWN) {
PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
rv = SECFailure;
break;
}
/* add to list */
rv = CERT_AddExtensionByOID (exthandle, &ext->id, &ext->value,
critical, PR_TRUE);
if (rv != SECSuccess)
break;
}
}
return rv;
}
/*
* get the value of the Netscape Certificate Type Extension
*/

View File

@ -35,10 +35,12 @@
* ***** END LICENSE BLOCK ***** */
#include "cert.h"
#include "certt.h"
#include "secder.h"
#include "key.h"
#include "secitem.h"
#include "secasn1.h"
#include "secerr.h"
const SEC_ASN1Template CERT_AttributeTemplate[] = {
{ SEC_ASN1_SEQUENCE,
@ -166,8 +168,7 @@ CERT_CreateCertificateRequest(CERTName *subject,
/* allocate space for attributes */
while(attributes[i] != NULL) i++;
certreq->attributes = (SECItem**)PORT_ArenaZAlloc(arena,
sizeof(SECItem *) * (i + 1));
certreq->attributes = PORT_ArenaZNewArray(arena,CERTAttribute*,i+1);
if(!certreq->attributes) {
goto loser;
}
@ -231,3 +232,96 @@ CERT_DestroyCertificateRequest(CERTCertificateRequest *req)
return;
}
static void
setCRExt(void *o, CERTCertExtension **exts)
{
((CERTCertificateRequest *)o)->attributes = (struct CERTAttributeStr **)exts;
}
/*
** Set up to start gathering cert extensions for a cert request.
** The list is created as CertExtensions and converted to an
** attribute list by CERT_FinishCRAttributes().
*/
extern void *cert_StartExtensions(void *owner, PRArenaPool *ownerArena,
void (*setExts)(void *object, CERTCertExtension **exts));
void *
CERT_StartCertificateRequestAttributes(CERTCertificateRequest *req)
{
return (cert_StartExtensions ((void *)req, req->arena, setCRExt));
}
/*
** At entry req->attributes actually contains an list of cert extensions--
** req-attributes is overloaded until the list is DER encoded (the first
** ...EncodeItem() below).
** We turn this into an attribute list by encapsulating it
** in a PKCS 10 Attribute structure
*/
SECStatus
CERT_FinishCertificateRequestAttributes(CERTCertificateRequest *req)
{ SECItem *extlist;
SECOidData *oidrec;
CERTAttribute *attribute;
if (!req || !req->arena) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (req->attributes == NULL)
return SECSuccess;
extlist = SEC_ASN1EncodeItem(req->arena, NULL, &req->attributes,
SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate));
if (extlist == NULL)
return(SECFailure);
oidrec = SECOID_FindOIDByTag(SEC_OID_PKCS9_EXTENSION_REQUEST);
if (oidrec == NULL)
return SECFailure;
/* now change the list of cert extensions into a list of attributes
*/
req->attributes = PORT_ArenaZNewArray(req->arena, CERTAttribute*, 2);
attribute = PORT_ArenaZNew(req->arena, CERTAttribute);
if (req->attributes == NULL || attribute == NULL ||
SECITEM_CopyItem(req->arena, &attribute->attrType, &oidrec->oid) != 0) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
}
attribute->attrValue = PORT_ArenaZNewArray(req->arena, SECItem*, 2);
if (attribute->attrValue == NULL)
return SECFailure;
attribute->attrValue[0] = extlist;
attribute->attrValue[1] = NULL;
req->attributes[0] = attribute;
req->attributes[1] = NULL;
return SECSuccess;
}
SECStatus
CERT_GetCertificateRequestExtensions(CERTCertificateRequest *req,
CERTCertExtension ***exts)
{
if (req == NULL || exts == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (req->attributes == NULL || *req->attributes == NULL)
return SECSuccess;
if ((*req->attributes)->attrValue == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
return(SEC_ASN1DecodeItem(req->arena, exts,
SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate),
(*req->attributes)->attrValue[0]));
}

View File

@ -820,11 +820,15 @@ CERT_DecodeCRLDistributionPoints;
CERT_DecodeNameConstraintsExtension;
CERT_DecodePrivKeyUsagePeriodExtension;
CERT_DestroyUserNotice;
CERT_FinishCertificateRequestAttributes;
CERT_GetCertificateNames;
CERT_GetCertificateRequestExtensions;
CERT_GetNextGeneralName;
CERT_GetNextNameConstraint;
CERT_GetPrevGeneralName;
CERT_GetPrevNameConstraint;
CERT_MergeExtensions;
CERT_StartCertificateRequestAttributes;
CERT_StartCRLEntryExtensions;
CERT_StartCRLExtensions;
CERT_UncacheCRL;