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