Shawn Willden | a2f1a9b | 2018-01-09 09:37:43 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2018 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 | #ifndef SYSTEM_KEYMASTER_BLOCK_CIPHER_OPERATION_H_ |
| 18 | #define SYSTEM_KEYMASTER_BLOCK_CIPHER_OPERATION_H_ |
| 19 | |
| 20 | #include <openssl/evp.h> |
| 21 | |
| 22 | #include <keymaster/operation.h> |
| 23 | |
| 24 | namespace keymaster { |
| 25 | |
| 26 | /** |
| 27 | * EvpCipherDescription is an abstract interface that provides information about a block cipher. |
| 28 | */ |
| 29 | class EvpCipherDescription { |
| 30 | public: |
| 31 | virtual ~EvpCipherDescription() {} |
| 32 | virtual keymaster_algorithm_t algorithm() const = 0; |
| 33 | |
| 34 | virtual const keymaster_block_mode_t* SupportedBlockModes(size_t* block_mode_count) const = 0; |
| 35 | |
| 36 | virtual const EVP_CIPHER* GetCipherInstance(size_t key_size, keymaster_block_mode_t block_mode, |
| 37 | keymaster_error_t* error) const = 0; |
| 38 | |
| 39 | virtual size_t block_size_bytes() const = 0; |
| 40 | }; |
| 41 | |
| 42 | /** |
| 43 | * Abstract base for block cipher operation factories. This class does all of the work to create |
| 44 | * block cipher operations. |
| 45 | */ |
| 46 | class BlockCipherOperationFactory : public OperationFactory { |
| 47 | public: |
Chih-Hung Hsieh | 82ac341 | 2019-01-02 13:34:23 -0800 | [diff] [blame] | 48 | explicit BlockCipherOperationFactory(keymaster_purpose_t purpose) : purpose_(purpose) {} |
Shawn Willden | a2f1a9b | 2018-01-09 09:37:43 -0700 | [diff] [blame] | 49 | |
| 50 | KeyType registry_key() const override { |
| 51 | return KeyType(GetCipherDescription().algorithm(), purpose_); |
| 52 | } |
| 53 | |
| 54 | OperationPtr CreateOperation(Key&& key, const AuthorizationSet& begin_params, |
Matthew Maurer | a47727e | 2019-04-04 00:09:39 +0000 | [diff] [blame] | 55 | keymaster_error_t* error) override; |
Shawn Willden | a2f1a9b | 2018-01-09 09:37:43 -0700 | [diff] [blame] | 56 | |
| 57 | const keymaster_block_mode_t* SupportedBlockModes(size_t* block_mode_count) const override { |
| 58 | return GetCipherDescription().SupportedBlockModes(block_mode_count); |
| 59 | } |
| 60 | |
| 61 | const keymaster_padding_t* SupportedPaddingModes(size_t* padding_count) const override; |
| 62 | |
| 63 | virtual const EvpCipherDescription& GetCipherDescription() const = 0; |
| 64 | |
| 65 | private: |
| 66 | const keymaster_purpose_t purpose_; |
| 67 | }; |
| 68 | |
| 69 | class BlockCipherEvpOperation : public Operation { |
| 70 | public: |
| 71 | BlockCipherEvpOperation(keymaster_purpose_t purpose, keymaster_block_mode_t block_mode, |
| 72 | keymaster_padding_t padding, bool caller_iv, size_t tag_length, |
| 73 | Key&& key, const EvpCipherDescription& cipher_description); |
| 74 | ~BlockCipherEvpOperation(); |
| 75 | |
| 76 | keymaster_error_t Begin(const AuthorizationSet& input_params, |
| 77 | AuthorizationSet* output_params) override; |
| 78 | keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input, |
| 79 | AuthorizationSet* output_params, Buffer* output, |
| 80 | size_t* input_consumed) override; |
| 81 | keymaster_error_t Finish(const AuthorizationSet& additional_params, const Buffer& input, |
| 82 | const Buffer& signature, AuthorizationSet* output_params, |
| 83 | Buffer* output) override; |
| 84 | keymaster_error_t Abort() override; |
| 85 | |
| 86 | protected: |
| 87 | virtual int evp_encrypt_mode() = 0; |
| 88 | |
| 89 | bool need_iv() const; |
| 90 | keymaster_error_t InitializeCipher(KeymasterKeyBlob key); |
| 91 | keymaster_error_t GetIv(const AuthorizationSet& input_params); |
| 92 | bool HandleAad(const AuthorizationSet& input_params, const Buffer& input, |
| 93 | keymaster_error_t* error); |
| 94 | bool ProcessAadBlocks(const uint8_t* data, size_t blocks, keymaster_error_t* error); |
| 95 | void FillBufferedAadBlock(keymaster_blob_t* aad); |
| 96 | bool ProcessBufferedAadBlock(keymaster_error_t* error); |
| 97 | bool InternalUpdate(const uint8_t* input, size_t input_length, Buffer* output, |
| 98 | keymaster_error_t* error); |
| 99 | bool UpdateForFinish(const AuthorizationSet& additional_params, const Buffer& input, |
| 100 | AuthorizationSet* output_params, Buffer* output, keymaster_error_t* error); |
| 101 | size_t block_size_bytes() const { return cipher_description_.block_size_bytes(); } |
| 102 | |
| 103 | const keymaster_block_mode_t block_mode_; |
| 104 | EVP_CIPHER_CTX ctx_; |
| 105 | KeymasterBlob iv_; |
| 106 | const bool caller_iv_; |
| 107 | const size_t tag_length_; |
| 108 | |
| 109 | private: |
| 110 | UniquePtr<uint8_t[]> aad_block_buf_; |
| 111 | size_t aad_block_buf_len_; |
| 112 | bool data_started_; |
| 113 | const keymaster_padding_t padding_; |
| 114 | KeymasterKeyBlob key_; |
| 115 | const EvpCipherDescription& cipher_description_; |
| 116 | }; |
| 117 | |
| 118 | class BlockCipherEvpEncryptOperation : public BlockCipherEvpOperation { |
| 119 | public: |
| 120 | BlockCipherEvpEncryptOperation(keymaster_block_mode_t block_mode, keymaster_padding_t padding, |
| 121 | bool caller_iv, size_t tag_length, Key&& key, |
| 122 | const EvpCipherDescription& cipher_description) |
| 123 | : BlockCipherEvpOperation(KM_PURPOSE_ENCRYPT, block_mode, padding, caller_iv, tag_length, |
| 124 | move(key), cipher_description) {} |
| 125 | |
| 126 | keymaster_error_t Begin(const AuthorizationSet& input_params, |
| 127 | AuthorizationSet* output_params) override; |
| 128 | keymaster_error_t Finish(const AuthorizationSet& additional_params, const Buffer& input, |
| 129 | const Buffer& signature, AuthorizationSet* output_params, |
| 130 | Buffer* output) override; |
| 131 | |
| 132 | int evp_encrypt_mode() override { return 1; } |
| 133 | |
| 134 | private: |
| 135 | keymaster_error_t GenerateIv(); |
| 136 | }; |
| 137 | |
| 138 | class BlockCipherEvpDecryptOperation : public BlockCipherEvpOperation { |
| 139 | public: |
| 140 | BlockCipherEvpDecryptOperation(keymaster_block_mode_t block_mode, keymaster_padding_t padding, |
| 141 | size_t tag_length, Key&& key, |
| 142 | const EvpCipherDescription& cipher_description) |
| 143 | : BlockCipherEvpOperation(KM_PURPOSE_DECRYPT, block_mode, padding, |
| 144 | false /* caller_iv -- don't care */, tag_length, move(key), |
| 145 | cipher_description) {} |
| 146 | |
| 147 | keymaster_error_t Begin(const AuthorizationSet& input_params, |
| 148 | AuthorizationSet* output_params) override; |
| 149 | keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input, |
| 150 | AuthorizationSet* output_params, Buffer* output, |
| 151 | size_t* input_consumed) override; |
| 152 | keymaster_error_t Finish(const AuthorizationSet& additional_params, const Buffer& input, |
| 153 | const Buffer& signature, AuthorizationSet* output_params, |
| 154 | Buffer* output) override; |
| 155 | |
| 156 | int evp_encrypt_mode() override { return 0; } |
| 157 | |
| 158 | private: |
| 159 | size_t tag_buf_unused() { return tag_length_ - tag_buf_len_; } |
| 160 | |
| 161 | keymaster_error_t ProcessAllButTagLengthBytes(const Buffer& input, Buffer* output); |
| 162 | bool ProcessTagBufContentsAsData(size_t to_process, Buffer* output, keymaster_error_t* error); |
| 163 | void BufferCandidateTagData(const uint8_t* data, size_t data_length); |
| 164 | |
| 165 | UniquePtr<uint8_t[]> tag_buf_; |
| 166 | size_t tag_buf_len_; |
| 167 | }; |
| 168 | |
| 169 | } // namespace keymaster |
| 170 | |
| 171 | #endif // SYSTEM_KEYMASTER_BLOCK_CIPHER_OPERATION_H_ |