12beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden/*
22beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden * Copyright 2015 The Android Open Source Project
32beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden *
42beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden * Licensed under the Apache License, Version 2.0 (the "License");
52beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden * you may not use this file except in compliance with the License.
62beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden * You may obtain a copy of the License at
72beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden *
82beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden *      http://www.apache.org/licenses/LICENSE-2.0
92beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden *
102beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden * Unless required by applicable law or agreed to in writing, software
112beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden * distributed under the License is distributed on an "AS IS" BASIS,
122beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden * See the License for the specific language governing permissions and
142beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden * limitations under the License.
152beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden */
162beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
172beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden#include "integrity_assured_key_blob.h"
182beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
192beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden#include <assert.h>
202beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
21f38a002624126ca837865826f948edc9100d6e8aJanis Danisevskis#include <keymaster/new>
220f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden
232beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden#include <openssl/hmac.h>
242beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden#include <openssl/mem.h>
252beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
262beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden#include <keymaster/android_keymaster_utils.h>
272beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden#include <keymaster/authorization_set.h>
282beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
292beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden#include "openssl_err.h"
302beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
312beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willdennamespace keymaster {
322beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
332beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willdenstatic const uint8_t BLOB_VERSION = 0;
342beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willdenstatic const size_t HMAC_SIZE = 8;
352beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willdenstatic const char HMAC_KEY[] = "IntegrityAssuredBlob0";
362beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
372beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willdeninline size_t min(size_t a, size_t b) {
382beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    if (a < b)
392beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        return a;
402beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    return b;
412beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden}
422beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
432beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willdenclass HmacCleanup {
442beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden  public:
4503d4b6d531eb8c2ebcb4d572a3bf118c70a83ff6Chih-Hung Hsieh    explicit HmacCleanup(HMAC_CTX* ctx) : ctx_(ctx) {}
462beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    ~HmacCleanup() { HMAC_CTX_cleanup(ctx_); }
472beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
482beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden  private:
492beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    HMAC_CTX* ctx_;
502beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden};
512beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
5236d41e230417ac3b86a1425ebf60fff6d92377ecShawn Willdenstatic keymaster_error_t ComputeHmac(const uint8_t* serialized_data, size_t serialized_data_size,
5301d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden                                     const AuthorizationSet& hidden, uint8_t hmac[HMAC_SIZE]) {
542beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    size_t hidden_bytes_size = hidden.SerializedSize();
5501d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden    UniquePtr<uint8_t[]> hidden_bytes(new (std::nothrow) uint8_t[hidden_bytes_size]);
560f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden    if (!hidden_bytes.get())
570f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
582beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    hidden.Serialize(hidden_bytes.get(), hidden_bytes.get() + hidden_bytes_size);
592beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
602beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    HMAC_CTX ctx;
612beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    HMAC_CTX_init(&ctx);
622beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    const EVP_MD* md = EVP_sha256();
632beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    if (!HMAC_Init_ex(&ctx, HMAC_KEY, sizeof(HMAC_KEY), md, NULL /* engine */))
642beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        return TranslateLastOpenSslError();
652beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    HmacCleanup cleanup(&ctx);
662beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
672beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    uint8_t tmp[EVP_MAX_MD_SIZE];
682beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    unsigned tmp_len;
692beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    if (!HMAC_Update(&ctx, serialized_data, serialized_data_size) ||
702beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        !HMAC_Update(&ctx, hidden_bytes.get(), hidden_bytes_size) ||  //
712beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        !HMAC_Final(&ctx, tmp, &tmp_len))
722beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        return TranslateLastOpenSslError();
732beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
742beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    assert(tmp_len >= HMAC_SIZE);
752beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    memcpy(hmac, tmp, min(HMAC_SIZE, tmp_len));
762beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
772beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    return KM_ERROR_OK;
782beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden}
792beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
802beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willdenkeymaster_error_t SerializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_material,
812beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                                                const AuthorizationSet& hidden,
822beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                                                const AuthorizationSet& hw_enforced,
832beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                                                const AuthorizationSet& sw_enforced,
842beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                                                KeymasterKeyBlob* key_blob) {
852beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    size_t size = 1 /* version */ +                //
862beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                  key_material.SerializedSize() +  //
872beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                  hw_enforced.SerializedSize() +   //
882beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                  sw_enforced.SerializedSize() +   //
892beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                  HMAC_SIZE;
902beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
912beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    if (!key_blob->Reset(size))
922beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
932beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
942beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    uint8_t* p = key_blob->writable_data();
952beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    *p++ = BLOB_VERSION;
962beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    p = key_material.Serialize(p, key_blob->end());
972beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    p = hw_enforced.Serialize(p, key_blob->end());
982beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    p = sw_enforced.Serialize(p, key_blob->end());
992beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
1002beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    return ComputeHmac(key_blob->key_material, p - key_blob->key_material, hidden, p);
1012beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden}
1022beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
1032beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willdenkeymaster_error_t DeserializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_blob,
1042beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                                                  const AuthorizationSet& hidden,
1052beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                                                  KeymasterKeyBlob* key_material,
1062beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                                                  AuthorizationSet* hw_enforced,
1072beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                                                  AuthorizationSet* sw_enforced) {
1082beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    const uint8_t* p = key_blob.begin();
1092beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    const uint8_t* end = key_blob.end();
1102beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
11101d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden    if (p > end || p + HMAC_SIZE > end)
1120f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden        return KM_ERROR_INVALID_KEY_BLOB;
1130f906ec40f6ade7955c6b967ea522aade54ea2e4Shawn Willden
1142beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    uint8_t computed_hmac[HMAC_SIZE];
1152beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    keymaster_error_t error = ComputeHmac(key_blob.begin(), key_blob.key_material_size - HMAC_SIZE,
1162beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden                                          hidden, computed_hmac);
1172beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    if (error != KM_ERROR_OK)
1182beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        return error;
1192beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
1202beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    if (CRYPTO_memcmp(key_blob.end() - HMAC_SIZE, computed_hmac, HMAC_SIZE) != 0)
1212beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        return KM_ERROR_INVALID_KEY_BLOB;
1222beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
12301d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden    return DeserializeIntegrityAssuredBlob_NoHmacCheck(key_blob, key_material, hw_enforced,
12401d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden                                                       sw_enforced);
12501d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden}
12601d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden
12701d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willdenkeymaster_error_t DeserializeIntegrityAssuredBlob_NoHmacCheck(const KeymasterKeyBlob& key_blob,
12801d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden                                                              KeymasterKeyBlob* key_material,
12901d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden                                                              AuthorizationSet* hw_enforced,
13001d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden                                                              AuthorizationSet* sw_enforced) {
13101d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden    const uint8_t* p = key_blob.begin();
13201d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden    const uint8_t* end = key_blob.end() - HMAC_SIZE;
13301d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden
13401d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden    if (p > end)
13501d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden        return KM_ERROR_INVALID_KEY_BLOB;
13601d8f24c45067bc3d909e3aae9a72582f3c985a1Shawn Willden
1372beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    if (*p != BLOB_VERSION)
1382beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        return KM_ERROR_INVALID_KEY_BLOB;
1392beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    ++p;
1402beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
1412beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    if (!key_material->Deserialize(&p, end) ||  //
1422beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        !hw_enforced->Deserialize(&p, end) ||   //
1432beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        !sw_enforced->Deserialize(&p, end))
1442beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden        return KM_ERROR_INVALID_KEY_BLOB;
1452beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
1462beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden    return KM_ERROR_OK;
1472beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden}
1482beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden
1492beb628bfefae72fa6bb84a6235da7e3de532823Shawn Willden}  // namespace keymaster;
150