diff options
Diffstat (limited to 'keystore/java')
| -rw-r--r-- | keystore/java/android/security/Credentials.java | 32 | ||||
| -rw-r--r-- | keystore/java/android/security/IKeyChainService.aidl | 2 | ||||
| -rw-r--r-- | keystore/java/android/security/KeyChain.java | 28 | ||||
| -rw-r--r-- | keystore/java/android/security/KeyStore.java | 72 |
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; } |
