Merge branch 'linux-linaro-lsk-v3.10' into linux-linaro-lsk-v3.10-android
[firefly-linux-kernel-4.4.55.git] / arch / arm / crypto / sha256_neon_glue.c
1 /*
2  * Glue code for the SHA256 Secure Hash Algorithm assembly implementation
3  * using NEON instructions.
4  *
5  * Copyright © 2015 Google Inc.
6  *
7  * This file is based on sha512_neon_glue.c:
8  *   Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by the Free
12  * Software Foundation; either version 2 of the License, or (at your option)
13  * any later version.
14  *
15  */
16
17 #include <crypto/internal/hash.h>
18 #include <linux/cryptohash.h>
19 #include <linux/types.h>
20 #include <linux/string.h>
21 #include <crypto/sha.h>
22 #include <asm/byteorder.h>
23 #include <asm/simd.h>
24 #include <asm/neon.h>
25 #include "sha256_glue.h"
26
27 asmlinkage void sha256_block_data_order_neon(u32 *digest, const void *data,
28                                       unsigned int num_blks);
29
30
31 static int __sha256_neon_update(struct shash_desc *desc, const u8 *data,
32                                 unsigned int len, unsigned int partial)
33 {
34         struct sha256_state *sctx = shash_desc_ctx(desc);
35         unsigned int done = 0;
36
37         sctx->count += len;
38
39         if (partial) {
40                 done = SHA256_BLOCK_SIZE - partial;
41                 memcpy(sctx->buf + partial, data, done);
42                 sha256_block_data_order_neon(sctx->state, sctx->buf, 1);
43         }
44
45         if (len - done >= SHA256_BLOCK_SIZE) {
46                 const unsigned int rounds = (len - done) / SHA256_BLOCK_SIZE;
47
48                 sha256_block_data_order_neon(sctx->state, data + done, rounds);
49                 done += rounds * SHA256_BLOCK_SIZE;
50         }
51
52         memcpy(sctx->buf, data + done, len - done);
53
54         return 0;
55 }
56
57 static int sha256_neon_update(struct shash_desc *desc, const u8 *data,
58                               unsigned int len)
59 {
60         struct sha256_state *sctx = shash_desc_ctx(desc);
61         unsigned int partial = sctx->count % SHA256_BLOCK_SIZE;
62         int res;
63
64         /* Handle the fast case right here */
65         if (partial + len < SHA256_BLOCK_SIZE) {
66                 sctx->count += len;
67                 memcpy(sctx->buf + partial, data, len);
68
69                 return 0;
70         }
71
72         if (!may_use_simd()) {
73                 res = __sha256_update(desc, data, len, partial);
74         } else {
75                 kernel_neon_begin();
76                 res = __sha256_neon_update(desc, data, len, partial);
77                 kernel_neon_end();
78         }
79
80         return res;
81 }
82
83 /* Add padding and return the message digest. */
84 static int sha256_neon_final(struct shash_desc *desc, u8 *out)
85 {
86         struct sha256_state *sctx = shash_desc_ctx(desc);
87         unsigned int i, index, padlen;
88         __be32 *dst = (__be32 *)out;
89         __be64 bits;
90         static const u8 padding[SHA256_BLOCK_SIZE] = { 0x80, };
91
92         /* save number of bits */
93         bits = cpu_to_be64(sctx->count << 3);
94
95         /* Pad out to 56 mod 64 and append length */
96         index = sctx->count % SHA256_BLOCK_SIZE;
97         padlen = (index < 56) ? (56 - index) : ((SHA256_BLOCK_SIZE+56)-index);
98
99         if (!may_use_simd()) {
100                 sha256_update(desc, padding, padlen);
101                 sha256_update(desc, (const u8 *)&bits, sizeof(bits));
102         } else {
103                 kernel_neon_begin();
104                 /* We need to fill a whole block for __sha256_neon_update() */
105                 if (padlen <= 56) {
106                         sctx->count += padlen;
107                         memcpy(sctx->buf + index, padding, padlen);
108                 } else {
109                         __sha256_neon_update(desc, padding, padlen, index);
110                 }
111                 __sha256_neon_update(desc, (const u8 *)&bits,
112                                         sizeof(bits), 56);
113                 kernel_neon_end();
114         }
115
116         /* Store state in digest */
117         for (i = 0; i < 8; i++)
118                 dst[i] = cpu_to_be32(sctx->state[i]);
119
120         /* Wipe context */
121         memset(sctx, 0, sizeof(*sctx));
122
123         return 0;
124 }
125
126 static int sha224_neon_final(struct shash_desc *desc, u8 *out)
127 {
128         u8 D[SHA256_DIGEST_SIZE];
129
130         sha256_neon_final(desc, D);
131
132         memcpy(out, D, SHA224_DIGEST_SIZE);
133         memset(D, 0, SHA256_DIGEST_SIZE);
134
135         return 0;
136 }
137
138 struct shash_alg sha256_neon_algs[] = { {
139         .digestsize     =       SHA256_DIGEST_SIZE,
140         .init           =       sha256_init,
141         .update         =       sha256_neon_update,
142         .final          =       sha256_neon_final,
143         .export         =       sha256_export,
144         .import         =       sha256_import,
145         .descsize       =       sizeof(struct sha256_state),
146         .statesize      =       sizeof(struct sha256_state),
147         .base           =       {
148                 .cra_name       =       "sha256",
149                 .cra_driver_name =      "sha256-neon",
150                 .cra_priority   =       250,
151                 .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
152                 .cra_blocksize  =       SHA256_BLOCK_SIZE,
153                 .cra_module     =       THIS_MODULE,
154         }
155 }, {
156         .digestsize     =       SHA224_DIGEST_SIZE,
157         .init           =       sha224_init,
158         .update         =       sha256_neon_update,
159         .final          =       sha224_neon_final,
160         .export         =       sha256_export,
161         .import         =       sha256_import,
162         .descsize       =       sizeof(struct sha256_state),
163         .statesize      =       sizeof(struct sha256_state),
164         .base           =       {
165                 .cra_name       =       "sha224",
166                 .cra_driver_name =      "sha224-neon",
167                 .cra_priority   =       250,
168                 .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
169                 .cra_blocksize  =       SHA224_BLOCK_SIZE,
170                 .cra_module     =       THIS_MODULE,
171         }
172 } };