Make key exchange strength available.
This change stores the size of the group/modulus (for RSA/DHE) or curve
ID (for ECDHE) in the |SSL_SESSION|. This makes it available for UIs
where desired.
Change-Id: I354141da432a08f71704c9683f298b361362483d
Reviewed-on: https://boringssl-review.googlesource.com/5280
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/internal.h b/ssl/internal.h
index 7d4214d..63046e8 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1072,6 +1072,11 @@
int tls1_ec_curve_id2nid(uint16_t curve_id);
int tls1_ec_nid2curve_id(uint16_t *out_curve_id, int nid);
+/* tls1_ec_curve_id2name returns a human-readable name for the
+ * curve specified by the TLS curve id in |curve_id|. If the
+ * curve is unknown, it returns NULL. */
+const char* tls1_ec_curve_id2name(uint16_t curve_id);
+
/* tls1_check_curve parses ECParameters out of |cbs|, modifying it. It
* checks the curve is one of our preferences and writes the
* NamedCurve value to |*out_curve_id|. It returns one on success and
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index ef24316..1ed1507 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1186,7 +1186,8 @@
goto err;
}
- if (DH_num_bits(dh) < 1024) {
+ s->session->key_exchange_info = DH_num_bits(dh);
+ if (s->session->key_exchange_info < 1024) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DH_P_LENGTH);
goto err;
}
@@ -1215,6 +1216,7 @@
}
ecdh = EC_KEY_new_by_curve_name(curve_nid);
+ s->session->key_exchange_info = curve_id;
if (ecdh == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_EC_LIB);
goto err;
@@ -1696,6 +1698,7 @@
goto err;
}
+ s->session->key_exchange_info = EVP_PKEY_bits(pkey);
rsa = pkey->pkey.rsa;
EVP_PKEY_free(pkey);
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index a2b6879..e516a45 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -116,6 +116,7 @@
* ocspResponse [16] OCTET STRING OPTIONAL,
* -- stapled OCSP response from the server
* extendedMasterSecret [17] BOOLEAN OPTIONAL,
+ * keyExchangeInfo [18] INTEGER OPTIONAL,
* }
*
* Note: historically this serialization has included other optional
@@ -154,6 +155,8 @@
CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 16;
static const int kExtendedMasterSecretTag =
CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 17;
+static const int kKeyExchangeInfoTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 18;
static int SSL_SESSION_to_bytes_full(SSL_SESSION *in, uint8_t **out_data,
size_t *out_len, int for_ticket) {
@@ -315,6 +318,13 @@
}
}
+ if (in->key_exchange_info > 0 &&
+ (!CBB_add_asn1(&session, &child, kKeyExchangeInfoTag) ||
+ !CBB_add_asn1_uint64(&child, in->key_exchange_info))) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
if (!CBB_finish(&cbb, out_data, out_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
@@ -413,7 +423,8 @@
CBS peer, sid_ctx, peer_sha256, original_handshake_hash;
int has_peer, has_peer_sha256, extended_master_secret;
uint64_t version, ssl_version;
- uint64_t session_time, timeout, verify_result, ticket_lifetime_hint;
+ uint64_t session_time, timeout, verify_result, ticket_lifetime_hint,
+ key_exchange_info;
ret = SSL_SESSION_new();
if (ret == NULL) {
@@ -470,13 +481,22 @@
}
if (!CBS_get_optional_asn1_bool(&session, &extended_master_secret,
kExtendedMasterSecretTag,
- 0 /* default to false */) ||
- CBS_len(&session) != 0) {
+ 0 /* default to false */)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
goto err;
}
ret->extended_master_secret = extended_master_secret;
+ if (!CBS_get_optional_asn1_uint64(&session, &key_exchange_info,
+ kKeyExchangeInfoTag, 0) ||
+ CBS_len(&session) != 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ if (key_exchange_info <= 0xffffffff) {
+ ret->key_exchange_info = key_exchange_info;
+ }
+
if (version != SSL_SESSION_ASN1_VERSION) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
goto err;
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index be3a2b9..6af0040 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2099,6 +2099,10 @@
return ssl_get_version(sess->ssl_version);
}
+const char* SSL_get_curve_name(uint16_t curve_id) {
+ return tls1_ec_curve_id2name(curve_id);
+}
+
void ssl_clear_cipher_ctx(SSL *s) {
SSL_AEAD_CTX_free(s->aead_read_ctx);
s->aead_read_ctx = NULL;
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 2c5dfe6..1c644fd 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -639,20 +639,12 @@
return 1;
}
-long SSL_SESSION_get_timeout(const SSL_SESSION *s) {
- if (s == NULL) {
- return 0;
- }
-
- return s->timeout;
+long SSL_SESSION_get_timeout(const SSL_SESSION *session) {
+ return session->timeout;
}
-long SSL_SESSION_get_time(const SSL_SESSION *s) {
- if (s == NULL) {
- return 0;
- }
-
- return s->time;
+long SSL_SESSION_get_time(const SSL_SESSION *session) {
+ return session->time;
}
long SSL_SESSION_set_time(SSL_SESSION *s, long t) {
@@ -664,6 +656,10 @@
return t;
}
+uint32_t SSL_SESSION_get_key_exchange_info(SSL_SESSION *session) {
+ return session->key_exchange_info;
+}
+
X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) { return s->peer; }
int SSL_SESSION_set1_id_context(SSL_SESSION *s, const uint8_t *sid_ctx,
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index f31e5a1..bfb6b50 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -24,6 +24,8 @@
#include <openssl/ssl.h>
#include "test/scoped_types.h"
+#include "../crypto/test/test_util.h"
+
struct ExpectedCipher {
unsigned long id;
@@ -418,6 +420,8 @@
if (encoded_len != input.size() ||
memcmp(bssl::vector_data(&input), encoded.get(), input.size()) != 0) {
fprintf(stderr, "SSL_SESSION_to_bytes did not round-trip\n");
+ hexdump(stderr, "Before: ", input.data(), input.size());
+ hexdump(stderr, "After: ", encoded_raw, encoded_len);
return false;
}
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index d2f8983..7a13f8e 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -336,14 +336,15 @@
struct tls_curve {
uint16_t curve_id;
int nid;
+ const char curve_name[8];
};
/* ECC curves from RFC4492. */
static const struct tls_curve tls_curves[] = {
- {21, NID_secp224r1},
- {23, NID_X9_62_prime256v1},
- {24, NID_secp384r1},
- {25, NID_secp521r1},
+ {21, NID_secp224r1, "P-224"},
+ {23, NID_X9_62_prime256v1, "P-256"},
+ {24, NID_secp384r1, "P-384"},
+ {25, NID_secp521r1, "P-521"},
};
static const uint16_t eccurves_default[] = {
@@ -372,6 +373,16 @@
return 0;
}
+const char* tls1_ec_curve_id2name(uint16_t curve_id) {
+ size_t i;
+ for (i = 0; i < sizeof(tls_curves) / sizeof(tls_curves[0]); i++) {
+ if (curve_id == tls_curves[i].curve_id) {
+ return tls_curves[i].curve_name;
+ }
+ }
+ return NULL;
+}
+
/* tls1_get_curvelist sets |*out_curve_ids| and |*out_curve_ids_len| to the
* list of allowed curve IDs. If |get_peer_curves| is non-zero, return the
* peer's curve list. Otherwise, return the preferred list. */