Provide asn1_get_primitive()
authorjsing <jsing@openbsd.org>
Sat, 26 Mar 2022 14:47:58 +0000 (14:47 +0000)
committerjsing <jsing@openbsd.org>
Sat, 26 Mar 2022 14:47:58 +0000 (14:47 +0000)
This takes a CBS, gets the ASN.1 identifier and length, ensures the
resulting identifier is a valid primitive, then returns the tag number and
the content as a CBS.

ok inoguchi@ tb@

lib/libcrypto/asn1/asn1_lib.c
lib/libcrypto/asn1/asn1_locl.h

index 542a72f..6a29c32 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: asn1_lib.c,v 1.51 2021/12/25 07:04:03 jsing Exp $ */
+/* $OpenBSD: asn1_lib.c,v 1.52 2022/03/26 14:47:58 jsing Exp $ */
 /*
  * Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
  *
@@ -16,6 +16,7 @@
  */
 
 #include <limits.h>
+#include <stdlib.h>
 
 #include "bytestring.h"
 
@@ -169,3 +170,33 @@ asn1_get_object_cbs(CBS *cbs, int der_mode, uint8_t *out_tag_class,
 
        return 1;
 }
+
+int
+asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number,
+    CBS *out_content)
+{
+       int constructed, indefinite;
+       uint32_t tag_number, length;
+       uint8_t tag_class;
+
+       *out_tag_number = 0;
+
+       CBS_init(out_content, NULL, 0);
+
+       if (!asn1_get_identifier_cbs(cbs, der_mode, &tag_class, &constructed,
+           &tag_number))
+               return 0;
+       if (!asn1_get_length_cbs(cbs, der_mode, &indefinite, &length))
+               return 0;
+
+       /* A primitive is not constructed and has a definite length. */
+       if (constructed || indefinite)
+               return 0;
+
+       if (!CBS_get_bytes(cbs, out_content, length))
+               return 0;
+
+       *out_tag_number = tag_number;
+
+       return 1;
+}
index 12f7ead..756e407 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: asn1_locl.h,v 1.23 2022/03/19 17:49:32 jsing Exp $ */
+/* $OpenBSD: asn1_locl.h,v 1.24 2022/03/26 14:47:58 jsing Exp $ */
 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project 2006.
  */
@@ -196,6 +196,8 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
 int asn1_get_object_cbs(CBS *cbs, int der_mode, uint8_t *out_class,
     int *out_constructed, uint32_t *out_tag_number, int *out_indefinite,
     uint32_t *out_length);
+int asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number,
+    CBS *out_content);
 
 int asn1_tag2charwidth(int tag);