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

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 uint8_t[hidden_bytes_size]);
    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();

    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;
