Skip to content
9 changes: 9 additions & 0 deletions src/wp_ecx_kmgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,15 @@ static int wp_ecx_get_params_priv_key(wp_Ecx* ecx, OSSL_PARAM params[])
WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_LEVEL_DEBUG, "exportPriv", rc);
ok = 0;
}
if (ok && ecx->clamped) {
if ((outLen < 2) || (p->data_size < outLen)) {
ok = 0;
}
else {
((unsigned char*)p->data)[0 ] = ecx->unclamped[0];
((unsigned char*)p->data)[outLen - 1] = ecx->unclamped[1];
}
}
}
p->return_size = outLen;
}
Expand Down
4 changes: 1 addition & 3 deletions src/wp_seed_src.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,10 +689,8 @@ static size_t wp_seed_src_get_seed(wp_SeedSrcCtx* ctx, unsigned char** pSeed,
static void wp_seed_src_clear_seed(wp_SeedSrcCtx* ctx, unsigned char* seed,
size_t seedLen)
{
(void)ctx;
OPENSSL_secure_clear_free(seed, seedLen);
if (ctx != NULL) {
ctx->state = EVP_RAND_STATE_UNINITIALISED;
}
}

/**
Expand Down
246 changes: 246 additions & 0 deletions test/test_aestag.c
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,116 @@ int test_aes128_gcm_set_iv_inv(void *data)
EVP_GCM_TLS_FIXED_IV_LEN, 12);
}

/******************************************************************************/

/*
* GCM streaming decryption with a tampered authentication tag.
* Verifies that DecryptFinal correctly rejects a forged tag.
*/
static int test_aes_gcm_bad_tag_helper(OSSL_LIB_CTX *libCtx,
const char *cipherName, int keyLen)
{
int err = 0;
EVP_CIPHER *cipher = NULL;
EVP_CIPHER_CTX *ctx = NULL;
unsigned char key[32];
unsigned char iv[12];
unsigned char aad[] = "additional data";
unsigned char pt[] = "GCM plaintext for tag test";
int ptLen = (int)(sizeof(pt) - 1);
unsigned char ct[64];
unsigned char tag[16];
unsigned char dec[64];
int outLen = 0, fLen = 0;

memset(key, 0xAA, keyLen);
memset(iv, 0xBB, sizeof(iv));

cipher = EVP_CIPHER_fetch(libCtx, cipherName, "");
if (cipher == NULL) {
err = 1;
}

/* Encrypt */
if (err == 0) {
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
err = 1;
}
if (err == 0) {
err = EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv) != 1;
}
if (err == 0) {
err = EVP_EncryptUpdate(ctx, NULL, &outLen, aad,
(int)(sizeof(aad) - 1)) != 1;
}
if (err == 0) {
err = EVP_EncryptUpdate(ctx, ct, &outLen, pt, ptLen) != 1;
}
if (err == 0) {
err = EVP_EncryptFinal_ex(ctx, ct + outLen, &fLen) != 1;
outLen += fLen;
}
if (err == 0) {
err = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, tag) != 1;
}
EVP_CIPHER_CTX_free(ctx);
ctx = NULL;

/* Tamper with the tag */
if (err == 0) {
tag[0] ^= 0x01;
}

/* Decrypt with tampered tag -- must fail at DecryptFinal */
if (err == 0) {
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
err = 1;
}
if (err == 0) {
err = EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv) != 1;
}
if (err == 0) {
err = EVP_DecryptUpdate(ctx, NULL, &fLen, aad,
(int)(sizeof(aad) - 1)) != 1;
}
if (err == 0) {
err = EVP_DecryptUpdate(ctx, dec, &fLen, ct, outLen) != 1;
}
if (err == 0) {
err = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, tag) != 1;
}
if (err == 0) {
int ret = EVP_DecryptFinal_ex(ctx, dec + fLen, &fLen);
if (ret == 1) {
PRINT_ERR_MSG("%s bad-tag: DecryptFinal should have failed",
cipherName);
err = 1;
}
}

EVP_CIPHER_CTX_free(ctx);
EVP_CIPHER_free(cipher);
return err;
}

int test_aes_gcm_bad_tag(void *data)
{
int err = 0;

(void)data;

PRINT_MSG("AES-128-GCM streaming decryption with tampered tag");
err = test_aes_gcm_bad_tag_helper(wpLibCtx, "AES-128-GCM", 16);
if (err == 0) {
PRINT_MSG("AES-256-GCM streaming decryption with tampered tag");
err = test_aes_gcm_bad_tag_helper(wpLibCtx, "AES-256-GCM", 32);
}

return err;
}

#endif /* WP_HAVE_AESGCM */

/******************************************************************************/
Expand Down Expand Up @@ -1245,5 +1355,141 @@ int test_aes128_ccm_tls(void *data)
EVP_CCM_TLS_FIXED_IV_LEN, 1);
}

/******************************************************************************/

/*
* CCM streaming decryption with a tampered authentication tag.
* Verifies that DecryptFinal correctly rejects a forged tag.
*/
static int test_aes_ccm_bad_tag_helper(OSSL_LIB_CTX *libCtx,
const char *cipherName, int keyLen)
{
int err = 0;
EVP_CIPHER *cipher = NULL;
EVP_CIPHER_CTX *ctx = NULL;
unsigned char key[32];
unsigned char iv[13];
unsigned char aad[] = "additional data";
unsigned char pt[] = "CCM plaintext for tag test";
int ptLen = (int)(sizeof(pt) - 1);
unsigned char ct[64];
unsigned char tag[16];
unsigned char dec[64];
int outLen = 0, fLen = 0;

memset(key, 0xAA, keyLen);
memset(iv, 0xBB, sizeof(iv));

cipher = EVP_CIPHER_fetch(libCtx, cipherName, "");
if (cipher == NULL) {
err = 1;
}

/* Encrypt */
if (err == 0) {
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
err = 1;
}
if (err == 0) {
err = EVP_EncryptInit(ctx, cipher, NULL, NULL) != 1;
}
if (err == 0) {
err = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN,
(int)sizeof(iv), NULL) != 1;
}
if (err == 0) {
err = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, NULL) != 1;
}
if (err == 0) {
err = EVP_EncryptInit(ctx, NULL, key, iv) != 1;
}
if (err == 0) {
err = EVP_EncryptUpdate(ctx, NULL, &outLen, NULL, ptLen) != 1;
}
if (err == 0) {
err = EVP_EncryptUpdate(ctx, NULL, &outLen, aad,
(int)(sizeof(aad) - 1)) != 1;
}
if (err == 0) {
err = EVP_EncryptUpdate(ctx, ct, &outLen, pt, ptLen) != 1;
}
if (err == 0) {
err = EVP_EncryptFinal_ex(ctx, ct + outLen, &fLen) != 1;
outLen += fLen;
}
if (err == 0) {
err = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, tag) != 1;
}
EVP_CIPHER_CTX_free(ctx);
ctx = NULL;

/* Tamper with the tag */
if (err == 0) {
tag[0] ^= 0x01;
}

/* Decrypt with tampered tag -- must fail */
if (err == 0) {
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
err = 1;
}
if (err == 0) {
err = EVP_DecryptInit(ctx, cipher, NULL, NULL) != 1;
}
if (err == 0) {
err = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN,
(int)sizeof(iv), NULL) != 1;
}
if (err == 0) {
err = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, tag) != 1;
}
if (err == 0) {
err = EVP_DecryptInit(ctx, NULL, key, iv) != 1;
}
if (err == 0) {
err = EVP_DecryptUpdate(ctx, NULL, &fLen, NULL, outLen) != 1;
}
if (err == 0) {
err = EVP_DecryptUpdate(ctx, NULL, &fLen, aad,
(int)(sizeof(aad) - 1)) != 1;
}
if (err == 0) {
/* CCM DecryptUpdate should fail with bad tag */
int ret = EVP_DecryptUpdate(ctx, dec, &fLen, ct, outLen);
if (ret == 1) {
/* If Update succeeded, Final must fail */
ret = EVP_DecryptFinal_ex(ctx, dec + fLen, &fLen);
if (ret == 1) {
PRINT_ERR_MSG("%s bad-tag: decryption should have failed",
cipherName);
err = 1;
}
}
/* else: Update failed, which is also correct for CCM bad tag */
}

EVP_CIPHER_CTX_free(ctx);
EVP_CIPHER_free(cipher);
return err;
}

int test_aes_ccm_bad_tag(void *data)
{
int err = 0;

(void)data;

PRINT_MSG("AES-128-CCM streaming decryption with tampered tag");
err = test_aes_ccm_bad_tag_helper(wpLibCtx, "AES-128-CCM", 16);
if (err == 0) {
PRINT_MSG("AES-256-CCM streaming decryption with tampered tag");
err = test_aes_ccm_bad_tag_helper(wpLibCtx, "AES-256-CCM", 32);
}

return err;
}

#endif /* WP_HAVE_AESCCM */

Loading
Loading