2 * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 * @file encryption-decryption-env.cpp
18 * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
22 #include <encryption-decryption-env.h>
26 EncryptionError SyncApi::encrypt(ckmc_param_list_h params,
27 const char *key_alias,
29 const ckmc_raw_buffer_s& decrypted,
30 ckmc_raw_buffer_s **ppencrypted)
32 return ckmcError2Result(ckmc_encrypt_data(params, key_alias, password, decrypted, ppencrypted));
35 EncryptionError SyncApi::decrypt(ckmc_param_list_h params,
36 const char *key_alias,
38 const ckmc_raw_buffer_s& encrypted,
39 ckmc_raw_buffer_s **ppdecrypted)
41 return ckmcError2Result(ckmc_decrypt_data(params, key_alias, password, encrypted, ppdecrypted));
44 EncryptionError SyncApi::ckmcError2Result(int 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;
57 void AsyncApi::Observer::ReceivedError(int error) {
60 void AsyncApi::Observer::ReceivedEncrypted(RawBuffer && buffer) {
61 m_buffer = std::move(buffer);
65 void AsyncApi::Observer::ReceivedDecrypted(RawBuffer && buffer) {
66 m_buffer = std::move(buffer);
70 void AsyncApi::Observer::WaitForResponse() {
71 std::unique_lock<std::mutex> lock(m_mutex);
72 m_cv.wait(lock, [this] {return m_finished;});
74 void AsyncApi::Observer::Finished(int error)
81 EncryptionError AsyncApi::crypt(cryptoFn operation,
82 ckmc_param_list_h params,
83 const char *key_alias,
85 const ckmc_raw_buffer_s& in,
86 ckmc_raw_buffer_s **ppout)
88 // C++ API doesn't have to check that
89 if(!params || !key_alias || !ppout)
90 return EncryptionError::INVALID_PARAM;
92 CKM::ManagerAsync mgr;
93 std::shared_ptr<Observer> obs = std::make_shared<Observer>();
96 const CryptoAlgorithm* ca = reinterpret_cast<const CryptoAlgorithm*>(params);
104 RawBuffer inBuffer(in.data, in.data + in.size);
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);
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;
116 return EncryptionError::SUCCESS;
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)
125 return crypt(&CKM::ManagerAsync::encrypt, params, key_alias, password, plain, ppencrypted);
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)
134 return crypt(&CKM::ManagerAsync::decrypt, params, key_alias, password, encrypted, ppdecrypted);
137 EncryptionError AsyncApi::ckmError2Result(int 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;
149 int CipherApi::crypt(ckmc_cipher_ctx_h ctx,
152 CKM::RawBuffer& output)
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;
161 if (left < CHUNK_SIZE)
164 ret = ckmc_buffer_new(ptr, size, &in);
165 if (ret != CKMC_ERROR_NONE)
168 ret = ckmc_cipher_update(ctx, *in, &out);
169 if (ret != CKMC_ERROR_NONE)
172 ckmc_buffer_free(in);
175 std::copy(out->data, out->data + out->size, std::back_inserter(output));
177 ckmc_buffer_free(out);
185 ckmc_buffer_free(out);
186 ckmc_buffer_free(in);
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)
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;
204 int ret = ckmc_param_list_get_integer(params, CKMC_PARAM_ALGO_TYPE, &algo);
205 if (ret != CKMC_ERROR_NONE)
209 ret = ckmc_cipher_initialize(params, key_alias, password, true, &ctx);
210 if (ret != CKMC_ERROR_NONE)
213 ret = crypt(ctx, ptr, left, encrypted);
214 if (ret != CKMC_ERROR_NONE)
217 ret = ckmc_cipher_finalize(ctx, nullptr, &out);
218 if (ret != CKMC_ERROR_NONE)
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)
228 if (tagLen / 8 != out->size) {
229 ret = CKMC_ERROR_SERVER_ERROR;
235 std::copy(out->data, out->data + out->size, std::back_inserter(encrypted));
238 ret = ckmc_buffer_new(encrypted.data(), encrypted.size(), &encrypted_c);
239 if (ret != CKMC_ERROR_NONE)
242 *ppencrypted = encrypted_c;
245 ckmc_buffer_free(out);
246 ckmc_cipher_free(ctx);
248 return ckmcError2Result(ret);
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)
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;
266 int ret = ckmc_param_list_get_integer(params, CKMC_PARAM_ALGO_TYPE, &algo);
267 if (ret != CKMC_ERROR_NONE)
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)
279 ret = CKMC_ERROR_INVALID_PARAMETER;
283 ret = ckmc_buffer_new(encrypted.data + encrypted.size - tagLen, tagLen, &tag);
284 if (ret != CKMC_ERROR_NONE)
291 ret = ckmc_cipher_initialize(params, key_alias, password, false, &ctx);
292 if (ret != CKMC_ERROR_NONE)
295 ret = crypt(ctx, ptr, left, decrypted);
296 if (ret != CKMC_ERROR_NONE)
299 ret = ckmc_cipher_finalize(ctx, tag, &out);
300 if (ret != CKMC_ERROR_NONE)
304 std::copy(out->data, out->data + out->size, std::back_inserter(decrypted));
307 ret = ckmc_buffer_new(decrypted.data(), decrypted.size(), &decrypted_c);
308 if (ret != CKMC_ERROR_NONE)
311 *ppdecrypted = decrypted_c;
314 ckmc_cipher_free(ctx);
315 ckmc_buffer_free(out);
316 ckmc_buffer_free(tag);
318 return ckmcError2Result(ret);
321 EncryptionError CipherApi::ckmcError2Result(int 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;