1ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales/* 2ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * Copyright 2015 The Android Open Source Project 3ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * 4ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * Licensed under the Apache License, Version 2.0 (the "License"); 5ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * you may not use this file except in compliance with the License. 6ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * You may obtain a copy of the License at 7ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * 8ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * http://www.apache.org/licenses/LICENSE-2.0 9ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * 10ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * Unless required by applicable law or agreed to in writing, software 11ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * distributed under the License is distributed on an "AS IS" BASIS, 12ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * See the License for the specific language governing permissions and 14ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * limitations under the License. 15ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales * 16ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales */ 17ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 18ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales#ifndef SOFT_GATEKEEPER_H_ 19ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales#define SOFT_GATEKEEPER_H_ 20ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 21ae242929da80d88a7db223984ec9baa5fd5949e6Andres Moralesextern "C" { 22ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales#include <openssl/rand.h> 23c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales#include <openssl/sha.h> 24c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales 25ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales#include <crypto_scrypt.h> 26ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales} 27ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 284f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/memory.h> 29ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales#include <UniquePtr.h> 30ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales#include <gatekeeper/gatekeeper.h> 3170309ff8c7dd84fb4852debeb9850f9ae1aa447eAndres Morales 32ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales#include <iostream> 33ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales#include <unordered_map> 34ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 35ae242929da80d88a7db223984ec9baa5fd5949e6Andres Moralesnamespace gatekeeper { 36ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 37c7ab1e81776876d226174248593c6d0f2a65892bAndres Moralesstruct fast_hash_t { 38c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales uint64_t salt; 39c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales uint8_t digest[SHA256_DIGEST_LENGTH]; 40c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales}; 41ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 42ae242929da80d88a7db223984ec9baa5fd5949e6Andres Moralesclass SoftGateKeeper : public GateKeeper { 43ae242929da80d88a7db223984ec9baa5fd5949e6Andres Moralespublic: 44ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales static const uint32_t SIGNATURE_LENGTH_BYTES = 32; 45ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 46ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales // scrypt params 47ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales static const uint64_t N = 16384; 48ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales static const uint32_t r = 8; 49ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales static const uint32_t p = 1; 50ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 51ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales static const int MAX_UINT_32_CHARS = 11; 52ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 53ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales SoftGateKeeper() { 54ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales key_.reset(new uint8_t[SIGNATURE_LENGTH_BYTES]); 55ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales memset(key_.get(), 0, SIGNATURE_LENGTH_BYTES); 56ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 57ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 58ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales virtual ~SoftGateKeeper() { 59ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 60ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 61ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales virtual bool GetAuthTokenKey(const uint8_t **auth_token_key, 62ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales uint32_t *length) const { 63ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales if (auth_token_key == NULL || length == NULL) return false; 64e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales uint8_t *auth_token_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES]; 65e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales memcpy(auth_token_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES); 66e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales 67e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales *auth_token_key = auth_token_key_copy; 68ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales *length = SIGNATURE_LENGTH_BYTES; 69ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales return true; 70ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 71ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 72ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales virtual void GetPasswordKey(const uint8_t **password_key, uint32_t *length) { 73ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales if (password_key == NULL || length == NULL) return; 74e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales uint8_t *password_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES]; 75e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales memcpy(password_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES); 76e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales 77e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales *password_key = password_key_copy; 78ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales *length = SIGNATURE_LENGTH_BYTES; 79ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 80ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 81ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales virtual void ComputePasswordSignature(uint8_t *signature, uint32_t signature_length, 82ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales const uint8_t *, uint32_t, const uint8_t *password, 83ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales uint32_t password_length, salt_t salt) const { 84ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales if (signature == NULL) return; 85ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales crypto_scrypt(password, password_length, reinterpret_cast<uint8_t *>(&salt), 86ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales sizeof(salt), N, r, p, signature, signature_length); 87ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 88ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 89ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales virtual void GetRandom(void *random, uint32_t requested_length) const { 90ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales if (random == NULL) return; 91ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales RAND_pseudo_bytes((uint8_t *) random, requested_length); 92ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 93ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 94ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales virtual void ComputeSignature(uint8_t *signature, uint32_t signature_length, 95ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales const uint8_t *, uint32_t, const uint8_t *, const uint32_t) const { 96ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales if (signature == NULL) return; 97ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales memset(signature, 0, signature_length); 98ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 99ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 100ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales virtual uint64_t GetMillisecondsSinceBoot() const { 101ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales struct timespec time; 102ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales int res = clock_gettime(CLOCK_BOOTTIME, &time); 103ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales if (res < 0) return 0; 104ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000); 105ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 106ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 107ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales virtual bool IsHardwareBacked() const { 108ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales return false; 109ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 110ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 111e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t *record, 112e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales bool /* secure */) { 113ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales failure_record_t *stored = &failure_map_[uid]; 114ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales if (user_id != stored->secure_user_id) { 115ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales stored->secure_user_id = user_id; 116ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales stored->last_checked_timestamp = 0; 117ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales stored->failure_counter = 0; 118ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 119ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales memcpy(record, stored, sizeof(*record)); 120ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales return true; 121ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 122ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 123e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales virtual bool ClearFailureRecord(uint32_t uid, secure_id_t user_id, bool /* secure */) { 124ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales failure_record_t *stored = &failure_map_[uid]; 125ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales stored->secure_user_id = user_id; 126ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales stored->last_checked_timestamp = 0; 127ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales stored->failure_counter = 0; 128e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales return true; 129ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 130ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 131e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales virtual bool WriteFailureRecord(uint32_t uid, failure_record_t *record, bool /* secure */) { 132ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales failure_map_[uid] = *record; 133ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales return true; 134ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales } 135ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 136c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales fast_hash_t ComputeFastHash(const SizedBuffer &password, uint64_t salt) { 137c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales fast_hash_t fast_hash; 138c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales size_t digest_size = password.length + sizeof(salt); 139c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales std::unique_ptr<uint8_t[]> digest(new uint8_t[digest_size]); 140c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales memcpy(digest.get(), &salt, sizeof(salt)); 141c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales memcpy(digest.get() + sizeof(salt), password.buffer.get(), password.length); 142c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales 143c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales SHA256(digest.get(), digest_size, (uint8_t *) &fast_hash.digest); 144c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales 145c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales fast_hash.salt = salt; 146c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales return fast_hash; 147c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales } 148c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales 149c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales bool VerifyFast(const fast_hash_t &fast_hash, const SizedBuffer &password) { 150c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales fast_hash_t computed = ComputeFastHash(password, fast_hash.salt); 151c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales return memcmp(computed.digest, fast_hash.digest, SHA256_DIGEST_LENGTH) == 0; 152c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales } 153c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales 154c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales bool DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password) { 15570309ff8c7dd84fb4852debeb9850f9ae1aa447eAndres Morales uint64_t user_id = android::base::get_unaligned(&expected_handle->user_id); 15670309ff8c7dd84fb4852debeb9850f9ae1aa447eAndres Morales FastHashMap::const_iterator it = fast_hash_map_.find(user_id); 1579ea9a06b062a22039929e6fd654d5f5e92221446Andres Morales if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) { 1589ea9a06b062a22039929e6fd654d5f5e92221446Andres Morales return true; 159c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales } else { 160c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales if (GateKeeper::DoVerify(expected_handle, password)) { 161c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales uint64_t salt; 162c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales GetRandom(&salt, sizeof(salt)); 16370309ff8c7dd84fb4852debeb9850f9ae1aa447eAndres Morales fast_hash_map_[user_id] = ComputeFastHash(password, salt); 164c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales return true; 165c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales } 166c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales } 167c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales 168c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales return false; 169c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales } 170c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales 171ae242929da80d88a7db223984ec9baa5fd5949e6Andres Moralesprivate: 172c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales 173c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales typedef std::unordered_map<uint32_t, failure_record_t> FailureRecordMap; 174c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales typedef std::unordered_map<uint64_t, fast_hash_t> FastHashMap; 175c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales 176e1f827fc1fb2e4a632d77bdd19c2741caa120e8aAndres Morales UniquePtr<uint8_t[]> key_; 177c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales FailureRecordMap failure_map_; 178c7ab1e81776876d226174248593c6d0f2a65892bAndres Morales FastHashMap fast_hash_map_; 179ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales}; 180ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales} 181ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales 182ae242929da80d88a7db223984ec9baa5fd5949e6Andres Morales#endif // SOFT_GATEKEEPER_H_ 183