Introduce constants for ASN1_BOOLEAN
Between the type being sometimes a tri-state and capturing the
underlying DER/BER representation, this type is a bit confusing. Add
constants for these.
I've left a case in ASN1_TBOOLEAN unconverted because it's actually
wrong. It will be fixed in a subsequent CL.
Change-Id: I75d846af14f6b4cd5278c3833b979e89c92c4203
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/56487
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/asn1/a_bool.c b/crypto/asn1/a_bool.c
index 2a4448c..8dc84d4 100644
--- a/crypto/asn1/a_bool.c
+++ b/crypto/asn1/a_bool.c
@@ -78,7 +78,7 @@
}
ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
- *p = a ? 0xff : 0x00;
+ *p = a ? ASN1_BOOLEAN_TRUE : ASN1_BOOLEAN_FALSE;
// If a new buffer was allocated, just return it back.
// If not, return the incremented buffer pointer.
@@ -94,22 +94,22 @@
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER);
- return -1;
+ return ASN1_BOOLEAN_NONE;
}
if (inf & V_ASN1_CONSTRUCTED) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE);
- return -1;
+ return ASN1_BOOLEAN_NONE;
}
if (tag != V_ASN1_BOOLEAN || xclass != V_ASN1_UNIVERSAL) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_BOOLEAN);
- return -1;
+ return ASN1_BOOLEAN_NONE;
}
if (len != 1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
- return -1;
+ return ASN1_BOOLEAN_NONE;
}
ASN1_BOOLEAN ret = (ASN1_BOOLEAN) * (p++);
if (a != NULL) {
diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c
index 5b9a8d4..afac17d 100644
--- a/crypto/asn1/tasn_enc.c
+++ b/crypto/asn1/tasn_enc.c
@@ -631,7 +631,7 @@
case V_ASN1_BOOLEAN:
tbool = (ASN1_BOOLEAN *)pval;
- if (*tbool == -1) {
+ if (*tbool == ASN1_BOOLEAN_NONE) {
*out_omit = 1;
return 0;
}
diff --git a/crypto/asn1/tasn_typ.c b/crypto/asn1/tasn_typ.c
index abfac93..a9409e2 100644
--- a/crypto/asn1/tasn_typ.c
+++ b/crypto/asn1/tasn_typ.c
@@ -107,9 +107,10 @@
DIRECTORYSTRING)
// Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE
-IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1)
+// TODO(davidben): ASN1_TBOOLEAN should be ASN1_BOOLEAN_TRUE, or 0xff.
+IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, ASN1_BOOLEAN_NONE)
IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1)
-IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0)
+IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, ASN1_BOOLEAN_FALSE)
ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY)
diff --git a/crypto/x509/x509_v3.c b/crypto/x509/x509_v3.c
index 4b88ea7..9153dce 100644
--- a/crypto/x509/x509_v3.c
+++ b/crypto/x509/x509_v3.c
@@ -250,7 +250,9 @@
if (ex == NULL) {
return 0;
}
- ex->critical = (crit) ? 0xFF : -1;
+ // The critical field is DEFAULT FALSE, so non-critical extensions should omit
+ // the value.
+ ex->critical = crit ? ASN1_BOOLEAN_TRUE : ASN1_BOOLEAN_NONE;
return 1;
}
diff --git a/crypto/x509v3/internal.h b/crypto/x509v3/internal.h
index 0632f23..51e15e4 100644
--- a/crypto/x509v3/internal.h
+++ b/crypto/x509v3/internal.h
@@ -134,7 +134,7 @@
int X509V3_NAME_from_section(X509_NAME *nm, const STACK_OF(CONF_VALUE) *dn_sk,
int chtype);
-int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool);
+int X509V3_get_value_bool(const CONF_VALUE *value, ASN1_BOOLEAN *asn1_bool);
int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint);
const STACK_OF(CONF_VALUE) *X509V3_get_section(const X509V3_CTX *ctx,
const char *section);
diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c
index bb5db40..eec7d08 100644
--- a/crypto/x509v3/v3_utl.c
+++ b/crypto/x509v3/v3_utl.c
@@ -300,19 +300,19 @@
return ret;
}
-int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool) {
+int X509V3_get_value_bool(const CONF_VALUE *value, ASN1_BOOLEAN *asn1_bool) {
char *btmp;
if (!(btmp = value->value)) {
goto err;
}
if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") || !strcmp(btmp, "Y") ||
!strcmp(btmp, "y") || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
- *asn1_bool = 0xff;
+ *asn1_bool = ASN1_BOOLEAN_TRUE;
return 1;
} else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") ||
!strcmp(btmp, "N") || !strcmp(btmp, "n") || !strcmp(btmp, "NO") ||
!strcmp(btmp, "no")) {
- *asn1_bool = 0;
+ *asn1_bool = ASN1_BOOLEAN_FALSE;
return 1;
}
err:
diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h
index b402c1d..7866deb 100644
--- a/include/openssl/asn1.h
+++ b/include/openssl/asn1.h
@@ -447,10 +447,22 @@
// integer type. FALSE is zero, TRUE is 0xff, and an omitted OPTIONAL BOOLEAN is
// -1.
+// ASN1_BOOLEAN_FALSE is FALSE as an |ASN1_BOOLEAN|.
+#define ASN1_BOOLEAN_FALSE 0
+
+// ASN1_BOOLEAN_TRUE is TRUE as an |ASN1_BOOLEAN|. Some code incorrectly uses
+// 1, so prefer |b != ASN1_BOOLEAN_FALSE| over |b == ASN1_BOOLEAN_TRUE|.
+#define ASN1_BOOLEAN_TRUE 0xff
+
+// ASN1_BOOLEAN_NONE, in contexts where the |ASN1_BOOLEAN| represents an
+// OPTIONAL BOOLEAN, is an omitted value. Using this value in other contexts is
+// undefined and may be misinterpreted as TRUE.
+#define ASN1_BOOLEAN_NONE (-1)
+
// d2i_ASN1_BOOLEAN parses a DER-encoded ASN.1 BOOLEAN from up to |len| bytes at
// |*inp|. On success, it advances |*inp| by the number of bytes read and
// returns the result. If |out| is non-NULL, it additionally writes the result
-// to |*out|. On error, it returns -1.
+// to |*out|. On error, it returns |ASN1_BOOLEAN_NONE|.
//
// This function does not reject trailing data in the input. This allows the
// caller to parse a sequence of concatenated structures. Callers parsing only
@@ -472,7 +484,8 @@
// The following |ASN1_ITEM|s have ASN.1 type BOOLEAN and C type |ASN1_BOOLEAN|.
// |ASN1_TBOOLEAN| and |ASN1_FBOOLEAN| must be marked OPTIONAL. When omitted,
-// they are parsed as TRUE and FALSE, respectively, rather than -1.
+// they are parsed as TRUE and FALSE, respectively, rather than
+// |ASN1_BOOLEAN_NONE|.
DECLARE_ASN1_ITEM(ASN1_BOOLEAN)
DECLARE_ASN1_ITEM(ASN1_TBOOLEAN)
DECLARE_ASN1_ITEM(ASN1_FBOOLEAN)