1*df1309ceSGerald Schaefer /* 2*df1309ceSGerald Schaefer * Cryptographic API. 3*df1309ceSGerald Schaefer * 4*df1309ceSGerald Schaefer * s390 implementation of the GHASH algorithm for GCM (Galois/Counter Mode). 5*df1309ceSGerald Schaefer * 6*df1309ceSGerald Schaefer * Copyright IBM Corp. 2011 7*df1309ceSGerald Schaefer * Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com> 8*df1309ceSGerald Schaefer */ 9*df1309ceSGerald Schaefer 10*df1309ceSGerald Schaefer #include <crypto/internal/hash.h> 11*df1309ceSGerald Schaefer #include <linux/module.h> 12*df1309ceSGerald Schaefer 13*df1309ceSGerald Schaefer #include "crypt_s390.h" 14*df1309ceSGerald Schaefer 15*df1309ceSGerald Schaefer #define GHASH_BLOCK_SIZE 16 16*df1309ceSGerald Schaefer #define GHASH_DIGEST_SIZE 16 17*df1309ceSGerald Schaefer 18*df1309ceSGerald Schaefer struct ghash_ctx { 19*df1309ceSGerald Schaefer u8 icv[16]; 20*df1309ceSGerald Schaefer u8 key[16]; 21*df1309ceSGerald Schaefer }; 22*df1309ceSGerald Schaefer 23*df1309ceSGerald Schaefer struct ghash_desc_ctx { 24*df1309ceSGerald Schaefer u8 buffer[GHASH_BLOCK_SIZE]; 25*df1309ceSGerald Schaefer u32 bytes; 26*df1309ceSGerald Schaefer }; 27*df1309ceSGerald Schaefer 28*df1309ceSGerald Schaefer static int ghash_init(struct shash_desc *desc) 29*df1309ceSGerald Schaefer { 30*df1309ceSGerald Schaefer struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); 31*df1309ceSGerald Schaefer 32*df1309ceSGerald Schaefer memset(dctx, 0, sizeof(*dctx)); 33*df1309ceSGerald Schaefer 34*df1309ceSGerald Schaefer return 0; 35*df1309ceSGerald Schaefer } 36*df1309ceSGerald Schaefer 37*df1309ceSGerald Schaefer static int ghash_setkey(struct crypto_shash *tfm, 38*df1309ceSGerald Schaefer const u8 *key, unsigned int keylen) 39*df1309ceSGerald Schaefer { 40*df1309ceSGerald Schaefer struct ghash_ctx *ctx = crypto_shash_ctx(tfm); 41*df1309ceSGerald Schaefer 42*df1309ceSGerald Schaefer if (keylen != GHASH_BLOCK_SIZE) { 43*df1309ceSGerald Schaefer crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 44*df1309ceSGerald Schaefer return -EINVAL; 45*df1309ceSGerald Schaefer } 46*df1309ceSGerald Schaefer 47*df1309ceSGerald Schaefer memcpy(ctx->key, key, GHASH_BLOCK_SIZE); 48*df1309ceSGerald Schaefer memset(ctx->icv, 0, GHASH_BLOCK_SIZE); 49*df1309ceSGerald Schaefer 50*df1309ceSGerald Schaefer return 0; 51*df1309ceSGerald Schaefer } 52*df1309ceSGerald Schaefer 53*df1309ceSGerald Schaefer static int ghash_update(struct shash_desc *desc, 54*df1309ceSGerald Schaefer const u8 *src, unsigned int srclen) 55*df1309ceSGerald Schaefer { 56*df1309ceSGerald Schaefer struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); 57*df1309ceSGerald Schaefer struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); 58*df1309ceSGerald Schaefer unsigned int n; 59*df1309ceSGerald Schaefer u8 *buf = dctx->buffer; 60*df1309ceSGerald Schaefer int ret; 61*df1309ceSGerald Schaefer 62*df1309ceSGerald Schaefer if (dctx->bytes) { 63*df1309ceSGerald Schaefer u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes); 64*df1309ceSGerald Schaefer 65*df1309ceSGerald Schaefer n = min(srclen, dctx->bytes); 66*df1309ceSGerald Schaefer dctx->bytes -= n; 67*df1309ceSGerald Schaefer srclen -= n; 68*df1309ceSGerald Schaefer 69*df1309ceSGerald Schaefer memcpy(pos, src, n); 70*df1309ceSGerald Schaefer src += n; 71*df1309ceSGerald Schaefer 72*df1309ceSGerald Schaefer if (!dctx->bytes) { 73*df1309ceSGerald Schaefer ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, 74*df1309ceSGerald Schaefer GHASH_BLOCK_SIZE); 75*df1309ceSGerald Schaefer BUG_ON(ret != GHASH_BLOCK_SIZE); 76*df1309ceSGerald Schaefer } 77*df1309ceSGerald Schaefer } 78*df1309ceSGerald Schaefer 79*df1309ceSGerald Schaefer n = srclen & ~(GHASH_BLOCK_SIZE - 1); 80*df1309ceSGerald Schaefer if (n) { 81*df1309ceSGerald Schaefer ret = crypt_s390_kimd(KIMD_GHASH, ctx, src, n); 82*df1309ceSGerald Schaefer BUG_ON(ret != n); 83*df1309ceSGerald Schaefer src += n; 84*df1309ceSGerald Schaefer srclen -= n; 85*df1309ceSGerald Schaefer } 86*df1309ceSGerald Schaefer 87*df1309ceSGerald Schaefer if (srclen) { 88*df1309ceSGerald Schaefer dctx->bytes = GHASH_BLOCK_SIZE - srclen; 89*df1309ceSGerald Schaefer memcpy(buf, src, srclen); 90*df1309ceSGerald Schaefer } 91*df1309ceSGerald Schaefer 92*df1309ceSGerald Schaefer return 0; 93*df1309ceSGerald Schaefer } 94*df1309ceSGerald Schaefer 95*df1309ceSGerald Schaefer static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx) 96*df1309ceSGerald Schaefer { 97*df1309ceSGerald Schaefer u8 *buf = dctx->buffer; 98*df1309ceSGerald Schaefer int ret; 99*df1309ceSGerald Schaefer 100*df1309ceSGerald Schaefer if (dctx->bytes) { 101*df1309ceSGerald Schaefer u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes); 102*df1309ceSGerald Schaefer 103*df1309ceSGerald Schaefer memset(pos, 0, dctx->bytes); 104*df1309ceSGerald Schaefer 105*df1309ceSGerald Schaefer ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, GHASH_BLOCK_SIZE); 106*df1309ceSGerald Schaefer BUG_ON(ret != GHASH_BLOCK_SIZE); 107*df1309ceSGerald Schaefer } 108*df1309ceSGerald Schaefer 109*df1309ceSGerald Schaefer dctx->bytes = 0; 110*df1309ceSGerald Schaefer } 111*df1309ceSGerald Schaefer 112*df1309ceSGerald Schaefer static int ghash_final(struct shash_desc *desc, u8 *dst) 113*df1309ceSGerald Schaefer { 114*df1309ceSGerald Schaefer struct ghash_desc_ctx *dctx = shash_desc_ctx(desc); 115*df1309ceSGerald Schaefer struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm); 116*df1309ceSGerald Schaefer 117*df1309ceSGerald Schaefer ghash_flush(ctx, dctx); 118*df1309ceSGerald Schaefer memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE); 119*df1309ceSGerald Schaefer 120*df1309ceSGerald Schaefer return 0; 121*df1309ceSGerald Schaefer } 122*df1309ceSGerald Schaefer 123*df1309ceSGerald Schaefer static struct shash_alg ghash_alg = { 124*df1309ceSGerald Schaefer .digestsize = GHASH_DIGEST_SIZE, 125*df1309ceSGerald Schaefer .init = ghash_init, 126*df1309ceSGerald Schaefer .update = ghash_update, 127*df1309ceSGerald Schaefer .final = ghash_final, 128*df1309ceSGerald Schaefer .setkey = ghash_setkey, 129*df1309ceSGerald Schaefer .descsize = sizeof(struct ghash_desc_ctx), 130*df1309ceSGerald Schaefer .base = { 131*df1309ceSGerald Schaefer .cra_name = "ghash", 132*df1309ceSGerald Schaefer .cra_driver_name = "ghash-s390", 133*df1309ceSGerald Schaefer .cra_priority = CRYPT_S390_PRIORITY, 134*df1309ceSGerald Schaefer .cra_flags = CRYPTO_ALG_TYPE_SHASH, 135*df1309ceSGerald Schaefer .cra_blocksize = GHASH_BLOCK_SIZE, 136*df1309ceSGerald Schaefer .cra_ctxsize = sizeof(struct ghash_ctx), 137*df1309ceSGerald Schaefer .cra_module = THIS_MODULE, 138*df1309ceSGerald Schaefer .cra_list = LIST_HEAD_INIT(ghash_alg.base.cra_list), 139*df1309ceSGerald Schaefer }, 140*df1309ceSGerald Schaefer }; 141*df1309ceSGerald Schaefer 142*df1309ceSGerald Schaefer static int __init ghash_mod_init(void) 143*df1309ceSGerald Schaefer { 144*df1309ceSGerald Schaefer if (!crypt_s390_func_available(KIMD_GHASH, 145*df1309ceSGerald Schaefer CRYPT_S390_MSA | CRYPT_S390_MSA4)) 146*df1309ceSGerald Schaefer return -EOPNOTSUPP; 147*df1309ceSGerald Schaefer 148*df1309ceSGerald Schaefer return crypto_register_shash(&ghash_alg); 149*df1309ceSGerald Schaefer } 150*df1309ceSGerald Schaefer 151*df1309ceSGerald Schaefer static void __exit ghash_mod_exit(void) 152*df1309ceSGerald Schaefer { 153*df1309ceSGerald Schaefer crypto_unregister_shash(&ghash_alg); 154*df1309ceSGerald Schaefer } 155*df1309ceSGerald Schaefer 156*df1309ceSGerald Schaefer module_init(ghash_mod_init); 157*df1309ceSGerald Schaefer module_exit(ghash_mod_exit); 158*df1309ceSGerald Schaefer 159*df1309ceSGerald Schaefer MODULE_ALIAS("ghash"); 160*df1309ceSGerald Schaefer 161*df1309ceSGerald Schaefer MODULE_LICENSE("GPL"); 162*df1309ceSGerald Schaefer MODULE_DESCRIPTION("GHASH Message Digest Algorithm, s390 implementation"); 163