From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35245) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YC5eZ-0003xG-7i for qemu-devel@nongnu.org; Fri, 16 Jan 2015 07:05:31 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YC5eS-0003cb-Tc for qemu-devel@nongnu.org; Fri, 16 Jan 2015 07:05:27 -0500 Received: from mnementh.archaic.org.uk ([2001:8b0:1d0::1]:54921) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YC5eS-0003bb-KQ for qemu-devel@nongnu.org; Fri, 16 Jan 2015 07:05:20 -0500 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1YC5eP-0001bW-DN for qemu-devel@nongnu.org; Fri, 16 Jan 2015 12:05:17 +0000 From: Peter Maydell Date: Fri, 16 Jan 2015 12:05:16 +0000 Message-Id: <1421409917-6137-2-git-send-email-peter.maydell@linaro.org> In-Reply-To: <1421409917-6137-1-git-send-email-peter.maydell@linaro.org> References: <1421409917-6137-1-git-send-email-peter.maydell@linaro.org> Subject: [Qemu-devel] [PULL 1/2] target-arm: crypto: fix BE host support List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org From: Ard Biesheuvel The crypto emulation code in target-arm/crypto_helper.c never worked correctly on big endian hosts, due to the fact that it uses a union of array types to convert between the native VFP register size (64 bits) and the types used in the algorithms (bytes and 32 bit words) We cannot just swab between LE and BE when reading and writing the registers, as the SHA code performs word additions, so instead, add array accessors for the CRYPTO_STATE type whose LE and BE specific implementations ensure that the correct array elements are referenced. Signed-off-by: Ard Biesheuvel Acked-by: Laszlo Ersek Message-id: 1420208303-24111-1-git-send-email-ard.biesheuvel@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target-arm/crypto_helper.c | 114 +++++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 51 deletions(-) diff --git a/target-arm/crypto_helper.c b/target-arm/crypto_helper.c index dd60d0b..1fe975d 100644 --- a/target-arm/crypto_helper.c +++ b/target-arm/crypto_helper.c @@ -22,6 +22,14 @@ union CRYPTO_STATE { uint64_t l[2]; }; +#ifdef HOST_WORDS_BIGENDIAN +#define CR_ST_BYTE(state, i) (state.bytes[(15 - (i)) ^ 8]) +#define CR_ST_WORD(state, i) (state.words[(3 - (i)) ^ 2]) +#else +#define CR_ST_BYTE(state, i) (state.bytes[i]) +#define CR_ST_WORD(state, i) (state.words[i]) +#endif + void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm, uint32_t decrypt) { @@ -46,7 +54,7 @@ void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm, /* combine ShiftRows operation and sbox substitution */ for (i = 0; i < 16; i++) { - st.bytes[i] = sbox[decrypt][rk.bytes[shift[decrypt][i]]]; + CR_ST_BYTE(st, i) = sbox[decrypt][CR_ST_BYTE(rk, shift[decrypt][i])]; } env->vfp.regs[rd] = make_float64(st.l[0]); @@ -198,11 +206,11 @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm, assert(decrypt < 2); for (i = 0; i < 16; i += 4) { - st.words[i >> 2] = cpu_to_le32( - mc[decrypt][st.bytes[i]] ^ - rol32(mc[decrypt][st.bytes[i + 1]], 8) ^ - rol32(mc[decrypt][st.bytes[i + 2]], 16) ^ - rol32(mc[decrypt][st.bytes[i + 3]], 24)); + CR_ST_WORD(st, i >> 2) = + mc[decrypt][CR_ST_BYTE(st, i)] ^ + rol32(mc[decrypt][CR_ST_BYTE(st, i + 1)], 8) ^ + rol32(mc[decrypt][CR_ST_BYTE(st, i + 2)], 16) ^ + rol32(mc[decrypt][CR_ST_BYTE(st, i + 3)], 24); } env->vfp.regs[rd] = make_float64(st.l[0]); @@ -255,24 +263,25 @@ void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn, switch (op) { case 0: /* sha1c */ - t = cho(d.words[1], d.words[2], d.words[3]); + t = cho(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3)); break; case 1: /* sha1p */ - t = par(d.words[1], d.words[2], d.words[3]); + t = par(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3)); break; case 2: /* sha1m */ - t = maj(d.words[1], d.words[2], d.words[3]); + t = maj(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3)); break; default: g_assert_not_reached(); } - t += rol32(d.words[0], 5) + n.words[0] + m.words[i]; - - n.words[0] = d.words[3]; - d.words[3] = d.words[2]; - d.words[2] = ror32(d.words[1], 2); - d.words[1] = d.words[0]; - d.words[0] = t; + t += rol32(CR_ST_WORD(d, 0), 5) + CR_ST_WORD(n, 0) + + CR_ST_WORD(m, i); + + CR_ST_WORD(n, 0) = CR_ST_WORD(d, 3); + CR_ST_WORD(d, 3) = CR_ST_WORD(d, 2); + CR_ST_WORD(d, 2) = ror32(CR_ST_WORD(d, 1), 2); + CR_ST_WORD(d, 1) = CR_ST_WORD(d, 0); + CR_ST_WORD(d, 0) = t; } } env->vfp.regs[rd] = make_float64(d.l[0]); @@ -286,8 +295,8 @@ void HELPER(crypto_sha1h)(CPUARMState *env, uint32_t rd, uint32_t rm) float64_val(env->vfp.regs[rm + 1]) } }; - m.words[0] = ror32(m.words[0], 2); - m.words[1] = m.words[2] = m.words[3] = 0; + CR_ST_WORD(m, 0) = ror32(CR_ST_WORD(m, 0), 2); + CR_ST_WORD(m, 1) = CR_ST_WORD(m, 2) = CR_ST_WORD(m, 3) = 0; env->vfp.regs[rd] = make_float64(m.l[0]); env->vfp.regs[rd + 1] = make_float64(m.l[1]); @@ -304,10 +313,10 @@ void HELPER(crypto_sha1su1)(CPUARMState *env, uint32_t rd, uint32_t rm) float64_val(env->vfp.regs[rm + 1]) } }; - d.words[0] = rol32(d.words[0] ^ m.words[1], 1); - d.words[1] = rol32(d.words[1] ^ m.words[2], 1); - d.words[2] = rol32(d.words[2] ^ m.words[3], 1); - d.words[3] = rol32(d.words[3] ^ d.words[0], 1); + CR_ST_WORD(d, 0) = rol32(CR_ST_WORD(d, 0) ^ CR_ST_WORD(m, 1), 1); + CR_ST_WORD(d, 1) = rol32(CR_ST_WORD(d, 1) ^ CR_ST_WORD(m, 2), 1); + CR_ST_WORD(d, 2) = rol32(CR_ST_WORD(d, 2) ^ CR_ST_WORD(m, 3), 1); + CR_ST_WORD(d, 3) = rol32(CR_ST_WORD(d, 3) ^ CR_ST_WORD(d, 0), 1); env->vfp.regs[rd] = make_float64(d.l[0]); env->vfp.regs[rd + 1] = make_float64(d.l[1]); @@ -356,20 +365,22 @@ void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn, int i; for (i = 0; i < 4; i++) { - uint32_t t = cho(n.words[0], n.words[1], n.words[2]) + n.words[3] - + S1(n.words[0]) + m.words[i]; - - n.words[3] = n.words[2]; - n.words[2] = n.words[1]; - n.words[1] = n.words[0]; - n.words[0] = d.words[3] + t; - - t += maj(d.words[0], d.words[1], d.words[2]) + S0(d.words[0]); - - d.words[3] = d.words[2]; - d.words[2] = d.words[1]; - d.words[1] = d.words[0]; - d.words[0] = t; + uint32_t t = cho(CR_ST_WORD(n, 0), CR_ST_WORD(n, 1), CR_ST_WORD(n, 2)) + + CR_ST_WORD(n, 3) + S1(CR_ST_WORD(n, 0)) + + CR_ST_WORD(m, i); + + CR_ST_WORD(n, 3) = CR_ST_WORD(n, 2); + CR_ST_WORD(n, 2) = CR_ST_WORD(n, 1); + CR_ST_WORD(n, 1) = CR_ST_WORD(n, 0); + CR_ST_WORD(n, 0) = CR_ST_WORD(d, 3) + t; + + t += maj(CR_ST_WORD(d, 0), CR_ST_WORD(d, 1), CR_ST_WORD(d, 2)) + + S0(CR_ST_WORD(d, 0)); + + CR_ST_WORD(d, 3) = CR_ST_WORD(d, 2); + CR_ST_WORD(d, 2) = CR_ST_WORD(d, 1); + CR_ST_WORD(d, 1) = CR_ST_WORD(d, 0); + CR_ST_WORD(d, 0) = t; } env->vfp.regs[rd] = make_float64(d.l[0]); @@ -394,13 +405,14 @@ void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn, int i; for (i = 0; i < 4; i++) { - uint32_t t = cho(d.words[0], d.words[1], d.words[2]) + d.words[3] - + S1(d.words[0]) + m.words[i]; - - d.words[3] = d.words[2]; - d.words[2] = d.words[1]; - d.words[1] = d.words[0]; - d.words[0] = n.words[3 - i] + t; + uint32_t t = cho(CR_ST_WORD(d, 0), CR_ST_WORD(d, 1), CR_ST_WORD(d, 2)) + + CR_ST_WORD(d, 3) + S1(CR_ST_WORD(d, 0)) + + CR_ST_WORD(m, i); + + CR_ST_WORD(d, 3) = CR_ST_WORD(d, 2); + CR_ST_WORD(d, 2) = CR_ST_WORD(d, 1); + CR_ST_WORD(d, 1) = CR_ST_WORD(d, 0); + CR_ST_WORD(d, 0) = CR_ST_WORD(n, 3 - i) + t; } env->vfp.regs[rd] = make_float64(d.l[0]); @@ -418,10 +430,10 @@ void HELPER(crypto_sha256su0)(CPUARMState *env, uint32_t rd, uint32_t rm) float64_val(env->vfp.regs[rm + 1]) } }; - d.words[0] += s0(d.words[1]); - d.words[1] += s0(d.words[2]); - d.words[2] += s0(d.words[3]); - d.words[3] += s0(m.words[0]); + CR_ST_WORD(d, 0) += s0(CR_ST_WORD(d, 1)); + CR_ST_WORD(d, 1) += s0(CR_ST_WORD(d, 2)); + CR_ST_WORD(d, 2) += s0(CR_ST_WORD(d, 3)); + CR_ST_WORD(d, 3) += s0(CR_ST_WORD(m, 0)); env->vfp.regs[rd] = make_float64(d.l[0]); env->vfp.regs[rd + 1] = make_float64(d.l[1]); @@ -443,10 +455,10 @@ void HELPER(crypto_sha256su1)(CPUARMState *env, uint32_t rd, uint32_t rn, float64_val(env->vfp.regs[rm + 1]) } }; - d.words[0] += s1(m.words[2]) + n.words[1]; - d.words[1] += s1(m.words[3]) + n.words[2]; - d.words[2] += s1(d.words[0]) + n.words[3]; - d.words[3] += s1(d.words[1]) + m.words[0]; + CR_ST_WORD(d, 0) += s1(CR_ST_WORD(m, 2)) + CR_ST_WORD(n, 1); + CR_ST_WORD(d, 1) += s1(CR_ST_WORD(m, 3)) + CR_ST_WORD(n, 2); + CR_ST_WORD(d, 2) += s1(CR_ST_WORD(d, 0)) + CR_ST_WORD(n, 3); + CR_ST_WORD(d, 3) += s1(CR_ST_WORD(d, 1)) + CR_ST_WORD(m, 0); env->vfp.regs[rd] = make_float64(d.l[0]); env->vfp.regs[rd + 1] = make_float64(d.l[1]); -- 1.9.1