diff nss/lib/certhigh/certreq.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nss/lib/certhigh/certreq.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,324 @@
+/* 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 "cert.h"
+#include "certt.h"
+#include "secder.h"
+#include "key.h"
+#include "secitem.h"
+#include "secasn1.h"
+#include "secerr.h"
+
+SEC_ASN1_MKSUB(SEC_AnyTemplate)
+
+const SEC_ASN1Template CERT_AttributeTemplate[] = {
+    { SEC_ASN1_SEQUENCE,
+	0, NULL, sizeof(CERTAttribute) },
+    { SEC_ASN1_OBJECT_ID, offsetof(CERTAttribute, attrType) },
+    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(CERTAttribute, attrValue),
+	SEC_ASN1_SUB(SEC_AnyTemplate) },
+    { 0 }
+};
+
+const SEC_ASN1Template CERT_SetOfAttributeTemplate[] = {
+    { SEC_ASN1_SET_OF, 0, CERT_AttributeTemplate },
+};
+
+const SEC_ASN1Template CERT_CertificateRequestTemplate[] = {
+    { SEC_ASN1_SEQUENCE,
+	  0, NULL, sizeof(CERTCertificateRequest) },
+    { SEC_ASN1_INTEGER,
+	  offsetof(CERTCertificateRequest,version) },
+    { SEC_ASN1_INLINE,
+	  offsetof(CERTCertificateRequest,subject),
+	  CERT_NameTemplate },
+    { SEC_ASN1_INLINE,
+	  offsetof(CERTCertificateRequest,subjectPublicKeyInfo),
+	  CERT_SubjectPublicKeyInfoTemplate },
+    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+	  offsetof(CERTCertificateRequest,attributes), 
+	  CERT_SetOfAttributeTemplate },
+    { 0 }
+};
+
+SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CertificateRequestTemplate)
+
+CERTCertificate *
+CERT_CreateCertificate(unsigned long serialNumber,
+		      CERTName *issuer,
+		      CERTValidity *validity,
+		      CERTCertificateRequest *req)
+{
+    CERTCertificate *c;
+    int rv;
+    PLArenaPool *arena;
+    
+    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    
+    if ( !arena ) {
+	return(0);
+    }
+
+    c = (CERTCertificate *)PORT_ArenaZAlloc(arena, sizeof(CERTCertificate));
+    
+    if (!c) {
+	PORT_FreeArena(arena, PR_FALSE);
+	return 0;
+    }
+
+    c->referenceCount = 1;
+    c->arena = arena;
+
+    /*
+     * Default is a plain version 1.
+     * If extensions are added, it will get changed as appropriate.
+     */
+    rv = DER_SetUInteger(arena, &c->version, SEC_CERTIFICATE_VERSION_1);
+    if (rv) goto loser;
+
+    rv = DER_SetUInteger(arena, &c->serialNumber, serialNumber);
+    if (rv) goto loser;
+
+    rv = CERT_CopyName(arena, &c->issuer, issuer);
+    if (rv) goto loser;
+
+    rv = CERT_CopyValidity(arena, &c->validity, validity);
+    if (rv) goto loser;
+
+    rv = CERT_CopyName(arena, &c->subject, &req->subject);
+    if (rv) goto loser;
+    rv = SECKEY_CopySubjectPublicKeyInfo(arena, &c->subjectPublicKeyInfo,
+					 &req->subjectPublicKeyInfo);
+    if (rv) goto loser;
+
+    return c;
+
+ loser:
+    CERT_DestroyCertificate(c);
+    return 0;
+}
+
+/************************************************************************/
+/* It's clear from the comments that the original author of this 
+ * function expected the template for certificate requests to treat
+ * the attributes as a SET OF ANY.  This function expected to be 
+ * passed an array of SECItems each of which contained an already encoded
+ * Attribute.  But the cert request template does not treat the 
+ * Attributes as a SET OF ANY, and AFAIK never has.  Instead the template
+ * encodes attributes as a SET OF xxxxxxx.  That is, it expects to encode
+ * each of the Attributes, not have them pre-encoded.  Consequently an 
+ * array of SECItems containing encoded Attributes is of no value to this 
+ * function.  But we cannot change the signature of this public function.
+ * It must continue to take SECItems.
+ *
+ * I have recoded this function so that each SECItem contains an 
+ * encoded cert extension.  The encoded cert extensions form the list for the
+ * single attribute of the cert request. In this implementation there is at most
+ * one attribute and it is always of type SEC_OID_PKCS9_EXTENSION_REQUEST.
+ */
+
+CERTCertificateRequest *
+CERT_CreateCertificateRequest(CERTName *subject,
+			     CERTSubjectPublicKeyInfo *spki,
+			     SECItem **attributes)
+{
+    CERTCertificateRequest *certreq;
+    PLArenaPool *arena;
+    CERTAttribute * attribute;
+    SECOidData * oidData;
+    SECStatus rv;
+    int i = 0;
+
+    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    if ( arena == NULL ) {
+	return NULL;
+    }
+    
+    certreq = PORT_ArenaZNew(arena, CERTCertificateRequest);
+    if (!certreq) {
+	PORT_FreeArena(arena, PR_FALSE);
+	return NULL;
+    }
+    /* below here it is safe to goto loser */
+
+    certreq->arena = arena;
+    
+    rv = DER_SetUInteger(arena, &certreq->version,
+			 SEC_CERTIFICATE_REQUEST_VERSION);
+    if (rv != SECSuccess)
+	goto loser;
+
+    rv = CERT_CopyName(arena, &certreq->subject, subject);
+    if (rv != SECSuccess)
+	goto loser;
+
+    rv = SECKEY_CopySubjectPublicKeyInfo(arena,
+				      &certreq->subjectPublicKeyInfo,
+				      spki);
+    if (rv != SECSuccess)
+	goto loser;
+
+    certreq->attributes = PORT_ArenaZNewArray(arena, CERTAttribute*, 2);
+    if(!certreq->attributes) 
+	goto loser;
+
+    /* Copy over attribute information */
+    if (!attributes || !attributes[0]) {
+	/*
+	 ** Invent empty attribute information. According to the
+	 ** pkcs#10 spec, attributes has this ASN.1 type:
+	 **
+	 ** attributes [0] IMPLICIT Attributes
+	 ** 
+	 ** Which means, we should create a NULL terminated list
+	 ** with the first entry being NULL;
+	 */
+	certreq->attributes[0] = NULL;
+	return certreq;
+    }	
+
+    /* allocate space for attributes */
+    attribute = PORT_ArenaZNew(arena, CERTAttribute);
+    if (!attribute) 
+	goto loser;
+
+    oidData = SECOID_FindOIDByTag( SEC_OID_PKCS9_EXTENSION_REQUEST );
+    PORT_Assert(oidData);
+    if (!oidData)
+	goto loser;
+    rv = SECITEM_CopyItem(arena, &attribute->attrType, &oidData->oid);
+    if (rv != SECSuccess)
+	goto loser;
+
+    for (i = 0; attributes[i] != NULL ; i++) 
+	;
+    attribute->attrValue = PORT_ArenaZNewArray(arena, SECItem *, i+1);
+    if (!attribute->attrValue) 
+	goto loser;
+
+    /* copy attributes */
+    for (i = 0; attributes[i]; i++) {
+	/*
+	** Attributes are a SetOf Attribute which implies
+	** lexigraphical ordering.  It is assumes that the
+	** attributes are passed in sorted.  If we need to
+	** add functionality to sort them, there is an
+	** example in the PKCS 7 code.
+	*/
+	attribute->attrValue[i] = SECITEM_ArenaDupItem(arena, attributes[i]);
+	if(!attribute->attrValue[i]) 
+	    goto loser;
+    }
+
+    certreq->attributes[0] = attribute;
+
+    return certreq;
+
+loser:
+    CERT_DestroyCertificateRequest(certreq);
+    return NULL;
+}
+
+void
+CERT_DestroyCertificateRequest(CERTCertificateRequest *req)
+{
+    if (req && req->arena) {
+	PORT_FreeArena(req->arena, PR_FALSE);
+    }
+    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, PLArenaPool *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 || req->attributes[0] == 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]));
+}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)