• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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/ec.h>
24 #include <openssl/ec_key.h>
25 #include <openssl/ecdh.h>
26 #include <openssl/evp.h>
27 #include <openssl/hkdf.h>
28 #include <openssl/hmac.h>
29 #include <openssl/rand.h>
30 #include <openssl/x509.h>
31 
32 #include <vector>
33 
34 // Copied from system/security/keystore/blob.h.
35 
36 constexpr size_t kGcmTagLength = 128 / 8;
37 constexpr 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 
49 class ArrayEraser {
50   public:
ArrayEraser(uint8_t * arr,size_t size)51     ArrayEraser(uint8_t* arr, size_t size) : mArr(arr), mSize(size) {}
~ArrayEraser()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  */
getAesCipherForKey(size_t key_size)62 const 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 
hmacSha256(const uint8_t * key,size_t key_size,const uint8_t * msg,size_t msg_size,uint8_t * out,size_t out_size)70 bool 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 
randomBytes(uint8_t * out,size_t len)78 bool randomBytes(uint8_t* out, size_t len) {
79     return RAND_bytes(out, len);
80 }
81 
82 /*
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  */
AES_gcm_encrypt(const uint8_t * in,uint8_t * out,size_t len,const uint8_t * key,size_t key_size,const uint8_t * iv,uint8_t * tag)87 bool 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  */
AES_gcm_decrypt(const uint8_t * in,uint8_t * out,size_t len,const uint8_t * key,size_t key_size,const uint8_t * iv,const uint8_t * tag)123 bool 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 
160 class EvpMdCtx {
161   public:
EvpMdCtx()162     EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
~EvpMdCtx()163     ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
164 
get()165     EVP_MD_CTX* get() { return &ctx_; }
166 
167   private:
168     EVP_MD_CTX ctx_;
169 };
170 
CreateKeyId(const uint8_t * key_blob,size_t len,km_id_t * out_id)171 bool 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 
189 static constexpr size_t SALT_SIZE = 16;
190 
191 // Copied from system/security/keystore/user_state.cpp.
192 
generateKeyFromPassword(uint8_t * key,size_t key_len,const char * pw,size_t pw_len,const uint8_t * salt)193 void generateKeyFromPassword(uint8_t* key, size_t key_len, const char* pw, size_t pw_len,
194                              const uint8_t* salt) {
195     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
200         salt = reinterpret_cast<const uint8_t*>("keystore");
201         // 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 }
214 
215 // New code.
216 
HKDFExtract(uint8_t * out_key,size_t * out_len,const uint8_t * secret,size_t secret_len,const uint8_t * salt,size_t salt_len)217 bool 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 
HKDFExpand(uint8_t * out_key,size_t out_len,const uint8_t * prk,size_t prk_len,const uint8_t * info,size_t info_len)224 bool 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 
ECDHComputeKey(void * out,const EC_POINT * pub_key,const EC_KEY * priv_key)231 int 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 
ECKEYGenerateKey()235 EC_KEY* ECKEYGenerateKey() {
236     EC_KEY* key = EC_KEY_new();
237     EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
238     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 
ECKEYMarshalPrivateKey(const EC_KEY * priv_key,uint8_t * buf,size_t len)248 size_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 
ECKEYParsePrivateKey(const uint8_t * buf,size_t len)260 EC_KEY* ECKEYParsePrivateKey(const uint8_t* buf, size_t len) {
261     CBS cbs;
262     CBS_init(&cbs, buf, len);
263     EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
264     auto result = EC_KEY_parse_private_key(&cbs, group);
265     EC_GROUP_free(group);
266     if (result != nullptr && CBS_len(&cbs) != 0) {
267         EC_KEY_free(result);
268         return nullptr;
269     }
270     return result;
271 }
272 
ECPOINTPoint2Oct(const EC_POINT * point,uint8_t * buf,size_t len)273 size_t ECPOINTPoint2Oct(const EC_POINT* point, uint8_t* buf, size_t len) {
274     EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
275     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 
ECPOINTOct2Point(const uint8_t * buf,size_t len)281 EC_POINT* ECPOINTOct2Point(const uint8_t* buf, size_t len) {
282     EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp521r1);
283     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 }
292 
extractSubjectFromCertificate(const uint8_t * cert_buf,size_t cert_len,uint8_t * subject_buf,size_t subject_buf_len)293 int 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 }
331