270 lines
8.7 KiB
C
270 lines
8.7 KiB
C
/*
|
|
**
|
|
** Copyright 2009, The Android Open Source Project
|
|
**
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
** you may not use this file except in compliance with the License.
|
|
** You may obtain a copy of the License at
|
|
**
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
**
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
** See the License for the specific language governing permissions and
|
|
** limitations under the License.
|
|
*/
|
|
#define LOG_TAG "CertTool"
|
|
|
|
#include <string.h>
|
|
#include <jni.h>
|
|
#include <cutils/log.h>
|
|
#include <openssl/pkcs12.h>
|
|
#include <openssl/x509v3.h>
|
|
|
|
#include "cert.h"
|
|
|
|
typedef int PKCS12_KEYSTORE_FUNC(PKCS12_KEYSTORE *store, char *buf, int size);
|
|
|
|
jstring
|
|
android_security_CertTool_generateCertificateRequest(JNIEnv* env,
|
|
jobject thiz,
|
|
jint bits,
|
|
jstring jChallenge)
|
|
|
|
{
|
|
int ret = -1;
|
|
jboolean bIsCopy;
|
|
char csr[REPLY_MAX];
|
|
const char* challenge = (*env)->GetStringUTFChars(env, jChallenge, &bIsCopy);
|
|
|
|
ret = gen_csr(bits, challenge , csr);
|
|
(*env)->ReleaseStringUTFChars(env, jChallenge, challenge);
|
|
if (ret == 0) return (*env)->NewStringUTF(env, csr);
|
|
return NULL;
|
|
}
|
|
|
|
jboolean
|
|
android_security_CertTool_isPkcs12Keystore(JNIEnv* env,
|
|
jobject thiz,
|
|
jbyteArray data)
|
|
{
|
|
int len = (*env)->GetArrayLength(env, data);
|
|
|
|
if (len > 0) {
|
|
PKCS12 *handle = NULL;
|
|
char buf[len];
|
|
|
|
(*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf);
|
|
return (jboolean)is_pkcs12(buf, len);
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
jint
|
|
android_security_CertTool_getPkcs12Handle(JNIEnv* env,
|
|
jobject thiz,
|
|
jbyteArray data,
|
|
jstring jPassword)
|
|
{
|
|
jboolean bIsCopy;
|
|
int len = (*env)->GetArrayLength(env, data);
|
|
const char* passwd = (*env)->GetStringUTFChars(env, jPassword , &bIsCopy);
|
|
|
|
if (len > 0) {
|
|
PKCS12_KEYSTORE *handle = NULL;
|
|
char buf[len];
|
|
|
|
(*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf);
|
|
handle = get_pkcs12_keystore_handle(buf, len, passwd);
|
|
(*env)->ReleaseStringUTFChars(env, jPassword, passwd);
|
|
return (jint)handle;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
jstring call_pkcs12_ks_func(PKCS12_KEYSTORE_FUNC *func,
|
|
JNIEnv* env,
|
|
jobject thiz,
|
|
jint phandle)
|
|
{
|
|
char buf[REPLY_MAX];
|
|
|
|
if (phandle == 0) return NULL;
|
|
if (func((PKCS12_KEYSTORE*)phandle, buf, sizeof(buf)) == 0) {
|
|
return (*env)->NewStringUTF(env, buf);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
jstring
|
|
android_security_CertTool_getPkcs12Certificate(JNIEnv* env,
|
|
jobject thiz,
|
|
jint phandle)
|
|
{
|
|
return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)get_pkcs12_certificate,
|
|
env, thiz, phandle);
|
|
}
|
|
|
|
jstring
|
|
android_security_CertTool_getPkcs12PrivateKey(JNIEnv* env,
|
|
jobject thiz,
|
|
jint phandle)
|
|
{
|
|
return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)get_pkcs12_private_key,
|
|
env, thiz, phandle);
|
|
}
|
|
|
|
jstring
|
|
android_security_CertTool_popPkcs12CertificateStack(JNIEnv* env,
|
|
jobject thiz,
|
|
jint phandle)
|
|
{
|
|
return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)pop_pkcs12_certs_stack,
|
|
env, thiz, phandle);
|
|
}
|
|
|
|
void android_security_CertTool_freePkcs12Handle(JNIEnv* env,
|
|
jobject thiz,
|
|
jint handle)
|
|
{
|
|
if (handle != 0) free_pkcs12_keystore((PKCS12_KEYSTORE*)handle);
|
|
}
|
|
|
|
jint
|
|
android_security_CertTool_generateX509Certificate(JNIEnv* env,
|
|
jobject thiz,
|
|
jbyteArray data)
|
|
{
|
|
char buf[REPLY_MAX];
|
|
int len = (*env)->GetArrayLength(env, data);
|
|
|
|
if (len > REPLY_MAX) return 0;
|
|
(*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf);
|
|
return (jint) parse_cert(buf, len);
|
|
}
|
|
|
|
jboolean android_security_CertTool_isCaCertificate(JNIEnv* env,
|
|
jobject thiz,
|
|
jint handle)
|
|
{
|
|
return (handle == 0) ? (jboolean)0 : (jboolean) is_ca_cert((X509*)handle);
|
|
}
|
|
|
|
jstring android_security_CertTool_getIssuerDN(JNIEnv* env,
|
|
jobject thiz,
|
|
jint handle)
|
|
{
|
|
char issuer[MAX_CERT_NAME_LEN];
|
|
|
|
if (handle == 0) return NULL;
|
|
if (get_issuer_name((X509*)handle, issuer, MAX_CERT_NAME_LEN)) return NULL;
|
|
return (*env)->NewStringUTF(env, issuer);
|
|
}
|
|
|
|
jstring android_security_CertTool_getCertificateDN(JNIEnv* env,
|
|
jobject thiz,
|
|
jint handle)
|
|
{
|
|
char name[MAX_CERT_NAME_LEN];
|
|
if (handle == 0) return NULL;
|
|
if (get_cert_name((X509*)handle, name, MAX_CERT_NAME_LEN)) return NULL;
|
|
return (*env)->NewStringUTF(env, name);
|
|
}
|
|
|
|
jstring android_security_CertTool_getPrivateKeyPEM(JNIEnv* env,
|
|
jobject thiz,
|
|
jint handle)
|
|
{
|
|
char pem[MAX_PEM_LENGTH];
|
|
if (handle == 0) return NULL;
|
|
if (get_private_key_pem((X509*)handle, pem, MAX_PEM_LENGTH)) return NULL;
|
|
return (*env)->NewStringUTF(env, pem);
|
|
}
|
|
|
|
void android_security_CertTool_freeX509Certificate(JNIEnv* env,
|
|
jobject thiz,
|
|
jint handle)
|
|
{
|
|
if (handle != 0) X509_free((X509*)handle);
|
|
}
|
|
|
|
/*
|
|
* Table of methods associated with the CertTool class.
|
|
*/
|
|
static JNINativeMethod gCertToolMethods[] = {
|
|
/* name, signature, funcPtr */
|
|
{"generateCertificateRequest", "(ILjava/lang/String;)Ljava/lang/String;",
|
|
(void*)android_security_CertTool_generateCertificateRequest},
|
|
{"isPkcs12Keystore", "([B)Z",
|
|
(void*)android_security_CertTool_isPkcs12Keystore},
|
|
{"getPkcs12Handle", "([BLjava/lang/String;)I",
|
|
(void*)android_security_CertTool_getPkcs12Handle},
|
|
{"getPkcs12Certificate", "(I)Ljava/lang/String;",
|
|
(void*)android_security_CertTool_getPkcs12Certificate},
|
|
{"getPkcs12PrivateKey", "(I)Ljava/lang/String;",
|
|
(void*)android_security_CertTool_getPkcs12PrivateKey},
|
|
{"popPkcs12CertificateStack", "(I)Ljava/lang/String;",
|
|
(void*)android_security_CertTool_popPkcs12CertificateStack},
|
|
{"freePkcs12Handle", "(I)V",
|
|
(void*)android_security_CertTool_freePkcs12Handle},
|
|
{"generateX509Certificate", "([B)I",
|
|
(void*)android_security_CertTool_generateX509Certificate},
|
|
{"isCaCertificate", "(I)Z",
|
|
(void*)android_security_CertTool_isCaCertificate},
|
|
{"getIssuerDN", "(I)Ljava/lang/String;",
|
|
(void*)android_security_CertTool_getIssuerDN},
|
|
{"getCertificateDN", "(I)Ljava/lang/String;",
|
|
(void*)android_security_CertTool_getCertificateDN},
|
|
{"getPrivateKeyPEM", "(I)Ljava/lang/String;",
|
|
(void*)android_security_CertTool_getPrivateKeyPEM},
|
|
{"freeX509Certificate", "(I)V",
|
|
(void*)android_security_CertTool_freeX509Certificate},
|
|
};
|
|
|
|
/*
|
|
* Register several native methods for one class.
|
|
*/
|
|
static int registerNatives(JNIEnv* env, const char* className,
|
|
JNINativeMethod* gMethods, int numMethods)
|
|
{
|
|
jclass clazz;
|
|
|
|
clazz = (*env)->FindClass(env, className);
|
|
if (clazz == NULL) {
|
|
LOGE("Can not find class %s\n", className);
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
|
|
LOGE("Can not RegisterNatives\n");
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
return JNI_TRUE;
|
|
}
|
|
|
|
jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
|
{
|
|
JNIEnv* env = NULL;
|
|
jint result = -1;
|
|
|
|
|
|
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
|
|
goto bail;
|
|
}
|
|
|
|
if (!registerNatives(env, "android/security/CertTool",
|
|
gCertToolMethods, nelem(gCertToolMethods))) {
|
|
goto bail;
|
|
}
|
|
|
|
/* success -- return valid version number */
|
|
result = JNI_VERSION_1_4;
|
|
|
|
bail:
|
|
return result;
|
|
}
|