From: Longfang Liu <liulongfang@huawei.com> Fix parameter validation during the coding process. Adopt constant-time programming techniques for handling sensitive data to enhance code resilience against attacks. Signed-off-by: Longfang Liu <liulongfang@huawei.com> --- drv/hisi_hpre.c | 6 +++--- drv/hisi_sec.c | 2 +- include/wd_internal.h | 2 ++ libwd.map | 1 + wd.c | 19 +++++++++++++++++++ wd_aead.c | 4 ++-- wd_agg.c | 8 +++++--- wd_cipher.c | 2 +- wd_join_gather.c | 2 +- 9 files changed, 35 insertions(+), 11 deletions(-) diff --git a/drv/hisi_hpre.c b/drv/hisi_hpre.c index 3c41826..83d8195 100644 --- a/drv/hisi_hpre.c +++ b/drv/hisi_hpre.c @@ -1176,7 +1176,7 @@ static bool less_than_latter(struct wd_dtb *d, struct wd_dtb *n) return true; shift = n->bsize - n->dsize; - ret = memcmp(d->data + shift, n->data + shift, n->dsize); + ret = memcmp_consttime(d->data + shift, n->data + shift, n->dsize); if (ret < 0) return true; else @@ -2434,7 +2434,7 @@ static void sm2_xor(struct wd_dtb *val1, struct wd_dtb *val2) static int is_equal(struct wd_dtb *src, struct wd_dtb *dst) { if (src->dsize == dst->dsize && - !memcmp(src->data, dst->data, src->dsize)) { + !memcmp_consttime(src->data, dst->data, src->dsize)) { return 0; } @@ -2913,7 +2913,7 @@ static void ecc_sess_eops_params_cfg(struct wd_alg_driver *drv, if (key_size != SECP256R1_KEY_SIZE) return; - ret = memcmp(data, cv->p.data, SECP256R1_PARAM_SIZE); + ret = memcmp_consttime(data, cv->p.data, SECP256R1_PARAM_SIZE); if (!ret) ecc_ctx->enable_hpcore = 1; } diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index c8b831c..aaaaa1d 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -2958,7 +2958,7 @@ static int gcm_do_soft_mac(struct wd_aead_msg *msg) msg->mac[i] = g[i] ^ ctr_r[i]; if (msg->op_type == WD_CIPHER_DECRYPTION_DIGEST) { - ret = memcmp(msg->mac, msg->dec_mac, msg->auth_bytes); + ret = memcmp_consttime(msg->mac, msg->dec_mac, msg->auth_bytes); if (ret) { msg->result = WD_IN_EPARA; WD_ERR("failed to do the gcm authentication!\n"); diff --git a/include/wd_internal.h b/include/wd_internal.h index d899555..4f19d3a 100644 --- a/include/wd_internal.h +++ b/include/wd_internal.h @@ -64,6 +64,8 @@ struct wd_datalist { struct wd_datalist *next; }; +int memcmp_consttime(const void *s1, const void *s2, size_t n); + #ifdef __cplusplus } #endif diff --git a/libwd.map b/libwd.map index 1267a8d..0635198 100644 --- a/libwd.map +++ b/libwd.map @@ -70,5 +70,6 @@ global: wd_get_free_num; wd_get_fail_num; wd_get_bufsize; + memcmp_consttime; local: *; }; diff --git a/wd.c b/wd.c index 7f21dc0..9cdc70f 100644 --- a/wd.c +++ b/wd.c @@ -56,6 +56,25 @@ static const char * const zip_dae_algs[] = { "gather", }; +/** + * Constant-time memory comparison function (primarily used for equality verification) + * It only supports equality/inequality results rather than full comparison results, + * the main goal is to provide timing-safe equality checks + */ +int memcmp_consttime(const void *s1, const void *s2, size_t n) +{ + const unsigned char *p1 = (const unsigned char *)s1; + const unsigned char *p2 = (const unsigned char *)s2; + unsigned char diff = 0; + size_t i; + + /* Constant-time byte-wise XOR accumulation */ + for (i = 0; i < n; i++) + diff |= p1[i] ^ p2[i]; + + return diff; +} + static int wd_check_ctx_type(handle_t h_ctx) { struct wd_ctx_h *ctx = (struct wd_ctx_h *)h_ctx; diff --git a/wd_aead.c b/wd_aead.c index 8467409..74d652b 100644 --- a/wd_aead.c +++ b/wd_aead.c @@ -191,7 +191,7 @@ int wd_aead_set_ckey(handle_t h_sess, const __u8 *key, __u16 key_len) struct wd_aead_sess *sess = (struct wd_aead_sess *)h_sess; int ret; - if (unlikely(!key || !sess)) { + if (unlikely(!key || !sess || !sess->ckey)) { WD_ERR("failed to check cipher key input param!\n"); return -WD_EINVAL; } @@ -230,7 +230,7 @@ int wd_aead_set_akey(handle_t h_sess, const __u8 *key, __u16 key_len) } sess->akey_bytes = key_len; - if (key_len) + if (key_len && sess->akey) memcpy(sess->akey, key, key_len); return 0; diff --git a/wd_agg.c b/wd_agg.c index 503bd49..bb834cb 100644 --- a/wd_agg.c +++ b/wd_agg.c @@ -308,6 +308,7 @@ static int fill_agg_session(struct wd_agg_sess *sess, struct wd_agg_sess_setup * sess->key_conf.cols_info = malloc(key_size); if (!sess->key_conf.cols_info) return -WD_ENOMEM; + sess->agg_conf.cols_info = malloc(agg_size); if (!sess->agg_conf.cols_info) goto out_key; @@ -1504,8 +1505,7 @@ int wd_agg_rehash_sync(handle_t h_sess, struct wd_agg_req *req) if (ret) { __atomic_store_n(&sess->state, WD_AGG_SESS_RESET, __ATOMIC_RELEASE); WD_ERR("failed to do agg rehash task!\n"); - free(cols); - return ret; + goto free_cols; } if (req->output_done) break; @@ -1513,8 +1513,10 @@ int wd_agg_rehash_sync(handle_t h_sess, struct wd_agg_req *req) } __atomic_store_n(&sess->state, WD_AGG_SESS_INPUT, __ATOMIC_RELEASE); + +free_cols: free(cols); - return WD_SUCCESS; + return ret; } struct wd_agg_msg *wd_agg_get_msg(__u32 idx, __u32 tag) diff --git a/wd_cipher.c b/wd_cipher.c index 58656dc..1c54d72 100644 --- a/wd_cipher.c +++ b/wd_cipher.c @@ -147,7 +147,7 @@ static bool is_des_weak_key(const __u8 *key) int i; for (i = 0; i < DES_WEAK_KEY_NUM; i++) { - if (memcmp(des_weak_keys[i], key, DES_KEY_SIZE) == 0) + if (memcmp_consttime(des_weak_keys[i], key, DES_KEY_SIZE) == 0) return true; } diff --git a/wd_join_gather.c b/wd_join_gather.c index 915c1b8..37e0022 100644 --- a/wd_join_gather.c +++ b/wd_join_gather.c @@ -217,7 +217,7 @@ static int check_key_cols_info(struct wd_join_gather_sess_setup *setup) return -WD_EINVAL; } - ret = memcmp(table->build_key_cols, table->probe_key_cols, + ret = memcmp_consttime(table->build_key_cols, table->probe_key_cols, table->build_key_cols_num * sizeof(struct wd_join_gather_col_info)); if (ret) { WD_ERR("invalid: build and probe table key infomation is not same!\n"); -- 2.33.0