+
+/////////////////////////////////////////
+// Cipher API only
+/////////////////////////////////////////
+RUNNER_TEST(TED_4000_cipher_missing_arguments)
+{
+ ckmc_raw_buffer_s* encrypted = nullptr;
+
+ auto [alias, params] = defaultGcmCipherSetup();
+
+ ckmc_cipher_ctx_h ctx = nullptr;
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+ auto ctxPtr = create_cipher_ctx(ctx);
+
+ // no AAD
+ assert_invalid_param(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+
+ // missing arguments
+ assert_invalid_param(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, nullptr);
+ assert_invalid_param(ckmc_cipher_update, nullptr, *PLAIN_DATA.get(), &encrypted);
+ assert_invalid_param(ckmc_cipher_update, ctx, *PLAIN_DATA.get(), nullptr);
+ assert_invalid_param(ckmc_cipher_finalize, nullptr, nullptr, &encrypted);
+ assert_invalid_param(ckmc_cipher_finalize, nullptr, nullptr, nullptr);
+}
+
+RUNNER_TEST(TED_4010_cipher_reinitialize_without_aad)
+{
+ auto [alias, params] = defaultGcmCipherSetup();
+
+ ckmc_cipher_ctx_h ctx = nullptr;
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+ auto ctxPtr = create_cipher_ctx(ctx);
+
+ // no AAD
+ assert_invalid_param(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+}
+
+RUNNER_TEST(TED_4020_cipher_tag_during_encryption)
+{
+ ckmc_raw_buffer_s* encrypted = nullptr;
+
+ auto [alias, params] = defaultGcmCipherSetup();
+
+ ckmc_cipher_ctx_h ctx = nullptr;
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+ auto ctxPtr = create_cipher_ctx(ctx);
+
+ // tag input during encryption
+ assert_invalid_param(ckmc_cipher_finalize, ctx, PLAIN_DATA.get(), &encrypted);
+}
+
+RUNNER_TEST(TED_4030_cipher_wrong_order)
+{
+ ckmc_raw_buffer_s* encrypted = nullptr;
+
+ auto [alias, params] = defaultGcmCipherSetup();
+
+ ckmc_cipher_ctx_h ctx = nullptr;
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+ auto ctxPtr = create_cipher_ctx(ctx);
+
+ assert_positive(ckmc_cipher_update, ctx, *PLAIN_DATA.get(), &encrypted);
+ ckmc_buffer_free(encrypted);
+
+ // initialize after update
+ setParam(params, CKMC_PARAM_ED_AAD, AAD32);
+ assert_invalid_param(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, nullptr);
+
+ assert_positive(ckmc_cipher_finalize, ctx, nullptr, &encrypted);
+ ckmc_buffer_free(encrypted);
+
+ // initialize after finalize
+ assert_invalid_param(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, nullptr);
+
+ // update after finalize
+ assert_invalid_param(ckmc_cipher_update, ctx, *PLAIN_DATA.get(), &encrypted);
+}
+
+RUNNER_TEST(TED_4040_cipher_gcm_aad_and_tag)
+{
+ ckmc_raw_buffer_s* encrypted = nullptr;
+
+ auto [alias, params] = defaultGcmCipherSetup();
+ setParam(params, CKMC_PARAM_ED_AAD, AAD32);
+
+ ckmc_cipher_ctx_h ctx = nullptr;
+
+ // encrypt
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+ auto ctxPtr = create_cipher_ctx(ctx);
+
+ // 2 more AAD chunks
+ setParam(params, CKMC_PARAM_ED_AAD, AAD64);
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+ setParam(params, CKMC_PARAM_ED_AAD, AAD32);
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, true, &ctx);
+
+ ckmc_raw_buffer_s* tag = nullptr;
+
+ assert_positive(ckmc_cipher_update, ctx, *PLAIN_DATA.get(), &encrypted);
+ auto encryptedPtr = create_raw_buffer(encrypted);
+ assert_positive(ckmc_cipher_finalize, ctx, nullptr, &tag);
+
+ ctxPtr.reset();
+ ctx = nullptr;
+
+ ckmc_raw_buffer_s* decrypted = nullptr;
+ ckmc_raw_buffer_s* empty = nullptr;
+
+ // decrypt with invalid AAD
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+ ctxPtr = create_cipher_ctx(ctx);
+
+ assert_positive(ckmc_cipher_update, ctx, *encrypted, &decrypted);
+ ckmc_buffer_free(decrypted);
+ assert_invalid_param(ckmc_cipher_finalize, ctx, tag, &empty);
+
+ ctxPtr.reset();
+ ctx = nullptr;
+
+ // decrypt without TAG
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+ ctxPtr = create_cipher_ctx(ctx);
+ setParam(params, CKMC_PARAM_ED_AAD, AAD64);
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+ setParam(params, CKMC_PARAM_ED_AAD, AAD32);
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+
+ assert_positive(ckmc_cipher_update, ctx, *encrypted, &decrypted);
+ ckmc_buffer_free(decrypted);
+ assert_invalid_param(ckmc_cipher_finalize, ctx, nullptr, &empty);
+
+ ctxPtr.reset();
+ ctx = nullptr;
+
+ // correct decrypt
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+ ctxPtr = create_cipher_ctx(ctx);
+ setParam(params, CKMC_PARAM_ED_AAD, AAD64);
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+ setParam(params, CKMC_PARAM_ED_AAD, AAD32);
+ assert_positive(ckmc_cipher_initialize, params.get(), alias.c_str(), nullptr, false, &ctx);
+
+ assert_positive(ckmc_cipher_update, ctx, *encrypted, &decrypted);
+ auto decryptedPtr = create_raw_buffer(decrypted);
+ assert_positive(ckmc_cipher_finalize, ctx, tag, &empty);
+
+ RUNNER_ASSERT(empty == nullptr);
+
+ assert_buffers_equal(PLAIN_DATA.get(), decrypted);
+}