ghash_s390.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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 <[email protected]>
  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. return -EINVAL;
  39. memcpy(ctx->key, key, GHASH_BLOCK_SIZE);
  40. return 0;
  41. }
  42. static int ghash_update(struct shash_desc *desc,
  43. const u8 *src, unsigned int srclen)
  44. {
  45. struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
  46. unsigned int n;
  47. u8 *buf = dctx->buffer;
  48. if (dctx->bytes) {
  49. u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes);
  50. n = min(srclen, dctx->bytes);
  51. dctx->bytes -= n;
  52. srclen -= n;
  53. memcpy(pos, src, n);
  54. src += n;
  55. if (!dctx->bytes) {
  56. cpacf_kimd(CPACF_KIMD_GHASH, dctx, buf,
  57. GHASH_BLOCK_SIZE);
  58. }
  59. }
  60. n = srclen & ~(GHASH_BLOCK_SIZE - 1);
  61. if (n) {
  62. cpacf_kimd(CPACF_KIMD_GHASH, dctx, src, n);
  63. src += n;
  64. srclen -= n;
  65. }
  66. if (srclen) {
  67. dctx->bytes = GHASH_BLOCK_SIZE - srclen;
  68. memcpy(buf, src, srclen);
  69. }
  70. return 0;
  71. }
  72. static int ghash_flush(struct ghash_desc_ctx *dctx)
  73. {
  74. u8 *buf = dctx->buffer;
  75. if (dctx->bytes) {
  76. u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes);
  77. memset(pos, 0, dctx->bytes);
  78. cpacf_kimd(CPACF_KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE);
  79. dctx->bytes = 0;
  80. }
  81. return 0;
  82. }
  83. static int ghash_final(struct shash_desc *desc, u8 *dst)
  84. {
  85. struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
  86. int ret;
  87. ret = ghash_flush(dctx);
  88. if (!ret)
  89. memcpy(dst, dctx->icv, GHASH_BLOCK_SIZE);
  90. return ret;
  91. }
  92. static struct shash_alg ghash_alg = {
  93. .digestsize = GHASH_DIGEST_SIZE,
  94. .init = ghash_init,
  95. .update = ghash_update,
  96. .final = ghash_final,
  97. .setkey = ghash_setkey,
  98. .descsize = sizeof(struct ghash_desc_ctx),
  99. .base = {
  100. .cra_name = "ghash",
  101. .cra_driver_name = "ghash-s390",
  102. .cra_priority = 300,
  103. .cra_blocksize = GHASH_BLOCK_SIZE,
  104. .cra_ctxsize = sizeof(struct ghash_ctx),
  105. .cra_module = THIS_MODULE,
  106. },
  107. };
  108. static int __init ghash_mod_init(void)
  109. {
  110. if (!cpacf_query_func(CPACF_KIMD, CPACF_KIMD_GHASH))
  111. return -ENODEV;
  112. return crypto_register_shash(&ghash_alg);
  113. }
  114. static void __exit ghash_mod_exit(void)
  115. {
  116. crypto_unregister_shash(&ghash_alg);
  117. }
  118. module_cpu_feature_match(S390_CPU_FEATURE_MSA, ghash_mod_init);
  119. module_exit(ghash_mod_exit);
  120. MODULE_ALIAS_CRYPTO("ghash");
  121. MODULE_LICENSE("GPL");
  122. MODULE_DESCRIPTION("GHASH hash function, s390 implementation");