/*
 * Copyright 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "integrity_assured_key_blob.h"

#include <assert.h>

#include <new>

#include <openssl/hmac.h>
#include <openssl/mem.h>

#include <keymaster/android_keymaster_utils.h>
#include <keymaster/authorization_set.h>

#include "openssl_err.h"

namespace keymaster {

static const uint8_t BLOB_VERSION = 0;
static const size_t HMAC_SIZE = 8;
static const char HMAC_KEY[] = "IntegrityAssuredBlob0";

inline size_t min(size_t a, size_t b) {
    if (a < b)
        return a;
    return b;
}

class HmacCleanup {
  public:
    HmacCleanup(HMAC_CTX* ctx) : ctx_(ctx) {}
    ~HmacCleanup() { HMAC_CTX_cleanup(ctx_); }

  private:
    HMAC_CTX* ctx_;
};

static keymaster_error_t ComputeHmac(const uint8_t* serialized_data, size_t serialized_data_size,
                                     const AuthorizationSet& hidden, uint8_t hmac[HMAC_SIZE]) {
    size_t hidden_bytes_size = hidden.SerializedSize();
    UniquePtr<uint8_t[]> hidden_bytes(new (std::nothrow) uint8_t[hidden_bytes_size]);
    if (!hidden_bytes.get())
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    hidden.Serialize(hidden_bytes.get(), hidden_bytes.get() + hidden_bytes_size);

    HMAC_CTX ctx;
    HMAC_CTX_init(&ctx);
    const EVP_MD* md = EVP_sha256();
    if (!HMAC_Init_ex(&ctx, HMAC_KEY, sizeof(HMAC_KEY), md, NULL /* engine */))
        return TranslateLastOpenSslError();
    HmacCleanup cleanup(&ctx);

    uint8_t tmp[EVP_MAX_MD_SIZE];
    unsigned tmp_len;
    if (!HMAC_Update(&ctx, serialized_data, serialized_data_size) ||
        !HMAC_Update(&ctx, hidden_bytes.get(), hidden_bytes_size) ||  //
        !HMAC_Final(&ctx, tmp, &tmp_len))
        return TranslateLastOpenSslError();

    assert(tmp_len >= HMAC_SIZE);
    memcpy(hmac, tmp, min(HMAC_SIZE, tmp_len));

    return KM_ERROR_OK;
}

keymaster_error_t SerializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_material,
                                                const AuthorizationSet& hidden,
                                                const AuthorizationSet& hw_enforced,
                                                const AuthorizationSet& sw_enforced,
                                                KeymasterKeyBlob* key_blob) {
    size_t size = 1 /* version */ +                //
                  key_material.SerializedSize() +  //
                  hw_enforced.SerializedSize() +   //
                  sw_enforced.SerializedSize() +   //
                  HMAC_SIZE;

    if (!key_blob->Reset(size))
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;

    uint8_t* p = key_blob->writable_data();
    *p++ = BLOB_VERSION;
    p = key_material.Serialize(p, key_blob->end());
    p = hw_enforced.Serialize(p, key_blob->end());
    p = sw_enforced.Serialize(p, key_blob->end());

    return ComputeHmac(key_blob->key_material, p - key_blob->key_material, hidden, p);
}

keymaster_error_t DeserializeIntegrityAssuredBlob(const KeymasterKeyBlob& key_blob,
                                                  const AuthorizationSet& hidden,
                                                  KeymasterKeyBlob* key_material,
                                                  AuthorizationSet* hw_enforced,
                                                  AuthorizationSet* sw_enforced) {
    const uint8_t* p = key_blob.begin();
    const uint8_t* end = key_blob.end();

    if (p > end || p + HMAC_SIZE > end)
        return KM_ERROR_INVALID_KEY_BLOB;

    uint8_t computed_hmac[HMAC_SIZE];
    keymaster_error_t error = ComputeHmac(key_blob.begin(), key_blob.key_material_size - HMAC_SIZE,
                                          hidden, computed_hmac);
    if (error != KM_ERROR_OK)
        return error;

    if (CRYPTO_memcmp(key_blob.end() - HMAC_SIZE, computed_hmac, HMAC_SIZE) != 0)
        return KM_ERROR_INVALID_KEY_BLOB;

    return DeserializeIntegrityAssuredBlob_NoHmacCheck(key_blob, key_material, hw_enforced,
                                                       sw_enforced);
}

keymaster_error_t DeserializeIntegrityAssuredBlob_NoHmacCheck(const KeymasterKeyBlob& key_blob,
                                                              KeymasterKeyBlob* key_material,
                                                              AuthorizationSet* hw_enforced,
                                                              AuthorizationSet* sw_enforced) {
    const uint8_t* p = key_blob.begin();
    const uint8_t* end = key_blob.end() - HMAC_SIZE;

    if (p > end)
        return KM_ERROR_INVALID_KEY_BLOB;

    if (*p != BLOB_VERSION)
        return KM_ERROR_INVALID_KEY_BLOB;
    ++p;

    if (!key_material->Deserialize(&p, end) ||  //
        !hw_enforced->Deserialize(&p, end) ||   //
        !sw_enforced->Deserialize(&p, end))
        return KM_ERROR_INVALID_KEY_BLOB;

    return KM_ERROR_OK;
}

}  // namespace keymaster;
