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
);
67 printk(KERN_INFO
"Using '%s' as fallback implementation.\n",
68 crypto_tfm_alg_driver_name(crypto_shash_tfm(fallback
)));
70 crypto_shash_set_flags(fallback
,
71 crypto_shash_get_flags((struct crypto_shash
74 /* Check if the descsize defined in the algorithm is still enough. */
75 if (shash_tfm
->descsize
< sizeof(struct p8_ghash_desc_ctx
)
76 + crypto_shash_descsize(fallback
)) {
78 "Desc size of the fallback implementation (%s) does not match the expected value: %lu vs %u\n",
80 shash_tfm
->descsize
- sizeof(struct p8_ghash_desc_ctx
),
81 crypto_shash_descsize(fallback
));
84 ctx
->fallback
= fallback
;
89 static void p8_ghash_exit_tfm(struct crypto_tfm
*tfm
)
91 struct p8_ghash_ctx
*ctx
= crypto_tfm_ctx(tfm
);
94 crypto_free_shash(ctx
->fallback
);
99 static int p8_ghash_init(struct shash_desc
*desc
)
101 struct p8_ghash_ctx
*ctx
= crypto_tfm_ctx(crypto_shash_tfm(desc
->tfm
));
102 struct p8_ghash_desc_ctx
*dctx
= shash_desc_ctx(desc
);
105 memset(dctx
->shash
, 0, GHASH_DIGEST_SIZE
);
106 dctx
->fallback_desc
.tfm
= ctx
->fallback
;
107 dctx
->fallback_desc
.flags
= desc
->flags
;
108 return crypto_shash_init(&dctx
->fallback_desc
);
111 static int p8_ghash_setkey(struct crypto_shash
*tfm
, const u8
*key
,
114 struct p8_ghash_ctx
*ctx
= crypto_tfm_ctx(crypto_shash_tfm(tfm
));
116 if (keylen
!= GHASH_BLOCK_SIZE
)
122 gcm_init_p8(ctx
->htable
, (const u64
*) key
);
123 disable_kernel_vsx();
126 return crypto_shash_setkey(ctx
->fallback
, key
, keylen
);
129 static int p8_ghash_update(struct shash_desc
*desc
,
130 const u8
*src
, unsigned int srclen
)
133 struct p8_ghash_ctx
*ctx
= crypto_tfm_ctx(crypto_shash_tfm(desc
->tfm
));
134 struct p8_ghash_desc_ctx
*dctx
= shash_desc_ctx(desc
);
137 return crypto_shash_update(&dctx
->fallback_desc
, src
,
141 if (dctx
->bytes
+ srclen
< GHASH_DIGEST_SIZE
) {
142 memcpy(dctx
->buffer
+ dctx
->bytes
, src
,
144 dctx
->bytes
+= srclen
;
147 memcpy(dctx
->buffer
+ dctx
->bytes
, src
,
148 GHASH_DIGEST_SIZE
- dctx
->bytes
);
152 gcm_ghash_p8(dctx
->shash
, ctx
->htable
,
153 dctx
->buffer
, GHASH_DIGEST_SIZE
);
154 disable_kernel_vsx();
157 src
+= GHASH_DIGEST_SIZE
- dctx
->bytes
;
158 srclen
-= GHASH_DIGEST_SIZE
- dctx
->bytes
;
161 len
= srclen
& ~(GHASH_DIGEST_SIZE
- 1);
166 gcm_ghash_p8(dctx
->shash
, ctx
->htable
, src
, len
);
167 disable_kernel_vsx();
174 memcpy(dctx
->buffer
, src
, srclen
);
175 dctx
->bytes
= srclen
;
181 static int p8_ghash_final(struct shash_desc
*desc
, u8
*out
)
184 struct p8_ghash_ctx
*ctx
= crypto_tfm_ctx(crypto_shash_tfm(desc
->tfm
));
185 struct p8_ghash_desc_ctx
*dctx
= shash_desc_ctx(desc
);
188 return crypto_shash_final(&dctx
->fallback_desc
, out
);
191 for (i
= dctx
->bytes
; i
< GHASH_DIGEST_SIZE
; i
++)
196 gcm_ghash_p8(dctx
->shash
, ctx
->htable
,
197 dctx
->buffer
, GHASH_DIGEST_SIZE
);
198 disable_kernel_vsx();
203 memcpy(out
, dctx
->shash
, GHASH_DIGEST_SIZE
);
208 struct shash_alg p8_ghash_alg
= {
209 .digestsize
= GHASH_DIGEST_SIZE
,
210 .init
= p8_ghash_init
,
211 .update
= p8_ghash_update
,
212 .final
= p8_ghash_final
,
213 .setkey
= p8_ghash_setkey
,
214 .descsize
= sizeof(struct p8_ghash_desc_ctx
)
215 + sizeof(struct ghash_desc_ctx
),
218 .cra_driver_name
= "p8_ghash",
219 .cra_priority
= 1000,
220 .cra_flags
= CRYPTO_ALG_TYPE_SHASH
| CRYPTO_ALG_NEED_FALLBACK
,
221 .cra_blocksize
= GHASH_BLOCK_SIZE
,
222 .cra_ctxsize
= sizeof(struct p8_ghash_ctx
),
223 .cra_module
= THIS_MODULE
,
224 .cra_init
= p8_ghash_init_tfm
,
225 .cra_exit
= p8_ghash_exit_tfm
,