*/
#include <encryption-decryption-env.h>
+#include <ckm-common.h>
using namespace CKM;
default: return EncryptionError::OTHER;
}
}
+
+int CipherApi::crypt(ckmc_cipher_ctx_h ctx,
+ unsigned char *ptr,
+ size_t left,
+ CKM::RawBuffer& output)
+{
+#ifdef TZ_BACKEND
+ ckmc_backend_info_h info;
+ size_t maxSize;
+ // All unexportable keys go to TZ if enabled (and all of them are unexportable)
+ assert_positive(ckmc_get_backend_info, CKMC_BACKEND_TZ, &info);
+ assert_positive(ckmc_backend_get_max_chunk_size, info, &maxSize);
+ const size_t CHUNK_SIZE = 80 < maxSize ? 80 : maxSize;
+#else
+ const size_t CHUNK_SIZE = 80;
+#endif
+ ckmc_raw_buffer_s* out = nullptr;
+ ckmc_raw_buffer_s* in = nullptr;
+ size_t size = CHUNK_SIZE;
+ int ret = CKMC_ERROR_NONE;
+
+ while (left > 0) {
+ if (left < CHUNK_SIZE)
+ size = left;
+
+ ret = ckmc_buffer_new(ptr, size, &in);
+ if (ret != CKMC_ERROR_NONE)
+ goto crypt_fail;
+
+ ret = ckmc_cipher_update(ctx, *in, &out);
+ if (ret != CKMC_ERROR_NONE)
+ goto crypt_fail;
+
+ ckmc_buffer_free(in);
+ in = nullptr;
+ if (out != nullptr)
+ std::copy(out->data, out->data + out->size, std::back_inserter(output));
+
+ ckmc_buffer_free(out);
+ out = nullptr;
+
+ left -= size;
+ ptr += size;
+ }
+
+crypt_fail:
+ ckmc_buffer_free(out);
+ ckmc_buffer_free(in);
+ return ret;
+}
+
+EncryptionError CipherApi::encrypt(ckmc_param_list_h params,
+ const char *key_alias,
+ const char *password,
+ const ckmc_raw_buffer_s& plain,
+ ckmc_raw_buffer_s **ppencrypted)
+{
+ ckmc_cipher_ctx_h ctx = nullptr;
+ size_t left = plain.size;
+ unsigned char* ptr = plain.data;
+ CKM::RawBuffer encrypted;
+ ckmc_raw_buffer_s* out = nullptr;
+ ckmc_raw_buffer_s* encrypted_c = nullptr;
+ uint64_t algo;
+
+ int ret = ckmc_param_list_get_integer(params, CKMC_PARAM_ALGO_TYPE, &algo);
+ if (ret != CKMC_ERROR_NONE)
+ goto encrypt_fail;
+
+ // encrypt
+ ret = ckmc_cipher_initialize(params, key_alias, password, true, &ctx);
+ if (ret != CKMC_ERROR_NONE)
+ goto encrypt_fail;
+
+ ret = crypt(ctx, ptr, left, encrypted);
+ if (ret != CKMC_ERROR_NONE)
+ goto encrypt_fail;
+
+ ret = ckmc_cipher_finalize(ctx, nullptr, &out);
+ if (ret != CKMC_ERROR_NONE)
+ goto encrypt_fail;
+
+ // make sure finalize returns exactly the tag
+ if (algo == CKMC_ALGO_AES_GCM) {
+ uint64_t tagLen = 128;
+ ret = ckmc_param_list_get_integer(params, CKMC_PARAM_ED_TAG_LEN, &tagLen);
+ if (ret != CKMC_ERROR_NONE && ret != CKMC_ERROR_INVALID_PARAMETER)
+ goto encrypt_fail;
+
+ if (tagLen / 8 != out->size) {
+ ret = CKMC_ERROR_SERVER_ERROR;
+ goto encrypt_fail;
+ }
+ }
+
+ if (out != nullptr)
+ std::copy(out->data, out->data + out->size, std::back_inserter(encrypted));
+ out = nullptr;
+
+ ret = ckmc_buffer_new(encrypted.data(), encrypted.size(), &encrypted_c);
+ if (ret != CKMC_ERROR_NONE)
+ goto encrypt_fail;
+
+ *ppencrypted = encrypted_c;
+
+encrypt_fail:
+ ckmc_buffer_free(out);
+ ckmc_cipher_free(ctx);
+
+ return ckmcError2Result(ret);
+}
+
+EncryptionError CipherApi::decrypt(ckmc_param_list_h params,
+ const char *key_alias,
+ const char *password,
+ const ckmc_raw_buffer_s& encrypted,
+ ckmc_raw_buffer_s **ppdecrypted)
+{
+ ckmc_cipher_ctx_h ctx = nullptr;
+ size_t left = encrypted.size;
+ unsigned char* ptr = encrypted.data;
+ CKM::RawBuffer decrypted;
+ ckmc_raw_buffer_s* out = nullptr;
+ ckmc_raw_buffer_s* decrypted_c = nullptr;
+ ckmc_raw_buffer_s* tag = nullptr;
+ uint64_t algo;
+
+ int ret = ckmc_param_list_get_integer(params, CKMC_PARAM_ALGO_TYPE, &algo);
+ if (ret != CKMC_ERROR_NONE)
+ goto decrypt_fail;
+
+ // extract the tag to pass in finalize
+ if (algo == CKMC_ALGO_AES_GCM) {
+ uint64_t tagLen = 128;
+ ret = ckmc_param_list_get_integer(params, CKMC_PARAM_ED_TAG_LEN, &tagLen);
+ if (ret != CKMC_ERROR_NONE && ret != CKMC_ERROR_INVALID_PARAMETER)
+ goto decrypt_fail;
+
+ tagLen /= 8;
+ if (tagLen > left) {
+ ret = CKMC_ERROR_INVALID_PARAMETER;
+ goto decrypt_fail;
+ }
+
+ ret = ckmc_buffer_new(encrypted.data + encrypted.size - tagLen, tagLen, &tag);
+ if (ret != CKMC_ERROR_NONE)
+ goto decrypt_fail;
+
+ left -= tagLen;
+ }
+
+ // decrypt
+ ret = ckmc_cipher_initialize(params, key_alias, password, false, &ctx);
+ if (ret != CKMC_ERROR_NONE)
+ goto decrypt_fail;
+
+ ret = crypt(ctx, ptr, left, decrypted);
+ if (ret != CKMC_ERROR_NONE)
+ goto decrypt_fail;
+
+ ret = ckmc_cipher_finalize(ctx, tag, &out);
+ if (ret != CKMC_ERROR_NONE)
+ goto decrypt_fail;
+
+ if (out != nullptr)
+ std::copy(out->data, out->data + out->size, std::back_inserter(decrypted));
+ out = nullptr;
+
+ ret = ckmc_buffer_new(decrypted.data(), decrypted.size(), &decrypted_c);
+ if (ret != CKMC_ERROR_NONE)
+ goto decrypt_fail;
+
+ *ppdecrypted = decrypted_c;
+
+decrypt_fail:
+ ckmc_cipher_free(ctx);
+ ckmc_buffer_free(out);
+ ckmc_buffer_free(tag);
+
+ return ckmcError2Result(ret);
+}
+
+EncryptionError CipherApi::ckmcError2Result(int error)
+{
+ switch (error) {
+ case CKMC_ERROR_NONE: return EncryptionError::SUCCESS;
+ case CKMC_ERROR_INVALID_PARAMETER: return EncryptionError::INVALID_PARAM;
+ case CKMC_ERROR_SERVER_ERROR: return EncryptionError::SERVER_ERROR;
+ case CKMC_ERROR_DB_ALIAS_UNKNOWN: return EncryptionError::ALIAS_UNKNOWN;
+ case CKMC_ERROR_AUTHENTICATION_FAILED: return EncryptionError::AUTH_FAILED;
+ default: return EncryptionError::OTHER;
+ }
+}