android: Add support for creating RSASSA-PSS signatures via JNI

This commit is contained in:
Tobias Brunner
2017-11-08 16:48:10 +01:00
parent 414f255561
commit 72b7c0ffd8
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2012-2014 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2012-2017 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -18,6 +18,7 @@
#include "../android_jni.h"
#include <utils/debug.h>
#include <asn1/asn1.h>
#include <credentials/keys/signature_params.h>
typedef struct private_private_key_t private_private_key_t;
@@ -52,6 +53,113 @@ struct private_private_key_t {
refcount_t ref;
};
/**
* Get the Java name for the given hash algorithm
*/
static jstring hash_name(JNIEnv *env, hash_algorithm_t alg)
{
const char *hash = NULL;
switch (alg)
{
case HASH_SHA1:
hash = "SHA-1";
break;
case HASH_SHA224:
hash = "SHA-224";
break;
case HASH_SHA256:
hash = "SHA-256";
break;
case HASH_SHA384:
hash = "SHA-384";
break;
case HASH_SHA512:
hash = "SHA-512";
break;
default:
return NULL;
}
return (*env)->NewStringUTF(env, hash);
}
/**
* Set PSSParameterSpec on Signature object
*/
static bool set_pss_params(private_private_key_t *this, JNIEnv *env,
jobject jsignature, rsa_pss_params_t *pss)
{
jmethodID method_id;
jclass cls;
jstring jhash, jmgf1;
jobject obj;
int slen;
/* create MGF1ParameterSpec instance */
cls = (*env)->FindClass(env, "java/security/spec/MGF1ParameterSpec");
if (!cls)
{
return FALSE;
}
method_id = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
if (!method_id)
{
return FALSE;
}
jhash = hash_name(env, pss->mgf1_hash);
if (!jhash)
{
return FALSE;
}
obj = (*env)->NewObject(env, cls, method_id, jhash);
if (!obj)
{
return FALSE;
}
/* create PSSParameterSpec instance */
cls = (*env)->FindClass(env, "java/security/spec/PSSParameterSpec");
if (!cls)
{
return FALSE;
}
method_id = (*env)->GetMethodID(env, cls, "<init>",
"(Ljava/lang/String;Ljava/lang/String;"
"Ljava/security/spec/AlgorithmParameterSpec;II)V");
if (!method_id)
{
return FALSE;
}
jhash = hash_name(env, pss->hash);
jmgf1 = (*env)->NewStringUTF(env, "MGF1");
if (!jhash || !jmgf1)
{
return FALSE;
}
slen = hasher_hash_size(pss->hash);
if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
{
slen = pss->salt_len;
}
obj = (*env)->NewObject(env, cls, method_id, jhash, jmgf1, obj, slen, 1);
if (!obj)
{
return FALSE;
}
/* update Signature instance */
method_id = (*env)->GetMethodID(env, this->signature_class, "setParameter",
"(Ljava/security/spec/AlgorithmParameterSpec;)V");
if (!method_id)
{
return FALSE;
}
(*env)->CallVoidMethod(env, jsignature, method_id, obj);
if (androidjni_exception_occurred(env))
{
return FALSE;
}
return TRUE;
}
METHOD(private_key_t, sign, bool,
private_private_key_t *this, signature_scheme_t scheme, void *params,
chunk_t data, chunk_t *signature)
@@ -59,6 +167,7 @@ METHOD(private_key_t, sign, bool,
JNIEnv *env;
jmethodID method_id;
const char *method = NULL;
rsa_pss_params_t *pss = NULL;
jstring jmethod;
jobject jsignature;
jbyteArray jdata, jsigarray;
@@ -89,6 +198,33 @@ METHOD(private_key_t, sign, bool,
case SIGN_RSA_EMSA_PKCS1_SHA2_512:
method = "SHA512withRSA";
break;
case SIGN_RSA_EMSA_PSS:
if (!params)
{
return FALSE;
}
pss = params;
switch (pss->hash)
{
case HASH_SHA1:
method = "SHA1withRSA/PSS";
break;
case HASH_SHA224:
method = "SHA224withRSA/PSS";
break;
case HASH_SHA256:
method = "SHA256withRSA/PSS";
break;
case HASH_SHA384:
method = "SHA384withRSA/PSS";
break;
case HASH_SHA512:
method = "SHA512withRSA/PSS";
break;
default:
break;
}
break;
default:
break;
}
@@ -145,6 +281,10 @@ METHOD(private_key_t, sign, bool,
{
goto failed;
}
if (pss && !set_pss_params(this, env, jsignature, pss))
{
goto failed;
}
method_id = (*env)->GetMethodID(env, this->signature_class, "initSign",
"(Ljava/security/PrivateKey;)V");
if (!method_id)