18c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin/* 28c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * Copyright (C) 2015 The Android Open Source Project 38c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * 48c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * Licensed under the Apache License, Version 2.0 (the "License"); 58c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * you may not use this file except in compliance with the License. 68c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * You may obtain a copy of the License at 78c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * 88c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * http://www.apache.org/licenses/LICENSE-2.0 98c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * 108c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * Unless required by applicable law or agreed to in writing, software 118c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * distributed under the License is distributed on an "AS IS" BASIS, 128c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * See the License for the specific language governing permissions and 148c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * limitations under the License. 158c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin */ 168c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin 17dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubinpackage android.security.keystore; 188c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin 19dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubinimport android.security.KeyStore; 208c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubinimport android.security.keymaster.KeymasterDefs; 218c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin 227cbcfd4fc1e538bd391a20cdd00dd1494ace2d0eAlex Klyubinimport libcore.util.EmptyArray; 237cbcfd4fc1e538bd391a20cdd00dd1494ace2d0eAlex Klyubin 248c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubinimport java.security.GeneralSecurityException; 258c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubinimport java.security.InvalidAlgorithmParameterException; 268c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubinimport java.security.InvalidKeyException; 2783a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubinimport java.security.SecureRandom; 288c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin 298c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin/** 308c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * Assorted utility methods for implementing crypto operations on top of KeyStore. 318c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * 328c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * @hide 338c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin */ 348c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubinabstract class KeyStoreCryptoOperationUtils { 3583a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin 3683a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin private static volatile SecureRandom sRng; 3783a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin 388c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin private KeyStoreCryptoOperationUtils() {} 398c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin 408c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin /** 418c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * Returns the {@link InvalidKeyException} to be thrown by the {@code init} method of 428c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * the crypto operation in response to {@code KeyStore.begin} operation or {@code null} if 438c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * the {@code init} method should succeed. 448c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin */ 458c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin static InvalidKeyException getInvalidKeyExceptionForInit( 46dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin KeyStore keyStore, AndroidKeyStoreKey key, int beginOpResultCode) { 478c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin if (beginOpResultCode == KeyStore.NO_ERROR) { 488c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin return null; 498c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin } 508c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin 518c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin // An error occured. However, some errors should not lead to init throwing an exception. 528c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin // See below. 538c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin InvalidKeyException e = 548c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin keyStore.getInvalidKeyException(key.getAlias(), beginOpResultCode); 558c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin switch (beginOpResultCode) { 568c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin case KeyStore.OP_AUTH_NEEDED: 578c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin // Operation needs to be authorized by authenticating the user. Don't throw an 588c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin // exception is such authentication is possible for this key 598c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin // (UserNotAuthenticatedException). An example of when it's not possible is where 608c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin // the key is permanently invalidated (KeyPermanentlyInvalidatedException). 618c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin if (e instanceof UserNotAuthenticatedException) { 628c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin return null; 638c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin } 648c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin break; 658c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin } 668c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin return e; 678c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin } 688c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin 698c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin /** 708c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * Returns the exception to be thrown by the {@code Cipher.init} method of the crypto operation 718c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * in response to {@code KeyStore.begin} operation or {@code null} if the {@code init} method 728c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin * should succeed. 738c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin */ 74dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin public static GeneralSecurityException getExceptionForCipherInit( 75dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin KeyStore keyStore, AndroidKeyStoreKey key, int beginOpResultCode) { 768c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin if (beginOpResultCode == KeyStore.NO_ERROR) { 778c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin return null; 788c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin } 798c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin 808c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin // Cipher-specific cases 818c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin switch (beginOpResultCode) { 828c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin case KeymasterDefs.KM_ERROR_INVALID_NONCE: 838c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin return new InvalidAlgorithmParameterException("Invalid IV"); 846358b881f2e483a4d96ff440fb19136e2d25e893Alex Klyubin case KeymasterDefs.KM_ERROR_CALLER_NONCE_PROHIBITED: 856358b881f2e483a4d96ff440fb19136e2d25e893Alex Klyubin return new InvalidAlgorithmParameterException("Caller-provided IV not permitted"); 868c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin } 878c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin 888c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin // General cases 898c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin return getInvalidKeyExceptionForInit(keyStore, key, beginOpResultCode); 908c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin } 9183a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin 9283a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin /** 9383a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin * Returns the requested number of random bytes to mix into keystore/keymaster RNG. 9483a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin * 9583a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin * @param rng RNG from which to obtain the random bytes or {@code null} for the platform-default 9683a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin * RNG. 9783a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin */ 9883a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin static byte[] getRandomBytesToMixIntoKeystoreRng(SecureRandom rng, int sizeBytes) { 997cbcfd4fc1e538bd391a20cdd00dd1494ace2d0eAlex Klyubin if (sizeBytes <= 0) { 1007cbcfd4fc1e538bd391a20cdd00dd1494ace2d0eAlex Klyubin return EmptyArray.BYTE; 1017cbcfd4fc1e538bd391a20cdd00dd1494ace2d0eAlex Klyubin } 10283a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin if (rng == null) { 10383a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin rng = getRng(); 10483a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin } 10583a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin byte[] result = new byte[sizeBytes]; 10683a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin rng.nextBytes(result); 10783a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin return result; 10883a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin } 10983a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin 11083a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin private static SecureRandom getRng() { 11183a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin // IMPLEMENTATION NOTE: It's OK to share a SecureRandom instance because SecureRandom is 11283a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin // required to be thread-safe. 11383a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin if (sRng == null) { 11483a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin sRng = new SecureRandom(); 11583a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin } 11683a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin return sRng; 11783a86c5ce4c04c6e885b08dbdf4a07a18371a3e5Alex Klyubin } 1188c82b4508f0e9f07bb24f106aa817466e39d0cc9Alex Klyubin} 119