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