From 7be7ee87aa5aff9ce8f4fffb181f14b149919ad9 Mon Sep 17 00:00:00 2001 From: jsing Date: Tue, 14 Dec 2021 17:35:21 +0000 Subject: [PATCH] Consolidate ASN.1 universal tag type data. There are currently three different tables in three different files that contain information about ASN.1 universal class tag types. Range checking is also implemented in three different places (with different implementations). Consolidate all of this into a single table, provide a lookup function that deals with the range checks and wrappers to deal with specific types. ok inoguchi@ tb@ --- lib/libcrypto/Makefile | 4 +- lib/libcrypto/asn1/a_strex.c | 47 ++---- lib/libcrypto/asn1/asn1_locl.h | 4 +- lib/libcrypto/asn1/asn1_par.c | 24 +-- lib/libcrypto/asn1/asn1_types.c | 263 ++++++++++++++++++++++++++++++++ lib/libcrypto/asn1/tasn_dec.c | 23 +-- 6 files changed, 283 insertions(+), 82 deletions(-) create mode 100644 lib/libcrypto/asn1/asn1_types.c diff --git a/lib/libcrypto/Makefile b/lib/libcrypto/Makefile index df4649acaaf..c7d84b437ba 100644 --- a/lib/libcrypto/Makefile +++ b/lib/libcrypto/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.55 2021/12/13 17:56:15 jsing Exp $ +# $OpenBSD: Makefile,v 1.56 2021/12/14 17:35:21 jsing Exp $ LIB= crypto LIBREBUILD=y @@ -65,7 +65,7 @@ SRCS+= f_int.c f_string.c n_pkey.c SRCS+= f_enum.c x_pkey.c x_exten.c bio_asn1.c bio_ndef.c asn_mime.c SRCS+= asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_strnid.c SRCS+= evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p8_pkey.c asn_moid.c -SRCS+= a_time_tm.c +SRCS+= a_time_tm.c asn1_types.c # bf/ SRCS+= bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c diff --git a/lib/libcrypto/asn1/a_strex.c b/lib/libcrypto/asn1/a_strex.c index 3b66ea8d36d..61672d29a44 100644 --- a/lib/libcrypto/asn1/a_strex.c +++ b/lib/libcrypto/asn1/a_strex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_strex.c,v 1.29 2021/11/01 20:53:08 tb Exp $ */ +/* $OpenBSD: a_strex.c,v 1.30 2021/12/14 17:35:21 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -322,22 +322,6 @@ do_dump(unsigned long lflags, char_io *io_ch, void *arg, const ASN1_STRING *str) return outlen + 1; } -/* Lookup table to convert tags to character widths, - * 0 = UTF8 encoded, -1 is used for non string types - * otherwise it is the number of bytes per character - */ - -static const signed char tag2nbyte[] = { - -1, -1, -1, -1, -1, /* 0-4 */ - -1, -1, -1, -1, -1, /* 5-9 */ - -1, -1, 0, -1, /* 10-13 */ - -1, -1, -1, -1, /* 15-17 */ - -1, 1, 1, /* 18-20 */ - -1, 1, 1, 1, /* 21-24 */ - -1, 1, -1, /* 25-27 */ - 4, -1, 2 /* 28-30 */ -}; - /* This is the main function, print out an * ASN1_STRING taking note of various escape * and display options. Returns number of @@ -371,19 +355,16 @@ do_print_ex(char_io *io_ch, void *arg, unsigned long lflags, /* Decide what to do with type, either dump content or display it */ - /* Dump everything */ - if (lflags & ASN1_STRFLGS_DUMP_ALL) + if (lflags & ASN1_STRFLGS_DUMP_ALL) { + /* Dump everything. */ type = -1; - /* Ignore the string type */ - else if (lflags & ASN1_STRFLGS_IGNORE_TYPE) + } else if (lflags & ASN1_STRFLGS_IGNORE_TYPE) { + /* Ignore the string type. */ type = 1; - else { - /* Else determine width based on type */ - if ((type > 0) && (type < 31)) - type = tag2nbyte[type]; - else - type = -1; - if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) + } else { + /* Else determine width based on type. */ + type = asn1_tag2charwidth(type); + if (type == -1 && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) type = 1; } @@ -627,17 +608,15 @@ int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in) { ASN1_STRING stmp, *str = &stmp; - int mbflag, type, ret; + int mbflag, ret; if (!in) return -1; - type = in->type; - if ((type < 0) || (type > 30)) - return -1; - mbflag = tag2nbyte[type]; - if (mbflag == -1) + + if ((mbflag = asn1_tag2charwidth(in->type)) == -1) return -1; mbflag |= MBSTRING_FLAG; + stmp.data = NULL; stmp.length = 0; ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, diff --git a/lib/libcrypto/asn1/asn1_locl.h b/lib/libcrypto/asn1/asn1_locl.h index 39779d9377b..f7731ec5dd3 100644 --- a/lib/libcrypto/asn1/asn1_locl.h +++ b/lib/libcrypto/asn1/asn1_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: asn1_locl.h,v 1.12 2019/10/24 16:36:10 jsing Exp $ */ +/* $OpenBSD: asn1_locl.h,v 1.13 2021/12/14 17:35:21 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -155,4 +155,6 @@ struct x509_crl_method_st { int UTF8_getc(const unsigned char *str, int len, unsigned long *val); int UTF8_putc(unsigned char *str, int len, unsigned long value); +int asn1_tag2charwidth(int tag); + __END_HIDDEN_DECLS diff --git a/lib/libcrypto/asn1/asn1_par.c b/lib/libcrypto/asn1/asn1_par.c index af948c52678..46049305932 100644 --- a/lib/libcrypto/asn1/asn1_par.c +++ b/lib/libcrypto/asn1/asn1_par.c @@ -1,4 +1,4 @@ -/* $OpenBSD: asn1_par.c,v 1.29 2021/12/13 17:58:41 tb Exp $ */ +/* $OpenBSD: asn1_par.c,v 1.30 2021/12/14 17:35:21 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -380,25 +380,3 @@ end: *pp = p; return (ret); } - -const char * -ASN1_tag2str(int tag) -{ - static const char * const tag2str[] = { - "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */ - "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */ - "ENUMERATED", "", "UTF8STRING", "", /* 10-13 */ - "", "", "SEQUENCE", "SET", /* 15-17 */ - "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */ - "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24 */ - "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */ - "UNIVERSALSTRING", "", "BMPSTRING" /* 28-30 */ - }; - - if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) - tag &= ~0x100; - - if (tag < 0 || tag > 30) - return "(unknown)"; - return tag2str[tag]; -} diff --git a/lib/libcrypto/asn1/asn1_types.c b/lib/libcrypto/asn1/asn1_types.c new file mode 100644 index 00000000000..c8e6b23f4fb --- /dev/null +++ b/lib/libcrypto/asn1/asn1_types.c @@ -0,0 +1,263 @@ +/* $OpenBSD: asn1_types.c,v 1.1 2021/12/14 17:35:21 jsing Exp $ */ +/* + * Copyright (c) 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +struct asn1_type { + const char *name; + uint32_t bit_value; + int char_width; +}; + +/* + * Universal class tag types - ITU X.680. + */ +static const struct asn1_type asn1_types[31] = { + [0] = { + /* Tag 0 (0x00) - Reserved for use by encoding rules */ + .name = "EOC", + .bit_value = 0, + .char_width = -1, + }, + [1] = { + /* Tag 1 (0x01) - Boolean */ + .name = "BOOLEAN", + .bit_value = 0, + .char_width = -1, + }, + [2] = { + /* Tag 2 (0x02) - Integer */ + .name = "INTEGER", + .bit_value = 0, + .char_width = -1, + }, + [3] = { + /* Tag 3 (0x03) - BitString */ + .name = "BIT STRING", + .bit_value = B_ASN1_BIT_STRING, + .char_width = -1, + }, + [4] = { + /* Tag 4 (0x04) - OctetString */ + .name = "OCTET STRING", + .bit_value = B_ASN1_OCTET_STRING, + .char_width = -1, + }, + [5] = { + /* Tag 5 (0x05) - Null */ + .name = "NULL", + .bit_value = 0, + .char_width = -1, + }, + [6] = { + /* Tag 6 (0x06) - Object Identifier */ + .name = "OBJECT", + .bit_value = 0, + .char_width = -1, + }, + [7] = { + /* Tag 7 (0x07) - Object Descriptor */ + .name = "OBJECT DESCRIPTOR", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [8] = { + /* Tag 8 (0x08) - External */ + .name = "EXTERNAL", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [9] = { + /* Tag 9 (0x09) - Real */ + .name = "REAL", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [10] = { + /* Tag 10 (0x0a) - Enumerated */ + .name = "ENUMERATED", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [11] = { + /* Tag 11 (0x0b) - Embedded PDV */ + .name = "", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [12] = { + /* Tag 12 (0x0c) - UTF8String */ + .name = "UTF8STRING", + .bit_value = B_ASN1_UTF8STRING, + .char_width = 0, + }, + [13] = { + /* Tag 13 (0x0d) - Relative Object Identifier */ + .name = "", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [14] = { + /* Tag 14 (0x0e) - Time */ + .name = "", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [15] = { + /* Tag 15 (0x0f) - Reserved */ + .name = "", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [16] = { + /* Tag 16 (0x10)- Sequence */ + .name = "SEQUENCE", + .bit_value = B_ASN1_SEQUENCE, + .char_width = -1, + }, + [17] = { + /* Tag 17 (0x11) - Set */ + .name = "SET", + .bit_value = 0, + .char_width = -1, + }, + [18] = { + /* Tag 18 (0x12) - NumericString */ + .name = "NUMERICSTRING", + .bit_value = B_ASN1_NUMERICSTRING, + .char_width = -1, + }, + [19] = { + /* Tag 19 (0x13) - PrintableString */ + .name = "PRINTABLESTRING", + .bit_value = B_ASN1_PRINTABLESTRING, + .char_width = 1, + }, + [20] = { + /* Tag 20 (0x14) - TeletexString (T61String) */ + .name = "T61STRING", + .bit_value = B_ASN1_T61STRING, + .char_width = 1, + }, + [21] = { + /* Tag 21 (0x15) - VideotexString */ + .name = "VIDEOTEXSTRING", + .bit_value = B_ASN1_VIDEOTEXSTRING, + .char_width = -1, + }, + [22] = { + /* Tag 22 (0x16) - IA5String */ + .name = "IA5STRING", + .bit_value = B_ASN1_IA5STRING, + .char_width = 1, + }, + [23] = { + /* Tag 23 (0x17) - UTCTime */ + .name = "UTCTIME", + .bit_value = B_ASN1_UTCTIME, + .char_width = 1, + }, + [24] = { + /* Tag 24 (0x18) - GeneralizedTime */ + .name = "GENERALIZEDTIME", + .bit_value = B_ASN1_GENERALIZEDTIME, + .char_width = 1, + }, + [25] = { + /* Tag 25 (0x19) - GraphicString */ + .name = "GRAPHICSTRING", + .bit_value = B_ASN1_GRAPHICSTRING, + .char_width = -1, + }, + [26] = { + /* Tag 26 (0x1a) - VisibleString (ISO646String) */ + .name = "VISIBLESTRING", + .bit_value = B_ASN1_ISO64STRING, + .char_width = 1, + }, + [27] = { + /* Tag 27 (0x1b) - GeneralString */ + .name = "GENERALSTRING", + .bit_value = B_ASN1_GENERALSTRING, + .char_width = -1, + }, + [28] = { + /* Tag 28 (0x1c) - UniversalString */ + .name = "UNIVERSALSTRING", + .bit_value = B_ASN1_UNIVERSALSTRING, + .char_width = 4, + }, + [29] = { + /* Tag 29 (0x1d) - Unallocated */ + .name = "", + .bit_value = B_ASN1_UNKNOWN, + .char_width = -1, + }, + [30] = { + /* Tag 30 (0x1e) - BMPString */ + .name = "BMPSTRING", + .bit_value = B_ASN1_BMPSTRING, + .char_width = 2, + }, +}; + +static const struct asn1_type * +asn1_type_by_tag(int tag) +{ + if (tag < 0 || tag > 30) + return NULL; + + return &asn1_types[tag]; +} + +int +asn1_tag2charwidth(int tag) +{ + const struct asn1_type *at; + + if ((at = asn1_type_by_tag(tag)) != NULL) + return at->char_width; + + return -1; +} + +unsigned long +ASN1_tag2bit(int tag) +{ + const struct asn1_type *at; + + if ((at = asn1_type_by_tag(tag)) != NULL) + return (unsigned long)at->bit_value; + + return 0; +} + +const char * +ASN1_tag2str(int tag) +{ + const struct asn1_type *at; + + if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED) + tag &= ~V_ASN1_NEG; + + if ((at = asn1_type_by_tag(tag)) != NULL) + return at->name; + + return "(unknown)"; +} diff --git a/lib/libcrypto/asn1/tasn_dec.c b/lib/libcrypto/asn1/tasn_dec.c index a04a84cce89..e207691e2ea 100644 --- a/lib/libcrypto/asn1/tasn_dec.c +++ b/lib/libcrypto/asn1/tasn_dec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tasn_dec.c,v 1.45 2021/12/13 17:50:24 jsing Exp $ */ +/* $OpenBSD: tasn_dec.c,v 1.46 2021/12/14 17:35:21 jsing Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -95,27 +95,6 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx); -/* Table to convert tags to bit values, used for MSTRING type */ -static const unsigned long tag2bit[32] = { - 0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */ - B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN,/* tags 4- 7 */ - B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,/* tags 8-11 */ - B_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */ - B_ASN1_SEQUENCE,0,B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */ - B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING, /* tags 20-22 */ - B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, /* tags 23-24 */ - B_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING, /* tags 25-27 */ - B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */ -}; - -unsigned long -ASN1_tag2bit(int tag) -{ - if ((tag < 0) || (tag > 30)) - return 0; - return tag2bit[tag]; -} - static void asn1_tlc_invalidate(ASN1_TLC *ctx) { -- 2.20.1