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 "ec_keymaster1_key.h"
     18 
     19 #include <memory>
     20 
     21 #include <keymaster/logger.h>
     22 
     23 #include "ecdsa_keymaster1_operation.h"
     24 #include "ecdsa_operation.h"
     25 
     26 using std::unique_ptr;
     27 
     28 namespace keymaster {
     29 
     30 EcdsaKeymaster1KeyFactory::EcdsaKeymaster1KeyFactory(const SoftKeymasterContext* context,
     31                                                      const Keymaster1Engine* engine)
     32     : EcKeyFactory(context), engine_(engine),
     33       sign_factory_(new EcdsaKeymaster1OperationFactory(KM_PURPOSE_SIGN, engine)),
     34       // For pubkey ops we can use the normal operation factories.
     35       verify_factory_(new EcdsaVerifyOperationFactory) {}
     36 
     37 static bool is_supported(uint32_t digest) {
     38     return digest == KM_DIGEST_NONE || digest == KM_DIGEST_SHA_2_256;
     39 }
     40 
     41 static void UpdateToWorkAroundUnsupportedDigests(const AuthorizationSet& key_description,
     42                                                  AuthorizationSet* new_description) {
     43     bool have_unsupported_digests = false;
     44     bool have_digest_none = false;
     45     for (const keymaster_key_param_t& entry : key_description) {
     46         new_description->push_back(entry);
     47 
     48         if (entry.tag == TAG_DIGEST) {
     49             if (entry.enumerated == KM_DIGEST_NONE) {
     50                 have_digest_none = true;
     51             } else if (!is_supported(entry.enumerated)) {
     52                 LOG_D("Found request for unsupported digest %u", entry.enumerated);
     53                 have_unsupported_digests = true;
     54             }
     55         }
     56     }
     57 
     58     if (have_unsupported_digests && !have_digest_none) {
     59         LOG_I("Adding KM_DIGEST_NONE to key authorization, to enable software digesting", 0);
     60         new_description->push_back(TAG_DIGEST, KM_DIGEST_NONE);
     61     }
     62 }
     63 
     64 keymaster_error_t EcdsaKeymaster1KeyFactory::GenerateKey(const AuthorizationSet& key_description,
     65                                                          KeymasterKeyBlob* key_blob,
     66                                                          AuthorizationSet* hw_enforced,
     67                                                          AuthorizationSet* sw_enforced) const {
     68     AuthorizationSet key_params_copy;
     69     UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
     70     return engine_->GenerateKey(key_params_copy, key_blob, hw_enforced, sw_enforced);
     71 }
     72 
     73 keymaster_error_t EcdsaKeymaster1KeyFactory::ImportKey(
     74     const AuthorizationSet& key_description, keymaster_key_format_t input_key_material_format,
     75     const KeymasterKeyBlob& input_key_material, KeymasterKeyBlob* output_key_blob,
     76     AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) const {
     77     AuthorizationSet key_params_copy;
     78     UpdateToWorkAroundUnsupportedDigests(key_description, &key_params_copy);
     79     return engine_->ImportKey(key_params_copy, input_key_material_format, input_key_material,
     80                               output_key_blob, hw_enforced, sw_enforced);
     81 }
     82 
     83 keymaster_error_t EcdsaKeymaster1KeyFactory::LoadKey(const KeymasterKeyBlob& key_material,
     84                                                      const AuthorizationSet& additional_params,
     85                                                      const AuthorizationSet& hw_enforced,
     86                                                      const AuthorizationSet& sw_enforced,
     87                                                      UniquePtr<Key>* key) const {
     88     if (!key)
     89         return KM_ERROR_OUTPUT_PARAMETER_NULL;
     90 
     91     keymaster_error_t error;
     92     unique_ptr<EC_KEY, EC_KEY_Delete> ecdsa(
     93         engine_->BuildEcKey(key_material, additional_params, &error));
     94     if (!ecdsa)
     95         return error;
     96 
     97     key->reset(new (std::nothrow)
     98                    EcdsaKeymaster1Key(ecdsa.release(), hw_enforced, sw_enforced, &error));
     99     if (!key->get())
    100         error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
    101 
    102     if (error != KM_ERROR_OK)
    103         return error;
    104 
    105     return KM_ERROR_OK;
    106 }
    107 
    108 OperationFactory*
    109 EcdsaKeymaster1KeyFactory::GetOperationFactory(keymaster_purpose_t purpose) const {
    110     switch (purpose) {
    111     case KM_PURPOSE_SIGN:
    112         return sign_factory_.get();
    113     case KM_PURPOSE_VERIFY:
    114         return verify_factory_.get();
    115     default:
    116         return nullptr;
    117     }
    118 }
    119 
    120 }  // namespace keymaster
    121