From 388ff0b076430b4fbcf5cf30575a304def28bf2d Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sun, 14 Feb 1999 16:48:22 +0000 Subject: [PATCH] Add support for raw extensions. This means that you can include the DER encoding of an arbitrary extension: e.g. 1.3.4.5=critical,RAW:12:34:56 Using this technique currently unsupported extensions can be generated if you know their DER encoding. Even if the extension is supported in future the raw extension will still work: that is the raw version can always be used even if it is a supported extension. --- CHANGES | 4 ++ apps/openssl.cnf | 5 ++ crypto/objects/obj_dat.c | 6 ++- crypto/x509v3/v3_conf.c | 113 +++++++++++++++++++++++++++++++++++---- 4 files changed, 116 insertions(+), 12 deletions(-) diff --git a/CHANGES b/CHANGES index 0a430566cf..7cc1ece6eb 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,10 @@ Changes between 0.9.1c and 0.9.2 + *) Support for RAW extensions where an arbitrary extension can be + created by including its DER encoding. See apps/openssl.cnf for + an example. + *) Make sure latest Perl versions don't interpret some generated C array code as Perl array code in the crypto/err/err_genc.pl script. [Lars Weber <3weber@informatik.uni-hamburg.de>] diff --git a/apps/openssl.cnf b/apps/openssl.cnf index 81dee57055..e5e2eee56f 100644 --- a/apps/openssl.cnf +++ b/apps/openssl.cnf @@ -156,3 +156,8 @@ keyUsage = cRLSign, keyCertSign # Some might want this also #nsCertType = sslCA, emailCA + +# RAW DER hex encoding of an extension: beware experts only! +# 1.2.3.5=RAW:02:03 +# You can even override a supported extension: +# basicConstraints= critical, RAW:30:03:01:01:FF diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c index 3df5cdd97b..563556e1f8 100644 --- a/crypto/objects/obj_dat.c +++ b/crypto/objects/obj_dat.c @@ -420,7 +420,11 @@ int no_name; /* Work out size of content octets */ i=a2d_ASN1_OBJECT(NULL,0,s,-1); - if (i <= 0) return NULL; + if (i <= 0) { + /* Clear the error */ + ERR_get_error(); + return NULL; + } /* Work out total size */ j = ASN1_object_size(0,i,V_ASN1_OBJECT); diff --git a/crypto/x509v3/v3_conf.c b/crypto/x509v3/v3_conf.c index b97e7939ba..a87af95f26 100644 --- a/crypto/x509v3/v3_conf.c +++ b/crypto/x509v3/v3_conf.c @@ -55,7 +55,7 @@ * Hudson (tjh@cryptsoft.com). * */ -/* config file utilities */ +/* extension creation utilities */ #include #include @@ -65,21 +65,53 @@ #include #include "x509v3.h" +#ifndef NOPROTO +static int v3_check_critical(char **value); +static int v3_check_generic(char **value); +static X509_EXTENSION *do_ext_conf(LHASH *conf, X509V3_CTX *ctx, int ext_nid, int crit, char *value); +static X509_EXTENSION *v3_generic_extension(char *ext, char *value, int crit, int type); +#else +static int v3_check_critical(); +static int v3_check_generic(); +static X509_EXTENSION *do_ext_conf(); +static X509V3_EXTENSION *v3_generic_extension(); +#endif + X509_EXTENSION *X509V3_EXT_conf(conf, ctx, name, value) LHASH *conf; /* Config file */ X509V3_CTX *ctx; char *name; /* Name */ char *value; /* Value */ { - return X509V3_EXT_conf_nid(conf, ctx, OBJ_sn2nid(name), value); + int crit; + int ext_type; + crit = v3_check_critical(&value); + if((ext_type = v3_check_generic(&value))) + return v3_generic_extension(name, value, crit, ext_type); + return do_ext_conf(conf, ctx, OBJ_sn2nid(name), crit, value); } - X509_EXTENSION *X509V3_EXT_conf_nid(conf, ctx, ext_nid, value) LHASH *conf; /* Config file */ X509V3_CTX *ctx; int ext_nid; char *value; /* Value */ +{ + int crit; + int ext_type; + crit = v3_check_critical(&value); + if((ext_type = v3_check_generic(&value))) + return v3_generic_extension(OBJ_nid2sn(ext_nid), + value, crit, ext_type); + return do_ext_conf(conf, ctx, ext_nid, crit, value); +} + +static X509_EXTENSION *do_ext_conf(conf, ctx, ext_nid, crit, value) +LHASH *conf; /* Config file */ +X509V3_CTX *ctx; +int ext_nid; +int crit; +char *value; /* Value */ { X509_EXTENSION *ext = NULL; X509V3_EXT_METHOD *method; @@ -87,20 +119,12 @@ char *value; /* Value */ char *ext_struc; char *ext_der, *p; int ext_len; - int crit = 0; ASN1_OCTET_STRING *ext_oct; if(ext_nid == NID_undef) return NULL; if(!(method = X509V3_EXT_get_nid(ext_nid))) { /* Add generic extension support here */ return NULL; } - /* Check for critical */ - if((strlen(value) >= 9) && !strncmp(value, "critical,", 9)) { - crit = 1; - value+=9; - } - /* Skip over spaces */ - while(isspace(*value)) value++; /* Now get internal extension representation based on type */ if(method->v2i) { if(*value == '@') nval = CONF_get_section(conf, value + 1); @@ -138,6 +162,73 @@ char *value; /* Value */ } +/* Check the extension string for critical flag */ +static int v3_check_critical(value) +char **value; +{ + char *p = *value; + if((strlen(p) < 9) || strncmp(p, "critical,", 9)) return 0; + p+=9; + while(isspace(*p)) p++; + *value = p; + return 1; +} + +/* Check extension string for generic extension and return the type */ +static int v3_check_generic(value) +char **value; +{ + char *p = *value; + if((strlen(p) < 4) || strncmp(p, "RAW:,", 4)) return 0; + p+=4; + while(isspace(*p)) p++; + *value = p; + return 1; +} + +/* Create a generic extension: for now just handle RAW type */ +static X509_EXTENSION *v3_generic_extension(ext, value, crit, type) +char *ext; +char *value; +int crit; +int type; +{ +unsigned char *ext_der=NULL; +long ext_len; +ASN1_OBJECT *obj=NULL; +ASN1_OCTET_STRING *oct=NULL; +X509_EXTENSION *extension=NULL; +if(!(obj = OBJ_txt2obj(ext, 0))) { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_NAME_ERROR); + ERR_add_error_data(2, "name=", ext); + goto err; +} + +if(!(ext_der = string_to_hex(value, &ext_len))) { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_VALUE_ERROR); + ERR_add_error_data(2, "value=", value); + goto err; +} + +if(!(oct = ASN1_OCTET_STRING_new())) { + X509V3err(X509V3_F_V3_GENERIC_EXTENSION,ERR_R_MALLOC_FAILURE); + goto err; +} + +oct->data = ext_der; +oct->length = ext_len; +ext_der = NULL; + +extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); + +err: +ASN1_OBJECT_free(obj); +ASN1_OCTET_STRING_free(oct); +if(ext_der) Free(ext_der); +return extension; +} + + /* This is the main function: add a bunch of extensions based on a config file * section */ -- 2.25.1