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