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