Add support for different AES key sizes
[platform/core/security/key-manager.git] / src / manager / crypto / sw-backend / crypto.h
1 /* Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
2  *
3  *  Licensed under the Apache License, Version 2.0 (the "License");
4  *  you may not use this file except in compliance with the License.
5  *  You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  *  Unless required by applicable law or agreed to in writing, software
10  *  distributed under the License is distributed on an "AS IS" BASIS,
11  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  *  See the License for the specific language governing permissions and
13  *  limitations under the License
14  *
15  *
16  * @file        crypto.h
17  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
18  * @version     1.0
19  * @brief       Crypto module implementation.
20  */
21 #pragma once
22
23 #include <vector>
24
25 #include <openssl/evp.h>
26
27 #include <dpl/log/log.h>
28 #include <dpl/raw-buffer.h>
29
30 #include <generic-backend/exception.h>
31
32 namespace CKM {
33 namespace Crypto {
34 namespace SW {
35 namespace Cipher {
36
37 template<class T>
38 struct Base {
39     Base()
40       : m_ctx(EVP_CIPHER_CTX_new())
41     {
42         static_assert(sizeof(typename T::value_type) == 1, "Unsupported type inside conatainer.");
43     }
44     Base(const Base&) = delete;
45     Base(Base &&) = delete;
46     Base<T>& operator=(const Base&) = delete;
47     Base<T>& operator=(Base &&) = delete;
48
49     // Low level api.
50     // Allows various cipher specific parameters to be determined and set.
51     int Control(int type, int arg, void *ptr) {
52         return EVP_CIPHER_CTX_ctrl(m_ctx, type, arg, ptr);
53     }
54
55     virtual T Append(const T&) = 0;
56     virtual T Finalize() = 0;
57     virtual ~Base(){
58         EVP_CIPHER_CTX_free(m_ctx);
59     }
60 protected:
61     EVP_CIPHER_CTX *m_ctx;
62 };
63
64 template<class T>
65 class EvpCipherWrapper : public Base<T> {
66 public:
67     using Base<T>::m_ctx;
68
69     EvpCipherWrapper(const EVP_CIPHER *type, const T &key, const T &iv, bool encryption)
70     {
71         if (static_cast<int>(key.size()) != EVP_CIPHER_key_length(type)) {
72             ThrowErr(Exc::Crypto::InternalError, "Wrong key size! Expected: ", EVP_CIPHER_key_length(type) ," Get: ", key.size());
73         }
74
75         if (static_cast<int>(iv.size()) < EVP_CIPHER_iv_length(type)) {
76             ThrowErr(Exc::Crypto::InternalError, "Wrong iv size! Expected: ", EVP_CIPHER_iv_length(type) , " Get: ", iv.size());
77         }
78
79         if (1 != EVP_CipherInit_ex(m_ctx, type, NULL, key.data(), iv.data(), encryption ? 1 : 0)) {
80             ThrowErr(Exc::Crypto::InternalError, "Failed in EVP_CipherInit");
81         }
82
83         EVP_CIPHER_CTX_set_padding(m_ctx, 1);
84     }
85
86     T Append(const T& data) {
87         static_assert(sizeof(typename T::value_type) == 1, "Unsupported type inside container.");
88         int bytesLen = static_cast<int>(data.size() + EVP_CIPHER_CTX_block_size(m_ctx));
89         T output(bytesLen);
90         if (1 != EVP_CipherUpdate(m_ctx, output.data(), &bytesLen, data.data(), data.size())) {
91             ThrowErr(Exc::Crypto::InternalError, "Failed in EVP_CipherUpdate");
92         }
93         output.resize(bytesLen);
94         return output;
95     }
96
97     T Finalize() {
98         int bytesLen = EVP_CIPHER_CTX_block_size(m_ctx);
99         T output(bytesLen);
100         if (1 != EVP_CipherFinal_ex(m_ctx, output.data(), &bytesLen)) {
101             ThrowErr(Exc::Crypto::InternalError, "Failed in EVP_CipherFinal");
102         }
103         output.resize(bytesLen);
104         return output;
105     }
106 };
107
108 #define DEFINE_CIPHER(__classname, __type, __evpcipher, __encryption) \
109 class __classname : public EvpCipherWrapper<__type> {                 \
110 public:                                                               \
111     __classname(const __type &key, const __type &iv)                  \
112       : EvpCipherWrapper(__evpcipher, key, iv, __encryption)          \
113     {}                                                                \
114 }
115
116 DEFINE_CIPHER(AesCbcEncryption128, RawBuffer, EVP_aes_128_cbc(), true);
117 DEFINE_CIPHER(AesCbcDecryption128, RawBuffer, EVP_aes_128_cbc(), false);
118 DEFINE_CIPHER(AesCbcEncryption192, RawBuffer, EVP_aes_192_cbc(), true);
119 DEFINE_CIPHER(AesCbcDecryption192, RawBuffer, EVP_aes_192_cbc(), false);
120 DEFINE_CIPHER(AesCbcEncryption256, RawBuffer, EVP_aes_256_cbc(), true);
121 DEFINE_CIPHER(AesCbcDecryption256, RawBuffer, EVP_aes_256_cbc(), false);
122
123 DEFINE_CIPHER(AesGcmEncryption128, RawBuffer, EVP_aes_128_gcm(), true);
124 DEFINE_CIPHER(AesGcmDecryption128, RawBuffer, EVP_aes_128_gcm(), false);
125 DEFINE_CIPHER(AesGcmEncryption192, RawBuffer, EVP_aes_192_gcm(), true);
126 DEFINE_CIPHER(AesGcmDecryption192, RawBuffer, EVP_aes_192_gcm(), false);
127 DEFINE_CIPHER(AesGcmEncryption256, RawBuffer, EVP_aes_256_gcm(), true);
128 DEFINE_CIPHER(AesGcmDecryption256, RawBuffer, EVP_aes_256_gcm(), false);
129
130 #undef DEFINE_CIPHER
131
132 } // namespace Cipher
133 } // namespace SW
134 } // namespace Crypto
135 } // namespace CKM
136