Unexport and remove support for implicit tagging on ASN1_ITYPE_EXTERN.

Currently, the only EXTERN type is X509_NAME. Implicitly tagging an
X509_NAME didn't work anyway because of the cached encoding. Moreover,
even if it did work, it'd be invalid. Name in RFC 5280 is actually a
one-element CHOICE type, and CHOICE types can never be implicitly
tagged. So just remove support.

One thing of note: I'm thinking EXTERN can be used later to retain
ASN1_ITEM compatibility, once X509 and friends no longer use the
template machinery. That means we're not only assuming X509_NAME is
never implicitly tagged, but also that external callers using
<openssl/asn1t.h> won't implicitly tag a built-in type.

This removes a case we need to handle in the rewritten tasn_enc.c. (In
particular, crypto/asn1 and crypto/bytestring use a different tag
representation and I'd like to minimum the number of conversions we
need.)

Update-Note: IMPLEMENT_EXTERN_ASN1 can no longer be used outside the
library. I found no callers using this machinery, and we're better off
gradually migrating every <openssl/asn1t.h> user to CBS/CBB anyway.

Bug: 548
Change-Id: I0aab531077d25960dd3f16183656f318d78a0806
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/56186
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
fips-20230428
David Benjamin 2 years ago committed by Boringssl LUCI CQ
parent 1df70cea5d
commit afa460c7b9
  1. 22
      crypto/asn1/internal.h
  2. 14
      crypto/asn1/tasn_dec.c
  3. 8
      crypto/asn1/tasn_enc.c
  4. 18
      crypto/x509/x_name.c
  5. 29
      include/openssl/asn1t.h

@ -230,6 +230,28 @@ typedef struct {
OPENSSL_EXPORT void asn1_get_string_table_for_testing(
const ASN1_STRING_TABLE **out_ptr, size_t *out_len);
typedef ASN1_VALUE *ASN1_new_func(void);
typedef void ASN1_free_func(ASN1_VALUE *a);
typedef ASN1_VALUE *ASN1_d2i_func(ASN1_VALUE **a, const unsigned char **in,
long length);
typedef int ASN1_i2d_func(ASN1_VALUE *a, unsigned char **in);
typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
const ASN1_ITEM *it, int opt, ASN1_TLC *ctx);
typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it);
typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
typedef struct ASN1_EXTERN_FUNCS_st {
ASN1_ex_new_func *asn1_ex_new;
ASN1_ex_free_func *asn1_ex_free;
ASN1_ex_free_func *asn1_ex_clear;
ASN1_ex_d2i *asn1_ex_d2i;
ASN1_ex_i2d *asn1_ex_i2d;
} ASN1_EXTERN_FUNCS;
#if defined(__cplusplus)
} // extern C

@ -161,7 +161,6 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
long len, const ASN1_ITEM *it, int tag, int aclass,
char opt, int depth) {
const ASN1_TEMPLATE *tt, *errtt = NULL;
const ASN1_EXTERN_FUNCS *ef;
const unsigned char *p = NULL, *q;
unsigned char oclass;
char cst, isopt;
@ -238,10 +237,15 @@ static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
}
return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0);
case ASN1_ITYPE_EXTERN:
// Use new style d2i
ef = it->funcs;
return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, NULL);
case ASN1_ITYPE_EXTERN: {
// We don't support implicit tagging with external types.
if (tag != -1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
goto err;
}
const ASN1_EXTERN_FUNCS *ef = it->funcs;
return ef->asn1_ex_d2i(pval, in, len, it, opt, NULL);
}
case ASN1_ITYPE_CHOICE: {
// It never makes sense for CHOICE types to have implicit tagging, so if

@ -186,9 +186,13 @@ int asn1_item_ex_i2d_opt(ASN1_VALUE **pval, unsigned char **out,
}
case ASN1_ITYPE_EXTERN: {
// If new style i2d it does all the work
// We don't support implicit tagging with external types.
if (tag != -1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_TEMPLATE);
return -1;
}
const ASN1_EXTERN_FUNCS *ef = it->funcs;
int ret = ef->asn1_ex_i2d(pval, out, it, tag, aclass);
int ret = ef->asn1_ex_i2d(pval, out, it);
if (ret == 0) {
// |asn1_ex_i2d| should never return zero. We have already checked
// for optional values generically, and |ASN1_ITYPE_EXTERN| fields

@ -80,11 +80,11 @@ DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
#define X509_NAME_MAX (1024 * 1024)
static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in,
long len, const ASN1_ITEM *it, int tag, int aclass,
char opt, ASN1_TLC *ctx);
long len, const ASN1_ITEM *it, int opt,
ASN1_TLC *ctx);
static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass);
const ASN1_ITEM *it);
static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it);
static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it);
@ -120,13 +120,11 @@ ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL)
// convert to the external form.
static const ASN1_EXTERN_FUNCS x509_name_ff = {
NULL,
x509_name_ex_new,
x509_name_ex_free,
0, // Default clear behaviour is OK
x509_name_ex_d2i,
x509_name_ex_i2d,
NULL,
};
IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff)
@ -189,8 +187,8 @@ static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne) {
}
static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in,
long len, const ASN1_ITEM *it, int tag, int aclass,
char opt, ASN1_TLC *ctx) {
long len, const ASN1_ITEM *it, int opt,
ASN1_TLC *ctx) {
const unsigned char *p = *in, *q;
STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL;
X509_NAME *nm = NULL;
@ -207,8 +205,8 @@ static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in,
// Get internal representation of Name
ASN1_VALUE *intname_val = NULL;
ret = ASN1_item_ex_d2i(&intname_val, &p, len,
ASN1_ITEM_rptr(X509_NAME_INTERNAL), tag, aclass, opt,
ctx);
ASN1_ITEM_rptr(X509_NAME_INTERNAL), /*tag=*/-1,
/*aclass=*/0, opt, ctx);
if (ret <= 0) {
return ret;
}
@ -258,7 +256,7 @@ err:
}
static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass) {
const ASN1_ITEM *it) {
X509_NAME *a = (X509_NAME *)*val;
if (a->modified && (!x509_name_encode(a) || !x509_name_canon(a))) {
return -1;

@ -512,35 +512,6 @@ const char *sname; /* Structure name */
/* Deprecated tag and length cache */
struct ASN1_TLC_st;
/* Typedefs for ASN1 function pointers */
typedef ASN1_VALUE * ASN1_new_func(void);
typedef void ASN1_free_func(ASN1_VALUE *a);
typedef ASN1_VALUE * ASN1_d2i_func(ASN1_VALUE **a, const unsigned char ** in, long length);
typedef int ASN1_i2d_func(ASN1_VALUE * a, unsigned char **in);
typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it,
int tag, int aclass, char opt, ASN1_TLC *ctx);
typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass);
typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it);
typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval,
int indent, const char *fname,
const ASN1_PCTX *pctx);
typedef struct ASN1_EXTERN_FUNCS_st {
void *app_data;
ASN1_ex_new_func *asn1_ex_new;
ASN1_ex_free_func *asn1_ex_free;
ASN1_ex_free_func *asn1_ex_clear;
ASN1_ex_d2i *asn1_ex_d2i;
ASN1_ex_i2d *asn1_ex_i2d;
/* asn1_ex_print is unused. */
ASN1_ex_print_func *asn1_ex_print;
} ASN1_EXTERN_FUNCS;
/* This is the ASN1_AUX structure: it handles various
* miscellaneous requirements. For example the use of
* reference counts and an informational callback.

Loading…
Cancel
Save