am e1cf7583: Merge "Don\'t offer crypto ops for public keys of trusted cert entries." into mnc-dev
* commit 'e1cf75833b1a8d19c040af4ecffde3119cc7a855': Don't offer crypto ops for public keys of trusted cert entries.
This commit is contained in:
@@ -140,21 +140,64 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
|||||||
throw new NullPointerException("alias == null");
|
throw new NullPointerException("alias == null");
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] certificate = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
|
byte[] encodedCert = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
|
||||||
if (certificate != null) {
|
if (encodedCert != null) {
|
||||||
return wrapIntoKeyStoreCertificate(
|
return getCertificateForPrivateKeyEntry(alias, encodedCert);
|
||||||
Credentials.USER_PRIVATE_KEY + alias, toCertificate(certificate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
certificate = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
|
encodedCert = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
|
||||||
if (certificate != null) {
|
if (encodedCert != null) {
|
||||||
return wrapIntoKeyStoreCertificate(
|
return getCertificateForTrustedCertificateEntry(encodedCert);
|
||||||
Credentials.USER_PRIVATE_KEY + alias, toCertificate(certificate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This entry/alias does not contain a certificate.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Certificate getCertificateForTrustedCertificateEntry(byte[] encodedCert) {
|
||||||
|
// For this certificate there shouldn't be a private key in this KeyStore entry. Thus,
|
||||||
|
// there's no need to wrap this certificate as opposed to the certificate associated with
|
||||||
|
// a private key entry.
|
||||||
|
return toCertificate(encodedCert);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Certificate getCertificateForPrivateKeyEntry(String alias, byte[] encodedCert) {
|
||||||
|
// All crypto algorithms offered by Android Keystore for its private keys must also
|
||||||
|
// be offered for the corresponding public keys stored in the Android Keystore. The
|
||||||
|
// complication is that the underlying keystore service operates only on full key pairs,
|
||||||
|
// rather than just public keys or private keys. As a result, Android Keystore-backed
|
||||||
|
// crypto can only be offered for public keys for which keystore contains the
|
||||||
|
// corresponding private key. This is not the case for certificate-only entries (e.g.,
|
||||||
|
// trusted certificates).
|
||||||
|
//
|
||||||
|
// getCertificate().getPublicKey() is the only way to obtain the public key
|
||||||
|
// corresponding to the private key stored in the KeyStore. Thus, we need to make sure
|
||||||
|
// that the returned public key points to the underlying key pair / private key
|
||||||
|
// when available.
|
||||||
|
|
||||||
|
X509Certificate cert = toCertificate(encodedCert);
|
||||||
|
if (cert == null) {
|
||||||
|
// Failed to parse the certificate.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
|
||||||
|
if (mKeyStore.contains(privateKeyAlias)) {
|
||||||
|
// As expected, keystore contains the private key corresponding to this public key. Wrap
|
||||||
|
// the certificate so that its getPublicKey method returns an Android Keystore
|
||||||
|
// PublicKey. This key will delegate crypto operations involving this public key to
|
||||||
|
// Android Keystore when higher-priority providers do not offer these crypto
|
||||||
|
// operations for this key.
|
||||||
|
return wrapIntoKeyStoreCertificate(privateKeyAlias, cert);
|
||||||
|
} else {
|
||||||
|
// This KeyStore entry/alias is supposed to contain the private key corresponding to
|
||||||
|
// the public key in this certificate, but it does not for some reason. It's probably a
|
||||||
|
// bug. Let other providers handle crypto operations involving the public key returned
|
||||||
|
// by this certificate's getPublicKey.
|
||||||
|
return cert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps the provided cerificate into {@link KeyStoreX509Certificate} so that the public key
|
* Wraps the provided cerificate into {@link KeyStoreX509Certificate} so that the public key
|
||||||
* returned by the certificate contains information about the alias of the private key in
|
* returned by the certificate contains information about the alias of the private key in
|
||||||
|
|||||||
Reference in New Issue
Block a user