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