xts128.c 4.3 KB

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