xts128.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the OpenSSL license (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 <openssl/crypto.h>
  10. #include "modes_local.h"
  11. #include <string.h>
  12. #ifndef STRICT_ALIGNMENT
  13. # ifdef __GNUC__
  14. typedef u64 u64_a1 __attribute((__aligned__(1)));
  15. # else
  16. typedef u64 u64_a1;
  17. # endif
  18. #endif
  19. int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx,
  20. const unsigned char iv[16],
  21. const unsigned char *inp, unsigned char *out,
  22. size_t len, int enc)
  23. {
  24. const union {
  25. long one;
  26. char little;
  27. } is_endian = {
  28. 1
  29. };
  30. union {
  31. u64 u[2];
  32. u32 d[4];
  33. u8 c[16];
  34. } tweak, scratch;
  35. unsigned int i;
  36. if (len < 16)
  37. return -1;
  38. memcpy(tweak.c, iv, 16);
  39. (*ctx->block2) (tweak.c, tweak.c, ctx->key2);
  40. if (!enc && (len % 16))
  41. len -= 16;
  42. while (len >= 16) {
  43. #if defined(STRICT_ALIGNMENT)
  44. memcpy(scratch.c, inp, 16);
  45. scratch.u[0] ^= tweak.u[0];
  46. scratch.u[1] ^= tweak.u[1];
  47. #else
  48. scratch.u[0] = ((u64_a1 *)inp)[0] ^ tweak.u[0];
  49. scratch.u[1] = ((u64_a1 *)inp)[1] ^ tweak.u[1];
  50. #endif
  51. (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
  52. #if defined(STRICT_ALIGNMENT)
  53. scratch.u[0] ^= tweak.u[0];
  54. scratch.u[1] ^= tweak.u[1];
  55. memcpy(out, scratch.c, 16);
  56. #else
  57. ((u64_a1 *)out)[0] = scratch.u[0] ^= tweak.u[0];
  58. ((u64_a1 *)out)[1] = scratch.u[1] ^= tweak.u[1];
  59. #endif
  60. inp += 16;
  61. out += 16;
  62. len -= 16;
  63. if (len == 0)
  64. return 0;
  65. if (is_endian.little) {
  66. unsigned int carry, res;
  67. res = 0x87 & (((int)tweak.d[3]) >> 31);
  68. carry = (unsigned int)(tweak.u[0] >> 63);
  69. tweak.u[0] = (tweak.u[0] << 1) ^ res;
  70. tweak.u[1] = (tweak.u[1] << 1) | carry;
  71. } else {
  72. size_t c;
  73. for (c = 0, i = 0; i < 16; ++i) {
  74. /*
  75. * + substitutes for |, because c is 1 bit
  76. */
  77. c += ((size_t)tweak.c[i]) << 1;
  78. tweak.c[i] = (u8)c;
  79. c = c >> 8;
  80. }
  81. tweak.c[0] ^= (u8)(0x87 & (0 - c));
  82. }
  83. }
  84. if (enc) {
  85. for (i = 0; i < len; ++i) {
  86. u8 c = inp[i];
  87. out[i] = scratch.c[i];
  88. scratch.c[i] = c;
  89. }
  90. scratch.u[0] ^= tweak.u[0];
  91. scratch.u[1] ^= tweak.u[1];
  92. (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
  93. scratch.u[0] ^= tweak.u[0];
  94. scratch.u[1] ^= tweak.u[1];
  95. memcpy(out - 16, scratch.c, 16);
  96. } else {
  97. union {
  98. u64 u[2];
  99. u8 c[16];
  100. } tweak1;
  101. if (is_endian.little) {
  102. unsigned int carry, res;
  103. res = 0x87 & (((int)tweak.d[3]) >> 31);
  104. carry = (unsigned int)(tweak.u[0] >> 63);
  105. tweak1.u[0] = (tweak.u[0] << 1) ^ res;
  106. tweak1.u[1] = (tweak.u[1] << 1) | carry;
  107. } else {
  108. size_t c;
  109. for (c = 0, i = 0; i < 16; ++i) {
  110. /*
  111. * + substitutes for |, because c is 1 bit
  112. */
  113. c += ((size_t)tweak.c[i]) << 1;
  114. tweak1.c[i] = (u8)c;
  115. c = c >> 8;
  116. }
  117. tweak1.c[0] ^= (u8)(0x87 & (0 - c));
  118. }
  119. #if defined(STRICT_ALIGNMENT)
  120. memcpy(scratch.c, inp, 16);
  121. scratch.u[0] ^= tweak1.u[0];
  122. scratch.u[1] ^= tweak1.u[1];
  123. #else
  124. scratch.u[0] = ((u64_a1 *)inp)[0] ^ tweak1.u[0];
  125. scratch.u[1] = ((u64_a1 *)inp)[1] ^ tweak1.u[1];
  126. #endif
  127. (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
  128. scratch.u[0] ^= tweak1.u[0];
  129. scratch.u[1] ^= tweak1.u[1];
  130. for (i = 0; i < len; ++i) {
  131. u8 c = inp[16 + i];
  132. out[16 + i] = scratch.c[i];
  133. scratch.c[i] = c;
  134. }
  135. scratch.u[0] ^= tweak.u[0];
  136. scratch.u[1] ^= tweak.u[1];
  137. (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
  138. #if defined(STRICT_ALIGNMENT)
  139. scratch.u[0] ^= tweak.u[0];
  140. scratch.u[1] ^= tweak.u[1];
  141. memcpy(out, scratch.c, 16);
  142. #else
  143. ((u64_a1 *)out)[0] = scratch.u[0] ^ tweak.u[0];
  144. ((u64_a1 *)out)[1] = scratch.u[1] ^ tweak.u[1];
  145. #endif
  146. }
  147. return 0;
  148. }