From 78d2857e363b5b7fede412924bc2884ee1a59f45 Mon Sep 17 00:00:00 2001
From: Rubin Xu <rubinxu@xxxxxxxxxx>
Date: Tue, 10 Nov 2015 17:14:51 +0000
Subject: [PATCH] Android: Support multiple CA certs when connecting to EAP
network
In the Android-specific case, Make ca_cert directive parse a space-separated
list of hex-encoded CA certificate aliases following the "keystores://"
prefix.
Server certificate validation should succeed as long as the chain ends with
one of them.
Bug: 22547958
Change-Id: I9c98f06f8ddf94ea1332f7ac291a14b7f1d96406
Signed-off-by: Rubin Xu <rubinxu@xxxxxxxxxx>
---
src/crypto/tls_openssl.c | 97
+++++++++++++++++++++++++++++++++++++-----------
1 file changed, 75 insertions(+), 22 deletions(-)
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 22d6dc4..1c25536 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -105,6 +105,49 @@ static BIO * BIO_from_keystore(const char *key)
free(value);
return bio;
}
+
+static int tls_add_ca_from_keystore(X509_STORE *ctx, const char *key_alias)
+{
+ BIO *bio = BIO_from_keystore(key_alias);
+ STACK_OF(X509_INFO) *stack = NULL;
+ stack_index_t i;
+
+ if (bio) {
+ stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ }
+ if (!stack)
+ return -1;
+
+ for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
+ X509_INFO *info = sk_X509_INFO_value(stack, i);
+ if (info->x509) {
+ X509_STORE_add_cert(ctx,
+ info->x509);
+ }
+ if (info->crl) {
+ X509_STORE_add_crl(ctx,
+ info->crl);
+ }
+ }
+ sk_X509_INFO_pop_free(stack, X509_INFO_free);
+ return 0;
+}
+
+static int tls_add_ca_from_keystore_encoded(X509_STORE *ctx, const char
*encoded_key_alias)
+{
+ int rc = -1;
+ int len = os_strlen(encoded_key_alias);
+ if (len & 1)
+ return rc;
+ unsigned char* decoded_alias = malloc(len / 2 + 1);
+ if (!hexstr2bin(encoded_key_alias, decoded_alias, len / 2)) {
+ decoded_alias[len / 2] = '\0';
+ rc = tls_add_ca_from_keystore(ctx, (char*) decoded_alias);
+ free(decoded_alias);
+ }
+ return rc;
+}
#endif /* ANDROID */
static int tls_openssl_ref_count = 0;
@@ -1989,32 +2032,42 @@ static int tls_connection_ca_cert(struct
tls_data *data,
}
#ifdef ANDROID
+ /* Single alias */
if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
- BIO *bio = BIO_from_keystore(&ca_cert[11]);
- STACK_OF(X509_INFO) *stack = NULL;
- stack_index_t i;
-
- if (bio) {
- stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
- BIO_free(bio);
- }
- if (!stack)
+ if (!tls_add_ca_from_keystore(ssl_ctx->cert_store, &ca_cert[11])) {
+ SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
+ return 0;
+ } else {
return -1;
-
- for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
- X509_INFO *info = sk_X509_INFO_value(stack, i);
- if (info->x509) {
- X509_STORE_add_cert(ssl_ctx->cert_store,
- info->x509);
- }
- if (info->crl) {
- X509_STORE_add_crl(ssl_ctx->cert_store,
- info->crl);
+ }
+ /* Multiple aliases separated by space */
+ } else if (ca_cert && os_strncmp("keystores://", ca_cert, 12) == 0) {
+ char *aliases = strdup(&ca_cert[12]);
+ const char *DELIMITER = " ";
+ char *savedptr;
+ char *alias;
+ int rc;
+ alias = strtok_r(aliases, DELIMITER, &savedptr);
+ if (!alias) {
+ rc = tls_add_ca_from_keystore_encoded(ssl_ctx->cert_store, aliases);
+ } else {
+ rc = 0;
+ for(; alias; alias = strtok_r(NULL, DELIMITER, &savedptr)) {
+ if (tls_add_ca_from_keystore_encoded(ssl_ctx->cert_store, alias)) {
+ wpa_printf(MSG_WARNING, "OpenSSL: %s - fail to add ca_cert"
+ " %s from keystore", __func__, alias);
+ rc = -1;
+ break;
+ }
}
}
- sk_X509_INFO_pop_free(stack, X509_INFO_free);
- SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
- return 0;
+ free(aliases);
+ if (!rc) {
+ SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
+ return 0;
+ } else {
+ return -1;
+ }
}
#endif /* ANDROID */
--
2.6.0.rc2.230.g3dd15c0
_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap