Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46a41e0e authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 26786 into eclair

* changes:
  Remove old keystore and related files.
parents 7c5c6076 ec05c46e
Loading
Loading
Loading
Loading
+0 −357
Original line number Diff line number Diff line
/*
 * 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);
    }
}
+0 −133
Original line number Diff line number Diff line
/*
 * 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;
        }
    }
}

keystore/jni/Android.mk

deleted100644 → 0
+0 −31
Original line number Diff line number Diff line
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)

keystore/jni/cert.c

deleted100644 → 0
+0 −344

File deleted.

Preview size limit exceeded, changes collapsed.

keystore/jni/cert.h

deleted100644 → 0
+0 −73
Original line number Diff line number Diff line
/*
**
** 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
Loading