Add support for OpenSSL ENGINE for keystore
keystore now has an OpenSSL ENGINE frontend that can be used to ask for
private keys or public keys to be loaded and also signing operations to
take place. Use that instead of the crazy byte-array marshalling of the
private key material that is used for the "privsep" stuff.
Change-Id: I6171ca1fb0e77e338c19f04d8c34ad7744984b63
diff --git a/Android.mk b/Android.mk
index 3a1c65f..c7ac4d7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -62,7 +62,7 @@
LOCAL_SHARED_LIBRARIES := libcutils libcrypto
-LOCAL_CFLAGS := -DANDROID_CHANGES -DHAVE_CONFIG_H
+LOCAL_CFLAGS := -DANDROID_CHANGES -DHAVE_CONFIG_H -DHAVE_OPENSSL_ENGINE_H
LOCAL_CFLAGS += -Wno-sign-compare -Wno-missing-field-initializers
@@ -78,7 +78,7 @@
src/libipsec/pfkey.c \
src/libipsec/ipsec_strerror.c
-LOCAL_CFLAGS := -DHAVE_CONFIG_H
+LOCAL_CFLAGS := -DHAVE_CONFIG_H -DHAVE_OPENSSL_ENGINE_H
LOCAL_CFLAGS += -Wno-sign-compare -Wno-missing-field-initializers
diff --git a/main.c b/main.c
index 2976ecc..d2e815e 100644
--- a/main.c
+++ b/main.c
@@ -27,6 +27,8 @@
#ifdef ANDROID_CHANGES
+#include <openssl/engine.h>
+
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -156,9 +158,17 @@
{
#ifdef ANDROID_CHANGES
int control = android_get_control_and_arguments(&argc, &argv);
+ ENGINE *e;
if (control != -1) {
pname = "%p";
monitor_fd(control, NULL);
+
+ ENGINE_load_dynamic();
+ e = ENGINE_by_id("keystore");
+ if (!e || !ENGINE_init(e)) {
+ do_plog(LLV_ERROR, "ipsec-tools: cannot load keystore engine");
+ exit(1);
+ }
}
#endif
@@ -194,6 +204,12 @@
}
}
}
+#ifdef ANDROID_CHANGES
+ if (e) {
+ ENGINE_finish(e);
+ ENGINE_free(e);
+ }
+#endif
return 0;
}
diff --git a/src/racoon/oakley.c b/src/racoon/oakley.c
index 183ac2f..c446bbb 100644
--- a/src/racoon/oakley.c
+++ b/src/racoon/oakley.c
@@ -40,6 +40,9 @@
#include <openssl/pkcs7.h>
#include <openssl/x509.h>
+#ifdef ANDROID_CHANGES
+#include <openssl/engine.h>
+#endif
#include <stdlib.h>
#include <stdio.h>
@@ -1799,6 +1802,44 @@
}
#endif
+#ifdef ANDROID_CHANGES
+static vchar_t* keystore_sign(vchar_t* src, const char* path) {
+ vchar_t* sig = NULL;
+
+ ENGINE* e = ENGINE_by_id("keystore");
+ if (!e) {
+ return NULL;
+ }
+
+ if (!ENGINE_init(e)) {
+ ENGINE_free(e);
+ return NULL;
+ }
+
+ const char *key_id;
+ if (sscanf(path, pname, &key_id) != 1) {
+ do_plog(LLV_ERROR, "couldn't read private key info\n");
+ return NULL;
+ }
+
+ EVP_PKEY* evp = ENGINE_load_private_key(e, key_id, NULL, NULL);
+ if (!evp) {
+ do_plog(LLV_ERROR, "couldn't retrieve private key");
+ ERR_clear_error();
+ return NULL;
+ }
+
+ sig = eay_rsa_sign(src, evp->pkey.rsa);
+
+ EVP_PKEY_free(evp);
+
+ ENGINE_finish(e);
+ ENGINE_free(e);
+
+ return sig;
+}
+#endif
+
/* get signature */
int
oakley_getsign(iph1)
@@ -1820,6 +1861,9 @@
getpathname(path, sizeof(path),
LC_PATHTYPE_CERT,
iph1->rmconf->myprivfile);
+#ifdef ANDROID_CHANGES
+ iph1->sig = keystore_sign(iph1->hash, path);
+#else
privkey = privsep_eay_get_pkcs1privkey(path);
if (privkey == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -1830,6 +1874,7 @@
plogdump(LLV_DEBUG2, privkey->v, privkey->l);
iph1->sig = eay_get_x509sign(iph1->hash, privkey);
+#endif
break;
#ifndef ANDROID_PATCHED
case ISAKMP_CERT_PLAINRSA: