typedef enum __ckmc_param_name {
CKMC_PARAM_ALGO_TYPE = 1, /**< integer - type of algorithm (see #ckmc_algo_type_e) */
- CKMC_PARAM_ED_IV = 101, /**< 16B buffer (up to 2^64-1 bytes long in case of AES GCM) */
+ CKMC_PARAM_ED_IV = 101, /**< buffer - initialization vector */
CKMC_PARAM_ED_CTR_LEN, /**< integer - ctr length in bits*/
CKMC_PARAM_ED_AAD, /**< buffer - Additional Authentication Data for AES GCM */
CKMC_PARAM_ED_TAG_LEN, /**< integer - tag length in bits */
CKMC_ALGO_AES_GCM, /**< AES-GCM algorithm
Supported parameters:
- #CKMC_PARAM_ALGO_TYPE = #CKMC_ALGO_AES_GCM (mandatory),
- - #CKMC_PARAM_ED_IV = initialization vector (mandatory)
+ - #CKMC_PARAM_ED_IV = 1 to (2^64-1) bytes long initialization vector.
+ Recommended length is 12B (mandatory)
- #CKMC_PARAM_ED_TAG_LEN = GCM tag length in bits. One of
{32, 64, 96, 104, 112, 120, 128} (optional, if not present, the
length 128 is used; since Tizen 5.0, if TrustZone backend is used,
};
};
+// Validates as true if parameter value is equal or greater than Min
+template <typename T, T Min>
+struct GreaterOrEqual {
+public:
+ static bool Check(const T &value)
+ {
+ return value >= Min;
+ }
+
+ static void Why(std::ostringstream &os)
+ {
+ os << "is smaller than " << static_cast<int>(Min);
+ }
+};
+
template <typename T>
struct Unsupported {
static bool Check(const T &)
ThrowErr(Exc::Crypto::InternalError, "Wrong key size! Expected: ",
EVP_CIPHER_key_length(type), " Get: ", key.size());
- if (static_cast<int>(iv.size()) < EVP_CIPHER_iv_length(type))
- ThrowErr(Exc::Crypto::InternalError, "Wrong iv size! Expected: ",
- EVP_CIPHER_iv_length(type), " Get: ", iv.size());
+ bool gcm = (EVP_CIPHER_mode(type) == EVP_CIPH_GCM_MODE);
+ int iv_len = EVP_CIPHER_iv_length(type);
- OPENSSL_ERROR_HANDLE(EVP_CipherInit_ex(m_ctx, type, NULL, key.data(), iv.data(),
- encryption ? 1 : 0));
+ OPENSSL_ERROR_HANDLE(EVP_CipherInit_ex(m_ctx, type, NULL, NULL, NULL, encryption ? 1 : 0));
+
+ if (gcm) {
+ if (iv.empty())
+ ThrowErr(Exc::Crypto::InternalError, "Empty iv provided!");
+
+ OPENSSL_ERROR_HANDLE(
+ EVP_CIPHER_CTX_ctrl(m_ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size(), NULL));
+ } else {
+ if (static_cast<int>(iv.size()) != iv_len)
+ ThrowErr(Exc::Crypto::InternalError, "Wrong iv size! Expected: ", iv_len, " Got: ",
+ iv.size());
+ }
+
+ OPENSSL_ERROR_HANDLE(
+ EVP_CipherInit_ex(m_ctx, NULL, NULL, key.data(), iv.data(), encryption ? 1 : 0));
EVP_CIPHER_CTX_set_padding(m_ctx, 1);
}
typedef ParamCheck<ParamName::ED_IV,
RawBuffer,
true,
- DefaultValidator<RawBuffer>> GcmIvCheck;
+ GreaterOrEqual<size_t, 1>,
+ BufferSizeGetter> GcmIvCheck;
typedef ParamCheck<ParamName::ED_TAG_LEN,
int,
BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT));
BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY));
- // short IV
- row.iv = RawBuffer(4);
- BOOST_REQUIRE_THROW(logic.encryptRow(row), Exc::InternalError);
- row.iv.clear();
-
// correct encryption
DB::Row encryptedRow;
BOOST_REQUIRE_NO_THROW(encryptedRow = logic.encryptRow(row));
ca.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GCM);
ca.setParam(ParamName::ED_AAD, createRandom(42));
encryptDecrypt();
+ ca.setParam(ParamName::ED_IV, createRandom(11));
+ encryptDecrypt();
+ ca.setParam(ParamName::ED_IV, createRandom(1));
+ encryptDecrypt();
+ ca.setParam(ParamName::ED_IV, createRandom(99));
+ encryptDecrypt();
}
NEGATIVE_TEST_CASE(symmetricEncryptDecrypt)
// no iv
BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InputParam);
- // short iv
- ca.setParam(ParamName::ED_IV, RawBuffer(1));
- BOOST_REQUIRE_THROW(key->encrypt(ca, data), Exc::Crypto::InternalError);
ca.setParam(ParamName::ED_IV, iv);
// short key
// no iv
BOOST_REQUIRE_THROW(key->decrypt(ca2, encrypted), Exc::Crypto::InputParam);
- // short iv
- ca2.setParam(ParamName::ED_IV, RawBuffer(1));
- BOOST_REQUIRE_THROW(key->decrypt(ca2, encrypted), Exc::Crypto::InternalError);
ca2.setParam(ParamName::ED_IV, iv);
// short key