aboutsummaryrefslogtreecommitdiff
path: root/core/tee
diff options
context:
space:
mode:
authorJens Wiklander <jens.wiklander@linaro.org>2018-11-20 15:24:17 +0100
committerJérôme Forissier <jerome.forissier@linaro.org>2019-01-21 18:28:37 +0100
commit84e9c40bd82d7f2b0946de15af2784a9707c9887 (patch)
tree4d2d717753de7257983f7c254686b41af3181656 /core/tee
parentd5c5b0b77b2b589666024d219a8007b3f5b6faeb (diff)
core: svc_cryp: fix truncated buffer length
Fixes truncated buffer length in multiple crypto syscalls. The buffer length is truncated on 32-bit systems because a size_t can't hold a uint64_t which is use to carry the buffer length. Fixes: "Truncated buffer length in crypto system calls (x4)" as reported by Riscure. Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org> Tested-by: Joakim Bech <joakim.bech@linaro.org> (QEMU v7, v8) Reviewed-by: Joakim Bech <joakim.bech@linaro.org> Reported-by: Riscure <inforequest@riscure.com> Reported-by: Alyssa Milburn <a.a.milburn@vu.nl> Acked-by: Etienne Carriere <etienne.carriere@linaro.org>
Diffstat (limited to 'core/tee')
-rw-r--r--core/tee/tee_svc_cryp.c92
1 files changed, 46 insertions, 46 deletions
diff --git a/core/tee/tee_svc_cryp.c b/core/tee/tee_svc_cryp.c
index 9e002aa0..7420ca86 100644
--- a/core/tee/tee_svc_cryp.c
+++ b/core/tee/tee_svc_cryp.c
@@ -824,6 +824,28 @@ static const struct attr_ops attr_ops[] = {
},
};
+static TEE_Result get_user_u64_as_size_t(size_t *dst, uint64_t *src)
+{
+ uint64_t d = 0;
+ TEE_Result res = tee_svc_copy_from_user(&d, src, sizeof(d));
+
+ /*
+ * On 32-bit systems a size_t can't hold a uint64_t so we need to
+ * check that the value isn't too large.
+ */
+ if (!res && ADD_OVERFLOW(0, d, dst))
+ return TEE_ERROR_OVERFLOW;
+
+ return res;
+}
+
+static TEE_Result put_user_u64(uint64_t *dst, size_t value)
+{
+ uint64_t v = value;
+
+ return tee_svc_copy_to_user(dst, &v, sizeof(v));
+}
+
TEE_Result syscall_cryp_obj_get_info(unsigned long obj, TEE_ObjectInfo *info)
{
TEE_Result res;
@@ -2283,6 +2305,7 @@ TEE_Result syscall_hash_final(unsigned long state, const void *chunk,
{
TEE_Result res, res2;
size_t hash_size;
+ size_t hlen = 0;
struct tee_cryp_state *cs;
struct tee_ta_session *sess;
@@ -2301,8 +2324,7 @@ TEE_Result syscall_hash_final(unsigned long state, const void *chunk,
if (res != TEE_SUCCESS)
return res;
- uint64_t hlen = 0;
- res = tee_svc_copy_from_user(&hlen, hash_len, sizeof(hlen));
+ res = get_user_u64_as_size_t(&hlen, hash_len);
if (res != TEE_SUCCESS)
return res;
@@ -2365,8 +2387,7 @@ TEE_Result syscall_hash_final(unsigned long state, const void *chunk,
return TEE_ERROR_BAD_PARAMETERS;
}
out:
- hlen = hash_size;
- res2 = tee_svc_copy_to_user(hash_len, &hlen, sizeof(*hash_len));
+ res2 = put_user_u64(hash_len, hash_size);
if (res2 != TEE_SUCCESS)
return res2;
return res;
@@ -2435,7 +2456,7 @@ static TEE_Result tee_svc_cipher_update_helper(unsigned long state,
TEE_Result res;
struct tee_cryp_state *cs;
struct tee_ta_session *sess;
- uint64_t dlen;
+ size_t dlen = 0;
res = tee_ta_get_current_session(&sess);
if (res != TEE_SUCCESS)
@@ -2455,7 +2476,7 @@ static TEE_Result tee_svc_cipher_update_helper(unsigned long state,
if (!dst_len) {
dlen = 0;
} else {
- res = tee_svc_copy_from_user(&dlen, dst_len, sizeof(dlen));
+ res = get_user_u64_as_size_t(&dlen, dst_len);
if (res != TEE_SUCCESS)
return res;
@@ -2489,8 +2510,7 @@ out:
dst_len != NULL) {
TEE_Result res2;
- dlen = src_len;
- res2 = tee_svc_copy_to_user(dst_len, &dlen, sizeof(*dst_len));
+ res2 = put_user_u64(dst_len, src_len);
if (res2 != TEE_SUCCESS)
res = res2;
}
@@ -2994,8 +3014,7 @@ TEE_Result syscall_authenc_update_payload(unsigned long state,
TEE_Result res;
struct tee_cryp_state *cs;
struct tee_ta_session *sess;
- uint64_t dlen;
- size_t tmp_dlen;
+ size_t dlen = 0;
res = tee_ta_get_current_session(&sess);
if (res != TEE_SUCCESS)
@@ -3012,7 +3031,7 @@ TEE_Result syscall_authenc_update_payload(unsigned long state,
if (res != TEE_SUCCESS)
return res;
- res = tee_svc_copy_from_user(&dlen, dst_len, sizeof(dlen));
+ res = get_user_u64_as_size_t(&dlen, dst_len);
if (res != TEE_SUCCESS)
return res;
@@ -3029,16 +3048,13 @@ TEE_Result syscall_authenc_update_payload(unsigned long state,
goto out;
}
- tmp_dlen = dlen;
res = crypto_authenc_update_payload(cs->ctx, cs->algo, cs->mode,
src_data, src_len, dst_data,
- &tmp_dlen);
- dlen = tmp_dlen;
-
+ &dlen);
out:
if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) {
- TEE_Result res2 = tee_svc_copy_to_user(dst_len, &dlen,
- sizeof(*dst_len));
+ TEE_Result res2 = put_user_u64(dst_len, dlen);
+
if (res2 != TEE_SUCCESS)
res = res2;
}
@@ -3053,10 +3069,8 @@ TEE_Result syscall_authenc_enc_final(unsigned long state,
TEE_Result res;
struct tee_cryp_state *cs;
struct tee_ta_session *sess;
- uint64_t dlen;
- uint64_t tlen = 0;
- size_t tmp_dlen;
- size_t tmp_tlen;
+ size_t dlen = 0;
+ size_t tlen = 0;
res = tee_ta_get_current_session(&sess);
if (res != TEE_SUCCESS)
@@ -3079,7 +3093,7 @@ TEE_Result syscall_authenc_enc_final(unsigned long state,
if (!dst_len) {
dlen = 0;
} else {
- res = tee_svc_copy_from_user(&dlen, dst_len, sizeof(dlen));
+ res = get_user_u64_as_size_t(&dlen, dst_len);
if (res != TEE_SUCCESS)
return res;
@@ -3097,7 +3111,7 @@ TEE_Result syscall_authenc_enc_final(unsigned long state,
goto out;
}
- res = tee_svc_copy_from_user(&tlen, tag_len, sizeof(tlen));
+ res = get_user_u64_as_size_t(&tlen, tag_len);
if (res != TEE_SUCCESS)
return res;
@@ -3109,26 +3123,20 @@ TEE_Result syscall_authenc_enc_final(unsigned long state,
if (res != TEE_SUCCESS)
return res;
- tmp_dlen = dlen;
- tmp_tlen = tlen;
res = crypto_authenc_enc_final(cs->ctx, cs->algo, src_data,
- src_len, dst_data, &tmp_dlen, tag,
- &tmp_tlen);
- dlen = tmp_dlen;
- tlen = tmp_tlen;
+ src_len, dst_data, &dlen, tag, &tlen);
out:
if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) {
TEE_Result res2;
if (dst_len != NULL) {
- res2 = tee_svc_copy_to_user(dst_len, &dlen,
- sizeof(*dst_len));
+ res2 = put_user_u64(dst_len, dlen);
if (res2 != TEE_SUCCESS)
return res2;
}
- res2 = tee_svc_copy_to_user(tag_len, &tlen, sizeof(*tag_len));
+ res2 = put_user_u64(tag_len, tlen);
if (res2 != TEE_SUCCESS)
return res2;
}
@@ -3143,8 +3151,7 @@ TEE_Result syscall_authenc_dec_final(unsigned long state,
TEE_Result res;
struct tee_cryp_state *cs;
struct tee_ta_session *sess;
- uint64_t dlen;
- size_t tmp_dlen;
+ size_t dlen = 0;
res = tee_ta_get_current_session(&sess);
if (res != TEE_SUCCESS)
@@ -3167,7 +3174,7 @@ TEE_Result syscall_authenc_dec_final(unsigned long state,
if (!dst_len) {
dlen = 0;
} else {
- res = tee_svc_copy_from_user(&dlen, dst_len, sizeof(dlen));
+ res = get_user_u64_as_size_t(&dlen, dst_len);
if (res != TEE_SUCCESS)
return res;
@@ -3192,17 +3199,14 @@ TEE_Result syscall_authenc_dec_final(unsigned long state,
if (res != TEE_SUCCESS)
return res;
- tmp_dlen = dlen;
res = crypto_authenc_dec_final(cs->ctx, cs->algo, src_data, src_len,
- dst_data, &tmp_dlen, tag, tag_len);
- dlen = tmp_dlen;
+ dst_data, &dlen, tag, tag_len);
out:
if ((res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) &&
dst_len != NULL) {
- TEE_Result res2;
+ TEE_Result res2 = put_user_u64(dst_len, dlen);
- res2 = tee_svc_copy_to_user(dst_len, &dlen, sizeof(*dst_len));
if (res2 != TEE_SUCCESS)
return res2;
}
@@ -3239,7 +3243,6 @@ TEE_Result syscall_asymm_operate(unsigned long state,
TEE_Result res;
struct tee_cryp_state *cs;
struct tee_ta_session *sess;
- uint64_t dlen64;
size_t dlen;
struct tee_obj *o;
void *label = NULL;
@@ -3265,10 +3268,9 @@ TEE_Result syscall_asymm_operate(unsigned long state,
if (res != TEE_SUCCESS)
return res;
- res = tee_svc_copy_from_user(&dlen64, dst_len, sizeof(dlen64));
+ res = get_user_u64_as_size_t(&dlen, dst_len);
if (res != TEE_SUCCESS)
return res;
- dlen = dlen64;
res = tee_mmu_check_access_rights(
utc,
@@ -3393,10 +3395,8 @@ out:
free(params);
if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) {
- TEE_Result res2;
+ TEE_Result res2 = put_user_u64(dst_len, dlen);
- dlen64 = dlen;
- res2 = tee_svc_copy_to_user(dst_len, &dlen64, sizeof(*dst_len));
if (res2 != TEE_SUCCESS)
return res2;
}