xts128gb.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright 2022 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. #include <string.h>
  10. #include <openssl/crypto.h>
  11. #include "internal/endian.h"
  12. #include "crypto/modes.h"
  13. #ifndef STRICT_ALIGNMENT
  14. # ifdef __GNUC__
  15. typedef u64 u64_a1 __attribute((__aligned__(1)));
  16. # else
  17. typedef u64 u64_a1;
  18. # endif
  19. #endif
  20. int ossl_crypto_xts128gb_encrypt(const XTS128_CONTEXT *ctx,
  21. const unsigned char iv[16],
  22. const unsigned char *inp, unsigned char *out,
  23. size_t len, int enc)
  24. {
  25. DECLARE_IS_ENDIAN;
  26. union {
  27. u64 u[2];
  28. u32 d[4];
  29. u8 c[16];
  30. } tweak, scratch;
  31. unsigned int i;
  32. if (len < 16)
  33. return -1;
  34. memcpy(tweak.c, iv, 16);
  35. (*ctx->block2) (tweak.c, tweak.c, ctx->key2);
  36. if (!enc && (len % 16))
  37. len -= 16;
  38. while (len >= 16) {
  39. #if defined(STRICT_ALIGNMENT)
  40. memcpy(scratch.c, inp, 16);
  41. scratch.u[0] ^= tweak.u[0];
  42. scratch.u[1] ^= tweak.u[1];
  43. #else
  44. scratch.u[0] = ((u64_a1 *)inp)[0] ^ tweak.u[0];
  45. scratch.u[1] = ((u64_a1 *)inp)[1] ^ tweak.u[1];
  46. #endif
  47. (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
  48. #if defined(STRICT_ALIGNMENT)
  49. scratch.u[0] ^= tweak.u[0];
  50. scratch.u[1] ^= tweak.u[1];
  51. memcpy(out, scratch.c, 16);
  52. #else
  53. ((u64_a1 *)out)[0] = scratch.u[0] ^= tweak.u[0];
  54. ((u64_a1 *)out)[1] = scratch.u[1] ^= tweak.u[1];
  55. #endif
  56. inp += 16;
  57. out += 16;
  58. len -= 16;
  59. if (len == 0)
  60. return 0;
  61. if (IS_LITTLE_ENDIAN) {
  62. u8 res;
  63. u64 hi, lo;
  64. #ifdef BSWAP8
  65. hi = BSWAP8(tweak.u[0]);
  66. lo = BSWAP8(tweak.u[1]);
  67. #else
  68. u8 *p = tweak.c;
  69. hi = (u64)GETU32(p) << 32 | GETU32(p + 4);
  70. lo = (u64)GETU32(p + 8) << 32 | GETU32(p + 12);
  71. #endif
  72. res = (u8)lo & 1;
  73. tweak.u[0] = (lo >> 1) | (hi << 63);
  74. tweak.u[1] = hi >> 1;
  75. if (res)
  76. tweak.c[15] ^= 0xe1;
  77. #ifdef BSWAP8
  78. hi = BSWAP8(tweak.u[0]);
  79. lo = BSWAP8(tweak.u[1]);
  80. #else
  81. p = tweak.c;
  82. hi = (u64)GETU32(p) << 32 | GETU32(p + 4);
  83. lo = (u64)GETU32(p + 8) << 32 | GETU32(p + 12);
  84. #endif
  85. tweak.u[0] = lo;
  86. tweak.u[1] = hi;
  87. } else {
  88. u8 carry, res;
  89. carry = 0;
  90. for (i = 0; i < 16; ++i) {
  91. res = (tweak.c[i] << 7) & 0x80;
  92. tweak.c[i] = ((tweak.c[i] >> 1) + carry) & 0xff;
  93. carry = res;
  94. }
  95. if (res)
  96. tweak.c[0] ^= 0xe1;
  97. }
  98. }
  99. if (enc) {
  100. for (i = 0; i < len; ++i) {
  101. u8 c = inp[i];
  102. out[i] = scratch.c[i];
  103. scratch.c[i] = c;
  104. }
  105. scratch.u[0] ^= tweak.u[0];
  106. scratch.u[1] ^= tweak.u[1];
  107. (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
  108. scratch.u[0] ^= tweak.u[0];
  109. scratch.u[1] ^= tweak.u[1];
  110. memcpy(out - 16, scratch.c, 16);
  111. } else {
  112. union {
  113. u64 u[2];
  114. u8 c[16];
  115. } tweak1;
  116. if (IS_LITTLE_ENDIAN) {
  117. u8 res;
  118. u64 hi, lo;
  119. #ifdef BSWAP8
  120. hi = BSWAP8(tweak.u[0]);
  121. lo = BSWAP8(tweak.u[1]);
  122. #else
  123. u8 *p = tweak.c;
  124. hi = (u64)GETU32(p) << 32 | GETU32(p + 4);
  125. lo = (u64)GETU32(p + 8) << 32 | GETU32(p + 12);
  126. #endif
  127. res = (u8)lo & 1;
  128. tweak1.u[0] = (lo >> 1) | (hi << 63);
  129. tweak1.u[1] = hi >> 1;
  130. if (res)
  131. tweak1.c[15] ^= 0xe1;
  132. #ifdef BSWAP8
  133. hi = BSWAP8(tweak1.u[0]);
  134. lo = BSWAP8(tweak1.u[1]);
  135. #else
  136. p = tweak1.c;
  137. hi = (u64)GETU32(p) << 32 | GETU32(p + 4);
  138. lo = (u64)GETU32(p + 8) << 32 | GETU32(p + 12);
  139. #endif
  140. tweak1.u[0] = lo;
  141. tweak1.u[1] = hi;
  142. } else {
  143. u8 carry, res;
  144. carry = 0;
  145. for (i = 0; i < 16; ++i) {
  146. res = (tweak.c[i] << 7) & 0x80;
  147. tweak1.c[i] = ((tweak.c[i] >> 1) + carry) & 0xff;
  148. carry = res;
  149. }
  150. if (res)
  151. tweak1.c[0] ^= 0xe1;
  152. }
  153. #if defined(STRICT_ALIGNMENT)
  154. memcpy(scratch.c, inp, 16);
  155. scratch.u[0] ^= tweak1.u[0];
  156. scratch.u[1] ^= tweak1.u[1];
  157. #else
  158. scratch.u[0] = ((u64_a1 *)inp)[0] ^ tweak1.u[0];
  159. scratch.u[1] = ((u64_a1 *)inp)[1] ^ tweak1.u[1];
  160. #endif
  161. (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
  162. scratch.u[0] ^= tweak1.u[0];
  163. scratch.u[1] ^= tweak1.u[1];
  164. for (i = 0; i < len; ++i) {
  165. u8 c = inp[16 + i];
  166. out[16 + i] = scratch.c[i];
  167. scratch.c[i] = c;
  168. }
  169. scratch.u[0] ^= tweak.u[0];
  170. scratch.u[1] ^= tweak.u[1];
  171. (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
  172. #if defined(STRICT_ALIGNMENT)
  173. scratch.u[0] ^= tweak.u[0];
  174. scratch.u[1] ^= tweak.u[1];
  175. memcpy(out, scratch.c, 16);
  176. #else
  177. ((u64_a1 *)out)[0] = scratch.u[0] ^ tweak.u[0];
  178. ((u64_a1 *)out)[1] = scratch.u[1] ^ tweak.u[1];
  179. #endif
  180. }
  181. return 0;
  182. }