diff options
-rw-r--r-- | keystore/java/android/security/CertTool.java | 357 | ||||
-rw-r--r-- | keystore/java/android/security/Keystore.java | 133 | ||||
-rw-r--r-- | keystore/jni/Android.mk | 31 | ||||
-rw-r--r-- | keystore/jni/cert.c | 344 | ||||
-rw-r--r-- | keystore/jni/cert.h | 73 | ||||
-rw-r--r-- | keystore/jni/certtool.c | 269 |
6 files changed, 0 insertions, 1207 deletions
diff --git a/keystore/java/android/security/CertTool.java b/keystore/java/android/security/CertTool.java deleted file mode 100644 index 88d6e3d..0000000 --- a/keystore/java/android/security/CertTool.java +++ /dev/null @@ -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); - } -} diff --git a/keystore/java/android/security/Keystore.java b/keystore/java/android/security/Keystore.java deleted file mode 100644 index b47ae12..0000000 --- a/keystore/java/android/security/Keystore.java +++ /dev/null @@ -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; - } - } -} diff --git a/keystore/jni/Android.mk b/keystore/jni/Android.mk deleted file mode 100644 index 92c2d6d..0000000 --- a/keystore/jni/Android.mk +++ /dev/null @@ -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) diff --git a/keystore/jni/cert.c b/keystore/jni/cert.c deleted file mode 100644 index 90f872e..0000000 --- a/keystore/jni/cert.c +++ /dev/null @@ -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; -} diff --git a/keystore/jni/cert.h b/keystore/jni/cert.h deleted file mode 100644 index a9e1a9e..0000000 --- a/keystore/jni/cert.h +++ /dev/null @@ -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 diff --git a/keystore/jni/certtool.c b/keystore/jni/certtool.c deleted file mode 100644 index b36b34a..0000000 --- a/keystore/jni/certtool.c +++ /dev/null @@ -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; -} |