ghash_s390.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Cryptographic API.
  4. *
  5. * s390 implementation of the GHASH algorithm for GCM (Galois/Counter Mode).
  6. *
  7. * Copyright IBM Corp. 2011
  8. * Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
  9. */
  10. #include <crypto/internal/hash.h>
  11. #include <linux/module.h>
  12. #include <linux/cpufeature.h>
  13. #include <asm/cpacf.h>
  14. #define GHASH_BLOCK_SIZE 16
  15. #define GHASH_DIGEST_SIZE 16
  16. struct ghash_ctx {
  17. u8 key[GHASH_BLOCK_SIZE];
  18. };
  19. struct ghash_desc_ctx {
  20. u8 icv[GHASH_BLOCK_SIZE];
  21. u8 key[GHASH_BLOCK_SIZE];
  22. u8 buffer[GHASH_BLOCK_SIZE];
  23. u32 bytes;
  24. };
  25. static int ghash_init(struct shash_desc *desc)
  26. {
  27. struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
  28. struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
  29. memset(dctx, 0, sizeof(*dctx));
  30. memcpy(dctx->key, ctx->key, GHASH_BLOCK_SIZE);
  31. return 0;
  32. }
  33. static int ghash_setkey(struct crypto_shash *tfm,
  34. const u8 *key, unsigned int keylen)
  35. {
  36. struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
  37. if (keylen != GHASH_BLOCK_SIZE) {
  38. crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
  39. return -EINVAL;
  40. }
  41. memcpy(ctx->key, key, GHASH_BLOCK_SIZE);
  42. return 0;
  43. }
  44. static int ghash_update(struct shash_desc *desc,
  45. const u8 *src, unsigned int srclen)
  46. {
  47. struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
  48. unsigned int n;
  49. u8 *buf = dctx->buffer;
  50. if (dctx->bytes) {
  51. u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes);
  52. n = min(srclen, dctx->bytes);
  53. dctx->bytes -= n;
  54. srclen -= n;
  55. memcpy(pos, src, n);
  56. src += n;
  57. if (!dctx->bytes) {
  58. cpacf_kimd(CPACF_KIMD_GHASH, dctx, buf,
  59. GHASH_BLOCK_SIZE);
  60. }
  61. }
  62. n = srclen & ~(GHASH_BLOCK_SIZE - 1);
  63. if (n) {
  64. cpacf_kimd(CPACF_KIMD_GHASH, dctx, src, n);
  65. src += n;
  66. srclen -= n;
  67. }
  68. if (srclen) {
  69. dctx->bytes = GHASH_BLOCK_SIZE - srclen;
  70. memcpy(buf, src, srclen);
  71. }
  72. return 0;
  73. }
  74. static int ghash_flush(struct ghash_desc_ctx *dctx)
  75. {
  76. u8 *buf = dctx->buffer;
  77. if (dctx->bytes) {
  78. u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes);
  79. memset(pos, 0, dctx->bytes);
  80. cpacf_kimd(CPACF_KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE);
  81. dctx->bytes = 0;
  82. }
  83. return 0;
  84. }
  85. static int ghash_final(struct shash_desc *desc, u8 *dst)
  86. {
  87. struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
  88. int ret;
  89. ret = ghash_flush(dctx);
  90. if (!ret)
  91. memcpy(dst, dctx->icv, GHASH_BLOCK_SIZE);
  92. return ret;
  93. }
  94. static struct shash_alg ghash_alg = {
  95. .digestsize = GHASH_DIGEST_SIZE,
  96. .init = ghash_init,
  97. .update = ghash_update,
  98. .final = ghash_final,
  99. .setkey = ghash_setkey,
  100. .descsize = sizeof(struct ghash_desc_ctx),
  101. .base = {
  102. .cra_name = "ghash",
  103. .cra_driver_name = "ghash-s390",
  104. .cra_priority = 300,
  105. .cra_blocksize = GHASH_BLOCK_SIZE,
  106. .cra_ctxsize = sizeof(struct ghash_ctx),
  107. .cra_module = THIS_MODULE,
  108. },
  109. };
  110. static int __init ghash_mod_init(void)
  111. {
  112. if (!cpacf_query_func(CPACF_KIMD, CPACF_KIMD_GHASH))
  113. return -EOPNOTSUPP;
  114. return crypto_register_shash(&ghash_alg);
  115. }
  116. static void __exit ghash_mod_exit(void)
  117. {
  118. crypto_unregister_shash(&ghash_alg);
  119. }
  120. module_cpu_feature_match(MSA, ghash_mod_init);
  121. module_exit(ghash_mod_exit);
  122. MODULE_ALIAS_CRYPTO("ghash");
  123. MODULE_LICENSE("GPL");
  124. MODULE_DESCRIPTION("GHASH Message Digest Algorithm, s390 implementation");