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