Add some more utility functions to bytestring.
Change-Id: I7932258890b0b2226ff6841af45926e1b11979ba
Reviewed-on: https://boringssl-review.googlesource.com/24844
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/bytestring/cbb.c b/crypto/bytestring/cbb.c
index eac6aa4..38e9a83 100644
--- a/crypto/bytestring/cbb.c
+++ b/crypto/bytestring/cbb.c
@@ -505,6 +505,28 @@
return CBB_flush(cbb);
}
+int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, size_t data_len) {
+ CBB child;
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child, data, data_len) ||
+ !CBB_flush(cbb)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+int CBB_add_asn1_bool(CBB *cbb, int value) {
+ CBB child;
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_BOOLEAN) ||
+ !CBB_add_u8(&child, value != 0 ? 0xff : 0) ||
+ !CBB_flush(cbb)) {
+ return 0;
+ }
+
+ return 1;
+}
+
// parse_dotted_decimal parses one decimal component from |cbs|, where |cbs| is
// an OID literal, e.g., "1.2.840.113554.4.1.72585". It consumes both the
// component and the dot, so |cbs| may be passed into the function again for the
diff --git a/crypto/bytestring/cbs.c b/crypto/bytestring/cbs.c
index e456330..909512e 100644
--- a/crypto/bytestring/cbs.c
+++ b/crypto/bytestring/cbs.c
@@ -425,6 +425,22 @@
return 1;
}
+int CBS_get_asn1_bool(CBS *cbs, int *out) {
+ CBS bytes;
+ if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_BOOLEAN) ||
+ CBS_len(&bytes) != 1) {
+ return 0;
+ }
+
+ const uint8_t value = *CBS_data(&bytes);
+ if (value != 0 && value != 0xff) {
+ return 0;
+ }
+
+ *out = !!value;
+ return 1;
+}
+
int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) {
int present = 0;
diff --git a/include/openssl/bytestring.h b/include/openssl/bytestring.h
index 2f25f14..39462a9 100644
--- a/include/openssl/bytestring.h
+++ b/include/openssl/bytestring.h
@@ -235,6 +235,10 @@
// in 64 bits.
OPENSSL_EXPORT int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out);
+// CBS_get_asn1_bool gets an ASN.1 BOOLEAN from |cbs| and sets |*out| to zero
+// or one based on its value. It returns one on success or zero on error.
+OPENSSL_EXPORT int CBS_get_asn1_bool(CBS *cbs, int *out);
+
// CBS_get_optional_asn1 gets an optional explicitly-tagged element from |cbs|
// tagged with |tag| and sets |*out| to its contents. If present and if
// |out_present| is not NULL, it sets |*out_present| to one, otherwise zero. It
@@ -450,6 +454,15 @@
// error.
OPENSSL_EXPORT int CBB_add_asn1_uint64(CBB *cbb, uint64_t value);
+// CBB_add_asn1_octet_string writes an ASN.1 OCTET STRING into |cbb| with the
+// given contents. It returns one on success and zero on error.
+OPENSSL_EXPORT int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data,
+ size_t data_len);
+
+// CBB_add_asn1_bool writes an ASN.1 BOOLEAN into |cbb| which is true iff
+// |value| is non-zero. It returns one on success and zero on error.
+OPENSSL_EXPORT int CBB_add_asn1_bool(CBB *cbb, int value);
+
// CBB_add_asn1_oid_from_text decodes |len| bytes from |text| as an ASCII OID
// representation, e.g. "1.2.840.113554.4.1.72585", and writes the DER-encoded
// contents to |cbb|. It returns one on success and zero on malloc failure or if
diff --git a/ssl/ssl_asn1.cc b/ssl/ssl_asn1.cc
index eb7df5b..67fd101 100644
--- a/ssl/ssl_asn1.cc
+++ b/ssl/ssl_asn1.cc
@@ -211,12 +211,11 @@
!CBB_add_asn1_uint64(&session, in->ssl_version) ||
!CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
!CBB_add_u16(&child, (uint16_t)(in->cipher->id & 0xffff)) ||
- !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
// The session ID is irrelevant for a session ticket.
- !CBB_add_bytes(&child, in->session_id,
- for_ticket ? 0 : in->session_id_length) ||
- !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
- !CBB_add_bytes(&child, in->master_key, in->master_key_length) ||
+ !CBB_add_asn1_octet_string(&session, in->session_id,
+ for_ticket ? 0 : in->session_id_length) ||
+ !CBB_add_asn1_octet_string(&session, in->master_key,
+ in->master_key_length) ||
!CBB_add_asn1(&session, &child, kTimeTag) ||
!CBB_add_asn1_uint64(&child, in->time) ||
!CBB_add_asn1(&session, &child, kTimeoutTag) ||
@@ -240,8 +239,7 @@
// Although it is OPTIONAL and usually empty, OpenSSL has
// historically always encoded the sid_ctx.
if (!CBB_add_asn1(&session, &child, kSessionIDContextTag) ||
- !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
- !CBB_add_bytes(&child2, in->sid_ctx, in->sid_ctx_length)) {
+ !CBB_add_asn1_octet_string(&child, in->sid_ctx, in->sid_ctx_length)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -256,9 +254,8 @@
if (in->psk_identity) {
if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) ||
- !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
- !CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity,
- strlen(in->psk_identity))) {
+ !CBB_add_asn1_octet_string(&child, (const uint8_t *)in->psk_identity,
+ strlen(in->psk_identity))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -274,8 +271,8 @@
if (in->tlsext_tick && !for_ticket) {
if (!CBB_add_asn1(&session, &child, kTicketTag) ||
- !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
- !CBB_add_bytes(&child2, in->tlsext_tick, in->tlsext_ticklen)) {
+ !CBB_add_asn1_octet_string(&child, in->tlsext_tick,
+ in->tlsext_ticklen)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -283,8 +280,8 @@
if (in->peer_sha256_valid) {
if (!CBB_add_asn1(&session, &child, kPeerSHA256Tag) ||
- !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
- !CBB_add_bytes(&child2, in->peer_sha256, sizeof(in->peer_sha256))) {
+ !CBB_add_asn1_octet_string(&child, in->peer_sha256,
+ sizeof(in->peer_sha256))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -292,9 +289,8 @@
if (in->original_handshake_hash_len > 0) {
if (!CBB_add_asn1(&session, &child, kOriginalHandshakeHashTag) ||
- !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
- !CBB_add_bytes(&child2, in->original_handshake_hash,
- in->original_handshake_hash_len)) {
+ !CBB_add_asn1_octet_string(&child, in->original_handshake_hash,
+ in->original_handshake_hash_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -302,10 +298,9 @@
if (in->signed_cert_timestamp_list != nullptr) {
if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) ||
- !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
- !CBB_add_bytes(&child2,
- CRYPTO_BUFFER_data(in->signed_cert_timestamp_list),
- CRYPTO_BUFFER_len(in->signed_cert_timestamp_list))) {
+ !CBB_add_asn1_octet_string(
+ &child, CRYPTO_BUFFER_data(in->signed_cert_timestamp_list),
+ CRYPTO_BUFFER_len(in->signed_cert_timestamp_list))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -313,9 +308,9 @@
if (in->ocsp_response != nullptr) {
if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) ||
- !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
- !CBB_add_bytes(&child2, CRYPTO_BUFFER_data(in->ocsp_response),
- CRYPTO_BUFFER_len(in->ocsp_response))) {
+ !CBB_add_asn1_octet_string(&child,
+ CRYPTO_BUFFER_data(in->ocsp_response),
+ CRYPTO_BUFFER_len(in->ocsp_response))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -323,8 +318,7 @@
if (in->extended_master_secret) {
if (!CBB_add_asn1(&session, &child, kExtendedMasterSecretTag) ||
- !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
- !CBB_add_u8(&child2, 0xff)) {
+ !CBB_add_asn1_bool(&child, true)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -367,8 +361,7 @@
if (!in->is_server) {
if (!CBB_add_asn1(&session, &child, kIsServerTag) ||
- !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
- !CBB_add_u8(&child2, 0x00)) {
+ !CBB_add_asn1_bool(&child, false)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
@@ -397,9 +390,8 @@
if (in->early_alpn) {
if (!CBB_add_asn1(&session, &child, kEarlyALPNTag) ||
- !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
- !CBB_add_bytes(&child2, (const uint8_t *)in->early_alpn,
- in->early_alpn_len)) {
+ !CBB_add_asn1_octet_string(&child, (const uint8_t *)in->early_alpn,
+ in->early_alpn_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}