Skip to content

Commit

Permalink
SHA-256 ARMv8 crypto extension implementation
Browse files Browse the repository at this point in the history
* Adds a ARMv8 crypto extension based SHA-256 implementation for LTC.
* Crypto extension based SHA-256 implementation is enabled for
  plat-vexpress-juno.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Pascal Brand <pascal.brand@linaro.org>
[jf: pick 0bea860, keep LTC changes only, remove trailing spaces]
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
  • Loading branch information
jenswi-linaro authored and jforissier committed Sep 12, 2019
1 parent 36c11dd commit e9fa8da
Show file tree
Hide file tree
Showing 4 changed files with 389 additions and 3 deletions.
214 changes: 214 additions & 0 deletions core/lib/libtomcrypt/src/hashes/sha2/sha256_arm32_ce.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
/*
* Copyright (c) 2015, Linaro Limited
* All rights reserved.
* Copyright (c) 2001-2007, Tom St Denis
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
#include "tomcrypt_arm_neon.h"

/**
@file sha256_arm32_ce.c
LTC_SHA256_ARM32_CE
*/

#ifdef LTC_SHA256_ARM32_CE

const struct ltc_hash_descriptor sha256_desc =
{
"sha256",
0,
32,
64,

/* OID */
{ 2, 16, 840, 1, 101, 3, 4, 2, 1, },
9,

&sha256_init,
&sha256_process,
&sha256_done,
&sha256_test,
NULL
};


/* Implemented in assembly */
int sha256_transform(ulong32 *state, unsigned char *buf);

static int sha256_compress(hash_state * md, unsigned char *buf)
{
struct tomcrypt_arm_neon_state state;

tomcrypt_arm_neon_enable(&state);
sha256_transform(md->sha256.state, buf);
tomcrypt_arm_neon_disable(&state);
#ifdef LTC_CLEAN_STACK
burn_stack(sizeof(ulong32) * 74);
#endif
return CRYPT_OK;
}

/**
Initialize the hash state
@param md The hash state you wish to initialize
@return CRYPT_OK if successful
*/
int sha256_init(hash_state * md)
{
LTC_ARGCHK(md != NULL);

md->sha256.curlen = 0;
md->sha256.length = 0;
md->sha256.state[0] = 0x6A09E667UL;
md->sha256.state[1] = 0xBB67AE85UL;
md->sha256.state[2] = 0x3C6EF372UL;
md->sha256.state[3] = 0xA54FF53AUL;
md->sha256.state[4] = 0x510E527FUL;
md->sha256.state[5] = 0x9B05688CUL;
md->sha256.state[6] = 0x1F83D9ABUL;
md->sha256.state[7] = 0x5BE0CD19UL;
return CRYPT_OK;
}

/**
Process a block of memory though the hash
@param md The hash state
@param in The data to hash
@param inlen The length of the data (octets)
@return CRYPT_OK if successful
*/
HASH_PROCESS(sha256_process, sha256_compress, sha256, 64)

/**
Terminate the hash to get the digest
@param md The hash state
@param out [out] The destination of the hash (32 bytes)
@return CRYPT_OK if successful
*/
int sha256_done(hash_state * md, unsigned char *out)
{
int i;

LTC_ARGCHK(md != NULL);
LTC_ARGCHK(out != NULL);

if (md->sha256.curlen >= sizeof(md->sha256.buf)) {
return CRYPT_INVALID_ARG;
}


/* increase the length of the message */
md->sha256.length += md->sha256.curlen * 8;

/* append the '1' bit */
md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;

/* if the length is currently above 56 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->sha256.curlen > 56) {
while (md->sha256.curlen < 64) {
md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
}
sha256_compress(md, md->sha256.buf);
md->sha256.curlen = 0;
}

/* pad upto 56 bytes of zeroes */
while (md->sha256.curlen < 56) {
md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
}

/* store length */
STORE64H(md->sha256.length, md->sha256.buf+56);
sha256_compress(md, md->sha256.buf);

/* copy output */
for (i = 0; i < 8; i++) {
STORE32H(md->sha256.state[i], out+(4*i));
}
#ifdef LTC_CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}

/**
Self-test the hash
@return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
*/
int sha256_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
static const struct {
const char *msg;
unsigned char hash[32];
} tests[] = {
{ "abc",
{ 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
},
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
{ 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
},
};

int i;
unsigned char tmp[32];
hash_state md;

for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
sha256_init(&md);
sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
sha256_done(&md, tmp);
if (XMEMCMP(tmp, tests[i].hash, 32) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
}
return CRYPT_OK;
#endif
}

#endif
131 changes: 131 additions & 0 deletions core/lib/libtomcrypt/src/hashes/sha2/sha256_arm32_ce_asm.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright (c) 2014-2015, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

/* SHA-256 secure hash using ARMv8 Crypto Extensions */

.text
.fpu crypto-neon-fp-armv8

k0 .req q7
k1 .req q8

ta0 .req q9
ta1 .req q10
tb0 .req q10
tb1 .req q9

dga .req q11
dgb .req q12

dg0 .req q13
dg1 .req q14
dg2 .req q15

.macro add_only, ev, s0
vmov dg2, dg0
.ifnb \s0
vld1.32 {k\ev}, [r3]!
.endif
sha256h.32 dg0, dg1, tb\ev
sha256h2.32 dg1, dg2, tb\ev
.ifnb \s0
vadd.u32 ta\ev, q\s0, k\ev
.endif
.endm

.macro add_update, ev, s0, s1, s2, s3
sha256su0.32 q\s0, q\s1
add_only \ev, \s1
sha256su1.32 q\s0, q\s2, q\s3
.endm

.align 6
.Lsha256_rcon:
.word 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5
.word 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5
.word 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3
.word 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174
.word 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc
.word 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da
.word 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7
.word 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967
.word 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13
.word 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85
.word 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3
.word 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070
.word 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5
.word 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
.word 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208
.word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2

.global sha256_transform
.type sha256_transform, %function
sha256_transform:
/* load round constants */
adr r3, .Lsha256_rcon
vld1.32 {k0}, [r3]!

/* load state */
vld1.8 {dga-dgb}, [r0]

/* load input */
vld1.8 {q0-q1}, [r1]!
vrev32.8 q0, q0
vrev32.8 q1, q1
vld1.8 {q2-q3}, [r1]
vrev32.8 q2, q2
vrev32.8 q3, q3

vadd.u32 ta0, q0, k0
vmov dg0, dga
vmov dg1, dgb

add_update 1, 0, 1, 2, 3
add_update 0, 1, 2, 3, 0
add_update 1, 2, 3, 0, 1
add_update 0, 3, 0, 1, 2
add_update 1, 0, 1, 2, 3
add_update 0, 1, 2, 3, 0
add_update 1, 2, 3, 0, 1
add_update 0, 3, 0, 1, 2
add_update 1, 0, 1, 2, 3
add_update 0, 1, 2, 3, 0
add_update 1, 2, 3, 0, 1
add_update 0, 3, 0, 1, 2

add_only 1, 1
add_only 0, 2
add_only 1, 3
add_only 0

/* update state */
vadd.u32 dga, dga, dg0
vadd.u32 dgb, dgb, dg1

/* store new state */
vst1.8 {dga-dgb}, [r0]
bx lr
41 changes: 41 additions & 0 deletions core/lib/libtomcrypt/src/headers/tomcrypt_arm_neon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2015, Linaro Limited
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TOMCRYPT_ARM_NEON_H
#define TOMCRYPT_ARM_NEON_H

#include <tomcrypt_macros.h>

struct tomcrypt_arm_neon_state {
ulong32 state;
};

/* Temporarily enables neon instructions */
void tomcrypt_arm_neon_enable(struct tomcrypt_arm_neon_state *state);
/* Disables neon instructions after a call to tomcrypt_arm_neon_enable() */
void tomcrypt_arm_neon_disable(struct tomcrypt_arm_neon_state *state);

#endif /*TOMCRYPT_ARM_NEON_H*/

0 comments on commit e9fa8da

Please sign in to comment.