Home | History | Annotate | Download | only in keymaster
      1 /*
      2  * Copyright 2014 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 "operation.h"
     18 
     19 #include <keymaster/authorization_set.h>
     20 #include <keymaster/keymaster_context.h>
     21 
     22 #include "key.h"
     23 
     24 namespace keymaster {
     25 
     26 bool OperationFactory::supported(keymaster_padding_t padding) const {
     27     size_t padding_count;
     28     const keymaster_padding_t* supported_paddings = SupportedPaddingModes(&padding_count);
     29     for (size_t i = 0; i < padding_count; ++i)
     30         if (padding == supported_paddings[i])
     31             return true;
     32     return false;
     33 }
     34 
     35 bool OperationFactory::supported(keymaster_block_mode_t block_mode) const {
     36     size_t block_mode_count;
     37     const keymaster_block_mode_t* supported_block_modes = SupportedBlockModes(&block_mode_count);
     38     for (size_t i = 0; i < block_mode_count; ++i)
     39         if (block_mode == supported_block_modes[i])
     40             return true;
     41     return false;
     42 }
     43 
     44 bool OperationFactory::supported(keymaster_digest_t digest) const {
     45     size_t digest_count;
     46     const keymaster_digest_t* supported_digests = SupportedDigests(&digest_count);
     47     for (size_t i = 0; i < digest_count; ++i)
     48         if (digest == supported_digests[i])
     49             return true;
     50     return false;
     51 }
     52 
     53 inline bool is_public_key_algorithm(keymaster_algorithm_t algorithm) {
     54     switch (algorithm) {
     55     case KM_ALGORITHM_HMAC:
     56     case KM_ALGORITHM_AES:
     57         return false;
     58     case KM_ALGORITHM_RSA:
     59     case KM_ALGORITHM_EC:
     60         return true;
     61     }
     62 
     63     // Unreachable.
     64     assert(false);
     65     return false;
     66 }
     67 
     68 bool OperationFactory::is_public_key_operation() const {
     69     KeyType key_type = registry_key();
     70 
     71     if (!is_public_key_algorithm(key_type.algorithm))
     72         return false;
     73 
     74     switch (key_type.purpose) {
     75     case KM_PURPOSE_VERIFY:
     76     case KM_PURPOSE_ENCRYPT:
     77         return true;
     78     case KM_PURPOSE_SIGN:
     79     case KM_PURPOSE_DECRYPT:
     80     case KM_PURPOSE_DERIVE_KEY:
     81         return false;
     82     };
     83 
     84     // Unreachable.
     85     assert(false);
     86     return false;
     87 }
     88 
     89 bool OperationFactory::GetAndValidatePadding(const AuthorizationSet& begin_params, const Key& key,
     90                                              keymaster_padding_t* padding,
     91                                              keymaster_error_t* error) const {
     92     *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
     93     if (!begin_params.GetTagValue(TAG_PADDING, padding)) {
     94         LOG_E("%d padding modes specified in begin params", begin_params.GetTagCount(TAG_PADDING));
     95         return false;
     96     } else if (!supported(*padding)) {
     97         LOG_E("Padding mode %d not supported", *padding);
     98         return false;
     99     } else if (
    100         // If it's a public key operation, all padding modes are authorized.
    101         !is_public_key_operation() &&
    102         // Otherwise the key needs to authorize the specific mode.
    103         !key.authorizations().Contains(TAG_PADDING, *padding) &&
    104         !key.authorizations().Contains(TAG_PADDING_OLD, *padding)) {
    105         LOG_E("Padding mode %d was specified, but not authorized by key", *padding);
    106         *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
    107         return false;
    108     }
    109 
    110     *error = KM_ERROR_OK;
    111     return true;
    112 }
    113 
    114 bool OperationFactory::GetAndValidateDigest(const AuthorizationSet& begin_params, const Key& key,
    115                                             keymaster_digest_t* digest,
    116                                             keymaster_error_t* error) const {
    117     *error = KM_ERROR_UNSUPPORTED_DIGEST;
    118     if (!begin_params.GetTagValue(TAG_DIGEST, digest)) {
    119         LOG_E("%d digests specified in begin params", begin_params.GetTagCount(TAG_DIGEST));
    120         return false;
    121     } else if (!supported(*digest)) {
    122         LOG_E("Digest %d not supported", *digest);
    123         return false;
    124     } else if (
    125         // If it's a public key operation, all digests are authorized.
    126         !is_public_key_operation() &&
    127         // Otherwise the key needs to authorize the specific digest.
    128         !key.authorizations().Contains(TAG_DIGEST, *digest) &&
    129         !key.authorizations().Contains(TAG_DIGEST_OLD, *digest)) {
    130         LOG_E("Digest %d was specified, but not authorized by key", *digest);
    131         *error = KM_ERROR_INCOMPATIBLE_DIGEST;
    132         return false;
    133     }
    134     *error = KM_ERROR_OK;
    135     return true;
    136 }
    137 
    138 keymaster_error_t Operation::CreateOperationHandle(const KeymasterContext& context,
    139                                                    keymaster_operation_handle_t* op_handle) {
    140     return context.GenerateRandom(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle));
    141 }
    142 
    143 keymaster_error_t Operation::UpdateForFinish(const AuthorizationSet& input_params,
    144                                              const Buffer& input) {
    145     if (!input_params.empty() || input.available_read()) {
    146         size_t input_consumed;
    147         Buffer output;
    148         AuthorizationSet output_params;
    149         keymaster_error_t error =
    150             Update(input_params, input, &output_params, &output, &input_consumed);
    151         if (error != KM_ERROR_OK)
    152             return error;
    153         assert(input_consumed == input.available_read());
    154         assert(output_params.empty());
    155         assert(output.available_read() == 0);
    156     }
    157 
    158     return KM_ERROR_OK;
    159 }
    160 
    161 }  // namespace keymaster
    162