Minor fixes to bytestring.h header.
Ryan noticed that CBS_ASN1_{SEQUENCE,SET} used CBS_ASN1_CONSTRUCTED
before it was defined. The C preprocessor expands late, so this works,
but it is weird. Flip the order.
There was also some question about the constructed bit, which is
different from how ASN.1 formally specifies it. (ASN.1 believes the
constructed bit is a property of the element, not the tag. We fold it in
because it's entirely computable[*] from the type in DER, so it's easier
to fold it in.) Move existing text to the section header and expand on
it.
[*] DER forbids constructed strings so string types are always
primitive. ASN.1 forbids implicitly tagging CHOICE or ANY, so the
inherited constructed bit cannot vary by value.
Change-Id: Ieb91f9d6898d582dda19fec8b042051b67f217a8
Reviewed-on: https://boringssl-review.googlesource.com/c/32725
Reviewed-by: Ryan Sleevi <rsleevi@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/include/openssl/bytestring.h b/include/openssl/bytestring.h
index 1400f2e..701466e 100644
--- a/include/openssl/bytestring.h
+++ b/include/openssl/bytestring.h
@@ -139,8 +139,48 @@
// Parsing ASN.1
+//
+// |CBS| may be used to parse DER structures. Rather than using a schema
+// compiler, the following functions act on tag-length-value elements in the
+// serialization itself. Thus the caller is responsible for looping over a
+// SEQUENCE, branching on CHOICEs or OPTIONAL fields, checking for trailing
+// data, and handling explict vs. implicit tagging.
+//
+// Tags are represented as |unsigned| values in memory. The upper few bits store
+// the class and constructed bit, and the remaining bits store the tag
+// number. Note this differs from the DER serialization, to support tag numbers
+// beyond 31. Consumers must use the constants defined below to decompose or
+// assemble tags.
+//
+// This library treats an element's constructed bit as part of its tag. In DER,
+// the constructed bit is computable from the type. The constants for universal
+// types have the bit set. Callers must set it correctly for tagged types.
+// Explicitly-tagged types are always constructed, and implicitly-tagged types
+// inherit the underlying type's bit.
-// The following values are tag numbers for UNIVERSAL elements.
+// CBS_ASN1_TAG_SHIFT is how much the in-memory representation shifts the class
+// and constructed bits from the DER serialization.
+#define CBS_ASN1_TAG_SHIFT 24
+
+// CBS_ASN1_CONSTRUCTED may be ORed into a tag to set the constructed bit.
+#define CBS_ASN1_CONSTRUCTED (0x20u << CBS_ASN1_TAG_SHIFT)
+
+// The following values specify the tag class and may be ORed into a tag number
+// to produce the final tag. If none is used, the tag will be UNIVERSAL.
+#define CBS_ASN1_UNIVERSAL (0u << CBS_ASN1_TAG_SHIFT)
+#define CBS_ASN1_APPLICATION (0x40u << CBS_ASN1_TAG_SHIFT)
+#define CBS_ASN1_CONTEXT_SPECIFIC (0x80u << CBS_ASN1_TAG_SHIFT)
+#define CBS_ASN1_PRIVATE (0xc0u << CBS_ASN1_TAG_SHIFT)
+
+// CBS_ASN1_CLASS_MASK may be ANDed with a tag to query its class. This will
+// give one of the four values above.
+#define CBS_ASN1_CLASS_MASK (0xc0u << CBS_ASN1_TAG_SHIFT)
+
+// CBS_ASN1_TAG_NUMBER_MASK may be ANDed with a tag to query its number.
+#define CBS_ASN1_TAG_NUMBER_MASK ((1u << (5 + CBS_ASN1_TAG_SHIFT)) - 1)
+
+// The following values are constants for UNIVERSAL tags. Note these constants
+// include the constructed bit.
#define CBS_ASN1_BOOLEAN 0x1u
#define CBS_ASN1_INTEGER 0x2u
#define CBS_ASN1_BITSTRING 0x3u
@@ -164,32 +204,6 @@
#define CBS_ASN1_UNIVERSALSTRING 0x1cu
#define CBS_ASN1_BMPSTRING 0x1eu
-// CBS_ASN1_TAG_SHIFT is how much the in-memory representation shifts the class
-// and constructed bits from the DER serialization. This allows representing tag
-// numbers beyond 31.
-//
-// Consumers must use the following constants to decompose or assemble tags.
-#define CBS_ASN1_TAG_SHIFT 24
-
-// CBS_ASN1_CONSTRUCTED may be ORed into a tag to toggle the constructed
-// bit. |CBS| and |CBB| APIs consider the constructed bit to be part of the
-// tag.
-#define CBS_ASN1_CONSTRUCTED (0x20u << CBS_ASN1_TAG_SHIFT)
-
-// The following values specify the tag class and may be ORed into a tag number
-// to produce the final tag. If none is used, the tag will be UNIVERSAL.
-#define CBS_ASN1_UNIVERSAL (0u << CBS_ASN1_TAG_SHIFT)
-#define CBS_ASN1_APPLICATION (0x40u << CBS_ASN1_TAG_SHIFT)
-#define CBS_ASN1_CONTEXT_SPECIFIC (0x80u << CBS_ASN1_TAG_SHIFT)
-#define CBS_ASN1_PRIVATE (0xc0u << CBS_ASN1_TAG_SHIFT)
-
-// CBS_ASN1_CLASS_MASK may be ANDed with a tag to query its class. This will
-// give one of the four values above.
-#define CBS_ASN1_CLASS_MASK (0xc0u << CBS_ASN1_TAG_SHIFT)
-
-// CBS_ASN1_TAG_NUMBER_MASK may be ANDed with a tag to query its number.
-#define CBS_ASN1_TAG_NUMBER_MASK ((1u << (5 + CBS_ASN1_TAG_SHIFT)) - 1)
-
// CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not
// including tag and length bytes) and advances |cbs| over it. The ASN.1
// element must match |tag_value|. It returns one on success and zero