/*
 * 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;

    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;
