Continued multibyte character support.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 27 Oct 1999 00:15:11 +0000 (00:15 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 27 Oct 1999 00:15:11 +0000 (00:15 +0000)
Add a bunch of functions to simplify the creation of X509_NAME structures.

Change the X509_NAME_entry_add stuff in req/ca so it no longer uses
X509_NAME_entry_count(): passing -1 has the same effect.

CHANGES
apps/ca.c
apps/openssl.cnf
apps/req.c
crypto/asn1/a_mbstr.c
crypto/asn1/a_strnid.c
crypto/asn1/asn1.h
crypto/x509/x509.h
crypto/x509/x509_err.c
crypto/x509/x509name.c
util/libeay.num

diff --git a/CHANGES b/CHANGES
index 474319de06d4e20ae3a9bf9ad0cb584b393c9ddb..1c4ce47afbda02500654cdad7f2fc3c25cacbbcb 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,24 @@
 
  Changes between 0.9.4 and 0.9.5  [xx XXX 1999]
 
 
  Changes between 0.9.4 and 0.9.5  [xx XXX 1999]
 
+  *) Add a bunch of functions that should simplify the creation of 
+     X509_NAME structures. Now you should be able to do:
+     X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC, "Steve", -1, -1, 0);
+     and have it automatically work out the correct field type and fill in
+     the structures. The more adventurous can try:
+     X509_NAME_add_entry_by_txt(nm, field, MBSTRING_UTF8, str, -1, -1, 0);
+     and it will (hopefully) work out the correct multibyte encoding.
+     [Steve Henson]
+
+  *) Change the 'req' utility to use the new field handling and multibyte
+     copy routines. Before the DN field creation was handled in an ad hoc
+     way in req, ca, and x509 which was rather broken and didn't support
+     BMPStrings or UTF8Strings. Since some software doesn't implement
+     BMPStrings or UTF8Strings yet, they can be enabled using the config file
+     using the dirstring_type option. See the new comment in the default
+     openssl.cnf for more info.
+     [Steve Henson]
+
   *) Make crypto/rand/md_rand.c more robust:
      - Assure unique random numbers after fork().
      - Make sure that concurrent threads access the global counter and
   *) Make crypto/rand/md_rand.c more robust:
      - Assure unique random numbers after fork().
      - Make sure that concurrent threads access the global counter and
index 9cafe400e62cc695714abe89ae124f63f2f95293..36c314e1c1c7af36681e3cfe5c781cd9f0df433d 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -1691,8 +1691,7 @@ again2:
 
                        if (push != NULL)
                                {
 
                        if (push != NULL)
                                {
-                               if (!X509_NAME_add_entry(subject,push,
-                                       X509_NAME_entry_count(subject),0))
+                               if (!X509_NAME_add_entry(subject,push, -1, 0))
                                        {
                                        if (push != NULL)
                                                X509_NAME_ENTRY_free(push);
                                        {
                                        if (push != NULL)
                                                X509_NAME_ENTRY_free(push);
@@ -2053,8 +2052,7 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
                        strlen(buf))) == NULL)
                        goto err;
 
                        strlen(buf))) == NULL)
                        goto err;
 
-               if (!X509_NAME_add_entry(n,ne,X509_NAME_entry_count(n),0))
-                       goto err;
+               if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
                }
        if (spki == NULL)
                {
                }
        if (spki == NULL)
                {
index 8d044fb6b281678e297033efceeb863432b0b817..33b0866f436fe775a7fd328f2314cc6564863ac2 100644 (file)
@@ -86,6 +86,17 @@ distinguished_name   = req_distinguished_name
 attributes             = req_attributes
 x509_extensions        = v3_ca # The extentions to add to the self signed cert
 
 attributes             = req_attributes
 x509_extensions        = v3_ca # The extentions to add to the self signed cert
 
+# This sets the permitted types in a DirectoryString. There are several
+# options. 
+# default: PrintableString, T61String, BMPString.
+# pkix  : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nobmp : PrintableString, T61String (no BMPStrings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+dirstring_type = nobmp
+
 # req_extensions = v3_req # The extensions to add to a certificate request
 
 [ req_distinguished_name ]
 # req_extensions = v3_req # The extensions to add to a certificate request
 
 [ req_distinguished_name ]
index a945610f92b938fbde87e69902798e7b8445b1a1..a395c39f4b3f9d68191054429632c7ddd91971f1 100644 (file)
@@ -82,6 +82,7 @@
 #define ATTRIBUTES     "attributes"
 #define V3_EXTENSIONS  "x509_extensions"
 #define REQ_EXTENSIONS "req_extensions"
 #define ATTRIBUTES     "attributes"
 #define V3_EXTENSIONS  "x509_extensions"
 #define REQ_EXTENSIONS "req_extensions"
+#define DIRSTRING_TYPE "dirstring_type"
 
 #define DEFAULT_KEY_LENGTH     512
 #define MIN_KEY_LENGTH         384
 
 #define DEFAULT_KEY_LENGTH     512
 #define MIN_KEY_LENGTH         384
@@ -452,6 +453,13 @@ bad:
                }
        }
 
                }
        }
 
+       p = CONF_get_string(req_conf, SECTION, DIRSTRING_TYPE);
+
+       if(p && !ASN1_STRING_set_default_mask_asc(p)) {
+               BIO_printf(bio_err, "Invalid DiretoryString setting %s", p);
+               goto end;
+       }
+
        if(!req_exts)
                req_exts = CONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
        if(req_exts) {
        if(!req_exts)
                req_exts = CONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
        if(req_exts) {
@@ -883,6 +891,9 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, int attribs)
 
        ri=req->req_info;
 
 
        ri=req->req_info;
 
+       /* setup version number */
+       if (!ASN1_INTEGER_set(ri->version,0L)) goto err; /* version 1 */
+
        BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n");
        BIO_printf(bio_err,"into your certificate request.\n");
        BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n");
        BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n");
        BIO_printf(bio_err,"into your certificate request.\n");
        BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n");
@@ -891,8 +902,6 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, int attribs)
        BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
        BIO_printf(bio_err,"-----\n");
 
        BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
        BIO_printf(bio_err,"-----\n");
 
-       /* setup version number */
-       if (!ASN1_INTEGER_set(ri->version,0L)) goto err; /* version 1 */
 
        if (sk_CONF_VALUE_num(sk))
                {
 
        if (sk_CONF_VALUE_num(sk))
                {
@@ -1003,8 +1012,7 @@ err:
 static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
             int nid, int min, int max)
        {
 static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
             int nid, int min, int max)
        {
-       int i,j,ret=0;
-       X509_NAME_ENTRY *ne=NULL;
+       int i,ret=0;
        MS_STATIC char buf[1024];
 
        BIO_printf(bio_err,"%s [%s]:",text,def);
        MS_STATIC char buf[1024];
 
        BIO_printf(bio_err,"%s [%s]:",text,def);
@@ -1039,21 +1047,13 @@ static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
                }
        buf[--i]='\0';
 
                }
        buf[--i]='\0';
 
-       j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
-       if (req_fix_data(nid,&j,i,min,max) == 0)
-               goto err;
 #ifdef CHARSET_EBCDIC
        ebcdic2ascii(buf, buf, i);
 #endif
 #ifdef CHARSET_EBCDIC
        ebcdic2ascii(buf, buf, i);
 #endif
-       if ((ne=X509_NAME_ENTRY_create_by_NID(NULL,nid,j,(unsigned char *)buf,
-               strlen(buf)))
-               == NULL) goto err;
-       if (!X509_NAME_add_entry(n,ne,X509_NAME_entry_count(n),0))
-               goto err;
-
+       if (!X509_NAME_add_entry_by_NID(n,nid, MBSTRING_ASC,
+                               (unsigned char *) buf, -1,-1,0)) goto err;
        ret=1;
 err:
        ret=1;
 err:
-       if (ne != NULL) X509_NAME_ENTRY_free(ne);
        return(ret);
        }
 
        return(ret);
        }
 
index 2fe658e085e7f3eecdcbf38e5d23aac56132156c..9e7c7c39e5eb9bcacb391063c2daa64f3b962fb9 100644 (file)
@@ -91,6 +91,35 @@ unsigned long ASN1_STRING_get_default_mask(void)
        return dirstring_mask;
 }
 
        return dirstring_mask;
 }
 
+/* This function sets the default to various "flavours" of configuration.
+ * based on an ASCII string. Currently this is:
+ * MASK:XXXX : a numerical mask value.
+ * nobmp : Don't use BMPStrings (just Printable, T61).
+ * pkix : PKIX recommendation in RFC2459.
+ * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
+ * default:   the default value, Printable, T61, BMP.
+ */
+
+int ASN1_STRING_set_default_mask_asc(char *p)
+{
+       unsigned long mask;
+       char *end;
+       if(!strncmp(p, "MASK:", 5)) {
+               if(!p[5]) return 0;
+               mask = strtoul(p + 5, &end, 0);
+               if(*end) return 0;
+       } else if(!strcmp(p, "nobmp"))
+                        mask = B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING;
+       else if(!strcmp(p, "pkix"))
+                       mask = B_ASN1_PRINTABLESTRING | B_ASN1_BMPSTRING;
+       else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING;
+       else if(!strcmp(p, "default"))
+           mask = B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_BMPSTRING;
+       else return 0;
+       ASN1_STRING_set_default_mask(mask);
+       return 1;
+}
+
 /* These functions take a string in UTF8, ASCII or multibyte form and
  * a mask of permissible ASN1 string types. It then works out the minimal
  * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
 /* These functions take a string in UTF8, ASCII or multibyte form and
  * a mask of permissible ASN1 string types. It then works out the minimal
  * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
index 520b11883f73f75d9b2c52b86053e969239877c7..cb37024db22902edc19d56291c30d94230eca099 100644 (file)
@@ -85,7 +85,7 @@ ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in,
                                        tbl->minsize, tbl->maxsize);
        else ret = ASN1_mbstring_copy(out, in, inlen, inform, 0);
        if(ret <= 0) return NULL;
                                        tbl->minsize, tbl->maxsize);
        else ret = ASN1_mbstring_copy(out, in, inlen, inform, 0);
        if(ret <= 0) return NULL;
-       return str;
+       return *out;
 }
 
 /* Now the tables and helper functions for the string table:
 }
 
 /* Now the tables and helper functions for the string table:
index 2a7da6bf4b8fc0c90c9f49c3bd42c94c81e8a2f2..8c42101d55307c3c8f5ea2ff76bd976b1da36678 100644 (file)
@@ -744,6 +744,7 @@ void *ASN1_unpack_string(ASN1_STRING *oct, char *(*d2i)());
 ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct);
 
 void ASN1_STRING_set_default_mask(unsigned long mask);
 ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct);
 
 void ASN1_STRING_set_default_mask(unsigned long mask);
+int ASN1_STRING_set_default_mask_asc(char *p);
 unsigned long ASN1_STRING_get_default_mask(void);
 int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
                                        int inform, unsigned long mask);
 unsigned long ASN1_STRING_get_default_mask(void);
 int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
                                        int inform, unsigned long mask);
index 64b07e47869417f160575fcbec5db3e871edb5fb..6091ffd4efef156cb5bd28cbd4bd3ce109e22dfb 100644 (file)
@@ -859,8 +859,16 @@ X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc);
 X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc);
 int            X509_NAME_add_entry(X509_NAME *name,X509_NAME_ENTRY *ne,
                        int loc, int set);
 X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc);
 int            X509_NAME_add_entry(X509_NAME *name,X509_NAME_ENTRY *ne,
                        int loc, int set);
+int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
+                       unsigned char *bytes, int len, int loc, int set);
+int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
+                       unsigned char *bytes, int len, int loc, int set);
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
+               char *field, int type, unsigned char *bytes, int len);
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
                        int type,unsigned char *bytes, int len);
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
                        int type,unsigned char *bytes, int len);
+int X509_NAME_add_entry_by_txt(X509_NAME *name, char *field, int type,
+                       unsigned char *bytes, int len, int loc, int set);
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
                        ASN1_OBJECT *obj, int type,unsigned char *bytes,
                        int len);
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
                        ASN1_OBJECT *obj, int type,unsigned char *bytes,
                        int len);
@@ -979,6 +987,7 @@ PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken);
 #define X509_F_X509_LOAD_CRL_FILE                       112
 #define X509_F_X509_NAME_ADD_ENTRY                      113
 #define X509_F_X509_NAME_ENTRY_CREATE_BY_NID            114
 #define X509_F_X509_LOAD_CRL_FILE                       112
 #define X509_F_X509_NAME_ADD_ENTRY                      113
 #define X509_F_X509_NAME_ENTRY_CREATE_BY_NID            114
+#define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT            131
 #define X509_F_X509_NAME_ENTRY_SET_OBJECT               115
 #define X509_F_X509_NAME_ONELINE                        116
 #define X509_F_X509_NAME_PRINT                          117
 #define X509_F_X509_NAME_ENTRY_SET_OBJECT               115
 #define X509_F_X509_NAME_ONELINE                        116
 #define X509_F_X509_NAME_PRINT                          117
@@ -1000,6 +1009,7 @@ PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken);
 #define X509_R_CERT_ALREADY_IN_HASH_TABLE               101
 #define X509_R_ERR_ASN1_LIB                             102
 #define X509_R_INVALID_DIRECTORY                        113
 #define X509_R_CERT_ALREADY_IN_HASH_TABLE               101
 #define X509_R_ERR_ASN1_LIB                             102
 #define X509_R_INVALID_DIRECTORY                        113
+#define X509_R_INVALID_FIELD_NAME                       119
 #define X509_R_KEY_TYPE_MISMATCH                        115
 #define X509_R_KEY_VALUES_MISMATCH                      116
 #define X509_R_LOADING_CERT_DIR                                 103
 #define X509_R_KEY_TYPE_MISMATCH                        115
 #define X509_R_KEY_VALUES_MISMATCH                      116
 #define X509_R_LOADING_CERT_DIR                                 103
index a2a0f1184fbdf079276a7c9f6b33e02c2cf827e2..0a0b704043209fe647d58b9ad780aae8d6d475b6 100644 (file)
@@ -80,6 +80,7 @@ static ERR_STRING_DATA X509_str_functs[]=
 {ERR_PACK(0,X509_F_X509_LOAD_CRL_FILE,0),      "X509_load_crl_file"},
 {ERR_PACK(0,X509_F_X509_NAME_ADD_ENTRY,0),     "X509_NAME_add_entry"},
 {ERR_PACK(0,X509_F_X509_NAME_ENTRY_CREATE_BY_NID,0),   "X509_NAME_ENTRY_create_by_NID"},
 {ERR_PACK(0,X509_F_X509_LOAD_CRL_FILE,0),      "X509_load_crl_file"},
 {ERR_PACK(0,X509_F_X509_NAME_ADD_ENTRY,0),     "X509_NAME_add_entry"},
 {ERR_PACK(0,X509_F_X509_NAME_ENTRY_CREATE_BY_NID,0),   "X509_NAME_ENTRY_create_by_NID"},
+{ERR_PACK(0,X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,0),   "X509_NAME_ENTRY_create_by_txt"},
 {ERR_PACK(0,X509_F_X509_NAME_ENTRY_SET_OBJECT,0),      "X509_NAME_ENTRY_set_object"},
 {ERR_PACK(0,X509_F_X509_NAME_ONELINE,0),       "X509_NAME_oneline"},
 {ERR_PACK(0,X509_F_X509_NAME_PRINT,0), "X509_NAME_print"},
 {ERR_PACK(0,X509_F_X509_NAME_ENTRY_SET_OBJECT,0),      "X509_NAME_ENTRY_set_object"},
 {ERR_PACK(0,X509_F_X509_NAME_ONELINE,0),       "X509_NAME_oneline"},
 {ERR_PACK(0,X509_F_X509_NAME_PRINT,0), "X509_NAME_print"},
@@ -104,6 +105,7 @@ static ERR_STRING_DATA X509_str_reasons[]=
 {X509_R_CERT_ALREADY_IN_HASH_TABLE       ,"cert already in hash table"},
 {X509_R_ERR_ASN1_LIB                     ,"err asn1 lib"},
 {X509_R_INVALID_DIRECTORY                ,"invalid directory"},
 {X509_R_CERT_ALREADY_IN_HASH_TABLE       ,"cert already in hash table"},
 {X509_R_ERR_ASN1_LIB                     ,"err asn1 lib"},
 {X509_R_INVALID_DIRECTORY                ,"invalid directory"},
+{X509_R_INVALID_FIELD_NAME               ,"invalid field name"},
 {X509_R_KEY_TYPE_MISMATCH                ,"key type mismatch"},
 {X509_R_KEY_VALUES_MISMATCH              ,"key values mismatch"},
 {X509_R_LOADING_CERT_DIR                 ,"loading cert dir"},
 {X509_R_KEY_TYPE_MISMATCH                ,"key type mismatch"},
 {X509_R_KEY_VALUES_MISMATCH              ,"key values mismatch"},
 {X509_R_LOADING_CERT_DIR                 ,"loading cert dir"},
index 64c13154955f876dfdb3a59bd6f2a5cb18e318f3..bd7b985629e4754dcfe2e0b2d238e7906a15cef9 100644 (file)
@@ -171,6 +171,33 @@ X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
        return(ret);
        }
 
        return(ret);
        }
 
+int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
+                       unsigned char *bytes, int len, int loc, int set)
+{
+       X509_NAME_ENTRY *ne;
+       ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
+       if(!ne) return 0;
+       return X509_NAME_add_entry(name, ne, loc, set);
+}
+
+int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
+                       unsigned char *bytes, int len, int loc, int set)
+{
+       X509_NAME_ENTRY *ne;
+       ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
+       if(!ne) return 0;
+       return X509_NAME_add_entry(name, ne, loc, set);
+}
+
+int X509_NAME_add_entry_by_txt(X509_NAME *name, char *field, int type,
+                       unsigned char *bytes, int len, int loc, int set)
+{
+       X509_NAME_ENTRY *ne;
+       ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
+       if(!ne) return 0;
+       return X509_NAME_add_entry(name, ne, loc, set);
+}
+
 /* if set is -1, append to previous set, 0 'a new one', and 1,
  * prepend to the guy we are about to stomp on. */
 int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
 /* if set is -1, append to previous set, 0 'a new one', and 1,
  * prepend to the guy we are about to stomp on. */
 int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
@@ -236,6 +263,21 @@ err:
        return(0);
        }
 
        return(0);
        }
 
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
+               char *field, int type, unsigned char *bytes, int len)
+       {
+       ASN1_OBJECT *obj;
+
+       obj=OBJ_txt2obj(field, 0);
+       if (obj == NULL)
+               {
+               X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
+                                               X509_R_INVALID_FIELD_NAME);
+               return(NULL);
+               }
+       return(X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len));
+       }
+
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
             int type, unsigned char *bytes, int len)
        {
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
             int type, unsigned char *bytes, int len)
        {
index 04d14eab860a2a2e0b0119eef93beed3db1879c0..939b6e90f50479a26c9ea9ded7e5e5fc09cb3a1d 100755 (executable)
@@ -1993,3 +1993,8 @@ EVP_PKEY_get_RSA                        2017
 EVP_PKEY_get_DH                         2018
 EVP_PKEY_get_DSA                        2019
 X509_PURPOSE_cleanup                    2020
 EVP_PKEY_get_DH                         2018
 EVP_PKEY_get_DSA                        2019
 X509_PURPOSE_cleanup                    2020
+ASN1_STRING_set_default_mask_asc        2021
+X509_NAME_add_entry_by_txt              2022
+X509_NAME_add_entry_by_NID              2023
+X509_NAME_add_entry_by_OBJ              2024
+X509_NAME_ENTRY_create_by_txt           2025