From 0ec3e77a136d72e26e660d86ad1ecaed5c0606c1 Mon Sep 17 00:00:00 2001
From: Jouni Malinen <jouni@codeaurora.org>
Date: Sun, 7 Oct 2018 16:47:25 +0300
Subject: [PATCH] TLS: Add tls_connection_peer_serial_num()

This can be used to fetch the serial number of the peer certificate in
the EAP server. For now, this is implemented only with OpenSSL.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
---
 src/crypto/tls.h          | 12 ++++++++++++
 src/crypto/tls_gnutls.c   |  8 ++++++++
 src/crypto/tls_internal.c |  8 ++++++++
 src/crypto/tls_none.c     |  7 +++++++
 src/crypto/tls_openssl.c  | 25 +++++++++++++++++++++++++
 src/crypto/tls_wolfssl.c  |  8 ++++++++
 6 files changed, 68 insertions(+)

diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 86a1cded6..481b34681 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -253,6 +253,18 @@ void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn);
  */
 int tls_connection_established(void *tls_ctx, struct tls_connection *conn);
 
+/**
+ * tls_connection_peer_serial_num - Fetch peer certificate serial number
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: Allocated string buffer containing the peer certificate serial
+ * number or %NULL on error.
+ *
+ * The caller is responsible for freeing the returned buffer with os_free().
+ */
+char * tls_connection_peer_serial_num(void *tls_ctx,
+				      struct tls_connection *conn);
+
 /**
  * tls_connection_shutdown - Shutdown TLS connection
  * @tls_ctx: TLS context data from tls_init()
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index 7ee3fa3a0..36dafd260 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -295,6 +295,14 @@ int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
 }
 
 
+char * tls_connection_peer_serial_num(void *tls_ctx,
+				      struct tls_connection *conn)
+{
+	/* TODO */
+	return NULL;
+}
+
+
 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
 {
 	struct tls_global *global = ssl_ctx;
diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c
index c7cb5ded3..d289c9442 100644
--- a/src/crypto/tls_internal.c
+++ b/src/crypto/tls_internal.c
@@ -177,6 +177,14 @@ int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
 }
 
 
+char * tls_connection_peer_serial_num(void *tls_ctx,
+				      struct tls_connection *conn)
+{
+	/* TODO */
+	return NULL;
+}
+
+
 int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
 {
 #ifdef CONFIG_TLS_INTERNAL_CLIENT
diff --git a/src/crypto/tls_none.c b/src/crypto/tls_none.c
index dd5681e9c..5d0c6bda1 100644
--- a/src/crypto/tls_none.c
+++ b/src/crypto/tls_none.c
@@ -45,6 +45,13 @@ int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
 }
 
 
+char * tls_connection_peer_serial_num(void *tls_ctx,
+				      struct tls_connection *conn)
+{
+	return NULL;
+}
+
+
 int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
 {
 	return -1;
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 0244897f3..0d5ebda69 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -1546,6 +1546,31 @@ int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
 }
 
 
+char * tls_connection_peer_serial_num(void *tls_ctx,
+				      struct tls_connection *conn)
+{
+	ASN1_INTEGER *ser;
+	char *serial_num;
+	size_t len;
+
+	if (!conn->peer_cert)
+		return NULL;
+
+	ser = X509_get_serialNumber(conn->peer_cert);
+	if (!ser)
+		return NULL;
+
+	len = ASN1_STRING_length(ser) * 2 + 1;
+	serial_num = os_malloc(len);
+	if (!serial_num)
+		return NULL;
+	wpa_snprintf_hex_uppercase(serial_num, len,
+				   ASN1_STRING_get0_data(ser),
+				   ASN1_STRING_length(ser));
+	return serial_num;
+}
+
+
 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
 {
 	if (conn == NULL)
diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c
index 9544e2f7e..cc8c70446 100644
--- a/src/crypto/tls_wolfssl.c
+++ b/src/crypto/tls_wolfssl.c
@@ -347,6 +347,14 @@ int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
 }
 
 
+char * tls_connection_peer_serial_num(void *tls_ctx,
+				      struct tls_connection *conn)
+{
+	/* TODO */
+	return NULL;
+}
+
+
 int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
 {
 	WOLFSSL_SESSION *session;