cipher_aes_gcm_siv_polyval.c 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. /*
  10. * AES low level APIs are deprecated for public use, but still ok for internal
  11. * use where we're using them to implement the higher level EVP interface, as is
  12. * the case here.
  13. */
  14. #include "internal/deprecated.h"
  15. #include <openssl/evp.h>
  16. #include <internal/endian.h>
  17. #include <prov/implementations.h>
  18. #include "cipher_aes_gcm_siv.h"
  19. static ossl_inline void mulx_ghash(uint64_t *a)
  20. {
  21. uint64_t t[2], mask;
  22. DECLARE_IS_ENDIAN;
  23. if (IS_LITTLE_ENDIAN) {
  24. t[0] = GSWAP8(a[0]);
  25. t[1] = GSWAP8(a[1]);
  26. } else {
  27. t[0] = a[0];
  28. t[1] = a[1];
  29. }
  30. mask = -(int64_t)(t[1] & 1) & 0xe1;
  31. mask <<= 56;
  32. if (IS_LITTLE_ENDIAN) {
  33. a[1] = GSWAP8((t[1] >> 1) ^ (t[0] << 63));
  34. a[0] = GSWAP8((t[0] >> 1) ^ mask);
  35. } else {
  36. a[1] = (t[1] >> 1) ^ (t[0] << 63);
  37. a[0] = (t[0] >> 1) ^ mask;
  38. }
  39. }
  40. #define aligned64(p) (((uintptr_t)p & 0x07) == 0)
  41. static ossl_inline void byte_reverse16(uint8_t *out, const uint8_t *in)
  42. {
  43. if (aligned64(out) && aligned64(in)) {
  44. ((uint64_t *)out)[0] = GSWAP8(((uint64_t *)in)[1]);
  45. ((uint64_t *)out)[1] = GSWAP8(((uint64_t *)in)[0]);
  46. } else {
  47. int i;
  48. for (i = 0; i < 16; i++)
  49. out[i] = in[15 - i];
  50. }
  51. }
  52. /* Initialization of POLYVAL via existing GHASH implementation */
  53. void ossl_polyval_ghash_init(u128 Htable[16], const uint64_t H[2])
  54. {
  55. uint64_t tmp[2];
  56. DECLARE_IS_ENDIAN;
  57. byte_reverse16((uint8_t *)tmp, (const uint8_t *)H);
  58. mulx_ghash(tmp);
  59. if (IS_LITTLE_ENDIAN) {
  60. /* "H is stored in host byte order" */
  61. tmp[0] = GSWAP8(tmp[0]);
  62. tmp[1] = GSWAP8(tmp[1]);
  63. }
  64. ossl_gcm_init_4bit(Htable, (u64*)tmp);
  65. }
  66. /* Implmentation of POLYVAL via existing GHASH implementation */
  67. void ossl_polyval_ghash_hash(const u128 Htable[16], uint8_t *tag, const uint8_t *inp, size_t len)
  68. {
  69. uint64_t out[2];
  70. uint64_t tmp[2];
  71. size_t i;
  72. byte_reverse16((uint8_t *)out, (uint8_t *)tag);
  73. /*
  74. * This implementation doesn't deal with partials, callers do,
  75. * so, len is a multiple of 16
  76. */
  77. for (i = 0; i < len; i += 16) {
  78. byte_reverse16((uint8_t *)tmp, &inp[i]);
  79. ossl_gcm_ghash_4bit((u64*)out, Htable, (uint8_t *)tmp, 16);
  80. }
  81. byte_reverse16(tag, (uint8_t *)out);
  82. }