Home | History | Annotate | Download | only in keystore
      1 /*
      2  * Copyright (C) 2015 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 "keystore"
     18 
     19 #include <arpa/inet.h>
     20 #include <errno.h>
     21 #include <fcntl.h>
     22 #include <string.h>
     23 
     24 #include <cutils/log.h>
     25 
     26 #include "blob.h"
     27 #include "entropy.h"
     28 
     29 #include "keystore_utils.h"
     30 
     31 namespace {
     32 
     33 constexpr size_t kGcmIvSizeBytes = 96 / 8;
     34 
     35 template <typename T, void (*FreeFunc)(T*)> struct OpenSslObjectDeleter {
     36     void operator()(T* p) { FreeFunc(p); }
     37 };
     38 
     39 #define DEFINE_OPENSSL_OBJECT_POINTER(name)                                                        \
     40     typedef OpenSslObjectDeleter<name, name##_free> name##_Delete;                                 \
     41     typedef std::unique_ptr<name, name##_Delete> name##_Ptr;
     42 
     43 DEFINE_OPENSSL_OBJECT_POINTER(EVP_CIPHER_CTX);
     44 
     45 #if defined(__clang__)
     46 #define OPTNONE __attribute__((optnone))
     47 #elif defined(__GNUC__)
     48 #define OPTNONE __attribute__((optimize("O0")))
     49 #else
     50 #error Need a definition for OPTNONE
     51 #endif
     52 
     53 class ArrayEraser {
     54   public:
     55     ArrayEraser(uint8_t* arr, size_t size) : mArr(arr), mSize(size) {}
     56     OPTNONE ~ArrayEraser() { std::fill(mArr, mArr + mSize, 0); }
     57 
     58   private:
     59     volatile uint8_t* mArr;
     60     size_t mSize;
     61 };
     62 
     63 /*
     64  * Encrypt 'len' data at 'in' with AES-GCM, using 128-bit key at 'key', 96-bit IV at 'iv' and write
     65  * output to 'out' (which may be the same location as 'in') and 128-bit tag to 'tag'.
     66  */
     67 ResponseCode AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
     68                              const uint8_t* iv, uint8_t* tag) {
     69     const EVP_CIPHER* cipher = EVP_aes_128_gcm();
     70     EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());
     71 
     72     EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
     73     EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
     74 
     75     std::unique_ptr<uint8_t[]> out_tmp(new uint8_t[len]);
     76     uint8_t* out_pos = out_tmp.get();
     77     int out_len;
     78 
     79     EVP_EncryptUpdate(ctx.get(), out_pos, &out_len, in, len);
     80     out_pos += out_len;
     81     EVP_EncryptFinal_ex(ctx.get(), out_pos, &out_len);
     82     out_pos += out_len;
     83     if (out_pos - out_tmp.get() != static_cast<ssize_t>(len)) {
     84         ALOGD("Encrypted ciphertext is the wrong size, expected %zu, got %zd", len,
     85               out_pos - out_tmp.get());
     86         return ResponseCode::SYSTEM_ERROR;
     87     }
     88 
     89     std::copy(out_tmp.get(), out_pos, out);
     90     EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kGcmTagLength, tag);
     91 
     92     return ResponseCode::NO_ERROR;
     93 }
     94 
     95 /*
     96  * Decrypt 'len' data at 'in' with AES-GCM, using 128-bit key at 'key', 96-bit IV at 'iv', checking
     97  * 128-bit tag at 'tag' and writing plaintext to 'out' (which may be the same location as 'in').
     98  */
     99 ResponseCode AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
    100                              const uint8_t* iv, const uint8_t* tag) {
    101     const EVP_CIPHER* cipher = EVP_aes_128_gcm();
    102     EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());
    103 
    104     EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
    105     EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
    106     EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kGcmTagLength, const_cast<uint8_t*>(tag));
    107 
    108     std::unique_ptr<uint8_t[]> out_tmp(new uint8_t[len]);
    109     ArrayEraser out_eraser(out_tmp.get(), len);
    110     uint8_t* out_pos = out_tmp.get();
    111     int out_len;
    112 
    113     EVP_DecryptUpdate(ctx.get(), out_pos, &out_len, in, len);
    114     out_pos += out_len;
    115     if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
    116         ALOGD("Failed to decrypt blob; ciphertext or tag is likely corrupted");
    117         return ResponseCode::VALUE_CORRUPTED;
    118     }
    119     out_pos += out_len;
    120     if (out_pos - out_tmp.get() != static_cast<ssize_t>(len)) {
    121         ALOGD("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
    122               out_pos - out_tmp.get());
    123         return ResponseCode::VALUE_CORRUPTED;
    124     }
    125 
    126     std::copy(out_tmp.get(), out_pos, out);
    127 
    128     return ResponseCode::NO_ERROR;
    129 }
    130 
    131 }  // namespace
    132 
    133 Blob::Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
    134            BlobType type) {
    135     memset(&mBlob, 0, sizeof(mBlob));
    136     if (valueLength > kValueSize) {
    137         valueLength = kValueSize;
    138         ALOGW("Provided blob length too large");
    139     }
    140     if (infoLength + valueLength > kValueSize) {
    141         infoLength = kValueSize - valueLength;
    142         ALOGW("Provided info length too large");
    143     }
    144     mBlob.length = valueLength;
    145     memcpy(mBlob.value, value, valueLength);
    146 
    147     mBlob.info = infoLength;
    148     memcpy(mBlob.value + valueLength, info, infoLength);
    149 
    150     mBlob.version = CURRENT_BLOB_VERSION;
    151     mBlob.type = uint8_t(type);
    152 
    153     if (type == TYPE_MASTER_KEY) {
    154         mBlob.flags = KEYSTORE_FLAG_ENCRYPTED;
    155     } else {
    156         mBlob.flags = KEYSTORE_FLAG_NONE;
    157     }
    158 }
    159 
    160 Blob::Blob(blobv3 b) {
    161     mBlob = b;
    162 }
    163 
    164 Blob::Blob() {
    165     memset(&mBlob, 0, sizeof(mBlob));
    166 }
    167 
    168 bool Blob::isEncrypted() const {
    169     if (mBlob.version < 2) {
    170         return true;
    171     }
    172 
    173     return mBlob.flags & KEYSTORE_FLAG_ENCRYPTED;
    174 }
    175 
    176 bool Blob::isSuperEncrypted() const {
    177     return mBlob.flags & KEYSTORE_FLAG_SUPER_ENCRYPTED;
    178 }
    179 
    180 bool Blob::isCriticalToDeviceEncryption() const {
    181     return mBlob.flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
    182 }
    183 
    184 inline uint8_t setFlag(uint8_t flags, bool set, KeyStoreFlag flag) {
    185     return set ? (flags | flag) : (flags & ~flag);
    186 }
    187 
    188 void Blob::setEncrypted(bool encrypted) {
    189     mBlob.flags = setFlag(mBlob.flags, encrypted, KEYSTORE_FLAG_ENCRYPTED);
    190 }
    191 
    192 void Blob::setSuperEncrypted(bool superEncrypted) {
    193     mBlob.flags = setFlag(mBlob.flags, superEncrypted, KEYSTORE_FLAG_SUPER_ENCRYPTED);
    194 }
    195 
    196 void Blob::setCriticalToDeviceEncryption(bool critical) {
    197     mBlob.flags = setFlag(mBlob.flags, critical, KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
    198 }
    199 
    200 void Blob::setFallback(bool fallback) {
    201     if (fallback) {
    202         mBlob.flags |= KEYSTORE_FLAG_FALLBACK;
    203     } else {
    204         mBlob.flags &= ~KEYSTORE_FLAG_FALLBACK;
    205     }
    206 }
    207 
    208 ResponseCode Blob::writeBlob(const std::string& filename, const uint8_t* aes_key, State state,
    209                              Entropy* entropy) {
    210     ALOGV("writing blob %s", filename.c_str());
    211 
    212     const size_t dataLength = mBlob.length;
    213     mBlob.length = htonl(mBlob.length);
    214 
    215     if (isEncrypted() || isSuperEncrypted()) {
    216         if (state != STATE_NO_ERROR) {
    217             ALOGD("couldn't insert encrypted blob while not unlocked");
    218             return ResponseCode::LOCKED;
    219         }
    220 
    221         memset(mBlob.initialization_vector, 0, AES_BLOCK_SIZE);
    222         if (!entropy->generate_random_data(mBlob.initialization_vector, kGcmIvSizeBytes)) {
    223             ALOGW("Could not read random data for: %s", filename.c_str());
    224             return ResponseCode::SYSTEM_ERROR;
    225         }
    226 
    227         auto rc = AES_gcm_encrypt(mBlob.value /* in */, mBlob.value /* out */, dataLength, aes_key,
    228                                   mBlob.initialization_vector, mBlob.aead_tag);
    229         if (rc != ResponseCode::NO_ERROR) return rc;
    230     }
    231 
    232     size_t fileLength = offsetof(blobv3, value) + dataLength + mBlob.info;
    233 
    234     const char* tmpFileName = ".tmp";
    235     int out =
    236         TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
    237     if (out < 0) {
    238         ALOGW("could not open file: %s: %s", tmpFileName, strerror(errno));
    239         return ResponseCode::SYSTEM_ERROR;
    240     }
    241 
    242     const size_t writtenBytes = writeFully(out, (uint8_t*)&mBlob, fileLength);
    243     if (close(out) != 0) {
    244         return ResponseCode::SYSTEM_ERROR;
    245     }
    246     if (writtenBytes != fileLength) {
    247         ALOGW("blob not fully written %zu != %zu", writtenBytes, fileLength);
    248         unlink(tmpFileName);
    249         return ResponseCode::SYSTEM_ERROR;
    250     }
    251     if (rename(tmpFileName, filename.c_str()) == -1) {
    252         ALOGW("could not rename blob to %s: %s", filename.c_str(), strerror(errno));
    253         return ResponseCode::SYSTEM_ERROR;
    254     }
    255     return ResponseCode::NO_ERROR;
    256 }
    257 
    258 ResponseCode Blob::readBlob(const std::string& filename, const uint8_t* aes_key, State state) {
    259     ALOGV("reading blob %s", filename.c_str());
    260     const int in = TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY));
    261     if (in < 0) {
    262         return (errno == ENOENT) ? ResponseCode::KEY_NOT_FOUND : ResponseCode::SYSTEM_ERROR;
    263     }
    264 
    265     // fileLength may be less than sizeof(mBlob)
    266     const size_t fileLength = readFully(in, (uint8_t*)&mBlob, sizeof(mBlob));
    267     if (close(in) != 0) {
    268         return ResponseCode::SYSTEM_ERROR;
    269     }
    270 
    271     if (fileLength == 0) {
    272         return ResponseCode::VALUE_CORRUPTED;
    273     }
    274 
    275     if ((isEncrypted() || isSuperEncrypted())) {
    276         if (state == STATE_LOCKED) return ResponseCode::LOCKED;
    277         if (state == STATE_UNINITIALIZED) return ResponseCode::UNINITIALIZED;
    278     }
    279 
    280     if (fileLength < offsetof(blobv3, value)) return ResponseCode::VALUE_CORRUPTED;
    281 
    282     if (mBlob.version == 3) {
    283         const ssize_t encryptedLength = ntohl(mBlob.length);
    284 
    285         if (isEncrypted() || isSuperEncrypted()) {
    286             auto rc = AES_gcm_decrypt(mBlob.value /* in */, mBlob.value /* out */, encryptedLength,
    287                                       aes_key, mBlob.initialization_vector, mBlob.aead_tag);
    288             if (rc != ResponseCode::NO_ERROR) return rc;
    289         }
    290     } else if (mBlob.version < 3) {
    291         blobv2& blob = reinterpret_cast<blobv2&>(mBlob);
    292         const size_t headerLength = offsetof(blobv2, encrypted);
    293         const ssize_t encryptedLength = fileLength - headerLength - blob.info;
    294         if (encryptedLength < 0) return ResponseCode::VALUE_CORRUPTED;
    295 
    296         if (isEncrypted() || isSuperEncrypted()) {
    297             if (encryptedLength % AES_BLOCK_SIZE != 0) {
    298                 return ResponseCode::VALUE_CORRUPTED;
    299             }
    300 
    301             AES_KEY key;
    302             AES_set_decrypt_key(aes_key, kAesKeySize * 8, &key);
    303             AES_cbc_encrypt(blob.encrypted, blob.encrypted, encryptedLength, &key, blob.vector,
    304                             AES_DECRYPT);
    305             key = {};  // clear key
    306 
    307             uint8_t computedDigest[MD5_DIGEST_LENGTH];
    308             ssize_t digestedLength = encryptedLength - MD5_DIGEST_LENGTH;
    309             MD5(blob.digested, digestedLength, computedDigest);
    310             if (memcmp(blob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
    311                 return ResponseCode::VALUE_CORRUPTED;
    312             }
    313         }
    314     }
    315 
    316     const ssize_t maxValueLength = fileLength - offsetof(blobv3, value) - mBlob.info;
    317     mBlob.length = ntohl(mBlob.length);
    318     if (mBlob.length < 0 || mBlob.length > maxValueLength ||
    319         mBlob.length + mBlob.info + AES_BLOCK_SIZE > static_cast<ssize_t>(sizeof(mBlob.value))) {
    320         return ResponseCode::VALUE_CORRUPTED;
    321     }
    322 
    323     if (mBlob.info != 0 && mBlob.version < 3) {
    324         // move info from after padding to after data
    325         memmove(mBlob.value + mBlob.length, mBlob.value + maxValueLength, mBlob.info);
    326     }
    327 
    328     return ResponseCode::NO_ERROR;
    329 }
    330 
    331 keystore::SecurityLevel Blob::getSecurityLevel() const {
    332     return keystore::flagsToSecurityLevel(mBlob.flags);
    333 }
    334 
    335 void Blob::setSecurityLevel(keystore::SecurityLevel secLevel) {
    336     mBlob.flags &= ~(KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX);
    337     mBlob.flags |= keystore::securityLevelToFlags(secLevel);
    338 }
    339