summaryrefslogtreecommitdiff
path: root/security/nss
diff options
context:
space:
mode:
authorneil.williams%sun.com <devnull@localhost>2005-03-09 23:02:48 +0000
committerneil.williams%sun.com <devnull@localhost>2005-03-09 23:02:48 +0000
commit74b23e389221c2739b8c35b2023709c4c98cfeb4 (patch)
tree93faa85ca560ea3fdcf664ec4c0971c610bc55c9 /security/nss
parent06f84535b4407812bbd408aae18e9b26e3843c34 (diff)
downloadnss-hg-74b23e389221c2739b8c35b2023709c4c98cfeb4.tar.gz
r=nelson Bug=263779
Diffstat (limited to 'security/nss')
-rw-r--r--security/nss/cmd/certutil/certutil.c166
-rw-r--r--security/nss/lib/certdb/cert.h27
-rw-r--r--security/nss/lib/certdb/certxutl.c45
-rw-r--r--security/nss/lib/certhigh/certreq.c98
-rw-r--r--security/nss/lib/nss/nss.def4
5 files changed, 287 insertions, 53 deletions
diff --git a/security/nss/cmd/certutil/certutil.c b/security/nss/cmd/certutil/certutil.c
index bbb1fd6c2..88eba3018 100644
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -399,9 +399,20 @@ getSignatureOidTag(KeyType keyType, SECOidTag hashAlgTag)
}
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));
@@ -2081,21 +2107,7 @@ AddCrlDistPoint(void *extHandle)
}
static SECStatus
-CreateCert(
- CERTCertDBHandle *handle,
- char * issuerNickName,
- PRFileDesc *inFile,
- PRFileDesc *outFile,
- SECKEYPrivateKey *selfsignprivkey,
- void *pwarg,
- SECOidTag hashAlgTag,
- unsigned int serialNumber,
- int warpmonths,
- int validitylength,
- const char *emailAddrs,
- const char *dnsNames,
- PRBool ascii,
- PRBool selfsign,
+AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
PRBool keyUsage,
PRBool extKeyUsage,
PRBool basicConstraint,
@@ -2103,38 +2115,8 @@ CreateCert(
PRBool crlDistPoints,
PRBool nscpCertType)
{
- void * extHandle;
- SECItem * certDER;
- PRArenaPool *arena = NULL;
- CERTCertificate *subjectCert = NULL;
- CERTCertificateRequest *certReq = NULL;
- SECStatus rv = SECSuccess;
- SECItem reqDER;
-
- reqDER.data = NULL;
+ SECStatus rv = SECSuccess;
do {
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (!arena) {
- GEN_BREAK (SECFailure);
- }
-
- /* Create a certrequest object from the input cert request der */
- certReq = GetCertRequest(inFile, ascii);
- if (certReq == NULL) {
- GEN_BREAK (SECFailure)
- }
-
- subjectCert = MakeV1Cert (handle, certReq, issuerNickName, selfsign,
- serialNumber, warpmonths, validitylength);
- 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);
@@ -2162,7 +2144,6 @@ CreateCert(
break;
}
-
if (crlDistPoints) {
rv = AddCrlDistPoint (extHandle);
if (rv)
@@ -2186,6 +2167,83 @@ CreateCert(
if (rv)
break;
}
+ } while (0);
+ return rv;
+}
+
+static SECStatus
+CreateCert(
+ CERTCertDBHandle *handle,
+ char * issuerNickName,
+ PRFileDesc *inFile,
+ PRFileDesc *outFile,
+ SECKEYPrivateKey *selfsignprivkey,
+ void *pwarg,
+ SECOidTag hashAlgTag,
+ unsigned int serialNumber,
+ int warpmonths,
+ int validitylength,
+ const char *emailAddrs,
+ const char *dnsNames,
+ PRBool ascii,
+ PRBool selfsign,
+ PRBool keyUsage,
+ PRBool extKeyUsage,
+ PRBool basicConstraint,
+ PRBool authKeyID,
+ PRBool crlDistPoints,
+ PRBool nscpCertType)
+{
+ void * extHandle;
+ SECItem * certDER;
+ PRArenaPool *arena = NULL;
+ CERTCertificate *subjectCert = NULL;
+ CERTCertificateRequest *certReq = NULL;
+ SECStatus rv = SECSuccess;
+ SECItem reqDER;
+ CERTCertExtension **CRexts;
+
+ reqDER.data = NULL;
+ do {
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ GEN_BREAK (SECFailure);
+ }
+
+ /* Create a certrequest object from the input cert request der */
+ certReq = GetCertRequest(inFile, ascii);
+ if (certReq == NULL) {
+ GEN_BREAK (SECFailure)
+ }
+
+ subjectCert = MakeV1Cert (handle, certReq, issuerNickName, selfsign,
+ serialNumber, warpmonths, validitylength);
+ if (subjectCert == NULL) {
+ GEN_BREAK (SECFailure)
+ }
+
+
+ extHandle = CERT_StartCertExtensions (subjectCert);
+ if (extHandle == NULL) {
+ GEN_BREAK (SECFailure)
+ }
+
+ 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;
diff --git a/security/nss/lib/certdb/cert.h b/security/nss/lib/certdb/cert.h
index 15b7e3af4..9dfe8d775 100644
--- a/security/nss/lib/certdb/cert.h
+++ b/security/nss/lib/certdb/cert.h
@@ -251,6 +251,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
*/
extern SECKEYPublicKey *CERT_ExtractPublicKey(CERTCertificate *cert);
@@ -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.
diff --git a/security/nss/lib/certdb/certxutl.c b/security/nss/lib/certdb/certxutl.c
index bb59fe002..1f77e0db9 100644
--- a/security/nss/lib/certdb/certxutl.c
+++ b/security/nss/lib/certdb/certxutl.c
@@ -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
*/
diff --git a/security/nss/lib/certhigh/certreq.c b/security/nss/lib/certhigh/certreq.c
index 243a2d960..300f15353 100644
--- a/security/nss/lib/certhigh/certreq.c
+++ b/security/nss/lib/certhigh/certreq.c
@@ -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]));
+}
diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def
index 2822c5daf..3ef2dc935 100644
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -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;