Add ARMv8/AArch64 Crypto Extension implementation of SHA-256
[libgcrypt.git] / cipher / sha256-armv8-aarch64-ce.S
1 /* sha256-armv8-aarch64-ce.S - ARM/CE accelerated SHA-256 transform function
2  * Copyright (C) 2016 Jussi Kivilinna <jussi.kivilinna@iki.fi>
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21
22 #if defined(__AARCH64EL__) && \
23     defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
24     defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO) && defined(USE_SHA256)
25
26 .arch armv8-a+crypto
27
28 .text
29
30
31 #define GET_DATA_POINTER(reg, name) \
32                 adrp    reg, :got:name ; \
33                 ldr     reg, [reg, #:got_lo12:name] ;
34
35
36 /* Constants */
37
38 .align 4
39 gcry_sha256_aarch64_ce_K:
40 .LK:
41   .long 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5
42   .long 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5
43   .long 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3
44   .long 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174
45   .long 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc
46   .long 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da
47   .long 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7
48   .long 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967
49   .long 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13
50   .long 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85
51   .long 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3
52   .long 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070
53   .long 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5
54   .long 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
55   .long 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208
56   .long 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
57
58
59 /* Register macros */
60
61 #define vH0123 v0
62 #define vH4567 v1
63
64 #define vABCD0 v2
65 #define qABCD0 q2
66 #define vABCD1 v3
67 #define qABCD1 q3
68 #define vEFGH  v4
69 #define qEFGH  q4
70
71 #define vT0 v5
72 #define vT1 v6
73
74 #define vW0 v16
75 #define vW1 v17
76 #define vW2 v18
77 #define vW3 v19
78
79 #define vK0 v20
80 #define vK1 v21
81 #define vK2 v22
82 #define vK3 v23
83
84
85 /* Round macros */
86
87 #define _(...) /*_*/
88
89 #define do_loadk(nk0, nk1) ld1 {nk0.16b-nk1.16b},[x3],#32;
90 #define do_add(a, b) add a.4s, a.4s, b.4s;
91 #define do_sha256su0(w0, w1) sha256su0 w0.4s, w1.4s;
92 #define do_sha256su1(w0, w2, w3) sha256su1 w0.4s, w2.4s, w3.4s;
93
94 #define do_rounds(k, nk0, nk1, w0, w1, w2, w3, loadk_fn, add_fn, su0_fn, su1_fn) \
95         loadk_fn(   v##nk0, v##nk1     ); \
96         su0_fn(     v##w0, v##w1       ); \
97         mov         vABCD1.16b, vABCD0.16b; \
98         sha256h     qABCD0, qEFGH, v##k.4s; \
99         sha256h2    qEFGH, qABCD1, v##k.4s; \
100         add_fn(     v##nk0, v##w2      ); \
101         su1_fn(     v##w0, v##w2, v##w3   );
102
103
104 /* Other functional macros */
105
106 #define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
107
108
109 /*
110  * unsigned int
111  * _gcry_sha256_transform_armv8_ce (u32 state[8], const void *input_data,
112  *                                  size_t num_blks)
113  */
114 .align 3
115 .globl _gcry_sha256_transform_armv8_ce
116 .type  _gcry_sha256_transform_armv8_ce,%function;
117 _gcry_sha256_transform_armv8_ce:
118   /* input:
119    *    r0: ctx, CTX
120    *    r1: data (64*nblks bytes)
121    *    r2: nblks
122    */
123
124   cbz x2, .Ldo_nothing;
125
126   GET_DATA_POINTER(x3, .LK);
127   mov x4, x3
128
129   ld1 {vH0123.4s-vH4567.4s}, [x0]  /* load state */
130
131   ld1 {vW0.16b-vW1.16b}, [x1], #32
132   do_loadk(vK0, vK1)
133   ld1 {vW2.16b-vW3.16b}, [x1], #32
134   mov vABCD0.16b, vH0123.16b
135   mov vEFGH.16b, vH4567.16b
136
137   rev32 vW0.16b, vW0.16b
138   rev32 vW1.16b, vW1.16b
139   rev32 vW2.16b, vW2.16b
140   do_add(vK0, vW0)
141   rev32 vW3.16b, vW3.16b
142   do_add(vK1, vW1)
143
144 .Loop:
145   do_rounds(K0, K2, K3, W0, W1, W2, W3, do_loadk, do_add, do_sha256su0, do_sha256su1)
146   sub x2,x2,#1
147   do_rounds(K1, K3, _ , W1, W2, W3, W0, _       , do_add, do_sha256su0, do_sha256su1)
148   do_rounds(K2, K0, K1, W2, W3, W0, W1, do_loadk, do_add, do_sha256su0, do_sha256su1)
149   do_rounds(K3, K1, _ , W3, W0, W1, W2, _       , do_add, do_sha256su0, do_sha256su1)
150
151   do_rounds(K0, K2, K3, W0, W1, W2, W3, do_loadk, do_add, do_sha256su0, do_sha256su1)
152   do_rounds(K1, K3, _ , W1, W2, W3, W0, _       , do_add, do_sha256su0, do_sha256su1)
153   do_rounds(K2, K0, K1, W2, W3, W0, W1, do_loadk, do_add, do_sha256su0, do_sha256su1)
154   do_rounds(K3, K1, _ , W3, W0, W1, W2, _       , do_add, do_sha256su0, do_sha256su1)
155
156   do_rounds(K0, K2, K3, W0, W1, W2, W3, do_loadk, do_add, do_sha256su0, do_sha256su1)
157   do_rounds(K1, K3, _ , W1, W2, W3, W0, _       , do_add, do_sha256su0, do_sha256su1)
158   do_rounds(K2, K0, K1, W2, W3, W0, W1, do_loadk, do_add, do_sha256su0, do_sha256su1)
159   do_rounds(K3, K1, _ , W3, W0, W1, W2, _       , do_add, do_sha256su0, do_sha256su1)
160
161   cbz x2, .Lend
162
163   do_rounds(K0, K2, K3, W0, _  , W2, W3, do_loadk, do_add, _, _)
164   ld1 {vW0.16b}, [x1], #16
165   mov x3, x4
166   do_rounds(K1, K3, _ , W1, _  , W3, _  , _       , do_add, _, _)
167   ld1 {vW1.16b}, [x1], #16
168   rev32 vW0.16b, vW0.16b
169   do_rounds(K2, K0, K1, W2, _  , W0, _  , do_loadk, do_add, _, _)
170   rev32 vW1.16b, vW1.16b
171   ld1 {vW2.16b}, [x1], #16
172   do_rounds(K3, K1, _ , W3, _  , W1, _  , _       , do_add, _, _)
173   ld1 {vW3.16b}, [x1], #16
174
175   do_add(vH0123, vABCD0)
176   do_add(vH4567, vEFGH)
177
178   rev32 vW2.16b, vW2.16b
179   mov vABCD0.16b, vH0123.16b
180   rev32 vW3.16b, vW3.16b
181   mov vEFGH.16b, vH4567.16b
182
183   b .Loop
184
185 .Lend:
186
187   do_rounds(K0, K2, K3, W0, _  , W2, W3, do_loadk, do_add, _, _)
188   do_rounds(K1, K3, _ , W1, _  , W3, _  , _       , do_add, _, _)
189   do_rounds(K2, _ , _ , W2, _  , _  , _  , _       , _, _, _)
190   do_rounds(K3, _ , _ , W3, _  , _  , _  , _       , _, _, _)
191
192   CLEAR_REG(vW0)
193   CLEAR_REG(vW1)
194   CLEAR_REG(vW2)
195   CLEAR_REG(vW3)
196   CLEAR_REG(vK0)
197   CLEAR_REG(vK1)
198   CLEAR_REG(vK2)
199   CLEAR_REG(vK3)
200
201   do_add(vH0123, vABCD0)
202   do_add(vH4567, vEFGH)
203
204   CLEAR_REG(vABCD0)
205   CLEAR_REG(vABCD1)
206   CLEAR_REG(vEFGH)
207
208   st1 {vH0123.4s-vH4567.4s}, [x0] /* store state */
209
210   CLEAR_REG(vH0123)
211   CLEAR_REG(vH4567)
212
213 .Ldo_nothing:
214   mov x0, #0
215   ret
216 .size _gcry_sha256_transform_armv8_ce,.-_gcry_sha256_transform_armv8_ce;
217
218 #endif