Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce T_COSE_OPT_ENABLE_NON_AEAD #284

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions inc/t_cose/t_cose_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,19 @@ enum t_cose_err_t {
*/
#define T_COSE_OPT_REQUIRE_KID 0x00001000

/**
* WARNING: DO NOT use this option flag without understanding the
* security consideration of RFC 9459.
kentakayama marked this conversation as resolved.
Show resolved Hide resolved
* By default, the error \ref T_COSE_ERR_UNSUPPORTED_ENCRYPTION_ALG
* is returned if non AEAD content encryption algorithms, such as
* AES-CTR and AES-CBC, are used.
* The sender and recipient can use them only with this option flag.
* The sender MUST use AES-CTR in conjunction with an authentication
* and integrity mechanism, such as a digital signature.
* The recipient MUST validate data authenticity and integrity.
kentakayama marked this conversation as resolved.
Show resolved Hide resolved
*/
#define T_COSE_OPT_ENABLE_NON_AEAD 0x00002000


/**
* \brief Check whether an algorithm is supported.
Expand Down
10 changes: 10 additions & 0 deletions inc/t_cose/t_cose_encrypt_dec.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@ struct t_cose_encrypt_dec_ctx {
* explicitly set the CEK, but it rarely needed as the CEK is
* generated automatocally from the random number generator when
* it is not set.
*
kentakayama marked this conversation as resolved.
Show resolved Hide resolved
* By default, the t_cose_encrypt_dec() decrypts COSE encrypted message
* only with AEAD content encryption algorithms, and returns
* \ref T_COSE_ERR_UNSUPPORTED_ENCRYPTION_ALG with non AEAD ones.
* If \c option_flags includes \ref T_COSE_OPT_ENABLE_NON_AEAD the function
* will also decrypt with non-AEAD ciphers.
* WARNING: Do not use this flag without considerations, because non-AEAD
* content encryption algorithms does NOT validate neither authentication
* nor integrity, it is library caller's responsibility to check them.
* See security considerations of RFC 9459.
*/
static void
t_cose_encrypt_dec_init(struct t_cose_encrypt_dec_ctx *context,
Expand Down
12 changes: 12 additions & 0 deletions inc/t_cose/t_cose_encrypt_enc.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,18 @@ struct t_cose_encrypt_enc {
* t_cose_recipient_enc being used. You can even have serveral with
* different algorithms (but there can only be one payload encryption
* algorithm).
*
kentakayama marked this conversation as resolved.
Show resolved Hide resolved
* By default, the t_cose_encrypt_enc() encrypts a message
* only with AEAD content encryption algorithms, and returns
* \ref T_COSE_ERR_UNSUPPORTED_ENCRYPTION_ALG with non AEAD ones.
* If \c option_flags includes \ref T_COSE_OPT_ENABLE_NON_AEAD the function
* will also encrypt with non-AEAD ciphers.
* WARNING: Do not use this flag without considerations, because non-AEAD
* content encryption algorithms does NOT provide neither authentication
* nor integrity, it is library caller's responsibility to deliver the
* COSE message in conjunction with an authentication and integrity
* mechanism, such as a digital signature.
* See security considerations of RFC 9459.
*/
void
t_cose_encypt_enc_init(struct t_cose_encrypt_enc *context,
Expand Down
4 changes: 4 additions & 0 deletions src/t_cose_encrypt_dec.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ t_cose_encrypt_dec_detached(struct t_cose_encrypt_dec_ctx* me,
return T_COSE_ERR_NO_ALG_ID;
}
if(t_cose_alg_is_non_aead(ce_alg.cose_alg_id)) {
/* Make sure that the library caller (recipient) explicitly enables non AEAD ciphers*/
if(!(me->option_flags & T_COSE_OPT_ENABLE_NON_AEAD)) {
return T_COSE_ERR_UNSUPPORTED_ENCRYPTION_ALG;
}
/* Make sure there are no protected headers for non-aead algorithms */
if(!t_cose_params_empty(protected_params)) {
return T_COSE_ERR_PROTECTED_NOT_ALLOWED;
Expand Down
8 changes: 8 additions & 0 deletions src/t_cose_encrypt_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ t_cose_encrypt_enc_detached(struct t_cose_encrypt_enc *me,
/* ---- Algorithm ID, IV and parameter list ---- */
/* Determine algorithm parameters */
is_non_aead_cipher = t_cose_alg_is_non_aead(me->payload_cose_algorithm_id);
if(is_non_aead_cipher && !(me->option_flags & T_COSE_OPT_ENABLE_NON_AEAD)) {
/* The libraty caller (sender) MUST explicitly enable non AEAD
* content encryption algorithms with \c T_COSE_OPT_ENABLE_NON_AEAD
* awaring that the COSE message MUST be in conjunction with an
* authentication and integrity mechanism, such as a digital signature.
*/
return T_COSE_ERR_UNSUPPORTED_ENCRYPTION_ALG;
kentakayama marked this conversation as resolved.
Show resolved Hide resolved
}
if(is_non_aead_cipher && !q_useful_buf_c_is_null_or_empty(ext_sup_data)) {
/* Section 6 of RFC9459 says,
* COSE libraries that support either AES-CTR or AES-CBC and
Expand Down
148 changes: 122 additions & 26 deletions test/t_cose_encrypt_decrypt_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,11 @@ check_headers(const struct t_cose_parameter *headers, bool is_non_aead)
}


int32_t encrypt0_enc_dec(int32_t cose_algorithm_id)
int32_t encrypt0_enc_dec(int32_t cose_algorithm_id, bool enable_non_aead_encryption, bool enable_non_aead_decryption)
{
struct t_cose_encrypt_enc enc_context;
uint32_t option_flags;
bool is_non_aead = false;
enum t_cose_err_t t_cose_err;
int32_t return_value;
struct t_cose_key cek;
Expand All @@ -143,19 +145,22 @@ int32_t encrypt0_enc_dec(int32_t cose_algorithm_id)
struct t_cose_parameter p_storage_array[10];

switch(cose_algorithm_id) {
case T_COSE_ALGORITHM_A128GCM:
case T_COSE_ALGORITHM_A128CTR:
case T_COSE_ALGORITHM_A128CBC:
is_non_aead = true;
case T_COSE_ALGORITHM_A128GCM:
cek_bytes = Q_USEFUL_BUF_FROM_SZ_LITERAL("128-bit key xxxx");
break;
case T_COSE_ALGORITHM_A192GCM:
case T_COSE_ALGORITHM_A192CTR:
case T_COSE_ALGORITHM_A192CBC:
is_non_aead = true;
case T_COSE_ALGORITHM_A192GCM:
cek_bytes = Q_USEFUL_BUF_FROM_SZ_LITERAL("192-bit key xxxxyyyyyyyy");
break;
case T_COSE_ALGORITHM_A256GCM:
case T_COSE_ALGORITHM_A256CTR:
case T_COSE_ALGORITHM_A256CBC:
is_non_aead = true;
case T_COSE_ALGORITHM_A256GCM:
cek_bytes = Q_USEFUL_BUF_FROM_SZ_LITERAL("256-bit key xxxxyyyyyyyyzzzzzzzz");
break;
case T_COSE_ALGORITHM_AES128CCM_16_128:
Expand All @@ -176,8 +181,12 @@ int32_t encrypt0_enc_dec(int32_t cose_algorithm_id)
goto Done2;
}

option_flags = T_COSE_OPT_MESSAGE_TYPE_ENCRYPT0;
if(enable_non_aead_encryption) {
option_flags |= T_COSE_OPT_ENABLE_NON_AEAD;
}
t_cose_encrypt_enc_init(&enc_context,
T_COSE_OPT_MESSAGE_TYPE_ENCRYPT0,
option_flags,
cose_algorithm_id);


Expand Down Expand Up @@ -206,13 +215,21 @@ int32_t encrypt0_enc_dec(int32_t cose_algorithm_id)
cose_message_buf,
&encrypted_cose_message);

if(t_cose_err) {
if(t_cose_err == T_COSE_ERR_UNSUPPORTED_ENCRYPTION_ALG && is_non_aead && !enable_non_aead_encryption) {
/* t_cose could prevent unintended use of non AEAD ciphers */
return_value = 0;
goto Done;
}
else if(t_cose_err) {
return_value = 2000 + (int32_t)t_cose_err;
goto Done;
}


t_cose_encrypt_dec_init(&dec_ctx, T_COSE_OPT_MESSAGE_TYPE_ENCRYPT0);
option_flags = T_COSE_OPT_MESSAGE_TYPE_ENCRYPT0;
if(enable_non_aead_decryption) {
option_flags |= T_COSE_OPT_ENABLE_NON_AEAD;
}
t_cose_encrypt_dec_init(&dec_ctx, option_flags);

t_cose_encrypt_dec_set_cek(&dec_ctx, cek);

Expand All @@ -236,7 +253,12 @@ int32_t encrypt0_enc_dec(int32_t cose_algorithm_id)
decrypted_payload_buf,
&decrypted_payload,
&decoded_parameters);
if(t_cose_err) {
if(t_cose_err == T_COSE_ERR_UNSUPPORTED_ENCRYPTION_ALG && is_non_aead && !enable_non_aead_decryption) {
/* t_cose could prevent unintended use of non AEAD ciphers */
return_value = 0;
goto Done;
}
else if(t_cose_err) {
return_value = 3000 + (int32_t)t_cose_err;
goto Done;
}
Expand All @@ -254,7 +276,7 @@ int32_t encrypt0_enc_dec(int32_t cose_algorithm_id)

/* ---- test detached ----- */
t_cose_encrypt_enc_init(&enc_context,
T_COSE_OPT_MESSAGE_TYPE_ENCRYPT0,
option_flags,
cose_algorithm_id);
t_cose_encrypt_set_cek(&enc_context, cek);
t_cose_err = t_cose_encrypt_enc_detached(&enc_context,
Expand All @@ -269,7 +291,7 @@ int32_t encrypt0_enc_dec(int32_t cose_algorithm_id)
goto Done;
}

t_cose_encrypt_dec_init(&dec_ctx, T_COSE_OPT_MESSAGE_TYPE_ENCRYPT0);
t_cose_encrypt_dec_init(&dec_ctx, option_flags);
t_cose_encrypt_dec_set_cek(&dec_ctx, cek);
t_cose_err = t_cose_encrypt_dec_detached(&dec_ctx,
encrypted_cose_message,
Expand Down Expand Up @@ -301,61 +323,131 @@ int32_t encrypt0_enc_dec(int32_t cose_algorithm_id)
int32_t base_encrypt_decrypt_test(void)
{
int32_t rv;
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A128GCM);
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A128GCM, false, false);
if(rv) {
return 10000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A192GCM);
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A192GCM, false, false);
if(rv) {
return 20000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A256GCM);
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A256GCM, false, false);
if(rv) {
return 30000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A128CTR);
/* Enable non-AEAD ciphers on both Sender and Recipient side.
* Success on both side are expected.
*/
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A128CTR, true, true);
if(rv) {
return 40000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A192CTR);
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A192CTR, true, true);
if(rv) {
return 50000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A256CTR);
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A256CTR, true, true);
if(rv) {
return 60000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A128CBC);
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A128CBC, true, true);
if(rv) {
return 70000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A192CBC);
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A192CBC, true, true);
if(rv) {
return 80000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A256CBC);
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A256CBC, true, true);
if(rv) {
return 90000 + rv;
}

/* Disable non-AEAD ciphers on both Sender and Recipient side.
* Failure and early return on Sender side is expected.
*/
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A128CTR, false, false);
if(rv) {
return 100000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A192CTR, false, false);
if(rv) {
return 110000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A256CTR, false, false);
if(rv) {
return 120000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A128CBC, false, false);
if(rv) {
return 130000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A192CBC, false, false);
if(rv) {
return 140000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A256CBC, false, false);
if(rv) {
return 150000 + rv;
}

/* Disable non-AEAD ciphers on only Recipient side.
* Failure and early return on Recipient side is expected.
*/
rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A128CTR, true, false);
if(rv) {
return 160000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A192CTR, true, false);
if(rv) {
return 170000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A256CTR, true, false);
if(rv) {
return 180000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A128CBC, true, false);
if(rv) {
return 190000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A192CBC, true, false);
if(rv) {
return 200000 + rv;
}

rv = encrypt0_enc_dec(T_COSE_ALGORITHM_A256CBC, true, false);
if(rv) {
return 210000 + rv;
}

return 0;

}


#ifndef T_COSE_DISABLE_KEYWRAP

int32_t decrypt_key_wrap(struct q_useful_buf_c cose_encrypt_buffer)
int32_t decrypt_key_wrap(struct q_useful_buf_c cose_encrypt_buffer, bool enable_non_aead)
{
enum t_cose_err_t result;
uint32_t option_flags;
int32_t return_value = 0;
struct t_cose_recipient_dec_keywrap kw_unwrap_recipient;
struct t_cose_encrypt_dec_ctx decrypt_context;
Expand All @@ -374,7 +466,11 @@ int32_t decrypt_key_wrap(struct q_useful_buf_c cose_encrypt_buffer)
goto Done2;
}

t_cose_encrypt_dec_init(&decrypt_context, T_COSE_OPT_MESSAGE_TYPE_ENCRYPT);
option_flags = T_COSE_OPT_MESSAGE_TYPE_ENCRYPT;
if(enable_non_aead) {
option_flags |= T_COSE_OPT_ENABLE_NON_AEAD;
}
t_cose_encrypt_dec_init(&decrypt_context, option_flags);
t_cose_recipient_dec_keywrap_init(&kw_unwrap_recipient);
t_cose_recipient_dec_keywrap_set_kek(&kw_unwrap_recipient, kek, NULL_Q_USEFUL_BUF_C);
t_cose_encrypt_dec_add_recipient(&decrypt_context, (struct t_cose_recipient_dec *)&kw_unwrap_recipient);
Expand Down Expand Up @@ -415,11 +511,11 @@ int32_t decrypt_known_good_aeskw_non_aead_test(void)
return INT32_MIN; /* Means no testing was actually done */
}

return_value = decrypt_key_wrap(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(cose_encrypt_a128ctr_a128kw));
return_value = decrypt_key_wrap(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(cose_encrypt_a128ctr_a128kw), true);
if(return_value != 0) {
return return_value + 10000;
}
return_value = decrypt_key_wrap(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(cose_encrypt_a128cbc_a128kw));
return_value = decrypt_key_wrap(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(cose_encrypt_a128cbc_a128kw), true);
if(return_value != 0) {
return return_value + 20000;
}
Expand Down Expand Up @@ -475,7 +571,7 @@ esdh_enc_dec(int32_t curve, int32_t payload_cose_algorithm_id)
* body of the message.
*/
t_cose_encrypt_enc_init(&enc_ctx,
T_COSE_OPT_MESSAGE_TYPE_ENCRYPT,
T_COSE_OPT_MESSAGE_TYPE_ENCRYPT | T_COSE_OPT_ENABLE_NON_AEAD,
payload_cose_algorithm_id);

/* Create the recipient object telling it the algorithm and the public key
Expand Down Expand Up @@ -507,7 +603,7 @@ esdh_enc_dec(int32_t curve, int32_t payload_cose_algorithm_id)
}


t_cose_encrypt_dec_init(&dec_ctx, 0);
t_cose_encrypt_dec_init(&dec_ctx, T_COSE_OPT_ENABLE_NON_AEAD);

t_cose_recipient_dec_esdh_init(&dec_recipient);

Expand Down
Loading