2 * GHASH routines supporting VMX instructions on the Power 8
4 * Copyright (C) 2015 International Business Machines Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 only.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 * Author: Marcelo Henrique Cerri <mhcerri@br.ibm.com>
22 #include <linux/types.h>
23 #include <linux/err.h>
24 #include <linux/crypto.h>
25 #include <linux/delay.h>
26 #include <linux/hardirq.h>
27 #include <asm/switch_to.h>
28 #include <crypto/aes.h>
29 #include <crypto/ghash.h>
30 #include <crypto/scatterwalk.h>
31 #include <crypto/internal/hash.h>
32 #include <crypto/b128ops.h>
34 #define IN_INTERRUPT in_interrupt()
36 void gcm_init_p8(u128 htable
[16], const u64 Xi
[2]);
37 void gcm_gmult_p8(u64 Xi
[2], const u128 htable
[16]);
38 void gcm_ghash_p8(u64 Xi
[2], const u128 htable
[16],
39 const u8
*in
, size_t len
);
43 struct crypto_shash
*fallback
;
46 struct p8_ghash_desc_ctx
{
48 u8 buffer
[GHASH_DIGEST_SIZE
];
50 struct shash_desc fallback_desc
;
53 static int p8_ghash_init_tfm(struct crypto_tfm
*tfm
)
55 const char *alg
= "ghash-generic";
56 struct crypto_shash
*fallback
;
57 struct crypto_shash
*shash_tfm
= __crypto_shash_cast(tfm
);
58 struct p8_ghash_ctx
*ctx
= crypto_tfm_ctx(tfm
);
60 fallback
= crypto_alloc_shash(alg
, 0, CRYPTO_ALG_NEED_FALLBACK
);
61 if (IS_ERR(fallback
)) {
63 "Failed to allocate transformation for '%s': %ld\n",
64 alg
, PTR_ERR(fallback
));
65 return PTR_ERR(fallback
);
68 crypto_shash_set_flags(fallback
,
69 crypto_shash_get_flags((struct crypto_shash
72 /* Check if the descsize defined in the algorithm is still enough. */
73 if (shash_tfm
->descsize
< sizeof(struct p8_ghash_desc_ctx
)
74 + crypto_shash_descsize(fallback
)) {
76 "Desc size of the fallback implementation (%s) does not match the expected value: %lu vs %u\n",
78 shash_tfm
->descsize
- sizeof(struct p8_ghash_desc_ctx
),
79 crypto_shash_descsize(fallback
));
82 ctx
->fallback
= fallback
;
87 static void p8_ghash_exit_tfm(struct crypto_tfm
*tfm
)
89 struct p8_ghash_ctx
*ctx
= crypto_tfm_ctx(tfm
);
92 crypto_free_shash(ctx
->fallback
);
97 static int p8_ghash_init(struct shash_desc
*desc
)
99 struct p8_ghash_ctx
*ctx
= crypto_tfm_ctx(crypto_shash_tfm(desc
->tfm
));
100 struct p8_ghash_desc_ctx
*dctx
= shash_desc_ctx(desc
);
103 memset(dctx
->shash
, 0, GHASH_DIGEST_SIZE
);
104 dctx
->fallback_desc
.tfm
= ctx
->fallback
;
105 dctx
->fallback_desc
.flags
= desc
->flags
;
106 return crypto_shash_init(&dctx
->fallback_desc
);
109 static int p8_ghash_setkey(struct crypto_shash
*tfm
, const u8
*key
,
112 struct p8_ghash_ctx
*ctx
= crypto_tfm_ctx(crypto_shash_tfm(tfm
));
114 if (keylen
!= GHASH_BLOCK_SIZE
)
120 gcm_init_p8(ctx
->htable
, (const u64
*) key
);
121 disable_kernel_vsx();
124 return crypto_shash_setkey(ctx
->fallback
, key
, keylen
);
127 static int p8_ghash_update(struct shash_desc
*desc
,
128 const u8
*src
, unsigned int srclen
)
131 struct p8_ghash_ctx
*ctx
= crypto_tfm_ctx(crypto_shash_tfm(desc
->tfm
));
132 struct p8_ghash_desc_ctx
*dctx
= shash_desc_ctx(desc
);
135 return crypto_shash_update(&dctx
->fallback_desc
, src
,
139 if (dctx
->bytes
+ srclen
< GHASH_DIGEST_SIZE
) {
140 memcpy(dctx
->buffer
+ dctx
->bytes
, src
,
142 dctx
->bytes
+= srclen
;
145 memcpy(dctx
->buffer
+ dctx
->bytes
, src
,
146 GHASH_DIGEST_SIZE
- dctx
->bytes
);
150 gcm_ghash_p8(dctx
->shash
, ctx
->htable
,
151 dctx
->buffer
, GHASH_DIGEST_SIZE
);
152 disable_kernel_vsx();
155 src
+= GHASH_DIGEST_SIZE
- dctx
->bytes
;
156 srclen
-= GHASH_DIGEST_SIZE
- dctx
->bytes
;
159 len
= srclen
& ~(GHASH_DIGEST_SIZE
- 1);
164 gcm_ghash_p8(dctx
->shash
, ctx
->htable
, src
, len
);
165 disable_kernel_vsx();
172 memcpy(dctx
->buffer
, src
, srclen
);
173 dctx
->bytes
= srclen
;
179 static int p8_ghash_final(struct shash_desc
*desc
, u8
*out
)
182 struct p8_ghash_ctx
*ctx
= crypto_tfm_ctx(crypto_shash_tfm(desc
->tfm
));
183 struct p8_ghash_desc_ctx
*dctx
= shash_desc_ctx(desc
);
186 return crypto_shash_final(&dctx
->fallback_desc
, out
);
189 for (i
= dctx
->bytes
; i
< GHASH_DIGEST_SIZE
; i
++)
194 gcm_ghash_p8(dctx
->shash
, ctx
->htable
,
195 dctx
->buffer
, GHASH_DIGEST_SIZE
);
196 disable_kernel_vsx();
201 memcpy(out
, dctx
->shash
, GHASH_DIGEST_SIZE
);
206 struct shash_alg p8_ghash_alg
= {
207 .digestsize
= GHASH_DIGEST_SIZE
,
208 .init
= p8_ghash_init
,
209 .update
= p8_ghash_update
,
210 .final
= p8_ghash_final
,
211 .setkey
= p8_ghash_setkey
,
212 .descsize
= sizeof(struct p8_ghash_desc_ctx
)
213 + sizeof(struct ghash_desc_ctx
),
216 .cra_driver_name
= "p8_ghash",
217 .cra_priority
= 1000,
218 .cra_flags
= CRYPTO_ALG_TYPE_SHASH
| CRYPTO_ALG_NEED_FALLBACK
,
219 .cra_blocksize
= GHASH_BLOCK_SIZE
,
220 .cra_ctxsize
= sizeof(struct p8_ghash_ctx
),
221 .cra_module
= THIS_MODULE
,
222 .cra_init
= p8_ghash_init_tfm
,
223 .cra_exit
= p8_ghash_exit_tfm
,