use of java.security.KeyStoreException in project jdk8u_jdk by JetBrains.
the class X509KeySelector method select.
/**
* Finds a key from the keystore satisfying the specified constraints.
*
* <p>This method compares data contained in {@link KeyInfo} entries
* with information stored in the <code>KeyStore</code>. The implementation
* iterates over the KeyInfo types and returns the first {@link PublicKey}
* of an X509Certificate in the keystore that is compatible with the
* specified AlgorithmMethod according to the following rules for each
* keyinfo type:
*
* X509Data X509Certificate: if it contains a <code>KeyUsage</code>
* extension that asserts the <code>digitalSignature</code> bit and
* matches an <code>X509Certificate</code> in the <code>KeyStore</code>.
* X509Data X509IssuerSerial: if the serial number and issuer DN match an
* <code>X509Certificate</code> in the <code>KeyStore</code>.
* X509Data X509SubjectName: if the subject DN matches an
* <code>X509Certificate</code> in the <code>KeyStore</code>.
* X509Data X509SKI: if the subject key identifier matches an
* <code>X509Certificate</code> in the <code>KeyStore</code>.
* KeyName: if the keyname matches an alias in the <code>KeyStore</code>.
* RetrievalMethod: supports rawX509Certificate and X509Data types. If
* rawX509Certificate type, it must match an <code>X509Certificate</code>
* in the <code>KeyStore</code>.
*
* @param keyInfo a <code>KeyInfo</code> (may be <code>null</code>)
* @param purpose the key's purpose
* @param method the algorithm method that this key is to be used for.
* Only keys that are compatible with the algorithm and meet the
* constraints of the specified algorithm should be returned.
* @param an <code>XMLCryptoContext</code> that may contain additional
* useful information for finding an appropriate key
* @return a key selector result
* @throws KeySelectorException if an exceptional condition occurs while
* attempting to find a key. Note that an inability to find a key is not
* considered an exception (<code>null</code> should be
* returned in that case). However, an error condition (ex: network
* communications failure) that prevented the <code>KeySelector</code>
* from finding a potential key should be considered an exception.
* @throws ClassCastException if the data type of <code>method</code>
* is not supported by this key selector
*/
public KeySelectorResult select(KeyInfo keyInfo, KeySelector.Purpose purpose, AlgorithmMethod method, XMLCryptoContext context) throws KeySelectorException {
SignatureMethod sm = (SignatureMethod) method;
try {
// return null if keyinfo is null or keystore is empty
if (keyInfo == null || ks.size() == 0) {
return new SimpleKeySelectorResult(null);
}
// Iterate through KeyInfo types
Iterator i = keyInfo.getContent().iterator();
while (i.hasNext()) {
XMLStructure kiType = (XMLStructure) i.next();
// check X509Data
if (kiType instanceof X509Data) {
X509Data xd = (X509Data) kiType;
KeySelectorResult ksr = x509DataSelect(xd, sm);
if (ksr != null) {
return ksr;
}
// check KeyName
} else if (kiType instanceof KeyName) {
KeyName kn = (KeyName) kiType;
Certificate cert = ks.getCertificate(kn.getName());
if (cert != null && algEquals(sm.getAlgorithm(), cert.getPublicKey().getAlgorithm())) {
return new SimpleKeySelectorResult(cert.getPublicKey());
}
// check RetrievalMethod
} else if (kiType instanceof RetrievalMethod) {
RetrievalMethod rm = (RetrievalMethod) kiType;
try {
KeySelectorResult ksr = null;
if (rm.getType().equals(X509Data.RAW_X509_CERTIFICATE_TYPE)) {
OctetStreamData data = (OctetStreamData) rm.dereference(context);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(data.getOctetStream());
ksr = certSelect(cert, sm);
} else if (rm.getType().equals(X509Data.TYPE)) {
X509Data xd = (X509Data) ((DOMRetrievalMethod) rm).dereferenceAsXMLStructure(context);
ksr = x509DataSelect(xd, sm);
} else {
// skip; keyinfo type is not supported
continue;
}
if (ksr != null) {
return ksr;
}
} catch (Exception e) {
throw new KeySelectorException(e);
}
}
}
} catch (KeyStoreException kse) {
// throw exception if keystore is uninitialized
throw new KeySelectorException(kse);
}
// return null since no match could be found
return new SimpleKeySelectorResult(null);
}
use of java.security.KeyStoreException in project android_frameworks_base by AOSPA.
the class AndroidKeyStoreSpi method engineSetEntry.
@Override
public void engineSetEntry(String alias, Entry entry, ProtectionParameter param) throws KeyStoreException {
if (entry == null) {
throw new KeyStoreException("entry == null");
}
Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid);
if (entry instanceof java.security.KeyStore.TrustedCertificateEntry) {
java.security.KeyStore.TrustedCertificateEntry trE = (java.security.KeyStore.TrustedCertificateEntry) entry;
engineSetCertificateEntry(alias, trE.getTrustedCertificate());
return;
}
if (entry instanceof PrivateKeyEntry) {
PrivateKeyEntry prE = (PrivateKeyEntry) entry;
setPrivateKeyEntry(alias, prE.getPrivateKey(), prE.getCertificateChain(), param);
} else if (entry instanceof SecretKeyEntry) {
SecretKeyEntry secE = (SecretKeyEntry) entry;
setSecretKeyEntry(alias, secE.getSecretKey(), param);
} else {
throw new KeyStoreException("Entry must be a PrivateKeyEntry, SecretKeyEntry or TrustedCertificateEntry" + "; was " + entry);
}
}
use of java.security.KeyStoreException in project android_frameworks_base by AOSPA.
the class AndroidKeyStoreSpi method setSecretKeyEntry.
private void setSecretKeyEntry(String entryAlias, SecretKey key, java.security.KeyStore.ProtectionParameter param) throws KeyStoreException {
if ((param != null) && (!(param instanceof KeyProtection))) {
throw new KeyStoreException("Unsupported protection parameter class: " + param.getClass().getName() + ". Supported: " + KeyProtection.class.getName());
}
KeyProtection params = (KeyProtection) param;
if (key instanceof AndroidKeyStoreSecretKey) {
// KeyStore-backed secret key. It cannot be duplicated into another entry and cannot
// overwrite its own entry.
String keyAliasInKeystore = ((AndroidKeyStoreSecretKey) key).getAlias();
if (keyAliasInKeystore == null) {
throw new KeyStoreException("KeyStore-backed secret key does not have an alias");
}
if (!keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)) {
throw new KeyStoreException("KeyStore-backed secret key has invalid alias: " + keyAliasInKeystore);
}
String keyEntryAlias = keyAliasInKeystore.substring(Credentials.USER_SECRET_KEY.length());
if (!entryAlias.equals(keyEntryAlias)) {
throw new KeyStoreException("Can only replace KeyStore-backed keys with same" + " alias: " + entryAlias + " != " + keyEntryAlias);
}
// This is the entry where this key is already stored. No need to do anything.
if (params != null) {
throw new KeyStoreException("Modifying KeyStore-backed key using protection" + " parameters not supported");
}
return;
}
if (params == null) {
throw new KeyStoreException("Protection parameters must be specified when importing a symmetric key");
}
// Not a KeyStore-backed secret key -- import its key material into keystore.
String keyExportFormat = key.getFormat();
if (keyExportFormat == null) {
throw new KeyStoreException("Only secret keys that export their key material are supported");
} else if (!"RAW".equals(keyExportFormat)) {
throw new KeyStoreException("Unsupported secret key material export format: " + keyExportFormat);
}
byte[] keyMaterial = key.getEncoded();
if (keyMaterial == null) {
throw new KeyStoreException("Key did not export its key material despite supporting" + " RAW format export");
}
KeymasterArguments args = new KeymasterArguments();
try {
int keymasterAlgorithm = KeyProperties.KeyAlgorithm.toKeymasterSecretKeyAlgorithm(key.getAlgorithm());
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);
int[] keymasterDigests;
if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
// JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
// implies SHA-256 digest). Because keymaster HMAC key is authorized only for one
// digest, we don't let import parameters override the digest implied by the key.
// If the parameters specify digests at all, they must specify only one digest, the
// only implied by key algorithm.
int keymasterImpliedDigest = KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
if (keymasterImpliedDigest == -1) {
throw new ProviderException("HMAC key algorithm digest unknown for key algorithm " + key.getAlgorithm());
}
keymasterDigests = new int[] { keymasterImpliedDigest };
if (params.isDigestsSpecified()) {
// Digest(s) explicitly specified in params -- check that the list consists of
// exactly one digest, the one implied by key algorithm.
int[] keymasterDigestsFromParams = KeyProperties.Digest.allToKeymaster(params.getDigests());
if ((keymasterDigestsFromParams.length != 1) || (keymasterDigestsFromParams[0] != keymasterImpliedDigest)) {
throw new KeyStoreException("Unsupported digests specification: " + Arrays.asList(params.getDigests()) + ". Only " + KeyProperties.Digest.fromKeymaster(keymasterImpliedDigest) + " supported for HMAC key algorithm " + key.getAlgorithm());
}
}
} else {
// Key algorithm does not imply a digest.
if (params.isDigestsSpecified()) {
keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
} else {
keymasterDigests = EmptyArray.INT;
}
}
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
@KeyProperties.PurposeEnum int purposes = params.getPurposes();
int[] keymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(params.getBlockModes());
if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0) && (params.isRandomizedEncryptionRequired())) {
for (int keymasterBlockMode : keymasterBlockModes) {
if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto(keymasterBlockMode)) {
throw new KeyStoreException("Randomized encryption (IND-CPA) required but may be violated by" + " block mode: " + KeyProperties.BlockMode.fromKeymaster(keymasterBlockMode) + ". See KeyProtection documentation.");
}
}
}
args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, KeyProperties.Purpose.allToKeymaster(purposes));
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes);
if (params.getSignaturePaddings().length > 0) {
throw new KeyStoreException("Signature paddings not supported for symmetric keys");
}
int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(params.getEncryptionPaddings());
args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
KeymasterUtils.addUserAuthArgs(args, params.isUserAuthenticationRequired(), params.getUserAuthenticationValidityDurationSeconds(), params.isUserAuthenticationValidWhileOnBody(), params.isInvalidatedByBiometricEnrollment());
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(args, keymasterAlgorithm, keymasterBlockModes, keymasterDigests);
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, params.getKeyValidityStart());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, params.getKeyValidityForOriginationEnd());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, params.getKeyValidityForConsumptionEnd());
if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0) && (!params.isRandomizedEncryptionRequired())) {
// Permit caller-provided IV when encrypting with this key
args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
}
} catch (IllegalArgumentException | IllegalStateException e) {
throw new KeyStoreException(e);
}
Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias, mUid);
String keyAliasInKeystore = Credentials.USER_SECRET_KEY + entryAlias;
int errorCode = mKeyStore.importKey(keyAliasInKeystore, args, KeymasterDefs.KM_KEY_FORMAT_RAW, keyMaterial, mUid, // flags
0, new KeyCharacteristics());
if (errorCode != KeyStore.NO_ERROR) {
throw new KeyStoreException("Failed to import secret key. Keystore error code: " + errorCode);
}
}
use of java.security.KeyStoreException in project android_frameworks_base by AOSPA.
the class LockSettingsService method migrateOldData.
private void migrateOldData() {
try {
// root user.
if (getString("migrated", null, 0) == null) {
final ContentResolver cr = mContext.getContentResolver();
for (String validSetting : VALID_SETTINGS) {
String value = Settings.Secure.getString(cr, validSetting);
if (value != null) {
setString(validSetting, value, 0);
}
}
// No need to move the password / pattern files. They're already in the right place.
setString("migrated", "true", 0);
Slog.i(TAG, "Migrated lock settings to new location");
}
// These Settings changed after multi-user was enabled, hence need to be moved per user.
if (getString("migrated_user_specific", null, 0) == null) {
final ContentResolver cr = mContext.getContentResolver();
List<UserInfo> users = mUserManager.getUsers();
for (int user = 0; user < users.size(); user++) {
// Migrate owner info
final int userId = users.get(user).id;
final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
if (!TextUtils.isEmpty(ownerInfo)) {
setString(OWNER_INFO, ownerInfo, userId);
Settings.Secure.putStringForUser(cr, OWNER_INFO, "", userId);
}
// Migrate owner info enabled. Note there was a bug where older platforms only
// stored this value if the checkbox was toggled at least once. The code detects
// this case by handling the exception.
final String OWNER_INFO_ENABLED = Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
boolean enabled;
try {
int ivalue = Settings.Secure.getIntForUser(cr, OWNER_INFO_ENABLED, userId);
enabled = ivalue != 0;
setLong(OWNER_INFO_ENABLED, enabled ? 1 : 0, userId);
} catch (SettingNotFoundException e) {
// Setting was never stored. Store it if the string is not empty.
if (!TextUtils.isEmpty(ownerInfo)) {
setLong(OWNER_INFO_ENABLED, 1, userId);
}
}
Settings.Secure.putIntForUser(cr, OWNER_INFO_ENABLED, 0, userId);
}
// No need to move the password / pattern files. They're already in the right place.
setString("migrated_user_specific", "true", 0);
Slog.i(TAG, "Migrated per-user lock settings to new location");
}
// Migrates biometric weak such that the fallback mechanism becomes the primary.
if (getString("migrated_biometric_weak", null, 0) == null) {
List<UserInfo> users = mUserManager.getUsers();
for (int i = 0; i < users.size(); i++) {
int userId = users.get(i).id;
long type = getLong(LockPatternUtils.PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
long alternateType = getLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
if (type == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
setLong(LockPatternUtils.PASSWORD_TYPE_KEY, alternateType, userId);
}
setLong(LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
}
setString("migrated_biometric_weak", "true", 0);
Slog.i(TAG, "Migrated biometric weak to use the fallback instead");
}
// user we disable the flag to remain consistent.
if (getString("migrated_lockscreen_disabled", null, 0) == null) {
final List<UserInfo> users = mUserManager.getUsers();
final int userCount = users.size();
int switchableUsers = 0;
for (int i = 0; i < userCount; i++) {
if (users.get(i).supportsSwitchTo()) {
switchableUsers++;
}
}
if (switchableUsers > 1) {
for (int i = 0; i < userCount; i++) {
int id = users.get(i).id;
if (getBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id)) {
setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
}
}
}
setString("migrated_lockscreen_disabled", "true", 0);
Slog.i(TAG, "Migrated lockscreen disabled flag");
}
final List<UserInfo> users = mUserManager.getUsers();
for (int i = 0; i < users.size(); i++) {
final UserInfo userInfo = users.get(i);
if (userInfo.isManagedProfile() && mStorage.hasChildProfileLock(userInfo.id)) {
// When managed profile has a unified lock, the password quality stored has 2
// possibilities only.
// 1). PASSWORD_QUALITY_UNSPECIFIED, which is upgraded from dp2, and we are
// going to set it back to PASSWORD_QUALITY_ALPHANUMERIC.
// 2). PASSWORD_QUALITY_ALPHANUMERIC, which is the actual password quality for
// unified lock.
final long quality = getLong(LockPatternUtils.PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userInfo.id);
if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
// Only possible when it's upgraded from nyc dp3
Slog.i(TAG, "Migrated tied profile lock type");
setLong(LockPatternUtils.PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, userInfo.id);
} else if (quality != DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC) {
// It should not happen
Slog.e(TAG, "Invalid tied profile lock type: " + quality);
}
}
try {
final String alias = LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userInfo.id;
java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
if (keyStore.containsAlias(alias)) {
keyStore.deleteEntry(alias);
}
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
Slog.e(TAG, "Unable to remove tied profile key", e);
}
}
boolean isWatch = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
// and device management the lockscreen must be re-enabled now for users that upgrade.
if (isWatch && getString("migrated_wear_lockscreen_disabled", null, 0) == null) {
final int userCount = users.size();
for (int i = 0; i < userCount; i++) {
int id = users.get(i).id;
setBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, id);
}
setString("migrated_wear_lockscreen_disabled", "true", 0);
Slog.i(TAG, "Migrated lockscreen_disabled for Wear devices");
}
} catch (RemoteException re) {
Slog.e(TAG, "Unable to migrate old data", re);
}
}
use of java.security.KeyStoreException in project android_frameworks_base by AOSPA.
the class LockSettingsService method verifyTiedProfileChallenge.
@Override
public VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern, long challenge, int userId) throws RemoteException {
checkPasswordReadPermission(userId);
if (!isManagedProfileWithUnifiedLock(userId)) {
throw new RemoteException("User id must be managed profile with unified lock");
}
final int parentProfileId = mUserManager.getProfileParent(userId).id;
// Unlock parent by using parent's challenge
final VerifyCredentialResponse parentResponse = isPattern ? doVerifyPattern(password, true, challenge, parentProfileId, null) : doVerifyPassword(password, true, challenge, parentProfileId, null);
if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
// Failed, just return parent's response
return parentResponse;
}
try {
// Unlock work profile, and work profile with unified lock must use password only
return doVerifyPassword(getDecryptedPasswordForTiedProfile(userId), true, challenge, userId, null);
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException | CertificateException | IOException e) {
Slog.e(TAG, "Failed to decrypt child profile key", e);
throw new RemoteException("Unable to get tied profile token");
}
}
Aggregations