1f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen/*
2f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * Copyright 2015 The Android Open Source Project
3f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen *
4f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * Licensed under the Apache License, Version 2.0 (the "License");
5f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * you may not use this file except in compliance with the License.
6f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * You may obtain a copy of the License at
7f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen *
8f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen *      http://www.apache.org/licenses/LICENSE-2.0
9f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen *
10f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * Unless required by applicable law or agreed to in writing, software
11f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * distributed under the License is distributed on an "AS IS" BASIS,
12f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * See the License for the specific language governing permissions and
14f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen * limitations under the License.
15f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen */
16f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
17f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen#include "iso18033kdf.h"
18f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen#include "openssl_utils.h"
19f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
20f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen#include <algorithm>
21f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
22f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen#include <openssl/evp.h>
23f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
24f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyennamespace keymaster {
25f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
26f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyeninline size_t min(size_t a, size_t b) {
27f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    return (a < b) ? a : b;
28f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen}
29f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
30f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyenbool Iso18033Kdf::GenerateKey(const uint8_t* info, size_t info_len, uint8_t* output,
31f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen                              size_t output_len) {
32f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    if (!is_initialized_ || output == nullptr)
33f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        return false;
34f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
35f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    /* Check whether output length is too long as specified in ISO/IEC 18033-2. */
36f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    if ((0xFFFFFFFFULL + start_counter_) * digest_size_ < (uint64_t)output_len)
37f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        return false;
38f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
39f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    EVP_MD_CTX ctx;
40f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    EvpMdCtxCleaner ctxCleaner(&ctx);
41f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    EVP_MD_CTX_init(&ctx);
42f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
43f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    size_t num_blocks = (output_len + digest_size_ - 1) / digest_size_;
44f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    UniquePtr<uint8_t[]> counter(new uint8_t[4]);
45f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    UniquePtr<uint8_t[]> digest_result(new uint8_t[digest_size_]);
46f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    if (counter.get() == nullptr || digest_result.get() == nullptr)
47f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        return false;
48f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    for (size_t block = 0; block < num_blocks; block++) {
49f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        switch (digest_type_) {
50f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        case KM_DIGEST_SHA1:
51f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen            if (!EVP_DigestInit_ex(&ctx, EVP_sha1(), nullptr /* default digest */))
52f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen                return false;
53f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen            break;
54f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        case KM_DIGEST_SHA_2_256:
55f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen            if (!EVP_DigestInit_ex(&ctx, EVP_sha256(), nullptr /* default digest */))
56f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen                return false;
57f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen            break;
58f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        default:
59f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen            return false;
60f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        }
61f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
62f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        if (!EVP_DigestUpdate(&ctx, secret_key_.get(), secret_key_len_) ||
63f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen            !Uint32ToBigEndianByteArray(block + start_counter_, counter.get()) ||
64f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen            !EVP_DigestUpdate(&ctx, counter.get(), 4))
65f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen            return false;
66f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
67f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        if (info != nullptr && info_len > 0) {
68f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen            if (!EVP_DigestUpdate(&ctx, info, info_len))
69f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen                return false;
70f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        }
71f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
72f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        /* OpenSSL does not accept size_t parameter. */
73f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        uint32_t uint32_digest_size_ = digest_size_;
74f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        if (!EVP_DigestFinal_ex(&ctx, digest_result.get(), &uint32_digest_size_) ||
75f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen            uint32_digest_size_ != digest_size_)
76f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen            return false;
77f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
78f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        size_t block_start = digest_size_ * block;
79f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        size_t block_length = min(digest_size_, output_len - block_start);
80f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen        memcpy(output + block_start, digest_result.get(), block_length);
81f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    }
82f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen    return true;
83f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen}
84f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen
85f7538e0127ec2cb5202b0cbc64ad8305aae6243bQuan Nguyen}  // namespace keymaster
86