CKM: Max chunk size test
[platform/core/test/security-tests.git] / src / ckm / unprivileged / encryption-decryption-env.cpp
1 /*
2  *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
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  * @file       encryption-decryption-env.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21
22 #include <encryption-decryption-env.h>
23 #include <ckm-common.h>
24
25 using namespace CKM;
26
27 EncryptionError SyncApi::encrypt(ckmc_param_list_h params,
28                                  const char *key_alias,
29                                  const char *password,
30                                  const ckmc_raw_buffer_s& decrypted,
31                                  ckmc_raw_buffer_s **ppencrypted)
32 {
33     return ckmcError2Result(ckmc_encrypt_data(params, key_alias, password, decrypted, ppencrypted));
34 }
35
36 EncryptionError SyncApi::decrypt(ckmc_param_list_h params,
37                                  const char *key_alias,
38                                  const char *password,
39                                  const ckmc_raw_buffer_s& encrypted,
40                                  ckmc_raw_buffer_s **ppdecrypted)
41 {
42     return ckmcError2Result(ckmc_decrypt_data(params, key_alias, password, encrypted, ppdecrypted));
43 }
44
45 EncryptionError SyncApi::ckmcError2Result(int error) {
46     switch (error) {
47     case CKMC_ERROR_NONE:                   return EncryptionError::SUCCESS;
48     case CKMC_ERROR_INVALID_PARAMETER:      return EncryptionError::INVALID_PARAM;
49     case CKMC_ERROR_SERVER_ERROR:           return EncryptionError::SERVER_ERROR;
50     case CKMC_ERROR_DB_ALIAS_UNKNOWN:       return EncryptionError::ALIAS_UNKNOWN;
51     case CKMC_ERROR_AUTHENTICATION_FAILED:  return EncryptionError::AUTH_FAILED;
52     default:                                return EncryptionError::OTHER;
53     }
54 }
55
56
57
58 void AsyncApi::Observer::ReceivedError(int error) {
59     Finished(error);
60 }
61 void AsyncApi::Observer::ReceivedEncrypted(RawBuffer && buffer) {
62     m_buffer = std::move(buffer);
63     Finished();
64 }
65
66 void AsyncApi::Observer::ReceivedDecrypted(RawBuffer && buffer) {
67     m_buffer = std::move(buffer);
68     Finished();
69 }
70
71 void AsyncApi::Observer::WaitForResponse() {
72     std::unique_lock<std::mutex> lock(m_mutex);
73     m_cv.wait(lock, [this] {return m_finished;});
74 }
75 void AsyncApi::Observer::Finished(int error)
76 {
77     m_error = error;
78     m_finished = true;
79     m_cv.notify_one();
80 }
81
82 EncryptionError AsyncApi::crypt(cryptoFn operation,
83                                 ckmc_param_list_h params,
84                                 const char *key_alias,
85                                 const char *password,
86                                 const ckmc_raw_buffer_s& in,
87                                 ckmc_raw_buffer_s **ppout)
88 {
89     // C++ API doesn't have to check that
90     if(!params || !key_alias || !ppout)
91         return EncryptionError::INVALID_PARAM;
92
93     CKM::ManagerAsync mgr;
94     std::shared_ptr<Observer> obs = std::make_shared<Observer>();
95
96     // params
97     const CryptoAlgorithm* ca = reinterpret_cast<const CryptoAlgorithm*>(params);
98
99     // password
100     Password pass;
101     if (password)
102         pass = password;
103
104     // buffer
105     RawBuffer inBuffer(in.data, in.data + in.size);
106
107     // crypto operation
108     (mgr.*operation)(obs, *ca, key_alias, pass, inBuffer);
109     obs->WaitForResponse();
110     if(obs->m_error != CKM_API_SUCCESS)
111         return ckmError2Result(obs->m_error);
112
113     int ret = ckmc_buffer_new(obs->m_buffer.data(), obs->m_buffer.size(), ppout);
114     if (ret != CKMC_ERROR_NONE)
115         return EncryptionError::OTHER;
116
117     return EncryptionError::SUCCESS;
118 }
119
120 EncryptionError AsyncApi::encrypt(ckmc_param_list_h params,
121                                   const char *key_alias,
122                                   const char *password,
123                                   const ckmc_raw_buffer_s& plain,
124                                   ckmc_raw_buffer_s **ppencrypted)
125 {
126     return crypt(&CKM::ManagerAsync::encrypt, params, key_alias, password, plain, ppencrypted);
127 }
128
129 EncryptionError AsyncApi::decrypt(ckmc_param_list_h params,
130                                   const char *key_alias,
131                                   const char *password,
132                                   const ckmc_raw_buffer_s& encrypted,
133                                   ckmc_raw_buffer_s **ppdecrypted)
134 {
135     return crypt(&CKM::ManagerAsync::decrypt, params, key_alias, password, encrypted, ppdecrypted);
136 }
137
138 EncryptionError AsyncApi::ckmError2Result(int error)
139 {
140     switch (error) {
141     case CKM_API_SUCCESS:                      return EncryptionError::SUCCESS;
142     case CKM_API_ERROR_INPUT_PARAM:            return EncryptionError::INVALID_PARAM;
143     case CKM_API_ERROR_SERVER_ERROR:           return EncryptionError::SERVER_ERROR;
144     case CKM_API_ERROR_DB_ALIAS_UNKNOWN:       return EncryptionError::ALIAS_UNKNOWN;
145     case CKM_API_ERROR_AUTHENTICATION_FAILED:  return EncryptionError::AUTH_FAILED;
146     default:                                   return EncryptionError::OTHER;
147     }
148 }
149
150 int CipherApi::crypt(ckmc_cipher_ctx_h ctx,
151                      unsigned char *ptr,
152                      size_t left,
153                      CKM::RawBuffer& output)
154 {
155 #ifdef TZ_BACKEND
156     ckmc_backend_info_h info;
157     size_t maxSize;
158     // All unexportable keys go to TZ if enabled (and all of them are unexportable)
159     assert_positive(ckmc_get_backend_info, CKMC_BACKEND_TZ, &info);
160     assert_positive(ckmc_backend_get_max_chunk_size, info, &maxSize);
161     const size_t CHUNK_SIZE = 80 < maxSize ? 80 : maxSize;
162 #else
163     const size_t CHUNK_SIZE = 80;
164 #endif
165     ckmc_raw_buffer_s* out = nullptr;
166     ckmc_raw_buffer_s* in = nullptr;
167     size_t size = CHUNK_SIZE;
168     int ret = CKMC_ERROR_NONE;
169
170     while (left > 0) {
171         if (left < CHUNK_SIZE)
172             size = left;
173
174         ret = ckmc_buffer_new(ptr, size, &in);
175         if (ret != CKMC_ERROR_NONE)
176             goto crypt_fail;
177
178         ret = ckmc_cipher_update(ctx, *in, &out);
179         if (ret != CKMC_ERROR_NONE)
180             goto crypt_fail;
181
182         ckmc_buffer_free(in);
183         in = nullptr;
184         if (out != nullptr)
185             std::copy(out->data, out->data + out->size, std::back_inserter(output));
186
187         ckmc_buffer_free(out);
188         out = nullptr;
189
190         left -= size;
191         ptr += size;
192     }
193
194 crypt_fail:
195     ckmc_buffer_free(out);
196     ckmc_buffer_free(in);
197     return ret;
198 }
199
200 EncryptionError CipherApi::encrypt(ckmc_param_list_h params,
201                                    const char *key_alias,
202                                    const char *password,
203                                    const ckmc_raw_buffer_s& plain,
204                                    ckmc_raw_buffer_s **ppencrypted)
205 {
206     ckmc_cipher_ctx_h ctx = nullptr;
207     size_t left = plain.size;
208     unsigned char* ptr = plain.data;
209     CKM::RawBuffer encrypted;
210     ckmc_raw_buffer_s* out = nullptr;
211     ckmc_raw_buffer_s* encrypted_c = nullptr;
212     uint64_t algo;
213
214     int ret = ckmc_param_list_get_integer(params, CKMC_PARAM_ALGO_TYPE, &algo);
215     if (ret != CKMC_ERROR_NONE)
216         goto encrypt_fail;
217
218     // encrypt
219     ret = ckmc_cipher_initialize(params, key_alias, password, true, &ctx);
220     if (ret != CKMC_ERROR_NONE)
221         goto encrypt_fail;
222
223     ret = crypt(ctx, ptr, left, encrypted);
224     if (ret != CKMC_ERROR_NONE)
225         goto encrypt_fail;
226
227     ret = ckmc_cipher_finalize(ctx, nullptr, &out);
228     if (ret != CKMC_ERROR_NONE)
229         goto encrypt_fail;
230
231     // make sure finalize returns exactly the tag
232     if (algo == CKMC_ALGO_AES_GCM) {
233         uint64_t tagLen = 128;
234         ret = ckmc_param_list_get_integer(params, CKMC_PARAM_ED_TAG_LEN, &tagLen);
235         if (ret != CKMC_ERROR_NONE && ret != CKMC_ERROR_INVALID_PARAMETER)
236             goto encrypt_fail;
237
238         if (tagLen / 8 != out->size) {
239             ret = CKMC_ERROR_SERVER_ERROR;
240             goto encrypt_fail;
241         }
242     }
243
244     if (out != nullptr)
245         std::copy(out->data, out->data + out->size, std::back_inserter(encrypted));
246     out = nullptr;
247
248     ret = ckmc_buffer_new(encrypted.data(), encrypted.size(), &encrypted_c);
249     if (ret != CKMC_ERROR_NONE)
250         goto encrypt_fail;
251
252     *ppencrypted = encrypted_c;
253
254 encrypt_fail:
255     ckmc_buffer_free(out);
256     ckmc_cipher_free(ctx);
257
258     return ckmcError2Result(ret);
259 }
260
261 EncryptionError CipherApi::decrypt(ckmc_param_list_h params,
262                                    const char *key_alias,
263                                    const char *password,
264                                    const ckmc_raw_buffer_s& encrypted,
265                                    ckmc_raw_buffer_s **ppdecrypted)
266 {
267     ckmc_cipher_ctx_h ctx = nullptr;
268     size_t left = encrypted.size;
269     unsigned char* ptr = encrypted.data;
270     CKM::RawBuffer decrypted;
271     ckmc_raw_buffer_s* out = nullptr;
272     ckmc_raw_buffer_s* decrypted_c = nullptr;
273     ckmc_raw_buffer_s* tag = nullptr;
274     uint64_t algo;
275
276     int ret = ckmc_param_list_get_integer(params, CKMC_PARAM_ALGO_TYPE, &algo);
277     if (ret != CKMC_ERROR_NONE)
278         goto decrypt_fail;
279
280     // extract the tag to pass in finalize
281     if (algo == CKMC_ALGO_AES_GCM) {
282         uint64_t tagLen = 128;
283         ret = ckmc_param_list_get_integer(params, CKMC_PARAM_ED_TAG_LEN, &tagLen);
284         if (ret != CKMC_ERROR_NONE && ret != CKMC_ERROR_INVALID_PARAMETER)
285             goto decrypt_fail;
286
287         tagLen /= 8;
288         if (tagLen > left) {
289             ret = CKMC_ERROR_INVALID_PARAMETER;
290             goto decrypt_fail;
291         }
292
293         ret = ckmc_buffer_new(encrypted.data + encrypted.size - tagLen, tagLen, &tag);
294         if (ret != CKMC_ERROR_NONE)
295             goto decrypt_fail;
296
297         left -= tagLen;
298     }
299
300     // decrypt
301     ret = ckmc_cipher_initialize(params, key_alias, password, false, &ctx);
302     if (ret != CKMC_ERROR_NONE)
303         goto decrypt_fail;
304
305     ret = crypt(ctx, ptr, left, decrypted);
306     if (ret != CKMC_ERROR_NONE)
307         goto decrypt_fail;
308
309     ret = ckmc_cipher_finalize(ctx, tag, &out);
310     if (ret != CKMC_ERROR_NONE)
311         goto decrypt_fail;
312
313     if (out != nullptr)
314         std::copy(out->data, out->data + out->size, std::back_inserter(decrypted));
315     out = nullptr;
316
317     ret = ckmc_buffer_new(decrypted.data(), decrypted.size(), &decrypted_c);
318     if (ret != CKMC_ERROR_NONE)
319         goto decrypt_fail;
320
321     *ppdecrypted = decrypted_c;
322
323 decrypt_fail:
324     ckmc_cipher_free(ctx);
325     ckmc_buffer_free(out);
326     ckmc_buffer_free(tag);
327
328     return ckmcError2Result(ret);
329 }
330
331 EncryptionError CipherApi::ckmcError2Result(int error)
332 {
333     switch (error) {
334     case CKMC_ERROR_NONE:                   return EncryptionError::SUCCESS;
335     case CKMC_ERROR_INVALID_PARAMETER:      return EncryptionError::INVALID_PARAM;
336     case CKMC_ERROR_SERVER_ERROR:           return EncryptionError::SERVER_ERROR;
337     case CKMC_ERROR_DB_ALIAS_UNKNOWN:       return EncryptionError::ALIAS_UNKNOWN;
338     case CKMC_ERROR_AUTHENTICATION_FAILED:  return EncryptionError::AUTH_FAILED;
339     default:                                return EncryptionError::OTHER;
340     }
341 }