Convert asn1_ex_c2i() to CBS.
authorjsing <jsing@openbsd.org>
Sat, 23 Apr 2022 18:47:08 +0000 (18:47 +0000)
committerjsing <jsing@openbsd.org>
Sat, 23 Apr 2022 18:47:08 +0000 (18:47 +0000)
This allows us to make direct use of c2i_ASN1_OBJECT_cbs().

ok inoguchi@ tb@

lib/libcrypto/asn1/a_object.c
lib/libcrypto/asn1/asn1_locl.h
lib/libcrypto/asn1/tasn_dec.c

index c6e4c77..c695499 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: a_object.c,v 1.46 2022/04/10 12:42:33 inoguchi Exp $ */
+/* $OpenBSD: a_object.c,v 1.47 2022/04/23 18:47:08 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -529,9 +529,14 @@ c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content)
        size_t data_len;
        CBS cbs;
 
-       if (out_aobj == NULL || *out_aobj != NULL)
+       if (out_aobj == NULL)
                goto err;
 
+       if (*out_aobj != NULL) {
+               ASN1_OBJECT_free(*out_aobj);
+               *out_aobj = NULL;
+       }
+
        /* Parse and validate OID encoding per X.690 8.19.2. */
        CBS_dup(content, &cbs);
        if (CBS_len(&cbs) == 0) {
index 756e407..d4ea3a9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: asn1_locl.h,v 1.24 2022/03/26 14:47:58 jsing Exp $ */
+/* $OpenBSD: asn1_locl.h,v 1.25 2022/04/23 18:47:08 jsing Exp $ */
 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2006.
  */
@@ -203,6 +203,7 @@ int asn1_tag2charwidth(int tag);
 
 int i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len,
     int no_name);
+int c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content);
 ASN1_OBJECT *t2i_ASN1_OBJECT_internal(const char *oid);
 
 __END_HIDDEN_DECLS
index d475c99..76dceaa 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tasn_dec.c,v 1.49 2022/03/13 14:58:14 jsing Exp $ */
+/* $OpenBSD: tasn_dec.c,v 1.50 2022/04/23 18:47:08 jsing Exp $ */
 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2000.
  */
@@ -95,8 +95,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
 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);
-static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len,
-    int utype, const ASN1_ITEM *it);
+static int asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype,
+    const ASN1_ITEM *it);
 
 static void
 asn1_tlc_invalidate(ASN1_TLC *ctx)
@@ -669,6 +669,7 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen,
        const unsigned char *content = NULL;
        uint8_t *data = NULL;
        size_t data_len = 0;
+       CBS cbs;
        CBB cbb;
        long len;
 
@@ -771,7 +772,10 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen,
        }
 
        /* We now have content length and type: translate into a structure */
-       if (!asn1_ex_c2i(pval, content, len, utype, it))
+       if (len < 0)
+               goto err;
+       CBS_init(&cbs, content, len);
+       if (!asn1_ex_c2i(pval, &cbs, utype, it))
                goto err;
 
        *in = p;
@@ -784,25 +788,31 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen,
        return ret;
 }
 
-/* Translate ASN1 content octets into a structure */
-
+/* Translate ASN.1 content octets into a structure. */
 static int
-asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype,
-    const ASN1_ITEM *it)
+asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it)
 {
        ASN1_VALUE **opval = NULL;
        ASN1_STRING *stmp;
        ASN1_TYPE *typ = NULL;
        ASN1_INTEGER **tint;
+       ASN1_BOOLEAN *tbool;
+       const uint8_t *p;
+       uint8_t u8val;
        int ret = 0;
 
+       if (CBS_len(content) > INT_MAX)
+               return 0;
+
        if (it->funcs != NULL) {
                const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
                char free_content = 0;
 
                if (pf->prim_c2i == NULL)
                        return 0;
-               return pf->prim_c2i(pval, content, len, utype, &free_content, it);
+
+               return pf->prim_c2i(pval, CBS_data(content), CBS_len(content),
+                   utype, &free_content, it);
        }
 
        /* If ANY type clear type and set pointer to internal value */
@@ -822,12 +832,12 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype,
        }
        switch (utype) {
        case V_ASN1_OBJECT:
-               if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &content, len))
+               if (!c2i_ASN1_OBJECT_cbs((ASN1_OBJECT **)pval, content))
                        goto err;
                break;
 
        case V_ASN1_NULL:
-               if (len) {
+               if (CBS_len(content) != 0) {
                        ASN1error(ASN1_R_NULL_IS_WRONG_LENGTH);
                        goto err;
                }
@@ -835,25 +845,28 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype,
                break;
 
        case V_ASN1_BOOLEAN:
-               if (len != 1) {
+               tbool = (ASN1_BOOLEAN *)pval;
+               if (CBS_len(content) != 1) {
                        ASN1error(ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
                        goto err;
-               } else {
-                       ASN1_BOOLEAN *tbool;
-                       tbool = (ASN1_BOOLEAN *)pval;
-                       *tbool = *content;
                }
+               if (!CBS_get_u8(content, &u8val))
+                       goto err;
+               *tbool = u8val;
                break;
 
        case V_ASN1_BIT_STRING:
-               if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &content, len))
+               p = CBS_data(content);
+               if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &p,
+                   CBS_len(content)))
                        goto err;
                break;
 
        case V_ASN1_INTEGER:
        case V_ASN1_ENUMERATED:
                tint = (ASN1_INTEGER **)pval;
-               if (!c2i_ASN1_INTEGER(tint, &content, len))
+               p = CBS_data(content);
+               if (!c2i_ASN1_INTEGER(tint, &p, CBS_len(content)))
                        goto err;
                /* Fixup type to match the expected form */
                (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
@@ -877,11 +890,11 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype,
        case V_ASN1_SET:
        case V_ASN1_SEQUENCE:
        default:
-               if (utype == V_ASN1_BMPSTRING && (len & 1)) {
+               if (utype == V_ASN1_BMPSTRING && (CBS_len(content) & 1)) {
                        ASN1error(ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
                        goto err;
                }
-               if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) {
+               if (utype == V_ASN1_UNIVERSALSTRING && (CBS_len(content) & 3)) {
                        ASN1error(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
                        goto err;
                }
@@ -896,7 +909,7 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype,
                        stmp = (ASN1_STRING *)*pval;
                        stmp->type = utype;
                }
-               if (!ASN1_STRING_set(stmp, content, len)) {
+               if (!ASN1_STRING_set(stmp, CBS_data(content), CBS_len(content))) {
                        ASN1_STRING_free(stmp);
                        *pval = NULL;
                        goto err;