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