summaryrefslogtreecommitdiffstats
path: root/keystore/java
diff options
context:
space:
mode:
Diffstat (limited to 'keystore/java')
-rw-r--r--keystore/java/android/security/Credentials.java32
-rw-r--r--keystore/java/android/security/IKeyChainService.aidl2
-rw-r--r--keystore/java/android/security/KeyChain.java28
-rw-r--r--keystore/java/android/security/KeyStore.java72
4 files changed, 118 insertions, 16 deletions
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index f75208d..68ba2b1 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -26,11 +26,13 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charsets;
import java.security.KeyPair;
+import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
@@ -73,6 +75,36 @@ public class Credentials {
public static final String EXTENSION_PFX = ".pfx";
/**
+ * Intent extra: name for the user's private key.
+ */
+ public static final String EXTRA_USER_PRIVATE_KEY_NAME = "user_private_key_name";
+
+ /**
+ * Intent extra: data for the user's private key in PEM-encoded PKCS#8.
+ */
+ public static final String EXTRA_USER_PRIVATE_KEY_DATA = "user_private_key_data";
+
+ /**
+ * Intent extra: name for the user's certificate.
+ */
+ public static final String EXTRA_USER_CERTIFICATE_NAME = "user_certificate_name";
+
+ /**
+ * Intent extra: data for the user's certificate in PEM-encoded X.509.
+ */
+ public static final String EXTRA_USER_CERTIFICATE_DATA = "user_certificate_data";
+
+ /**
+ * Intent extra: name for CA certificate chain
+ */
+ public static final String EXTRA_CA_CERTIFICATES_NAME = "ca_certificates_name";
+
+ /**
+ * Intent extra: data for CA certificate chain in PEM-encoded X.509.
+ */
+ public static final String EXTRA_CA_CERTIFICATES_DATA = "ca_certificates_data";
+
+ /**
* Convert objects to a PEM format, which is used for
* CA_CERTIFICATE, USER_CERTIFICATE, and USER_PRIVATE_KEY
* entries.
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index f38f6ce..60fd7f7 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -23,7 +23,7 @@ package android.security;
*/
interface IKeyChainService {
// APIs used by KeyChain
- byte[] getPrivateKey(String alias);
+ String requestPrivateKey(String alias);
byte[] getCertificate(String alias);
// APIs used by CertInstaller
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index fe03437..483ccb2 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -27,6 +27,7 @@ import android.os.RemoteException;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.IOException;
+import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.Principal;
import java.security.PrivateKey;
@@ -39,6 +40,8 @@ import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import libcore.util.Objects;
+
+import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
import org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore;
/**
@@ -301,14 +304,21 @@ public final class KeyChain {
}
KeyChainConnection keyChainConnection = bind(context);
try {
- IKeyChainService keyChainService = keyChainConnection.getService();
- byte[] privateKeyBytes = keyChainService.getPrivateKey(alias);
- return toPrivateKey(privateKeyBytes);
+ final IKeyChainService keyChainService = keyChainConnection.getService();
+ final String keyId = keyChainService.requestPrivateKey(alias);
+ if (keyId == null) {
+ throw new KeyChainException("keystore had a problem");
+ }
+
+ final OpenSSLEngine engine = OpenSSLEngine.getInstance("keystore");
+ return engine.getPrivateKeyById(keyId);
} catch (RemoteException e) {
throw new KeyChainException(e);
} catch (RuntimeException e) {
// only certain RuntimeExceptions can be propagated across the IKeyChainService call
throw new KeyChainException(e);
+ } catch (InvalidKeyException e) {
+ throw new KeyChainException(e);
} finally {
keyChainConnection.close();
}
@@ -356,18 +366,6 @@ public final class KeyChain {
}
}
- private static PrivateKey toPrivateKey(byte[] bytes) {
- if (bytes == null) {
- throw new IllegalArgumentException("bytes == null");
- }
- try {
- KeyPair keyPair = (KeyPair) Credentials.convertFromPem(bytes).get(0);
- return keyPair.getPrivate();
- } catch (IOException e) {
- throw new AssertionError(e);
- }
- }
-
private static X509Certificate toCertificate(byte[] bytes) {
if (bytes == null) {
throw new IllegalArgumentException("bytes == null");
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 9058cae..a32e469 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -155,6 +155,78 @@ public class KeyStore {
return mError == KEY_NOT_FOUND;
}
+ private boolean generate(byte[] key) {
+ execute('a', key);
+ return mError == NO_ERROR;
+ }
+
+ public boolean generate(String key) {
+ return generate(getBytes(key));
+ }
+
+ private boolean importKey(byte[] keyName, byte[] key) {
+ execute('m', keyName, key);
+ return mError == NO_ERROR;
+ }
+
+ public boolean importKey(String keyName, byte[] key) {
+ return importKey(getBytes(keyName), key);
+ }
+
+ private byte[] getPubkey(byte[] key) {
+ ArrayList<byte[]> values = execute('b', key);
+ return (values == null || values.isEmpty()) ? null : values.get(0);
+ }
+
+ public byte[] getPubkey(String key) {
+ return getPubkey(getBytes(key));
+ }
+
+ private boolean delKey(byte[] key) {
+ execute('k', key);
+ return mError == NO_ERROR;
+ }
+
+ public boolean delKey(String key) {
+ return delKey(getBytes(key));
+ }
+
+ private byte[] sign(byte[] keyName, byte[] data) {
+ final ArrayList<byte[]> values = execute('n', keyName, data);
+ return (values == null || values.isEmpty()) ? null : values.get(0);
+ }
+
+ public byte[] sign(String key, byte[] data) {
+ return sign(getBytes(key), data);
+ }
+
+ private boolean verify(byte[] keyName, byte[] data, byte[] signature) {
+ execute('v', keyName, data, signature);
+ return mError == NO_ERROR;
+ }
+
+ public boolean verify(String key, byte[] data, byte[] signature) {
+ return verify(getBytes(key), data, signature);
+ }
+
+ private boolean grant(byte[] key, byte[] uid) {
+ execute('x', key, uid);
+ return mError == NO_ERROR;
+ }
+
+ public boolean grant(String key, int uid) {
+ return grant(getBytes(key), Integer.toString(uid).getBytes());
+ }
+
+ private boolean ungrant(byte[] key, byte[] uid) {
+ execute('y', key, uid);
+ return mError == NO_ERROR;
+ }
+
+ public boolean ungrant(String key, int uid) {
+ return ungrant(getBytes(key), Integer.toString(uid).getBytes());
+ }
+
public int getLastError() {
return mError;
}