blob: 3cc19c5ad5bad9a712c8fd614198e6691e04cc50 [file] [log] [blame]
Joel Galensonca0efb12020-10-01 14:32:30 -07001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "keystore2"
18
19#include "crypto.hpp"
20
21#include <log/log.h>
22#include <openssl/aes.h>
Joel Galenson05914582021-01-08 09:30:41 -080023#include <openssl/ec.h>
24#include <openssl/ec_key.h>
25#include <openssl/ecdh.h>
Joel Galensonca0efb12020-10-01 14:32:30 -070026#include <openssl/evp.h>
Joel Galenson05914582021-01-08 09:30:41 -080027#include <openssl/hkdf.h>
Janis Danisevskis9d90b812020-11-25 21:02:11 -080028#include <openssl/rand.h>
Joel Galensonca0efb12020-10-01 14:32:30 -070029
30#include <vector>
31
32// Copied from system/security/keystore/blob.h.
33
34constexpr size_t kGcmTagLength = 128 / 8;
35constexpr size_t kAes128KeySizeBytes = 128 / 8;
36
37// Copied from system/security/keystore/blob.cpp.
38
39#if defined(__clang__)
40#define OPTNONE __attribute__((optnone))
41#elif defined(__GNUC__)
42#define OPTNONE __attribute__((optimize("O0")))
43#else
44#error Need a definition for OPTNONE
45#endif
46
47class ArrayEraser {
48 public:
49 ArrayEraser(uint8_t* arr, size_t size) : mArr(arr), mSize(size) {}
50 OPTNONE ~ArrayEraser() { std::fill(mArr, mArr + mSize, 0); }
51
52 private:
53 volatile uint8_t* mArr;
54 size_t mSize;
55};
56
57/**
58 * Returns a EVP_CIPHER appropriate for the given key size.
59 */
60const EVP_CIPHER* getAesCipherForKey(size_t key_size) {
61 const EVP_CIPHER* cipher = EVP_aes_256_gcm();
62 if (key_size == kAes128KeySizeBytes) {
63 cipher = EVP_aes_128_gcm();
64 }
65 return cipher;
66}
67
Janis Danisevskis9d90b812020-11-25 21:02:11 -080068bool randomBytes(uint8_t* out, size_t len) {
69 return RAND_bytes(out, len);
70}
71
Joel Galensonca0efb12020-10-01 14:32:30 -070072/*
73 * Encrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
74 * 'iv' and write output to 'out' (which may be the same location as 'in') and 128-bit tag to
75 * 'tag'.
76 */
77bool AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
78 size_t key_size, const uint8_t* iv, uint8_t* tag) {
79
80 // There can be 128-bit and 256-bit keys
81 const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
82
83 bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
84
85 EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
86 EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
87
88 std::vector<uint8_t> out_tmp(len);
89 uint8_t* out_pos = out_tmp.data();
90 int out_len;
91
92 EVP_EncryptUpdate(ctx.get(), out_pos, &out_len, in, len);
93 out_pos += out_len;
94 EVP_EncryptFinal_ex(ctx.get(), out_pos, &out_len);
95 out_pos += out_len;
96 if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
97 ALOGD("Encrypted ciphertext is the wrong size, expected %zu, got %zd", len,
98 out_pos - out_tmp.data());
99 return false;
100 }
101
102 std::copy(out_tmp.data(), out_pos, out);
103 EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kGcmTagLength, tag);
104
105 return true;
106}
107
108/*
109 * Decrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
110 * 'iv', checking 128-bit tag at 'tag' and writing plaintext to 'out'(which may be the same
111 * location as 'in').
112 */
113bool AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
114 size_t key_size, const uint8_t* iv, const uint8_t* tag) {
115
116 // There can be 128-bit and 256-bit keys
117 const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
118
119 bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
120
121 EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
122 EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
123 EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kGcmTagLength, const_cast<uint8_t*>(tag));
124
125 std::vector<uint8_t> out_tmp(len);
126 ArrayEraser out_eraser(out_tmp.data(), len);
127 uint8_t* out_pos = out_tmp.data();
128 int out_len;
129
130 EVP_DecryptUpdate(ctx.get(), out_pos, &out_len, in, len);
131 out_pos += out_len;
132 if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
133 ALOGE("Failed to decrypt blob; ciphertext or tag is likely corrupted");
134 return false;
135 }
136 out_pos += out_len;
137 if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
138 ALOGE("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
139 out_pos - out_tmp.data());
140 return false;
141 }
142
143 std::copy(out_tmp.data(), out_pos, out);
144
145 return true;
146}
147
148// Copied from system/security/keystore/keymaster_enforcement.cpp.
149
150class EvpMdCtx {
151 public:
152 EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
153 ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
154
155 EVP_MD_CTX* get() { return &ctx_; }
156
157 private:
158 EVP_MD_CTX ctx_;
159};
160
161bool CreateKeyId(const uint8_t* key_blob, size_t len, km_id_t* out_id) {
162 EvpMdCtx ctx;
163
164 uint8_t hash[EVP_MAX_MD_SIZE];
165 unsigned int hash_len;
166 if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) &&
167 EVP_DigestUpdate(ctx.get(), key_blob, len) &&
168 EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) {
169 assert(hash_len >= sizeof(*out_id));
170 memcpy(out_id, hash, sizeof(*out_id));
171 return true;
172 }
173
174 return false;
175}
176
177// Copied from system/security/keystore/user_state.h
178
179static constexpr size_t SALT_SIZE = 16;
180
181// Copied from system/security/keystore/user_state.cpp.
182
183void generateKeyFromPassword(uint8_t* key, size_t key_len, const char* pw, size_t pw_len,
Janis Danisevskis9d90b812020-11-25 21:02:11 -0800184 const uint8_t* salt) {
Joel Galensonca0efb12020-10-01 14:32:30 -0700185 size_t saltSize;
186 if (salt != nullptr) {
187 saltSize = SALT_SIZE;
188 } else {
189 // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
Janis Danisevskis9d90b812020-11-25 21:02:11 -0800190 salt = reinterpret_cast<const uint8_t*>("keystore");
Joel Galensonca0efb12020-10-01 14:32:30 -0700191 // sizeof = 9, not strlen = 8
192 saltSize = sizeof("keystore");
193 }
194
195 const EVP_MD* digest = EVP_sha256();
196
197 // SHA1 was used prior to increasing the key size
198 if (key_len == kAes128KeySizeBytes) {
199 digest = EVP_sha1();
200 }
201
202 PKCS5_PBKDF2_HMAC(pw, pw_len, salt, saltSize, 8192, digest, key_len, key);
203}
Joel Galenson05914582021-01-08 09:30:41 -0800204
205// New code.
206
207bool HKDFExtract(uint8_t* out_key, size_t* out_len, const uint8_t* secret, size_t secret_len,
208 const uint8_t* salt, size_t salt_len) {
209 const EVP_MD* digest = EVP_sha256();
210 auto result = HKDF_extract(out_key, out_len, digest, secret, secret_len, salt, salt_len);
211 return result == 1;
212}
213
214bool HKDFExpand(uint8_t* out_key, size_t out_len, const uint8_t* prk, size_t prk_len,
215 const uint8_t* info, size_t info_len) {
216 const EVP_MD* digest = EVP_sha256();
217 auto result = HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len);
218 return result == 1;
219}
220
221int ECDHComputeKey(void* out, const EC_POINT* pub_key, const EC_KEY* priv_key) {
222 return ECDH_compute_key(out, EC_MAX_BYTES, pub_key, priv_key, nullptr);
223}
224
225EC_KEY* ECKEYGenerateKey() {
226 EC_KEY* key = EC_KEY_new();
227 EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
228 EC_KEY_set_group(key, group);
229 auto result = EC_KEY_generate_key(key);
230 if (result == 0) {
231 EC_GROUP_free(group);
232 EC_KEY_free(key);
233 return nullptr;
234 }
235 return key;
236}
237
238EC_KEY* ECKEYDeriveFromSecret(const uint8_t* secret, size_t secret_len) {
239 EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
240 auto result = EC_KEY_derive_from_secret(group, secret, secret_len);
241 EC_GROUP_free(group);
242 return result;
243}
244
245size_t ECPOINTPoint2Oct(const EC_POINT* point, uint8_t* buf, size_t len) {
246 EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
247 point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
248 auto result = EC_POINT_point2oct(group, point, form, buf, len, nullptr);
249 EC_GROUP_free(group);
250 return result;
251}
252
253EC_POINT* ECPOINTOct2Point(const uint8_t* buf, size_t len) {
254 EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
255 EC_POINT* point = EC_POINT_new(group);
256 auto result = EC_POINT_oct2point(group, point, buf, len, nullptr);
257 EC_GROUP_free(group);
258 if (result == 0) {
259 EC_POINT_free(point);
260 return nullptr;
261 }
262 return point;
263}