Merge change 26786 into eclair
* changes: Remove old keystore and related files.
This commit is contained in:
@@ -1,357 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
package android.security;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.security.Keystore;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* The CertTool class provides the functions to list the certs/keys,
|
||||
* generate the certificate request(csr) and store certificates into
|
||||
* keystore.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public class CertTool {
|
||||
static {
|
||||
System.loadLibrary("certtool_jni");
|
||||
}
|
||||
|
||||
/** Keystore namespace for CA certificates. */
|
||||
public static final String CA_CERTIFICATE = "CACERT";
|
||||
|
||||
/** Keystore namespace for user certificates. */
|
||||
public static final String USER_CERTIFICATE = "USRCERT";
|
||||
|
||||
/** Keystore namespace for user private keys. */
|
||||
public static final String USER_KEY = "USRKEY";
|
||||
|
||||
/** Action string for adding certificates to keystore. */
|
||||
public static final String ACTION_ADD_CREDENTIAL =
|
||||
"android.security.ADD_CREDENTIAL";
|
||||
|
||||
/** Action string for installing certificates to keystore from sdcard. */
|
||||
public static final String ACTION_INSTALL_CERT_FROM_SDCARD =
|
||||
"android.security.INSTALL_CERT_FROM_SDCARD";
|
||||
|
||||
/** Dialog title for adding a CA certificate. */
|
||||
public static final String TITLE_CA_CERT = "CA Certificate";
|
||||
|
||||
/** Dialog title for adding a user certificate. */
|
||||
public static final String TITLE_USER_CERT = "User Certificate";
|
||||
|
||||
/** Dialog title for adding a user private key. */
|
||||
public static final String TITLE_PRIVATE_KEY = "Private Key";
|
||||
|
||||
/** Dialog title for adding a PKCS12 keystore. */
|
||||
public static final String TITLE_PKCS12_KEYSTORE = "PKCS12 Keystore";
|
||||
|
||||
public static final int INCORRECT_PKCS12_PASSPHRASE = -100;
|
||||
|
||||
/**
|
||||
* The builder class for building an add-credential-to-keystore intent.
|
||||
*/
|
||||
public static class AddCredentialIntentBuilder {
|
||||
private Intent mIntent;
|
||||
private int mCount;
|
||||
|
||||
/**
|
||||
* Creates a builder to build a add-credential-to-keystore intent.
|
||||
*
|
||||
* @param title title of the dialog for adding this credential
|
||||
* @param descriptions description strings to show on the dialog
|
||||
*/
|
||||
public AddCredentialIntentBuilder(String title,
|
||||
String... descriptions) {
|
||||
Intent intent = new Intent(ACTION_ADD_CREDENTIAL);
|
||||
intent.putExtra(KEY_TITLE, title);
|
||||
|
||||
int i = 0;
|
||||
for (String description : descriptions) {
|
||||
intent.putExtra(KEY_DESCRIPTION + (i++), description);
|
||||
}
|
||||
mIntent = intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds credential data to the intent.
|
||||
*
|
||||
* @param namespace the namespace of the keystore to add the credential
|
||||
* data to
|
||||
* @param data the credential data
|
||||
* @return this builder
|
||||
*/
|
||||
public AddCredentialIntentBuilder addCredential(String namespace,
|
||||
byte[] data) {
|
||||
mIntent.putExtra(KEY_NAMESPACE + mCount, namespace);
|
||||
mIntent.putExtra(KEY_ITEM + mCount, data);
|
||||
mCount++;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns the intent. */
|
||||
public Intent build() {
|
||||
return mIntent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request for adding credential data to keystore.
|
||||
*/
|
||||
public static class AddCredentialRequest {
|
||||
private Intent mIntent;
|
||||
|
||||
/**
|
||||
* Creates an add-credential-data-to-keystore request.
|
||||
*
|
||||
* @param intent an add-credential-data-to-keystore intent
|
||||
* @see AddCredentialIntentBuilder
|
||||
*/
|
||||
public AddCredentialRequest(Intent intent) {
|
||||
mIntent = intent;
|
||||
}
|
||||
|
||||
/** Returns the dialog title. */
|
||||
public String getTitle() {
|
||||
return mIntent.getStringExtra(KEY_TITLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the i'th credential data.
|
||||
* @return the data or null if not exists
|
||||
*/
|
||||
public byte[] getDataAt(int i) {
|
||||
return mIntent.getByteArrayExtra(KEY_ITEM + i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the namespace of the i'th credential data.
|
||||
* @return the namespace string or null if missing
|
||||
*/
|
||||
public String getNamespaceAt(int i) {
|
||||
return mIntent.getStringExtra(KEY_NAMESPACE + i);
|
||||
}
|
||||
|
||||
/** Returns the descriptions of the credential data. */
|
||||
public String[] getDescriptions() {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
for (int i = 0; ; i++) {
|
||||
String s = mIntent.getStringExtra(KEY_DESCRIPTION + i);
|
||||
if (s == null) break;
|
||||
list.add(s);
|
||||
}
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String KEY_TITLE = "typeName";
|
||||
private static final String KEY_ITEM = "item";
|
||||
private static final String KEY_NAMESPACE = "namespace";
|
||||
private static final String KEY_DESCRIPTION = "description";
|
||||
|
||||
private static final String TAG = "CertTool";
|
||||
private static final String UNKNOWN = "Unknown";
|
||||
private static final String ISSUER_NAME = "Issuer Name:";
|
||||
private static final String DISTINCT_NAME = "Distinct Name:";
|
||||
|
||||
private static final String KEYNAME_DELIMITER = "_";
|
||||
private static final Keystore sKeystore = Keystore.getInstance();
|
||||
|
||||
private native int getPkcs12Handle(byte[] data, String password);
|
||||
private native String getPkcs12Certificate(int handle);
|
||||
private native String getPkcs12PrivateKey(int handle);
|
||||
private native String popPkcs12CertificateStack(int handle);
|
||||
private native void freePkcs12Handle(int handle);
|
||||
private native String generateCertificateRequest(int bits, String challenge);
|
||||
private native boolean isPkcs12Keystore(byte[] data);
|
||||
private native int generateX509Certificate(byte[] data);
|
||||
private native boolean isCaCertificate(int handle);
|
||||
private native String getIssuerDN(int handle);
|
||||
private native String getCertificateDN(int handle);
|
||||
private native String getPrivateKeyPEM(int handle);
|
||||
private native void freeX509Certificate(int handle);
|
||||
|
||||
private static CertTool sSingleton = null;
|
||||
|
||||
private CertTool() { }
|
||||
|
||||
public static final CertTool getInstance() {
|
||||
if (sSingleton == null) {
|
||||
sSingleton = new CertTool();
|
||||
}
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full key to retrieve the user private key from the keystore.
|
||||
* @see #getAllUserCertificateKeys()
|
||||
*/
|
||||
public String getUserPrivateKey(String key) {
|
||||
return USER_KEY + KEYNAME_DELIMITER + key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full key to retrieve the user certificate from the keystore.
|
||||
* @see #getAllUserCertificateKeys()
|
||||
*/
|
||||
public String getUserCertificate(String key) {
|
||||
return USER_CERTIFICATE + KEYNAME_DELIMITER + key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full key to retrieve the CA certificate from the keystore.
|
||||
* @see #getAllCaCertificateKeys()
|
||||
*/
|
||||
public String getCaCertificate(String key) {
|
||||
return CA_CERTIFICATE + KEYNAME_DELIMITER + key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the keys to the user certificates/private keys stored in the
|
||||
* keystore.
|
||||
* @see #getUserCertificate(String)
|
||||
* @see #getUserPrivateKey(String)
|
||||
*/
|
||||
public String[] getAllUserCertificateKeys() {
|
||||
return sKeystore.listKeys(USER_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the keys to the CA certificates stored in the keystore.
|
||||
* @see #getCaCertificate(String)
|
||||
*/
|
||||
public String[] getAllCaCertificateKeys() {
|
||||
return sKeystore.listKeys(CA_CERTIFICATE);
|
||||
}
|
||||
|
||||
public String[] getSupportedKeyStrenghs() {
|
||||
return new String[] {"High Grade", "Medium Grade"};
|
||||
}
|
||||
|
||||
private int getKeyLength(int index) {
|
||||
if (index == 0) return 2048;
|
||||
return 1024;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a key pair.
|
||||
*
|
||||
* @param keyStrengthIndex index to the array of supported key strengths;
|
||||
* see {@link #getSupportedKeyStrenghs()}
|
||||
* @param challenge the challenge string for generating the pair
|
||||
* @param dirName (not used)
|
||||
* @return a certificate request from the resulted public key
|
||||
*/
|
||||
public String generateKeyPair(int keyStrengthIndex, String challenge,
|
||||
String dirName) {
|
||||
return generateCertificateRequest(getKeyLength(keyStrengthIndex),
|
||||
challenge);
|
||||
}
|
||||
|
||||
private int extractAndStoreKeysFromPkcs12(int handle, String keyname) {
|
||||
int ret, i = 0;
|
||||
String pemData;
|
||||
|
||||
if ((pemData = getPkcs12Certificate(handle)) != null) {
|
||||
if ((ret = sKeystore.put(USER_CERTIFICATE, keyname, pemData)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if ((pemData = getPkcs12PrivateKey(handle)) != null) {
|
||||
if ((ret = sKeystore.put(USER_KEY, keyname, pemData)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if ((pemData = this.popPkcs12CertificateStack(handle)) != null) {
|
||||
if ((ret = sKeystore.put(CA_CERTIFICATE, keyname, pemData)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Adds a PKCS12 keystore to the keystore. */
|
||||
public int addPkcs12Keystore(byte[] p12Data, String password,
|
||||
String keyname) {
|
||||
int handle, ret;
|
||||
Log.i("CertTool", "addPkcs12Keystore()");
|
||||
|
||||
if ((handle = getPkcs12Handle(p12Data, password)) == 0) {
|
||||
return INCORRECT_PKCS12_PASSPHRASE;
|
||||
}
|
||||
ret = extractAndStoreKeysFromPkcs12(handle, keyname);
|
||||
freePkcs12Handle(handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a certificate to the keystore.
|
||||
*
|
||||
* @param data the certificate data
|
||||
* @param context the context to send an add-credential-to-keystore intent
|
||||
*/
|
||||
public synchronized void addCertificate(byte[] data, Context context) {
|
||||
int handle;
|
||||
Intent intent = null;
|
||||
|
||||
Log.i("CertTool", "addCertificate()");
|
||||
if (isPkcs12Keystore(data)) {
|
||||
intent = prepareIntent(TITLE_PKCS12_KEYSTORE, UNKNOWN, UNKNOWN)
|
||||
.addCredential(USER_KEY, data).build();
|
||||
} else if ((handle = generateX509Certificate(data)) != 0) {
|
||||
String issuer = getIssuerDN(handle);
|
||||
String distinctName = getCertificateDN(handle);
|
||||
String privateKeyPEM = getPrivateKeyPEM(handle);
|
||||
if (isCaCertificate(handle)) {
|
||||
intent = prepareIntent(TITLE_CA_CERT, issuer, distinctName)
|
||||
.addCredential(CA_CERTIFICATE, data).build();
|
||||
} else {
|
||||
AddCredentialIntentBuilder builder =
|
||||
prepareIntent(TITLE_USER_CERT, issuer, distinctName)
|
||||
.addCredential(USER_CERTIFICATE, data);
|
||||
if (!TextUtils.isEmpty(privateKeyPEM)) {
|
||||
builder.addCredential(USER_KEY, privateKeyPEM.getBytes());
|
||||
}
|
||||
intent = builder.build();
|
||||
}
|
||||
freeX509Certificate(handle);
|
||||
}
|
||||
if (intent != null) {
|
||||
context.startActivity(intent);
|
||||
} else {
|
||||
Log.w("CertTool", "incorrect data for addCertificate()");
|
||||
}
|
||||
}
|
||||
|
||||
private AddCredentialIntentBuilder prepareIntent(
|
||||
String title, String issuer, String distinctName) {
|
||||
return new AddCredentialIntentBuilder(title, ISSUER_NAME + issuer,
|
||||
DISTINCT_NAME + distinctName);
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
package android.security;
|
||||
|
||||
/**
|
||||
* The Keystore class provides the functions to list the certs/keys in keystore.
|
||||
* {@hide}
|
||||
*/
|
||||
|
||||
public abstract class Keystore {
|
||||
/** Action to unlock (or initialize) the keystore. */
|
||||
public static final String ACTION_UNLOCK_CREDENTIAL_STORAGE =
|
||||
"android.security.UNLOCK_CREDENTIAL_STORAGE";
|
||||
|
||||
// Keystore States
|
||||
public static final int BOOTUP = 0;
|
||||
public static final int UNINITIALIZED = 1;
|
||||
public static final int LOCKED = 2;
|
||||
public static final int UNLOCKED = 3;
|
||||
|
||||
private static final String TAG = "Keystore";
|
||||
private static final String[] NOTFOUND = new String[0];
|
||||
|
||||
public static Keystore getInstance() {
|
||||
return new FileKeystore();
|
||||
}
|
||||
|
||||
public abstract int lock();
|
||||
public abstract int unlock(String password);
|
||||
public abstract int getState();
|
||||
public abstract int changePassword(String oldPassword, String newPassword);
|
||||
public abstract int setPassword(String firstPassword);
|
||||
public abstract String[] listKeys(String namespace);
|
||||
public abstract int put(String namespace, String keyname, String value);
|
||||
public abstract String get(String namespace, String keyname);
|
||||
public abstract int remove(String namespace, String keyname);
|
||||
public abstract int reset();
|
||||
|
||||
private static class FileKeystore extends Keystore {
|
||||
private static final String SERVICE_NAME = "keystore";
|
||||
private static final String CA_CERTIFICATE = "CaCertificate";
|
||||
private static final String USER_CERTIFICATE = "UserCertificate";
|
||||
private static final String USER_KEY = "UserPrivateKey";
|
||||
private static final ServiceCommand mServiceCommand =
|
||||
new ServiceCommand(SERVICE_NAME);
|
||||
|
||||
@Override
|
||||
public int lock() {
|
||||
Reply result = mServiceCommand.execute(ServiceCommand.LOCK);
|
||||
return (result != null) ? result.returnCode : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int unlock(String password) {
|
||||
Reply result = mServiceCommand.execute(ServiceCommand.UNLOCK,
|
||||
password);
|
||||
return (result != null) ? result.returnCode : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getState() {
|
||||
Reply result = mServiceCommand.execute(ServiceCommand.GET_STATE);
|
||||
return (result != null) ? result.returnCode : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int changePassword(String oldPassword, String newPassword) {
|
||||
Reply result = mServiceCommand.execute(ServiceCommand.PASSWD,
|
||||
oldPassword, newPassword);
|
||||
return (result != null) ? result.returnCode : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setPassword(String firstPassword) {
|
||||
Reply result = mServiceCommand.execute(ServiceCommand.PASSWD,
|
||||
firstPassword);
|
||||
return (result != null) ? result.returnCode : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] listKeys(String namespace) {
|
||||
Reply result = mServiceCommand.execute(ServiceCommand.LIST_KEYS,
|
||||
namespace);
|
||||
if ((result == null) || (result.returnCode != 0) ||
|
||||
(result.len == 0)) {
|
||||
return NOTFOUND;
|
||||
}
|
||||
return new String(result.data, 0, result.len).split("\\s+");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int put(String namespace, String keyname, String value) {
|
||||
Reply result = mServiceCommand.execute(ServiceCommand.PUT_KEY,
|
||||
namespace, keyname, value);
|
||||
return (result != null) ? result.returnCode : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(String namespace, String keyname) {
|
||||
Reply result = mServiceCommand.execute(ServiceCommand.GET_KEY,
|
||||
namespace, keyname);
|
||||
return (result != null) ? ((result.returnCode != 0) ? null :
|
||||
new String(result.data, 0, result.len)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int remove(String namespace, String keyname) {
|
||||
Reply result = mServiceCommand.execute(ServiceCommand.REMOVE_KEY,
|
||||
namespace, keyname);
|
||||
return (result != null) ? result.returnCode : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int reset() {
|
||||
Reply result = mServiceCommand.execute(ServiceCommand.RESET);
|
||||
return (result != null) ? result.returnCode : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
cert.c certtool.c
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(JNI_H_INCLUDE) \
|
||||
external/openssl/include
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcutils \
|
||||
libnativehelper \
|
||||
libutils \
|
||||
libcrypto
|
||||
|
||||
ifeq ($(TARGET_SIMULATOR),true)
|
||||
ifeq ($(TARGET_OS),linux)
|
||||
ifeq ($(TARGET_ARCH),x86)
|
||||
LOCAL_LDLIBS += -lpthread -ldl -lrt -lssl
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
|
||||
LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
|
||||
endif
|
||||
|
||||
LOCAL_MODULE:= libcerttool_jni
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
@@ -1,344 +0,0 @@
|
||||
/*
|
||||
**
|
||||
** 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 <stdio.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/pkcs12.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "cert.h"
|
||||
|
||||
static PKEY_STORE pkey_store[KEYGEN_STORE_SIZE];
|
||||
static int store_index = 0;
|
||||
|
||||
static char emsg[][30] = {
|
||||
"",
|
||||
STR(ERR_INVALID_KEY_LENGTH),
|
||||
STR(ERR_CONSTRUCT_NEW_DATA),
|
||||
STR(ERR_RSA_KEYGEN),
|
||||
STR(ERR_X509_PROCESS),
|
||||
STR(ERR_SPKAC_TOO_LONG),
|
||||
STR(ERR_INVALID_ARGS),
|
||||
};
|
||||
|
||||
static void save_in_store(EVP_PKEY *pkey)
|
||||
{
|
||||
EVP_PKEY *newpkey = EVP_PKEY_new();
|
||||
RSA *rsa = EVP_PKEY_get1_RSA(pkey);
|
||||
EVP_PKEY_set1_RSA(newpkey, rsa);
|
||||
PKEY_STORE_free(pkey_store[store_index]);
|
||||
pkey_store[store_index].key_len = i2d_RSA_PUBKEY(rsa, &pkey_store[store_index].public_key);
|
||||
pkey_store[store_index++].pkey = newpkey;
|
||||
store_index %= KEYGEN_STORE_SIZE;
|
||||
RSA_free(rsa);
|
||||
}
|
||||
|
||||
static EVP_PKEY *get_pkey_from_store(X509 *cert)
|
||||
{
|
||||
int i, key_len;
|
||||
unsigned char *buf = NULL;
|
||||
if ((key_len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &buf)) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0 ; i < KEYGEN_STORE_SIZE ; ++i) {
|
||||
if ((key_len == pkey_store[i].key_len) &&
|
||||
memcmp(buf, pkey_store[i].public_key, key_len) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
return (i == KEYGEN_STORE_SIZE) ? NULL : pkey_store[i].pkey;
|
||||
}
|
||||
|
||||
int gen_csr(int bits, const char *challenge, char reply[REPLY_MAX])
|
||||
{
|
||||
int len, ret_code = 0;
|
||||
BIGNUM *bn = NULL;
|
||||
char *spkstr = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
RSA *rsa = NULL;
|
||||
NETSCAPE_SPKI *req = NULL;
|
||||
|
||||
if (challenge == NULL) {
|
||||
ret_code = ERR_INVALID_ARGS;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((bits != KEYLENGTH_MEDIUM) && (bits != KEYLENGTH_MAXIMUM)) {
|
||||
ret_code = ERR_INVALID_KEY_LENGTH;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (((pkey = EVP_PKEY_new()) == NULL) ||
|
||||
((req = NETSCAPE_SPKI_new()) == NULL) ||
|
||||
((rsa = RSA_new()) == NULL) || ((bn = BN_new()) == NULL)) {
|
||||
ret_code = ERR_CONSTRUCT_NEW_DATA;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_set_word(bn, RSA_F4) ||
|
||||
!RSA_generate_key_ex(rsa, bits, bn, NULL) ||
|
||||
!EVP_PKEY_assign_RSA(pkey, rsa)) {
|
||||
ret_code = ERR_RSA_KEYGEN;
|
||||
goto err;
|
||||
}
|
||||
|
||||
rsa = NULL;
|
||||
ASN1_STRING_set(req->spkac->challenge, challenge, (int)strlen(challenge));
|
||||
NETSCAPE_SPKI_set_pubkey(req, pkey);
|
||||
NETSCAPE_SPKI_sign(req, pkey, EVP_md5());
|
||||
spkstr = NETSCAPE_SPKI_b64_encode(req);
|
||||
|
||||
if ((strlcpy(reply, spkstr, REPLY_MAX)) < REPLY_MAX) {
|
||||
save_in_store(pkey);
|
||||
} else {
|
||||
ret_code = ERR_SPKAC_TOO_LONG;
|
||||
}
|
||||
|
||||
err:
|
||||
if (rsa) RSA_free(rsa);
|
||||
if (bn) BN_free(bn);
|
||||
if (req) NETSCAPE_SPKI_free(req);
|
||||
if (pkey) EVP_PKEY_free(pkey);
|
||||
if (spkstr) OPENSSL_free(spkstr);
|
||||
if ((ret_code > 0) && (ret_code < ERR_MAXIMUM)) LOGE(emsg[ret_code]);
|
||||
return -ret_code;
|
||||
}
|
||||
|
||||
PKCS12 *get_p12_handle(const char *buf, int bufLen)
|
||||
{
|
||||
BIO *bp = NULL;
|
||||
PKCS12 *p12 = NULL;
|
||||
|
||||
if (!buf || (bufLen < 1) || (buf[0] != 48)) goto err;
|
||||
|
||||
bp = BIO_new(BIO_s_mem());
|
||||
if (!bp) goto err;
|
||||
|
||||
if (!BIO_write(bp, buf, bufLen)) goto err;
|
||||
|
||||
p12 = d2i_PKCS12_bio(bp, NULL);
|
||||
|
||||
err:
|
||||
if (bp) BIO_free(bp);
|
||||
return p12;
|
||||
}
|
||||
|
||||
PKCS12_KEYSTORE *get_pkcs12_keystore_handle(const char *buf, int bufLen,
|
||||
const char *passwd)
|
||||
{
|
||||
PKCS12_KEYSTORE *p12store = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
X509 *cert = NULL;
|
||||
STACK_OF(X509) *certs = NULL;
|
||||
PKCS12 *p12 = get_p12_handle(buf, bufLen);
|
||||
|
||||
if (p12 == NULL) return NULL;
|
||||
if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) {
|
||||
LOGE("Can not parse PKCS12 content");
|
||||
PKCS12_free(p12);
|
||||
return NULL;
|
||||
}
|
||||
if ((p12store = malloc(sizeof(PKCS12_KEYSTORE))) == NULL) {
|
||||
if (cert) X509_free(cert);
|
||||
if (pkey) EVP_PKEY_free(pkey);
|
||||
if (certs) sk_X509_free(certs);
|
||||
}
|
||||
p12store->p12 = p12;
|
||||
p12store->pkey = pkey;
|
||||
p12store->cert = cert;
|
||||
p12store->certs = certs;
|
||||
return p12store;
|
||||
}
|
||||
|
||||
void free_pkcs12_keystore(PKCS12_KEYSTORE *p12store)
|
||||
{
|
||||
if (p12store != NULL) {
|
||||
if (p12store->cert) X509_free(p12store->cert);
|
||||
if (p12store->pkey) EVP_PKEY_free(p12store->pkey);
|
||||
if (p12store->certs) sk_X509_free(p12store->certs);
|
||||
free(p12store);
|
||||
}
|
||||
}
|
||||
|
||||
int is_pkcs12(const char *buf, int bufLen)
|
||||
{
|
||||
int ret = 0;
|
||||
PKCS12 *p12 = get_p12_handle(buf, bufLen);
|
||||
if (p12 != NULL) ret = 1;
|
||||
PKCS12_free(p12);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int convert_to_pem(void *data, int is_cert, char *buf, int size)
|
||||
{
|
||||
int len = 0;
|
||||
BIO *bio = NULL;
|
||||
|
||||
if (data == NULL) return -1;
|
||||
|
||||
if ((bio = BIO_new(BIO_s_mem())) == NULL) goto err;
|
||||
if (is_cert) {
|
||||
if ((len = PEM_write_bio_X509(bio, (X509*)data)) == 0) {
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if ((len = PEM_write_bio_PrivateKey(bio, (EVP_PKEY *)data, NULL,
|
||||
NULL, 0, NULL, NULL)) == 0) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (len < size && (len = BIO_read(bio, buf, size - 1)) > 0) {
|
||||
buf[len] = 0;
|
||||
}
|
||||
err:
|
||||
if (bio) BIO_free(bio);
|
||||
return len;
|
||||
}
|
||||
|
||||
int get_pkcs12_certificate(PKCS12_KEYSTORE *p12store, char *buf, int size)
|
||||
{
|
||||
if ((p12store != NULL) && (p12store->cert != NULL)) {
|
||||
int len = convert_to_pem((void*)p12store->cert, 1, buf, size);
|
||||
return (len == 0) ? -1 : 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int get_pkcs12_private_key(PKCS12_KEYSTORE *p12store, char *buf, int size)
|
||||
{
|
||||
if ((p12store != NULL) && (p12store->pkey != NULL)) {
|
||||
int len = convert_to_pem((void*)p12store->pkey, 0, buf, size);
|
||||
return (len == 0) ? -1 : 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pop_pkcs12_certs_stack(PKCS12_KEYSTORE *p12store, char *buf, int size)
|
||||
{
|
||||
X509 *cert = NULL;
|
||||
int len = 0;
|
||||
|
||||
if ((p12store != NULL) && (p12store->certs != NULL)) {
|
||||
while (((cert = sk_X509_pop(p12store->certs)) != NULL) && (len < size)) {
|
||||
int s = convert_to_pem((void*)cert, 1, buf + len, size - len);
|
||||
if (s == 0) {
|
||||
LOGE("buffer size is too small. len=%d size=%d\n", len, size);
|
||||
return -1;
|
||||
}
|
||||
len += s;
|
||||
X509_free(cert);
|
||||
}
|
||||
return (len == 0) ? -1 : 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
X509* parse_cert(const char *buf, int bufLen)
|
||||
{
|
||||
X509 *cert = NULL;
|
||||
BIO *bp = NULL;
|
||||
|
||||
if(!buf || bufLen < 1)
|
||||
return NULL;
|
||||
|
||||
bp = BIO_new(BIO_s_mem());
|
||||
if (!bp) goto err;
|
||||
|
||||
if (!BIO_write(bp, buf, bufLen)) goto err;
|
||||
|
||||
cert = PEM_read_bio_X509(bp, NULL, NULL, NULL);
|
||||
if (!cert) {
|
||||
BIO_free(bp);
|
||||
if((bp = BIO_new(BIO_s_mem())) == NULL) goto err;
|
||||
|
||||
if(!BIO_write(bp, (char *) buf, bufLen)) goto err;
|
||||
cert = d2i_X509_bio(bp, NULL);
|
||||
}
|
||||
|
||||
err:
|
||||
if (bp) BIO_free(bp);
|
||||
return cert;
|
||||
}
|
||||
|
||||
static int get_distinct_name(X509_NAME *dname, char *buf, int size)
|
||||
{
|
||||
int i, len;
|
||||
char *p, *name;
|
||||
|
||||
if (X509_NAME_oneline(dname, buf, size) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
name = strstr(buf, "/CN=");
|
||||
p = name = name ? (name + 4) : buf;
|
||||
while (*p != 0) {
|
||||
if (*p == ' ') *p = '_';
|
||||
if (*p == '/') {
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_cert_name(X509 *cert, char *buf, int size)
|
||||
{
|
||||
if (!cert) return -1;
|
||||
return get_distinct_name(X509_get_subject_name(cert), buf, size);
|
||||
}
|
||||
|
||||
int get_issuer_name(X509 *cert, char *buf, int size)
|
||||
{
|
||||
if (!cert) return -1;
|
||||
return get_distinct_name(X509_get_issuer_name(cert), buf, size);
|
||||
}
|
||||
|
||||
int is_ca_cert(X509 *cert)
|
||||
{
|
||||
int ret = 0;
|
||||
BASIC_CONSTRAINTS *bs = (BASIC_CONSTRAINTS *)
|
||||
X509_get_ext_d2i(cert, NID_basic_constraints, NULL, NULL);
|
||||
if (bs != NULL) ret = bs->ca;
|
||||
if (bs) BASIC_CONSTRAINTS_free(bs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_private_key_pem(X509 *cert, char *buf, int size)
|
||||
{
|
||||
int len = 0;
|
||||
BIO *bio = NULL;
|
||||
EVP_PKEY *pkey = get_pkey_from_store(cert);
|
||||
|
||||
if (pkey == NULL) return -1;
|
||||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
if ((bio = BIO_new(BIO_s_mem())) == NULL) goto err;
|
||||
if (!PEM_write_bio_PrivateKey(bio, pkey, NULL,NULL,0,NULL, NULL)) {
|
||||
goto err;
|
||||
}
|
||||
if ((len = BIO_read(bio, buf, size - 1)) > 0) {
|
||||
buf[len] = 0;
|
||||
}
|
||||
err:
|
||||
if (bio) BIO_free(bio);
|
||||
return (len == 0) ? -1 : 0;
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
|
||||
#ifndef __CERT_H__
|
||||
#define __CERT_H__
|
||||
|
||||
#define ANDROID_KEYSTORE "Android Keystore"
|
||||
#define KEYGEN_STORE_SIZE 5
|
||||
#define KEYLENGTH_MEDIUM 1024
|
||||
#define KEYLENGTH_MAXIMUM 2048
|
||||
#define MAX_CERT_NAME_LEN 128
|
||||
#define MAX_PEM_LENGTH 4096
|
||||
#define REPLY_MAX MAX_PEM_LENGTH
|
||||
|
||||
|
||||
#define STR(token) #token
|
||||
#define ERR_INVALID_KEY_LENGTH 1
|
||||
#define ERR_CONSTRUCT_NEW_DATA 2
|
||||
#define ERR_RSA_KEYGEN 3
|
||||
#define ERR_X509_PROCESS 4
|
||||
#define ERR_SPKAC_TOO_LONG 5
|
||||
#define ERR_INVALID_ARGS 6
|
||||
#define ERR_MAXIMUM 7
|
||||
|
||||
typedef struct {
|
||||
EVP_PKEY *pkey;
|
||||
unsigned char *public_key;
|
||||
int key_len;
|
||||
} PKEY_STORE;
|
||||
|
||||
typedef struct {
|
||||
PKCS12 *p12;
|
||||
EVP_PKEY *pkey;
|
||||
X509 *cert;
|
||||
STACK_OF(X509) *certs;
|
||||
} PKCS12_KEYSTORE;
|
||||
|
||||
#define PKEY_STORE_free(x) { \
|
||||
if(x.pkey) EVP_PKEY_free(x.pkey); \
|
||||
if(x.public_key) free(x.public_key); \
|
||||
}
|
||||
|
||||
#define nelem(x) (sizeof (x) / sizeof *(x))
|
||||
|
||||
int gen_csr(int bits, const char *organizations, char reply[REPLY_MAX]);
|
||||
PKCS12_KEYSTORE *get_pkcs12_keystore_handle(const char *buf, int bufLen,
|
||||
const char *passwd);
|
||||
int get_pkcs12_certificate(PKCS12_KEYSTORE *p12store, char *buf, int size);
|
||||
int get_pkcs12_private_key(PKCS12_KEYSTORE *p12store, char *buf, int size);
|
||||
int pop_pkcs12_certs_stack(PKCS12_KEYSTORE *p12store, char *buf, int size);
|
||||
void free_pkcs12_keystore(PKCS12_KEYSTORE *p12store);
|
||||
int is_pkcs12(const char *buf, int bufLen);
|
||||
X509 *parse_cert(const char *buf, int bufLen);
|
||||
int get_cert_name(X509 *cert, char *buf, int size);
|
||||
int get_issuer_name(X509 *cert, char *buf, int size);
|
||||
int is_ca_cert(X509 *cert);
|
||||
int get_private_key_pem(X509 *cert, char *buf, int size);
|
||||
|
||||
#endif
|
||||
@@ -1,269 +0,0 @@
|
||||
/*
|
||||
**
|
||||
** 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;
|
||||
}
|
||||
Reference in New Issue
Block a user