Move a_strex.c back to asn1, split X509_NAME bits out. With io_ch unwound, X509_NAME_print_ex just calls ASN1_STRING_print_ex, so we can put all the code in the right directories. We need to duplicate maybe_write, but it's a one-line function. Change-Id: Ifaa9f1a24ee609cbaa24f93eb992f7d911f1b4a0 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48774 Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index 57fa3ee..990df00 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt
@@ -211,6 +211,7 @@ asn1/a_object.c asn1/a_octet.c asn1/a_print.c + asn1/a_strex.c asn1/a_strnid.c asn1/a_time.c asn1/a_type.c @@ -350,13 +351,13 @@ trust_token/voprf.c x509/a_digest.c x509/a_sign.c - x509/a_strex.c x509/a_verify.c x509/algorithm.c x509/asn1_gen.c x509/by_dir.c x509/by_file.c x509/i2d_pr.c + x509/name_print.c x509/rsa_pss.c x509/t_crl.c x509/t_req.c
diff --git a/crypto/x509/a_strex.c b/crypto/asn1/a_strex.c similarity index 71% rename from crypto/x509/a_strex.c rename to crypto/asn1/a_strex.c index 4f216fa..2e9f08a 100644 --- a/crypto/x509/a_strex.c +++ b/crypto/asn1/a_strex.c
@@ -54,23 +54,17 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ -#include <openssl/x509.h> +#include <openssl/asn1.h> #include <inttypes.h> #include <string.h> -#include <openssl/asn1.h> +#include <openssl/bio.h> #include <openssl/mem.h> -#include <openssl/obj.h> #include "charmap.h" -#include "../asn1/internal.h" +#include "internal.h" -/* - * ASN1_STRING_print_ex() and X509_NAME_print_ex(). Enhanced string and name - * printing routines handling multibyte characters, RFC2253 and a host of - * other options. - */ #define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253) @@ -428,188 +422,6 @@ return ret; } -/* Used for line indenting: print 'indent' spaces */ - -static int do_indent(BIO *out, int indent) -{ - int i; - for (i = 0; i < indent; i++) - if (!maybe_write(out, " ", 1)) - return 0; - return 1; -} - -#define FN_WIDTH_LN 25 -#define FN_WIDTH_SN 10 - -static int do_name_ex(BIO *out, const X509_NAME *n, int indent, - unsigned long flags) -{ - int i, prev = -1, orflags, cnt; - int fn_opt, fn_nid; - ASN1_OBJECT *fn; - ASN1_STRING *val; - X509_NAME_ENTRY *ent; - char objtmp[80]; - const char *objbuf; - int outlen, len; - const char *sep_dn, *sep_mv, *sep_eq; - int sep_dn_len, sep_mv_len, sep_eq_len; - if (indent < 0) - indent = 0; - outlen = indent; - if (!do_indent(out, indent)) - return -1; - switch (flags & XN_FLAG_SEP_MASK) { - case XN_FLAG_SEP_MULTILINE: - sep_dn = "\n"; - sep_dn_len = 1; - sep_mv = " + "; - sep_mv_len = 3; - break; - - case XN_FLAG_SEP_COMMA_PLUS: - sep_dn = ","; - sep_dn_len = 1; - sep_mv = "+"; - sep_mv_len = 1; - indent = 0; - break; - - case XN_FLAG_SEP_CPLUS_SPC: - sep_dn = ", "; - sep_dn_len = 2; - sep_mv = " + "; - sep_mv_len = 3; - indent = 0; - break; - - case XN_FLAG_SEP_SPLUS_SPC: - sep_dn = "; "; - sep_dn_len = 2; - sep_mv = " + "; - sep_mv_len = 3; - indent = 0; - break; - - default: - return -1; - } - - if (flags & XN_FLAG_SPC_EQ) { - sep_eq = " = "; - sep_eq_len = 3; - } else { - sep_eq = "="; - sep_eq_len = 1; - } - - fn_opt = flags & XN_FLAG_FN_MASK; - - cnt = X509_NAME_entry_count(n); - for (i = 0; i < cnt; i++) { - if (flags & XN_FLAG_DN_REV) - ent = X509_NAME_get_entry(n, cnt - i - 1); - else - ent = X509_NAME_get_entry(n, i); - if (prev != -1) { - if (prev == ent->set) { - if (!maybe_write(out, sep_mv, sep_mv_len)) - return -1; - outlen += sep_mv_len; - } else { - if (!maybe_write(out, sep_dn, sep_dn_len)) - return -1; - outlen += sep_dn_len; - if (!do_indent(out, indent)) - return -1; - outlen += indent; - } - } - prev = ent->set; - fn = X509_NAME_ENTRY_get_object(ent); - val = X509_NAME_ENTRY_get_data(ent); - fn_nid = OBJ_obj2nid(fn); - if (fn_opt != XN_FLAG_FN_NONE) { - int objlen, fld_len; - if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) { - OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1); - fld_len = 0; /* XXX: what should this be? */ - objbuf = objtmp; - } else { - if (fn_opt == XN_FLAG_FN_SN) { - fld_len = FN_WIDTH_SN; - objbuf = OBJ_nid2sn(fn_nid); - } else if (fn_opt == XN_FLAG_FN_LN) { - fld_len = FN_WIDTH_LN; - objbuf = OBJ_nid2ln(fn_nid); - } else { - fld_len = 0; /* XXX: what should this be? */ - objbuf = ""; - } - } - objlen = strlen(objbuf); - if (!maybe_write(out, objbuf, objlen)) - return -1; - if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { - if (!do_indent(out, fld_len - objlen)) - return -1; - outlen += fld_len - objlen; - } - if (!maybe_write(out, sep_eq, sep_eq_len)) - return -1; - outlen += objlen + sep_eq_len; - } - /* - * If the field name is unknown then fix up the DER dump flag. We - * might want to limit this further so it will DER dump on anything - * other than a few 'standard' fields. - */ - if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) - orflags = ASN1_STRFLGS_DUMP_ALL; - else - orflags = 0; - - len = ASN1_STRING_print_ex(out, val, flags | orflags); - if (len < 0) - return -1; - outlen += len; - } - return outlen; -} - -/* Wrappers round the main functions */ - -int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, - unsigned long flags) -{ - if (flags == XN_FLAG_COMPAT) - return X509_NAME_print(out, nm, indent); - return do_name_ex(out, nm, indent, flags); -} - -int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent, - unsigned long flags) -{ - BIO *bio = NULL; - if (fp != NULL) { - /* If |fp| is NULL, this function returns the number of bytes without - * writing. */ - bio = BIO_new_fp(fp, BIO_NOCLOSE); - if (bio == NULL) { - return -1; - } - } - int ret = X509_NAME_print_ex(bio, nm, indent, flags); - BIO_free(bio); - return ret; -} - -/* - * Utility function: convert any string type to UTF8, returns number of bytes - * in output string or a negative error code - */ - int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in) { ASN1_STRING stmp, *str = &stmp; @@ -626,9 +438,8 @@ stmp.data = NULL; stmp.length = 0; stmp.flags = 0; - ret = - ASN1_mbstring_copy(&str, in->data, in->length, mbflag, - B_ASN1_UTF8STRING); + ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, + B_ASN1_UTF8STRING); if (ret < 0) return ret; *out = stmp.data;
diff --git a/crypto/x509/charmap.h b/crypto/asn1/charmap.h similarity index 100% rename from crypto/x509/charmap.h rename to crypto/asn1/charmap.h
diff --git a/crypto/x509/name_print.c b/crypto/x509/name_print.c new file mode 100644 index 0000000..115edde --- /dev/null +++ b/crypto/x509/name_print.c
@@ -0,0 +1,246 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#include <openssl/x509.h> + +#include <inttypes.h> +#include <string.h> + +#include <openssl/asn1.h> +#include <openssl/bio.h> +#include <openssl/obj.h> + + +static int maybe_write(BIO *out, const void *buf, int len) +{ + /* If |out| is NULL, ignore the output but report the length. */ + return out == NULL || BIO_write(out, buf, len) == len; +} + +/* do_indent prints |indent| spaces to |out|. */ +static int do_indent(BIO *out, int indent) +{ + for (int i = 0; i < indent; i++) { + if (!maybe_write(out, " ", 1)) { + return 0; + } + } + return 1; +} + +#define FN_WIDTH_LN 25 +#define FN_WIDTH_SN 10 + +static int do_name_ex(BIO *out, const X509_NAME *n, int indent, + unsigned long flags) +{ + int i, prev = -1, orflags, cnt; + int fn_opt, fn_nid; + ASN1_OBJECT *fn; + ASN1_STRING *val; + X509_NAME_ENTRY *ent; + char objtmp[80]; + const char *objbuf; + int outlen, len; + const char *sep_dn, *sep_mv, *sep_eq; + int sep_dn_len, sep_mv_len, sep_eq_len; + if (indent < 0) + indent = 0; + outlen = indent; + if (!do_indent(out, indent)) + return -1; + switch (flags & XN_FLAG_SEP_MASK) { + case XN_FLAG_SEP_MULTILINE: + sep_dn = "\n"; + sep_dn_len = 1; + sep_mv = " + "; + sep_mv_len = 3; + break; + + case XN_FLAG_SEP_COMMA_PLUS: + sep_dn = ","; + sep_dn_len = 1; + sep_mv = "+"; + sep_mv_len = 1; + indent = 0; + break; + + case XN_FLAG_SEP_CPLUS_SPC: + sep_dn = ", "; + sep_dn_len = 2; + sep_mv = " + "; + sep_mv_len = 3; + indent = 0; + break; + + case XN_FLAG_SEP_SPLUS_SPC: + sep_dn = "; "; + sep_dn_len = 2; + sep_mv = " + "; + sep_mv_len = 3; + indent = 0; + break; + + default: + return -1; + } + + if (flags & XN_FLAG_SPC_EQ) { + sep_eq = " = "; + sep_eq_len = 3; + } else { + sep_eq = "="; + sep_eq_len = 1; + } + + fn_opt = flags & XN_FLAG_FN_MASK; + + cnt = X509_NAME_entry_count(n); + for (i = 0; i < cnt; i++) { + if (flags & XN_FLAG_DN_REV) + ent = X509_NAME_get_entry(n, cnt - i - 1); + else + ent = X509_NAME_get_entry(n, i); + if (prev != -1) { + if (prev == ent->set) { + if (!maybe_write(out, sep_mv, sep_mv_len)) + return -1; + outlen += sep_mv_len; + } else { + if (!maybe_write(out, sep_dn, sep_dn_len)) + return -1; + outlen += sep_dn_len; + if (!do_indent(out, indent)) + return -1; + outlen += indent; + } + } + prev = ent->set; + fn = X509_NAME_ENTRY_get_object(ent); + val = X509_NAME_ENTRY_get_data(ent); + fn_nid = OBJ_obj2nid(fn); + if (fn_opt != XN_FLAG_FN_NONE) { + int objlen, fld_len; + if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) { + OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1); + fld_len = 0; /* XXX: what should this be? */ + objbuf = objtmp; + } else { + if (fn_opt == XN_FLAG_FN_SN) { + fld_len = FN_WIDTH_SN; + objbuf = OBJ_nid2sn(fn_nid); + } else if (fn_opt == XN_FLAG_FN_LN) { + fld_len = FN_WIDTH_LN; + objbuf = OBJ_nid2ln(fn_nid); + } else { + fld_len = 0; /* XXX: what should this be? */ + objbuf = ""; + } + } + objlen = strlen(objbuf); + if (!maybe_write(out, objbuf, objlen)) + return -1; + if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { + if (!do_indent(out, fld_len - objlen)) + return -1; + outlen += fld_len - objlen; + } + if (!maybe_write(out, sep_eq, sep_eq_len)) + return -1; + outlen += objlen + sep_eq_len; + } + /* + * If the field name is unknown then fix up the DER dump flag. We + * might want to limit this further so it will DER dump on anything + * other than a few 'standard' fields. + */ + if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) + orflags = ASN1_STRFLGS_DUMP_ALL; + else + orflags = 0; + + len = ASN1_STRING_print_ex(out, val, flags | orflags); + if (len < 0) + return -1; + outlen += len; + } + return outlen; +} + +int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, + unsigned long flags) +{ + if (flags == XN_FLAG_COMPAT) + return X509_NAME_print(out, nm, indent); + return do_name_ex(out, nm, indent, flags); +} + +int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent, + unsigned long flags) +{ + BIO *bio = NULL; + if (fp != NULL) { + /* If |fp| is NULL, this function returns the number of bytes without + * writing. */ + bio = BIO_new_fp(fp, BIO_NOCLOSE); + if (bio == NULL) { + return -1; + } + } + int ret = X509_NAME_print_ex(bio, nm, indent, flags); + BIO_free(bio); + return ret; +}