[vlc-devel] [PATCH 09/13] memory_file: encrypt/decrypt password via AndroidKeyStore
Thomas Guillem
thomas at gllm.fr
Wed Feb 24 14:25:18 CET 2016
This works only on Android M, the used cipher is AES/CBC/PKCS7Padding, the IV
(Initialisation Vector) is generated by Android, and the key is stored by
Android.
---
modules/keystore/Makefile.am | 3 +
modules/keystore/memory-android.c | 620 ++++++++++++++++++++++++++++++++++++++
modules/keystore/memory-crypt.h | 7 +-
3 files changed, 624 insertions(+), 6 deletions(-)
create mode 100644 modules/keystore/memory-android.c
diff --git a/modules/keystore/Makefile.am b/modules/keystore/Makefile.am
index 99eed83..9c09d91 100644
--- a/modules/keystore/Makefile.am
+++ b/modules/keystore/Makefile.am
@@ -2,6 +2,9 @@ keystoredir = $(pluginsdir)/keystore
libmemory_file_keystore_plugin_la_SOURCES = keystore/memory-file.c
keystore/memory-crypt.h
+if HAVE_ANDROID
+libmemory_file_keystore_plugin_la_SOURCES += keystore/memory-android.c
+endif
keystore_LTLIBRARIES = libmemory_file_keystore_plugin.la
libsecret_plugin_la_SOURCES = keystore/secret.c
diff --git a/modules/keystore/memory-android.c b/modules/keystore/memory-android.c
new file mode 100644
index 0000000..cabfd66
--- /dev/null
+++ b/modules/keystore/memory-android.c
@@ -0,0 +1,620 @@
+/*****************************************************************************
+ * memory-android.c: Crypt using AndroidKeyStore
+ *****************************************************************************
+ * Copyright © 2016 VLC authors, VideoLAN and VideoLabs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <vlc_common.h>
+#include <vlc_memory.h>
+#include <vlc_keystore.h>
+
+#include "memory-crypt.h"
+
+#include <jni.h>
+
+JNIEnv * android_getEnv(vlc_object_t *, const char *);
+#define GET_ENV() android_getEnv(VLC_OBJECT(p_keystore), "android keystore")
+
+static struct
+{
+ struct
+ {
+ jmethodID toString;
+ } Object;
+ struct
+ {
+ jclass clazz;
+ jmethodID getInstance;
+ jmethodID load;
+ jmethodID getEntry;
+ struct
+ {
+ jmethodID getSecretKey;
+ } SecretKeyEntry;
+ } KeyStore;
+ struct
+ {
+ jint PURPOSE_ENCRYPT;
+ jint PURPOSE_DECRYPT;
+ jstring BLOCK_MODE_CBC;
+ jstring ENCRYPTION_PADDING_PKCS7;
+ jstring KEY_ALGORITHM_AES;
+ } KeyProperties;
+ struct
+ {
+ jclass clazz;
+ jmethodID getInstance;
+ jmethodID init;
+ jmethodID generateKey;
+ } KeyGenerator;
+ struct
+ {
+ struct
+ {
+ jclass clazz;
+ jmethodID ctor;
+ jmethodID setKeySize;
+ jmethodID setBlockModes;
+ jmethodID setEncryptionPaddings;
+ jmethodID build;
+ } Builder;
+ } KeyGenParameterSpec;
+ struct
+ {
+ jclass clazz;
+ jmethodID ctor;
+ } IvParameterSpec;
+ struct
+ {
+ jclass clazz;
+ jmethodID getInstance;
+ jmethodID init;
+ jmethodID doFinal;
+ jmethodID getIV;
+ jint ENCRYPT_MODE;
+ jint DECRYPT_MODE;
+ } Cipher;
+ jstring VLC_CIPHER;
+} fields;
+static jobject s_jkey = NULL;
+
+#define CALL(caller, obj, method, ...) \
+ (*p_env)->caller(p_env, obj, fields.method, ##__VA_ARGS__)
+
+#define CALL_VOID(obj, method, ...) \
+ CALL(CallVoidMethod, obj, method, ##__VA_ARGS__)
+
+#define CALL_OBJ(obj, method, ...) \
+ CALL(CallObjectMethod, obj, method, ##__VA_ARGS__)
+
+#define CALL_STATICOBJ(obj, method, ...) \
+ CALL(CallStaticObjectMethod, fields.obj.clazz, method, ##__VA_ARGS__)
+
+#define CALL_INT(obj, method, ...) \
+ CALL(CallIntMethod, obj, method, ##__VA_ARGS__)
+
+#define CALL_BOOL(obj, method, ...) \
+ CALL(CallBooleanMethod, obj, method, ##__VA_ARGS__)
+
+#define NEW_OBJECT(arg, ...) \
+ (*p_env)->NewObject(p_env, fields.arg.clazz, fields.arg.ctor, ##__VA_ARGS__)
+
+#define NEW_GREF(obj) \
+ (*p_env)->NewGlobalRef(p_env, obj)
+
+#define DEL_GREF(obj) \
+ (*p_env)->DeleteGlobalRef(p_env, obj)
+
+#define DEL_LREF(obj) \
+ (*p_env)->DeleteLocalRef(p_env, obj)
+
+#define NEW_STR(str) \
+ (*p_env)->NewStringUTF(p_env, str)
+
+static bool
+check_expection(vlc_keystore *p_keystore, JNIEnv *p_env)
+{
+ jthrowable jex = (*p_env)->ExceptionOccurred(p_env);
+ if (jex != NULL)
+ {
+ (*p_env)->ExceptionClear(p_env);
+ if (fields.Object.toString != NULL)
+ {
+ const char *psz_str = NULL;
+ jstring jstr = NULL;
+
+ jstr = (jstring) CALL_OBJ(jex, Object.toString);
+ if (jstr != NULL)
+ psz_str = (*p_env)->GetStringUTFChars(p_env, jstr, NULL);
+ if (psz_str != NULL)
+ {
+ msg_Err(p_keystore, "%s", psz_str);
+ (*p_env)->ReleaseStringUTFChars(p_env, jstr, psz_str);
+ }
+ DEL_LREF(jstr);
+ }
+ else
+ msg_Err(p_keystore, "unknown exception");
+ DEL_LREF(jex);
+ return true;
+ }
+ return false;
+}
+#define CHECK_EXCEPTION() check_expection(p_keystore, p_env)
+
+#define GET_CLASS(str) do { \
+ if (clazz != NULL) \
+ DEL_LREF(clazz); \
+ clazz = (*p_env)->FindClass(p_env, (str)); \
+ if (CHECK_EXCEPTION()) \
+ return VLC_EGENERIC; \
+} while (0)
+#define GET_GLOBAL_CLASS(id) do { \
+ fields.id.clazz = (jclass) NEW_GREF(clazz); \
+} while (0)
+#define GET_ID(get, id, str, args) do { \
+ fields.id = (*p_env)->get(p_env, clazz, (str), (args)); \
+ if (CHECK_EXCEPTION()) \
+ return VLC_EGENERIC; \
+} while (0)
+#define GET_CONST_INT(id, str) do { \
+ jfieldID field = (*p_env)->GetStaticFieldID(p_env, clazz, (str), "I"); \
+ if (!CHECK_EXCEPTION()) \
+ { \
+ fields.id = (*p_env)->GetStaticIntField(p_env, clazz, field); \
+ if (CHECK_EXCEPTION()) \
+ return VLC_EGENERIC; \
+ } else { \
+ return VLC_EGENERIC; \
+ } \
+} while(0)
+#define GET_CONST_OBJ(id, str, type) do { \
+ jfieldID field = (*p_env)->GetStaticFieldID(p_env, clazz, (str), type); \
+ if (!CHECK_EXCEPTION()) \
+ { \
+ jobject jobj = (*p_env)->GetStaticObjectField(p_env, clazz, field); \
+ if (CHECK_EXCEPTION()) \
+ return VLC_EGENERIC; \
+ fields.id = NEW_GREF(jobj); \
+ DEL_LREF(jobj); \
+ } else { \
+ return VLC_EGENERIC; \
+ } \
+} while(0)
+
+/*
+ * Init JNI fields that will be used to fetch the key and crypt/encrypt
+ */
+static int
+InitJni(vlc_keystore *p_keystore, JNIEnv *p_env)
+{
+ jclass clazz = NULL;
+
+ GET_CLASS("java/lang/Object");
+ GET_ID(GetMethodID, Object.toString, "toString", "()Ljava/lang/String;");
+
+ GET_CLASS("java/security/KeyStore");
+ GET_GLOBAL_CLASS(KeyStore);
+ GET_ID(GetStaticMethodID, KeyStore.getInstance, "getInstance",
+ "(Ljava/lang/String;)Ljava/security/KeyStore;");
+ GET_ID(GetMethodID, KeyStore.load, "load",
+ "(Ljava/security/KeyStore$LoadStoreParameter;)V");
+ GET_ID(GetMethodID, KeyStore.getEntry, "getEntry",
+ "(Ljava/lang/String;Ljava/security/KeyStore$ProtectionParameter;)"
+ "Ljava/security/KeyStore$Entry;");
+
+ GET_CLASS("java/security/KeyStore$SecretKeyEntry");
+ GET_ID(GetMethodID, KeyStore.SecretKeyEntry.getSecretKey, "getSecretKey",
+ "()Ljavax/crypto/SecretKey;");
+
+
+ GET_CLASS("javax/crypto/spec/IvParameterSpec");
+ GET_GLOBAL_CLASS(IvParameterSpec);
+ GET_ID(GetMethodID, IvParameterSpec.ctor, "<init>", "([B)V");
+
+ GET_CLASS("javax/crypto/Cipher");
+ GET_GLOBAL_CLASS(Cipher);
+ GET_ID(GetStaticMethodID, Cipher.getInstance, "getInstance",
+ "(Ljava/lang/String;)Ljavax/crypto/Cipher;");
+ GET_ID(GetMethodID, Cipher.init, "init",
+ "(ILjava/security/Key;Ljava/security/spec/AlgorithmParameterSpec;)V");
+ GET_ID(GetMethodID, Cipher.doFinal, "doFinal", "([B)[B");
+ GET_ID(GetMethodID, Cipher.getIV, "getIV", "()[B");
+ GET_CONST_INT(Cipher.ENCRYPT_MODE, "ENCRYPT_MODE");
+ GET_CONST_INT(Cipher.DECRYPT_MODE, "DECRYPT_MODE");
+
+ DEL_LREF(clazz);
+
+ jstring VLC_CIPHER = NEW_STR("AES/CBC/PKCS7Padding");
+ if (CHECK_EXCEPTION())
+ return VLC_EGENERIC;
+ fields.VLC_CIPHER = NEW_GREF(VLC_CIPHER);
+ DEL_LREF(VLC_CIPHER);
+
+ return VLC_SUCCESS;
+}
+
+/*
+ * Init JNI fields that will be used by generateKey()
+ */
+static int
+InitJniGenKey(vlc_keystore *p_keystore, JNIEnv *p_env)
+{
+ jclass clazz = NULL;
+
+ GET_CLASS("android/security/keystore/KeyProperties");
+ GET_CONST_INT(KeyProperties.PURPOSE_ENCRYPT, "PURPOSE_ENCRYPT");
+ GET_CONST_INT(KeyProperties.PURPOSE_DECRYPT, "PURPOSE_DECRYPT");
+ GET_CONST_OBJ(KeyProperties.BLOCK_MODE_CBC,
+ "BLOCK_MODE_CBC", "Ljava/lang/String;");
+ GET_CONST_OBJ(KeyProperties.ENCRYPTION_PADDING_PKCS7,
+ "ENCRYPTION_PADDING_PKCS7", "Ljava/lang/String;");
+ GET_CONST_OBJ(KeyProperties.KEY_ALGORITHM_AES,
+ "KEY_ALGORITHM_AES", "Ljava/lang/String;");
+
+ GET_CLASS("android/security/keystore/KeyGenParameterSpec$Builder");
+ GET_GLOBAL_CLASS(KeyGenParameterSpec.Builder);
+ GET_ID(GetMethodID, KeyGenParameterSpec.Builder.ctor, "<init>",
+ "(Ljava/lang/String;I)V");
+ GET_ID(GetMethodID, KeyGenParameterSpec.Builder.setKeySize, "setKeySize",
+ "(I)Landroid/security/keystore/KeyGenParameterSpec$Builder;");
+ GET_ID(GetMethodID, KeyGenParameterSpec.Builder.setBlockModes, "setBlockModes",
+ "([Ljava/lang/String;)"
+ "Landroid/security/keystore/KeyGenParameterSpec$Builder;");
+ GET_ID(GetMethodID, KeyGenParameterSpec.Builder.setEncryptionPaddings,
+ "setEncryptionPaddings", "([Ljava/lang/String;)"
+ "Landroid/security/keystore/KeyGenParameterSpec$Builder;");
+ GET_ID(GetMethodID, KeyGenParameterSpec.Builder.build, "build",
+ "()Landroid/security/keystore/KeyGenParameterSpec;");
+
+ GET_CLASS("javax/crypto/KeyGenerator");
+ GET_GLOBAL_CLASS(KeyGenerator);
+ GET_ID(GetStaticMethodID, KeyGenerator.getInstance, "getInstance",
+ "(Ljava/lang/String;Ljava/lang/String;)Ljavax/crypto/KeyGenerator;");
+ GET_ID(GetMethodID, KeyGenerator.init, "init",
+ "(Ljava/security/spec/AlgorithmParameterSpec;)V");
+ GET_ID(GetMethodID, KeyGenerator.generateKey, "generateKey",
+ "()Ljavax/crypto/SecretKey;");
+
+ DEL_LREF(clazz);
+ return VLC_SUCCESS;
+}
+
+/*
+ * Encrypt or Decrypt
+ */
+static size_t
+Process(vlc_keystore *p_keystore, JNIEnv *p_env, jobject jcipher,
+ const uint8_t *p_src, size_t i_src_len,
+ const uint8_t *p_iv, uint32_t i_iv_len, uint8_t **pp_dst)
+{
+ size_t i_dst_size = 0;
+ uint8_t *p_dst;
+ jbyteArray jsrcArray = NULL, jdstArray = NULL;
+
+ jsrcArray = (*p_env)->NewByteArray(p_env, i_src_len);
+ if (CHECK_EXCEPTION())
+ goto end;
+ (*p_env)->SetByteArrayRegion(p_env, jsrcArray, 0, i_src_len, (jbyte *)p_src);
+
+ jdstArray = (jbyteArray) CALL_OBJ(jcipher, Cipher.doFinal, jsrcArray);
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ if (jdstArray == NULL)
+ goto end;
+
+ jsize dstSize = (*p_env)->GetArrayLength(p_env, jdstArray);
+
+ if (dstSize == 0)
+ goto end;
+
+ jbyte *p_bytes = (*p_env)->GetByteArrayElements(p_env, jdstArray, 0);
+
+ p_dst = i_iv_len > 0 ? malloc(dstSize + i_iv_len + sizeof(uint32_t))
+ : malloc(dstSize);
+ if (p_dst == NULL)
+ {
+ (*p_env)->ReleaseByteArrayElements(p_env, jdstArray, p_bytes, 0);
+ free(p_dst);
+ goto end;
+ }
+
+ if (i_iv_len > 0)
+ {
+ /* Store the IV just before the encrypted password */
+ memcpy(p_dst, &i_iv_len, sizeof(uint32_t));
+ memcpy(p_dst + sizeof(uint32_t), p_iv, i_iv_len);
+ memcpy(p_dst + sizeof(uint32_t) + i_iv_len, p_bytes, dstSize);
+ i_dst_size = dstSize + i_iv_len + sizeof(uint32_t);
+ }
+ else
+ {
+ memcpy(p_dst, p_bytes, dstSize);
+ i_dst_size = dstSize;
+ }
+ (*p_env)->ReleaseByteArrayElements(p_env, jdstArray, p_bytes, 0);
+
+ *pp_dst = p_dst;
+
+end:
+ if (jsrcArray != NULL)
+ DEL_LREF(jsrcArray);
+ if (jdstArray != NULL)
+ DEL_LREF(jdstArray);
+ return i_dst_size;
+}
+
+static size_t
+AndroidEncrypt(vlc_keystore *p_keystore, void *p_ctx, const uint8_t *p_src,
+ size_t i_src_len, uint8_t **pp_dst)
+{
+ (void) p_ctx;
+ JNIEnv *p_env = GET_ENV();
+ if (p_env == NULL)
+ return 0;
+
+ jobject jcipher = NULL;
+ jcipher = CALL_STATICOBJ(Cipher, Cipher.getInstance, fields.VLC_CIPHER);
+ if (CHECK_EXCEPTION())
+ return 0;
+
+ size_t i_dst_len = 0;
+ CALL_VOID(jcipher, Cipher.init, fields.Cipher.ENCRYPT_MODE, s_jkey, NULL);
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ /* Get the IV (Initialization Vector) initialized by Android that will be
+ * used to decrypt this secret. This IV will be stored with the encrypted
+ * secret */
+ jarray jivArray = (jarray) CALL_OBJ(jcipher, Cipher.getIV);
+ if (jivArray == NULL)
+ goto end;
+
+ jsize i_iv_len = (*p_env)->GetArrayLength(p_env, jivArray);
+ if (i_iv_len == 0)
+ goto end;
+ jbyte *p_iv_bytes = (*p_env)->GetByteArrayElements(p_env, jivArray, 0);
+
+ i_dst_len = Process(p_keystore, p_env, jcipher, p_src, i_src_len,
+ (const uint8_t *)p_iv_bytes, i_iv_len, pp_dst);
+
+ (*p_env)->ReleaseByteArrayElements(p_env, jivArray, p_iv_bytes, 0);
+ DEL_LREF(jivArray);
+
+end:
+
+ DEL_LREF(jcipher);
+ return i_dst_len;
+}
+
+static size_t
+AndroidDecrypt(vlc_keystore *p_keystore, void *p_ctx, const uint8_t *p_src,
+ size_t i_src_len, uint8_t **pp_dst)
+{
+ (void) p_ctx;
+ JNIEnv *p_env = GET_ENV();
+ if (p_env == NULL)
+ return 0;
+
+ jobject jivArray = NULL, jiv = NULL, jcipher = NULL;
+
+ jcipher = CALL_STATICOBJ(Cipher, Cipher.getInstance, fields.VLC_CIPHER);
+ if (CHECK_EXCEPTION())
+ return 0;
+
+ /* Get the IV located at the beginning of the secret */
+ size_t i_dst_len = 0;
+ uint32_t i_iv_len;
+ if (i_src_len < sizeof(uint32_t))
+ goto end;
+
+ memcpy(&i_iv_len, p_src, sizeof(uint32_t));
+ if (i_iv_len == 0 || i_src_len < (sizeof(uint32_t) + i_iv_len))
+ goto end;
+
+ jivArray = (*p_env)->NewByteArray(p_env, i_iv_len);
+ if (CHECK_EXCEPTION())
+ goto end;
+ (*p_env)->SetByteArrayRegion(p_env, jivArray, 0, i_iv_len,
+ (jbyte *)(p_src + sizeof(uint32_t)) );
+
+ jiv = NEW_OBJECT(IvParameterSpec, jivArray);
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ /* Use the IV to initialize the decrypt Cipher */
+ CALL_VOID(jcipher, Cipher.init, fields.Cipher.DECRYPT_MODE, s_jkey, jiv);
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ i_dst_len = Process(p_keystore, p_env, jcipher,
+ p_src + sizeof(uint32_t) + i_iv_len,
+ i_src_len - sizeof(uint32_t) - i_iv_len,
+ NULL, 0, pp_dst);
+
+end:
+ DEL_LREF(jcipher);
+ if (jivArray != NULL)
+ DEL_LREF(jivArray);
+ if (jiv != NULL)
+ DEL_LREF(jiv);
+ return i_dst_len;
+}
+
+/*
+ * Generate a AES/CBC/PKCS7Padding key that will be stored by the Android
+ * Keystore
+ */
+static jobject
+GenerateKey(vlc_keystore *p_keystore, JNIEnv *p_env, jstring jstringAlias,
+ jstring jstringProvider)
+{
+ if (InitJniGenKey(p_keystore, p_env) != VLC_SUCCESS)
+ return NULL;
+
+ jobject jkey = NULL, jbuilder = NULL, jspec = NULL,
+ jkeyGen = NULL;
+ jclass jstringClass = NULL;
+ jobjectArray jarray = NULL;
+
+ jbuilder = NEW_OBJECT(KeyGenParameterSpec.Builder, jstringAlias,
+ fields.KeyProperties.PURPOSE_ENCRYPT |
+ fields.KeyProperties.PURPOSE_DECRYPT);
+ CALL_OBJ(jbuilder, KeyGenParameterSpec.Builder.setKeySize, 256);
+
+ jstringClass = (*p_env)->FindClass(p_env, "java/lang/String");
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ jarray = (*p_env)->NewObjectArray(p_env, 1, jstringClass, NULL);
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ (*p_env)->SetObjectArrayElement(p_env, jarray, 0,
+ fields.KeyProperties.BLOCK_MODE_CBC);
+ CALL_OBJ(jbuilder, KeyGenParameterSpec.Builder.setBlockModes, jarray);
+
+ (*p_env)->SetObjectArrayElement(p_env, jarray, 0,
+ fields.KeyProperties.ENCRYPTION_PADDING_PKCS7);
+ CALL_OBJ(jbuilder, KeyGenParameterSpec.Builder.setEncryptionPaddings, jarray);
+ jspec = CALL_OBJ(jbuilder, KeyGenParameterSpec.Builder.build);
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ jkeyGen = CALL_STATICOBJ(KeyGenerator, KeyGenerator.getInstance,
+ fields.KeyProperties.KEY_ALGORITHM_AES,
+ jstringProvider);
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ CALL_VOID(jkeyGen, KeyGenerator.init, jspec);
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ jkey = CALL_OBJ(jkeyGen, KeyGenerator.generateKey);
+ CHECK_EXCEPTION();
+
+end:
+ if (jbuilder != NULL)
+ DEL_LREF(jbuilder);
+ if (jstringClass != NULL)
+ DEL_LREF(jstringClass);
+ if (jarray != NULL)
+ DEL_LREF(jarray);
+ if (jspec != NULL)
+ DEL_LREF(jspec);
+ if (jkeyGen != NULL)
+ DEL_LREF(jkeyGen);
+
+ return jkey;
+}
+
+/*
+ * Init JNI fields, fetch the key stored by Android or generate a new one
+ */
+static void
+AndroidInit(vlc_keystore *p_keystore)
+{
+ JNIEnv *p_env = GET_ENV();
+ if (p_env == NULL)
+ return;
+
+ if (InitJni(p_keystore, p_env) != VLC_SUCCESS)
+ return;
+
+ jobject jkeystore = NULL, jentry = NULL, jkey = NULL;
+ jstring jstringAlias = NULL, jstringProvider = NULL;
+
+ jstringAlias = NEW_STR("LibVLCAndroid");
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ jstringProvider = NEW_STR("AndroidKeyStore");
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ jkeystore = CALL_STATICOBJ(KeyStore, KeyStore.getInstance, jstringProvider);
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ CALL_VOID(jkeystore, KeyStore.load, NULL);
+ if (CHECK_EXCEPTION())
+ goto end;
+
+ jentry = CALL_OBJ(jkeystore, KeyStore.getEntry, jstringAlias, NULL);
+ if (CHECK_EXCEPTION())
+ goto end;
+ if (jentry != NULL)
+ {
+ jkey = CALL_OBJ(jentry, KeyStore.SecretKeyEntry.getSecretKey);
+ if (CHECK_EXCEPTION())
+ goto end;
+ }
+ else
+ {
+ jkey = GenerateKey(p_keystore, p_env, jstringAlias, jstringProvider);
+ if (jkey == NULL)
+ goto end;
+ }
+
+ s_jkey = NEW_GREF(jkey);
+
+end:
+ if (jstringAlias != NULL)
+ DEL_LREF(jstringAlias);
+ if (jstringProvider != NULL)
+ DEL_LREF(jstringProvider);
+ if (jkeystore != NULL)
+ DEL_LREF(jkeystore);
+ if (jentry != NULL)
+ DEL_LREF(jentry);
+ if (jkey != NULL)
+ DEL_LREF(jkey);
+}
+
+int
+CryptInit(vlc_keystore *p_keystore, struct crypt *p_crypt)
+{
+ static vlc_mutex_t s_lock = VLC_STATIC_MUTEX;
+ static bool s_init = false;
+
+ vlc_mutex_lock(&s_lock);
+ if (!s_init)
+ {
+ AndroidInit(p_keystore);
+ s_init = true;
+ }
+ if (s_jkey == NULL)
+ {
+ vlc_mutex_unlock(&s_lock);
+ return VLC_EGENERIC;
+ }
+ vlc_mutex_unlock(&s_lock);
+
+ p_crypt->pf_encrypt = AndroidEncrypt;
+ p_crypt->pf_decrypt = AndroidDecrypt;
+
+ return VLC_SUCCESS;
+}
diff --git a/modules/keystore/memory-crypt.h b/modules/keystore/memory-crypt.h
index 4b4b815..be88626 100644
--- a/modules/keystore/memory-crypt.h
+++ b/modules/keystore/memory-crypt.h
@@ -18,13 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
-#if 0
-#if defined(__ANDROID__) || defined(_WIN32)
+#if defined(__ANDROID__) /* TODO || defined(_WIN32) */
# define CRYPTFILE
-#endif
-#endif
-
-#ifdef CRYPTFILE
struct crypt
{
--
2.7.0
More information about the vlc-devel
mailing list