blob: 173ed11b97742dc34d261392089dd5a1f9a61b96 [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>
23#include <openssl/evp.h>
Janis Danisevskis9d90b812020-11-25 21:02:11 -080024#include <openssl/rand.h>
Joel Galensonca0efb12020-10-01 14:32:30 -070025
26#include <vector>
27
28// Copied from system/security/keystore/blob.h.
29
30constexpr size_t kGcmTagLength = 128 / 8;
31constexpr size_t kAes128KeySizeBytes = 128 / 8;
32
33// Copied from system/security/keystore/blob.cpp.
34
35#if defined(__clang__)
36#define OPTNONE __attribute__((optnone))
37#elif defined(__GNUC__)
38#define OPTNONE __attribute__((optimize("O0")))
39#else
40#error Need a definition for OPTNONE
41#endif
42
43class ArrayEraser {
44 public:
45 ArrayEraser(uint8_t* arr, size_t size) : mArr(arr), mSize(size) {}
46 OPTNONE ~ArrayEraser() { std::fill(mArr, mArr + mSize, 0); }
47
48 private:
49 volatile uint8_t* mArr;
50 size_t mSize;
51};
52
53/**
54 * Returns a EVP_CIPHER appropriate for the given key size.
55 */
56const EVP_CIPHER* getAesCipherForKey(size_t key_size) {
57 const EVP_CIPHER* cipher = EVP_aes_256_gcm();
58 if (key_size == kAes128KeySizeBytes) {
59 cipher = EVP_aes_128_gcm();
60 }
61 return cipher;
62}
63
Janis Danisevskis9d90b812020-11-25 21:02:11 -080064bool randomBytes(uint8_t* out, size_t len) {
65 return RAND_bytes(out, len);
66}
67
Joel Galensonca0efb12020-10-01 14:32:30 -070068/*
69 * Encrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
70 * 'iv' and write output to 'out' (which may be the same location as 'in') and 128-bit tag to
71 * 'tag'.
72 */
73bool AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
74 size_t key_size, const uint8_t* iv, uint8_t* tag) {
75
76 // There can be 128-bit and 256-bit keys
77 const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
78
79 bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
80
81 EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
82 EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
83
84 std::vector<uint8_t> out_tmp(len);
85 uint8_t* out_pos = out_tmp.data();
86 int out_len;
87
88 EVP_EncryptUpdate(ctx.get(), out_pos, &out_len, in, len);
89 out_pos += out_len;
90 EVP_EncryptFinal_ex(ctx.get(), out_pos, &out_len);
91 out_pos += out_len;
92 if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
93 ALOGD("Encrypted ciphertext is the wrong size, expected %zu, got %zd", len,
94 out_pos - out_tmp.data());
95 return false;
96 }
97
98 std::copy(out_tmp.data(), out_pos, out);
99 EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kGcmTagLength, tag);
100
101 return true;
102}
103
104/*
105 * Decrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
106 * 'iv', checking 128-bit tag at 'tag' and writing plaintext to 'out'(which may be the same
107 * location as 'in').
108 */
109bool AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
110 size_t key_size, const uint8_t* iv, const uint8_t* tag) {
111
112 // There can be 128-bit and 256-bit keys
113 const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
114
115 bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
116
117 EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
118 EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
119 EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kGcmTagLength, const_cast<uint8_t*>(tag));
120
121 std::vector<uint8_t> out_tmp(len);
122 ArrayEraser out_eraser(out_tmp.data(), len);
123 uint8_t* out_pos = out_tmp.data();
124 int out_len;
125
126 EVP_DecryptUpdate(ctx.get(), out_pos, &out_len, in, len);
127 out_pos += out_len;
128 if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
129 ALOGE("Failed to decrypt blob; ciphertext or tag is likely corrupted");
130 return false;
131 }
132 out_pos += out_len;
133 if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
134 ALOGE("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
135 out_pos - out_tmp.data());
136 return false;
137 }
138
139 std::copy(out_tmp.data(), out_pos, out);
140
141 return true;
142}
143
144// Copied from system/security/keystore/keymaster_enforcement.cpp.
145
146class EvpMdCtx {
147 public:
148 EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
149 ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
150
151 EVP_MD_CTX* get() { return &ctx_; }
152
153 private:
154 EVP_MD_CTX ctx_;
155};
156
157bool CreateKeyId(const uint8_t* key_blob, size_t len, km_id_t* out_id) {
158 EvpMdCtx ctx;
159
160 uint8_t hash[EVP_MAX_MD_SIZE];
161 unsigned int hash_len;
162 if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) &&
163 EVP_DigestUpdate(ctx.get(), key_blob, len) &&
164 EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) {
165 assert(hash_len >= sizeof(*out_id));
166 memcpy(out_id, hash, sizeof(*out_id));
167 return true;
168 }
169
170 return false;
171}
172
173// Copied from system/security/keystore/user_state.h
174
175static constexpr size_t SALT_SIZE = 16;
176
177// Copied from system/security/keystore/user_state.cpp.
178
179void generateKeyFromPassword(uint8_t* key, size_t key_len, const char* pw, size_t pw_len,
Janis Danisevskis9d90b812020-11-25 21:02:11 -0800180 const uint8_t* salt) {
Joel Galensonca0efb12020-10-01 14:32:30 -0700181 size_t saltSize;
182 if (salt != nullptr) {
183 saltSize = SALT_SIZE;
184 } else {
185 // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
Janis Danisevskis9d90b812020-11-25 21:02:11 -0800186 salt = reinterpret_cast<const uint8_t*>("keystore");
Joel Galensonca0efb12020-10-01 14:32:30 -0700187 // sizeof = 9, not strlen = 8
188 saltSize = sizeof("keystore");
189 }
190
191 const EVP_MD* digest = EVP_sha256();
192
193 // SHA1 was used prior to increasing the key size
194 if (key_len == kAes128KeySizeBytes) {
195 digest = EVP_sha1();
196 }
197
198 PKCS5_PBKDF2_HMAC(pw, pw_len, salt, saltSize, 8192, digest, key_len, key);
199}