blob: 34a9a40324c8d17469acf21cafbe8a63c8a8bd74 [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>
David Drysdalec97eb9e2022-01-26 13:03:48 -080028#include <openssl/hmac.h>
Janis Danisevskis9d90b812020-11-25 21:02:11 -080029#include <openssl/rand.h>
Shawn Willden8fde4c22021-02-14 13:58:22 -070030#include <openssl/x509.h>
Joel Galensonca0efb12020-10-01 14:32:30 -070031
32#include <vector>
33
34// Copied from system/security/keystore/blob.h.
35
36constexpr size_t kGcmTagLength = 128 / 8;
37constexpr size_t kAes128KeySizeBytes = 128 / 8;
38
39// Copied from system/security/keystore/blob.cpp.
40
41#if defined(__clang__)
42#define OPTNONE __attribute__((optnone))
43#elif defined(__GNUC__)
44#define OPTNONE __attribute__((optimize("O0")))
45#else
46#error Need a definition for OPTNONE
47#endif
48
49class ArrayEraser {
50 public:
51 ArrayEraser(uint8_t* arr, size_t size) : mArr(arr), mSize(size) {}
52 OPTNONE ~ArrayEraser() { std::fill(mArr, mArr + mSize, 0); }
53
54 private:
55 volatile uint8_t* mArr;
56 size_t mSize;
57};
58
59/**
60 * Returns a EVP_CIPHER appropriate for the given key size.
61 */
62const EVP_CIPHER* getAesCipherForKey(size_t key_size) {
63 const EVP_CIPHER* cipher = EVP_aes_256_gcm();
64 if (key_size == kAes128KeySizeBytes) {
65 cipher = EVP_aes_128_gcm();
66 }
67 return cipher;
68}
69
David Drysdalec97eb9e2022-01-26 13:03:48 -080070bool hmacSha256(const uint8_t* key, size_t key_size, const uint8_t* msg, size_t msg_size,
71 uint8_t* out, size_t out_size) {
72 const EVP_MD* digest = EVP_sha256();
73 unsigned int actual_out_size = out_size;
74 uint8_t* p = HMAC(digest, key, key_size, msg, msg_size, out, &actual_out_size);
75 return (p != nullptr);
76}
77
Janis Danisevskis9d90b812020-11-25 21:02:11 -080078bool randomBytes(uint8_t* out, size_t len) {
79 return RAND_bytes(out, len);
80}
81
Joel Galensonca0efb12020-10-01 14:32:30 -070082/*
83 * Encrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
84 * 'iv' and write output to 'out' (which may be the same location as 'in') and 128-bit tag to
85 * 'tag'.
86 */
87bool AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
88 size_t key_size, const uint8_t* iv, uint8_t* tag) {
89
90 // There can be 128-bit and 256-bit keys
91 const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
92
93 bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
94
95 EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
96 EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
97
98 std::vector<uint8_t> out_tmp(len);
99 uint8_t* out_pos = out_tmp.data();
100 int out_len;
101
102 EVP_EncryptUpdate(ctx.get(), out_pos, &out_len, in, len);
103 out_pos += out_len;
104 EVP_EncryptFinal_ex(ctx.get(), out_pos, &out_len);
105 out_pos += out_len;
106 if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
107 ALOGD("Encrypted ciphertext is the wrong size, expected %zu, got %zd", len,
108 out_pos - out_tmp.data());
109 return false;
110 }
111
112 std::copy(out_tmp.data(), out_pos, out);
113 EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kGcmTagLength, tag);
114
115 return true;
116}
117
118/*
119 * Decrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
120 * 'iv', checking 128-bit tag at 'tag' and writing plaintext to 'out'(which may be the same
121 * location as 'in').
122 */
123bool AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
124 size_t key_size, const uint8_t* iv, const uint8_t* tag) {
125
126 // There can be 128-bit and 256-bit keys
127 const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
128
129 bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
130
131 EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
132 EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
133 EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kGcmTagLength, const_cast<uint8_t*>(tag));
134
135 std::vector<uint8_t> out_tmp(len);
136 ArrayEraser out_eraser(out_tmp.data(), len);
137 uint8_t* out_pos = out_tmp.data();
138 int out_len;
139
140 EVP_DecryptUpdate(ctx.get(), out_pos, &out_len, in, len);
141 out_pos += out_len;
142 if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
143 ALOGE("Failed to decrypt blob; ciphertext or tag is likely corrupted");
144 return false;
145 }
146 out_pos += out_len;
147 if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
148 ALOGE("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
149 out_pos - out_tmp.data());
150 return false;
151 }
152
153 std::copy(out_tmp.data(), out_pos, out);
154
155 return true;
156}
157
158// Copied from system/security/keystore/keymaster_enforcement.cpp.
159
160class EvpMdCtx {
161 public:
162 EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
163 ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
164
165 EVP_MD_CTX* get() { return &ctx_; }
166
167 private:
168 EVP_MD_CTX ctx_;
169};
170
171bool CreateKeyId(const uint8_t* key_blob, size_t len, km_id_t* out_id) {
172 EvpMdCtx ctx;
173
174 uint8_t hash[EVP_MAX_MD_SIZE];
175 unsigned int hash_len;
176 if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) &&
177 EVP_DigestUpdate(ctx.get(), key_blob, len) &&
178 EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) {
179 assert(hash_len >= sizeof(*out_id));
180 memcpy(out_id, hash, sizeof(*out_id));
181 return true;
182 }
183
184 return false;
185}
186
187// Copied from system/security/keystore/user_state.h
188
189static constexpr size_t SALT_SIZE = 16;
190
191// Copied from system/security/keystore/user_state.cpp.
192
193void generateKeyFromPassword(uint8_t* key, size_t key_len, const char* pw, size_t pw_len,
Janis Danisevskis9d90b812020-11-25 21:02:11 -0800194 const uint8_t* salt) {
Joel Galensonca0efb12020-10-01 14:32:30 -0700195 size_t saltSize;
196 if (salt != nullptr) {
197 saltSize = SALT_SIZE;
198 } else {
199 // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
Janis Danisevskis9d90b812020-11-25 21:02:11 -0800200 salt = reinterpret_cast<const uint8_t*>("keystore");
Joel Galensonca0efb12020-10-01 14:32:30 -0700201 // sizeof = 9, not strlen = 8
202 saltSize = sizeof("keystore");
203 }
204
205 const EVP_MD* digest = EVP_sha256();
206
207 // SHA1 was used prior to increasing the key size
208 if (key_len == kAes128KeySizeBytes) {
209 digest = EVP_sha1();
210 }
211
212 PKCS5_PBKDF2_HMAC(pw, pw_len, salt, saltSize, 8192, digest, key_len, key);
213}
Joel Galenson05914582021-01-08 09:30:41 -0800214
215// New code.
216
217bool HKDFExtract(uint8_t* out_key, size_t* out_len, const uint8_t* secret, size_t secret_len,
218 const uint8_t* salt, size_t salt_len) {
219 const EVP_MD* digest = EVP_sha256();
220 auto result = HKDF_extract(out_key, out_len, digest, secret, secret_len, salt, salt_len);
221 return result == 1;
222}
223
224bool HKDFExpand(uint8_t* out_key, size_t out_len, const uint8_t* prk, size_t prk_len,
225 const uint8_t* info, size_t info_len) {
226 const EVP_MD* digest = EVP_sha256();
227 auto result = HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len);
228 return result == 1;
229}
230
231int ECDHComputeKey(void* out, const EC_POINT* pub_key, const EC_KEY* priv_key) {
232 return ECDH_compute_key(out, EC_MAX_BYTES, pub_key, priv_key, nullptr);
233}
234
235EC_KEY* ECKEYGenerateKey() {
236 EC_KEY* key = EC_KEY_new();
Paul Crowley52f017f2021-06-22 08:16:01 -0700237 EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
Joel Galenson05914582021-01-08 09:30:41 -0800238 EC_KEY_set_group(key, group);
239 auto result = EC_KEY_generate_key(key);
240 if (result == 0) {
241 EC_GROUP_free(group);
242 EC_KEY_free(key);
243 return nullptr;
244 }
245 return key;
246}
247
Paul Crowley7bb5edd2021-03-20 20:26:43 -0700248size_t ECKEYMarshalPrivateKey(const EC_KEY* priv_key, uint8_t* buf, size_t len) {
249 CBB cbb;
250 size_t out_len;
251 if (!CBB_init_fixed(&cbb, buf, len) ||
252 !EC_KEY_marshal_private_key(&cbb, priv_key, EC_PKEY_NO_PARAMETERS | EC_PKEY_NO_PUBKEY) ||
253 !CBB_finish(&cbb, nullptr, &out_len)) {
254 return 0;
255 } else {
256 return out_len;
257 }
258}
259
260EC_KEY* ECKEYParsePrivateKey(const uint8_t* buf, size_t len) {
261 CBS cbs;
262 CBS_init(&cbs, buf, len);
Paul Crowley52f017f2021-06-22 08:16:01 -0700263 EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
Paul Crowley7bb5edd2021-03-20 20:26:43 -0700264 auto result = EC_KEY_parse_private_key(&cbs, group);
Joel Galenson05914582021-01-08 09:30:41 -0800265 EC_GROUP_free(group);
Paul Crowley7bb5edd2021-03-20 20:26:43 -0700266 if (result != nullptr && CBS_len(&cbs) != 0) {
267 EC_KEY_free(result);
268 return nullptr;
269 }
Joel Galenson05914582021-01-08 09:30:41 -0800270 return result;
271}
272
273size_t ECPOINTPoint2Oct(const EC_POINT* point, uint8_t* buf, size_t len) {
Paul Crowley52f017f2021-06-22 08:16:01 -0700274 EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
Joel Galenson05914582021-01-08 09:30:41 -0800275 point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
276 auto result = EC_POINT_point2oct(group, point, form, buf, len, nullptr);
277 EC_GROUP_free(group);
278 return result;
279}
280
281EC_POINT* ECPOINTOct2Point(const uint8_t* buf, size_t len) {
Paul Crowley52f017f2021-06-22 08:16:01 -0700282 EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
Joel Galenson05914582021-01-08 09:30:41 -0800283 EC_POINT* point = EC_POINT_new(group);
284 auto result = EC_POINT_oct2point(group, point, buf, len, nullptr);
285 EC_GROUP_free(group);
286 if (result == 0) {
287 EC_POINT_free(point);
288 return nullptr;
289 }
290 return point;
291}
Shawn Willden8fde4c22021-02-14 13:58:22 -0700292
293int extractSubjectFromCertificate(const uint8_t* cert_buf, size_t cert_len, uint8_t* subject_buf,
294 size_t subject_buf_len) {
295 if (!cert_buf || !subject_buf) {
296 ALOGE("extractSubjectFromCertificate: received null pointer");
297 return 0;
298 }
299
300 const uint8_t* p = cert_buf;
301 bssl::UniquePtr<X509> cert(d2i_X509(nullptr /* Allocate X509 struct */, &p, cert_len));
302 if (!cert) {
303 ALOGE("extractSubjectFromCertificate: failed to parse certificate");
304 return 0;
305 }
306
307 X509_NAME* subject = X509_get_subject_name(cert.get());
308 if (!subject) {
309 ALOGE("extractSubjectFromCertificate: failed to retrieve subject name");
310 return 0;
311 }
312
313 int subject_len = i2d_X509_NAME(subject, nullptr /* Don't copy the data */);
314 if (subject_len < 0) {
315 ALOGE("extractSubjectFromCertificate: error obtaining encoded subject name length");
316 return 0;
317 }
318
319 if (subject_len > subject_buf_len) {
320 // Return the subject length, negated, so the caller knows how much
321 // buffer space is required.
322 ALOGI("extractSubjectFromCertificate: needed %d bytes for subject, caller provided %zu",
323 subject_len, subject_buf_len);
324 return -subject_len;
325 }
326
327 // subject_buf has enough space.
328 uint8_t* tmp = subject_buf;
329 return i2d_X509_NAME(subject, &tmp);
330}