summaryrefslogtreecommitdiff
path: root/keystore/java/android/security/AndroidKeyStore.java
diff options
context:
space:
mode:
Diffstat (limited to 'keystore/java/android/security/AndroidKeyStore.java')
-rw-r--r--keystore/java/android/security/AndroidKeyStore.java58
1 files changed, 46 insertions, 12 deletions
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
index e19217f25a2d..7b6e54009411 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -16,7 +16,9 @@
package android.security;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
import android.util.Log;
@@ -193,17 +195,41 @@ public class AndroidKeyStore extends KeyStoreSpi {
private void setPrivateKeyEntry(String alias, PrivateKey key, Certificate[] chain)
throws KeyStoreException {
- // Make sure the PrivateKey format is the one we support.
- final String keyFormat = key.getFormat();
- if ((keyFormat == null) || (!"PKCS#8".equals(keyFormat))) {
- throw new KeyStoreException(
- "Only PrivateKeys that can be encoded into PKCS#8 are supported");
+ byte[] keyBytes = null;
+
+ final String pkeyAlias;
+ if (key instanceof OpenSSLRSAPrivateKey) {
+ pkeyAlias = ((OpenSSLRSAPrivateKey) key).getPkeyAlias();
+ } else if (key instanceof OpenSSLDSAPrivateKey) {
+ pkeyAlias = ((OpenSSLDSAPrivateKey) key).getPkeyAlias();
+ } else {
+ pkeyAlias = null;
}
- // Make sure we can actually encode the key.
- final byte[] keyBytes = key.getEncoded();
- if (keyBytes == null) {
- throw new KeyStoreException("PrivateKey has no encoding");
+ final boolean shouldReplacePrivateKey;
+ if (pkeyAlias != null && pkeyAlias.startsWith(Credentials.USER_PRIVATE_KEY)) {
+ final String keySubalias = pkeyAlias.substring(Credentials.USER_PRIVATE_KEY.length());
+ if (!alias.equals(keySubalias)) {
+ throw new KeyStoreException("Can only replace keys with same alias: " + alias
+ + " != " + keySubalias);
+ }
+
+ shouldReplacePrivateKey = false;
+ } else {
+ // Make sure the PrivateKey format is the one we support.
+ final String keyFormat = key.getFormat();
+ if ((keyFormat == null) || (!"PKCS#8".equals(keyFormat))) {
+ throw new KeyStoreException(
+ "Only PrivateKeys that can be encoded into PKCS#8 are supported");
+ }
+
+ // Make sure we can actually encode the key.
+ keyBytes = key.getEncoded();
+ if (keyBytes == null) {
+ throw new KeyStoreException("PrivateKey has no encoding");
+ }
+
+ shouldReplacePrivateKey = true;
}
// Make sure the chain exists since this is a PrivateKey
@@ -273,17 +299,25 @@ public class AndroidKeyStore extends KeyStoreSpi {
}
/*
- * Make sure we clear out all the types we know about before trying to
+ * Make sure we clear out all the appropriate types before trying to
* write.
*/
- Credentials.deleteAllTypesForAlias(mKeyStore, alias);
+ if (shouldReplacePrivateKey) {
+ Credentials.deleteAllTypesForAlias(mKeyStore, alias);
+ } else {
+ Credentials.deleteCertificateTypesForAlias(mKeyStore, alias);
+ }
- if (!mKeyStore.importKey(Credentials.USER_PRIVATE_KEY + alias, keyBytes)) {
+ if (shouldReplacePrivateKey
+ && !mKeyStore.importKey(Credentials.USER_PRIVATE_KEY + alias, keyBytes)) {
+ Credentials.deleteAllTypesForAlias(mKeyStore, alias);
throw new KeyStoreException("Couldn't put private key in keystore");
} else if (!mKeyStore.put(Credentials.USER_CERTIFICATE + alias, userCertBytes)) {
+ Credentials.deleteAllTypesForAlias(mKeyStore, alias);
throw new KeyStoreException("Couldn't put certificate #1 in keystore");
} else if (chainBytes != null
&& !mKeyStore.put(Credentials.CA_CERTIFICATE + alias, chainBytes)) {
+ Credentials.deleteAllTypesForAlias(mKeyStore, alias);
throw new KeyStoreException("Couldn't put certificate chain in keystore");
}
}