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         return false;
     80     };
     81 
     82     // Unreachable.
     83     assert(false);
     84     return false;
     85 }
     86 
     87 bool OperationFactory::GetAndValidatePadding(const AuthorizationSet& begin_params, const Key& key,
     88                                              keymaster_padding_t* padding,
     89                                              keymaster_error_t* error) const {
     90     *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
     91     if (!begin_params.GetTagValue(TAG_PADDING, padding)) {
     92         LOG_E("%d padding modes specified in begin params", begin_params.GetTagCount(TAG_PADDING));
     93         return false;
     94     } else if (!supported(*padding)) {
     95         LOG_E("Padding mode %d not supported", *padding);
     96         return false;
     97     } else if (
     98         // If it's a public key operation, all padding modes are authorized.
     99         !is_public_key_operation() &&
    100         // Otherwise the key needs to authorize the specific mode.
    101         !key.authorizations().Contains(TAG_PADDING, *padding) &&
    102         !key.authorizations().Contains(TAG_PADDING_OLD, *padding)) {
    103         LOG_E("Padding mode %d was specified, but not authorized by key", *padding);
    104         *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
    105         return false;
    106     }
    107 
    108     *error = KM_ERROR_OK;
    109     return true;
    110 }
    111 
    112 bool OperationFactory::GetAndValidateDigest(const AuthorizationSet& begin_params, const Key& key,
    113                                             keymaster_digest_t* digest,
    114                                             keymaster_error_t* error) const {
    115     *error = KM_ERROR_UNSUPPORTED_DIGEST;
    116     if (!begin_params.GetTagValue(TAG_DIGEST, digest)) {
    117         LOG_E("%d digests specified in begin params", begin_params.GetTagCount(TAG_DIGEST));
    118         return false;
    119     } else if (!supported(*digest)) {
    120         LOG_E("Digest %d not supported", *digest);
    121         return false;
    122     } else if (
    123         // If it's a public key operation, all digests are authorized.
    124         !is_public_key_operation() &&
    125         // Otherwise the key needs to authorize the specific digest.
    126         !key.authorizations().Contains(TAG_DIGEST, *digest) &&
    127         !key.authorizations().Contains(TAG_DIGEST_OLD, *digest)) {
    128         LOG_E("Digest %d was specified, but not authorized by key", *digest);
    129         *error = KM_ERROR_INCOMPATIBLE_DIGEST;
    130         return false;
    131     }
    132     *error = KM_ERROR_OK;
    133     return true;
    134 }
    135 
    136 }  // namespace keymaster
    137