xts128.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Copyright 2011-2020 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 CRYPTO_xts128_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. unsigned int carry, res;
  63. res = 0x87 & (((int)tweak.d[3]) >> 31);
  64. carry = (unsigned int)(tweak.u[0] >> 63);
  65. tweak.u[0] = (tweak.u[0] << 1) ^ res;
  66. tweak.u[1] = (tweak.u[1] << 1) | carry;
  67. } else {
  68. size_t c;
  69. for (c = 0, i = 0; i < 16; ++i) {
  70. /*
  71. * + substitutes for |, because c is 1 bit
  72. */
  73. c += ((size_t)tweak.c[i]) << 1;
  74. tweak.c[i] = (u8)c;
  75. c = c >> 8;
  76. }
  77. tweak.c[0] ^= (u8)(0x87 & (0 - c));
  78. }
  79. }
  80. if (enc) {
  81. for (i = 0; i < len; ++i) {
  82. u8 c = inp[i];
  83. out[i] = scratch.c[i];
  84. scratch.c[i] = c;
  85. }
  86. scratch.u[0] ^= tweak.u[0];
  87. scratch.u[1] ^= tweak.u[1];
  88. (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
  89. scratch.u[0] ^= tweak.u[0];
  90. scratch.u[1] ^= tweak.u[1];
  91. memcpy(out - 16, scratch.c, 16);
  92. } else {
  93. union {
  94. u64 u[2];
  95. u8 c[16];
  96. } tweak1;
  97. if (IS_LITTLE_ENDIAN) {
  98. unsigned int carry, res;
  99. res = 0x87 & (((int)tweak.d[3]) >> 31);
  100. carry = (unsigned int)(tweak.u[0] >> 63);
  101. tweak1.u[0] = (tweak.u[0] << 1) ^ res;
  102. tweak1.u[1] = (tweak.u[1] << 1) | carry;
  103. } else {
  104. size_t c;
  105. for (c = 0, i = 0; i < 16; ++i) {
  106. /*
  107. * + substitutes for |, because c is 1 bit
  108. */
  109. c += ((size_t)tweak.c[i]) << 1;
  110. tweak1.c[i] = (u8)c;
  111. c = c >> 8;
  112. }
  113. tweak1.c[0] ^= (u8)(0x87 & (0 - c));
  114. }
  115. #if defined(STRICT_ALIGNMENT)
  116. memcpy(scratch.c, inp, 16);
  117. scratch.u[0] ^= tweak1.u[0];
  118. scratch.u[1] ^= tweak1.u[1];
  119. #else
  120. scratch.u[0] = ((u64_a1 *)inp)[0] ^ tweak1.u[0];
  121. scratch.u[1] = ((u64_a1 *)inp)[1] ^ tweak1.u[1];
  122. #endif
  123. (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
  124. scratch.u[0] ^= tweak1.u[0];
  125. scratch.u[1] ^= tweak1.u[1];
  126. for (i = 0; i < len; ++i) {
  127. u8 c = inp[16 + i];
  128. out[16 + i] = scratch.c[i];
  129. scratch.c[i] = c;
  130. }
  131. scratch.u[0] ^= tweak.u[0];
  132. scratch.u[1] ^= tweak.u[1];
  133. (*ctx->block1) (scratch.c, scratch.c, ctx->key1);
  134. #if defined(STRICT_ALIGNMENT)
  135. scratch.u[0] ^= tweak.u[0];
  136. scratch.u[1] ^= tweak.u[1];
  137. memcpy(out, scratch.c, 16);
  138. #else
  139. ((u64_a1 *)out)[0] = scratch.u[0] ^ tweak.u[0];
  140. ((u64_a1 *)out)[1] = scratch.u[1] ^ tweak.u[1];
  141. #endif
  142. }
  143. return 0;
  144. }