Home | History | Annotate | Download | only in android_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 <keymaster/authorization_set.h>
     18 #include <keymaster/key.h>
     19 #include <keymaster/operation.h>
     20 
     21 
     22 namespace keymaster {
     23 
     24 bool OperationFactory::supported(keymaster_padding_t padding) const {
     25     size_t padding_count;
     26     const keymaster_padding_t* supported_paddings = SupportedPaddingModes(&padding_count);
     27     for (size_t i = 0; i < padding_count; ++i)
     28         if (padding == supported_paddings[i])
     29             return true;
     30     return false;
     31 }
     32 
     33 bool OperationFactory::supported(keymaster_block_mode_t block_mode) const {
     34     size_t block_mode_count;
     35     const keymaster_block_mode_t* supported_block_modes = SupportedBlockModes(&block_mode_count);
     36     for (size_t i = 0; i < block_mode_count; ++i)
     37         if (block_mode == supported_block_modes[i])
     38             return true;
     39     return false;
     40 }
     41 
     42 bool OperationFactory::supported(keymaster_digest_t digest) const {
     43     size_t digest_count;
     44     const keymaster_digest_t* supported_digests = SupportedDigests(&digest_count);
     45     for (size_t i = 0; i < digest_count; ++i)
     46         if (digest == supported_digests[i])
     47             return true;
     48     return false;
     49 }
     50 
     51 inline bool is_public_key_algorithm(keymaster_algorithm_t algorithm) {
     52     switch (algorithm) {
     53     case KM_ALGORITHM_HMAC:
     54     case KM_ALGORITHM_AES:
     55     case KM_ALGORITHM_TRIPLE_DES:
     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     case KM_PURPOSE_WRAP:
     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::UpdateForFinish(const AuthorizationSet& input_params,
    139                                              const Buffer& input) {
    140     if (!input_params.empty() || input.available_read()) {
    141         size_t input_consumed;
    142         Buffer output;
    143         AuthorizationSet output_params;
    144         keymaster_error_t error =
    145             Update(input_params, input, &output_params, &output, &input_consumed);
    146         if (error != KM_ERROR_OK)
    147             return error;
    148         assert(input_consumed == input.available_read());
    149         assert(output_params.empty());
    150         assert(output.available_read() == 0);
    151     }
    152 
    153     return KM_ERROR_OK;
    154 }
    155 
    156 }  // namespace keymaster
    157