Home | History | Annotate | Download | only in keymaster
      1 /*
      2  * Copyright 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 #include "integrity_assured_key_blob.h"
     18 
     19 #include <assert.h>
     20 
     21 #include <new>
     22 
     23 #include <openssl/hmac.h>
     24 #include <openssl/mem.h>
     25 
     26 #include <keymaster/android_keymaster_utils.h>
     27 #include <keymaster/authorization_set.h>
     28 
     29 #include "openssl_err.h"
     30 
     31 namespace keymaster {
     32 
     33 static const uint8_t BLOB_VERSION = 0;
     34 static const size_t HMAC_SIZE = 8;
     35 static const char HMAC_KEY[] = "IntegrityAssuredBlob0";
     36 
     37 inline size_t min(size_t a, size_t b) {
     38     if (a < b)
     39         return a;
     40     return b;
     41 }
     42 
     43 class HmacCleanup {
     44   public:
     45     explicit HmacCleanup(HMAC_CTX* ctx) : ctx_(ctx) {}
     46     ~HmacCleanup() { HMAC_CTX_cleanup(ctx_); }
     47 
     48   private:
     49     HMAC_CTX* ctx_;
     50 };
     51 
     52 static keymaster_error_t ComputeHmac(const uint8_t* serialized_data, size_t serialized_data_size,
     53                                      const AuthorizationSet& hidden, uint8_t hmac[HMAC_SIZE]) {
     54     size_t hidden_bytes_size = hidden.SerializedSize();
     55     UniquePtr<uint8_t[]> hidden_bytes(new (std::nothrow) uint8_t[hidden_bytes_size]);
     56     if (!hidden_bytes.get())
     57         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
     58     hidden.Serialize(hidden_bytes.get(), hidden_bytes.get() + hidden_bytes_size);
     59 
     60     HMAC_CTX ctx;
     61     HMAC_CTX_init(&ctx);
     62     const EVP_MD* md = EVP_sha256();
     63     if (!HMAC_Init_ex(&ctx, HMAC_KEY, sizeof(HMAC_KEY), md, NULL /* engine */))
     64         return TranslateLastOpenSslError();
     65     HmacCleanup cleanup(&ctx);
     66 
     67     uint8_t tmp[EVP_MAX_MD_SIZE];
     68     unsigned tmp_len;
     69     if (!HMAC_Update(&ctx, serialized_data, serialized_data_size) ||
     70         !HMAC_Update(&ctx, hidden_bytes.get(), hidden_bytes_size) ||  //
     71         !HMAC_Final(&ctx, tmp, &tmp_len))
     72         return TranslateLastOpenSslError();
     73 
     74     assert(tmp_len >= HMAC_SIZE);
     75     memcpy(hmac, tmp, min(HMAC_SIZE, tmp_len));
     76 
     77     return KM_ERROR_OK;
     78 }
     79 
     80 keymaster_error_t SerializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_material,
     81                                                 const AuthorizationSet& hidden,
     82                                                 const AuthorizationSet& hw_enforced,
     83                                                 const AuthorizationSet& sw_enforced,
     84                                                 KeymasterKeyBlob* key_blob) {
     85     size_t size = 1 /* version */ +                //
     86                   key_material.SerializedSize() +  //
     87                   hw_enforced.SerializedSize() +   //
     88                   sw_enforced.SerializedSize() +   //
     89                   HMAC_SIZE;
     90 
     91     if (!key_blob->Reset(size))
     92         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
     93 
     94     uint8_t* p = key_blob->writable_data();
     95     *p++ = BLOB_VERSION;
     96     p = key_material.Serialize(p, key_blob->end());
     97     p = hw_enforced.Serialize(p, key_blob->end());
     98     p = sw_enforced.Serialize(p, key_blob->end());
     99 
    100     return ComputeHmac(key_blob->key_material, p - key_blob->key_material, hidden, p);
    101 }
    102 
    103 keymaster_error_t DeserializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_blob,
    104                                                   const AuthorizationSet& hidden,
    105                                                   KeymasterKeyBlob* key_material,
    106                                                   AuthorizationSet* hw_enforced,
    107                                                   AuthorizationSet* sw_enforced) {
    108     const uint8_t* p = key_blob.begin();
    109     const uint8_t* end = key_blob.end();
    110 
    111     if (p > end || p + HMAC_SIZE > end)
    112         return KM_ERROR_INVALID_KEY_BLOB;
    113 
    114     uint8_t computed_hmac[HMAC_SIZE];
    115     keymaster_error_t error = ComputeHmac(key_blob.begin(), key_blob.key_material_size - HMAC_SIZE,
    116                                           hidden, computed_hmac);
    117     if (error != KM_ERROR_OK)
    118         return error;
    119 
    120     if (CRYPTO_memcmp(key_blob.end() - HMAC_SIZE, computed_hmac, HMAC_SIZE) != 0)
    121         return KM_ERROR_INVALID_KEY_BLOB;
    122 
    123     return DeserializeIntegrityAssuredBlob_NoHmacCheck(key_blob, key_material, hw_enforced,
    124                                                        sw_enforced);
    125 }
    126 
    127 keymaster_error_t DeserializeIntegrityAssuredBlob_NoHmacCheck(const KeymasterKeyBlob& key_blob,
    128                                                               KeymasterKeyBlob* key_material,
    129                                                               AuthorizationSet* hw_enforced,
    130                                                               AuthorizationSet* sw_enforced) {
    131     const uint8_t* p = key_blob.begin();
    132     const uint8_t* end = key_blob.end() - HMAC_SIZE;
    133 
    134     if (p > end)
    135         return KM_ERROR_INVALID_KEY_BLOB;
    136 
    137     if (*p != BLOB_VERSION)
    138         return KM_ERROR_INVALID_KEY_BLOB;
    139     ++p;
    140 
    141     if (!key_material->Deserialize(&p, end) ||  //
    142         !hw_enforced->Deserialize(&p, end) ||   //
    143         !sw_enforced->Deserialize(&p, end))
    144         return KM_ERROR_INVALID_KEY_BLOB;
    145 
    146     return KM_ERROR_OK;
    147 }
    148 
    149 }  // namespace keymaster;
    150