raw_ocb.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /* ===================================================================
  2. *
  3. * Copyright (c) 2014, Legrandin <helderijs@gmail.com>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in
  14. * the documentation and/or other materials provided with the
  15. * distribution.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  27. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. * ===================================================================
  30. */
  31. #include "common.h"
  32. FAKE_INIT(raw_ocb)
  33. #include "block_base.h"
  34. #include <assert.h>
  35. #include <stdio.h>
  36. #define BLOCK_SIZE 16
  37. typedef uint8_t DataBlock[BLOCK_SIZE];
  38. typedef struct {
  39. BlockBase *cipher;
  40. DataBlock L_star;
  41. DataBlock L_dollar;
  42. DataBlock L[65]; /** 0..64 **/
  43. /** Associated data **/
  44. uint64_t counter_A;
  45. DataBlock offset_A;
  46. DataBlock sum;
  47. /** Ciphertext/plaintext **/
  48. uint64_t counter_P;
  49. DataBlock offset_P;
  50. DataBlock checksum;
  51. } OcbModeState;
  52. static void double_L(DataBlock *out, DataBlock *in)
  53. {
  54. unsigned carry;
  55. int i;
  56. carry = 0;
  57. for (i=BLOCK_SIZE-1; i>=0; i--) {
  58. unsigned t;
  59. t = ((unsigned)(*in)[i] << 1) | carry;
  60. carry = t >> 8;
  61. (*out)[i] = (uint8_t)t;
  62. }
  63. carry |= 0x100;
  64. carry |= carry << 1;
  65. carry |= carry << 2;
  66. carry |= carry << 4;
  67. (*out)[BLOCK_SIZE-1] = (uint8_t)((*out)[BLOCK_SIZE-1] ^ (carry & 0x87));
  68. }
  69. static unsigned ntz(uint64_t counter)
  70. {
  71. unsigned i;
  72. for (i=0; i<65; i++) {
  73. if (counter & 1)
  74. return i;
  75. counter >>= 1;
  76. }
  77. return 64;
  78. }
  79. EXPORT_SYM int OCB_start_operation(BlockBase *cipher,
  80. const uint8_t *offset_0,
  81. size_t offset_0_len,
  82. OcbModeState **pState)
  83. {
  84. OcbModeState *state;
  85. int result;
  86. unsigned i;
  87. if ((NULL == cipher) || (NULL == pState)) {
  88. return ERR_NULL;
  89. }
  90. if ((BLOCK_SIZE != cipher->block_len) || (BLOCK_SIZE != offset_0_len)) {
  91. return ERR_BLOCK_SIZE;
  92. }
  93. *pState = state = calloc(1, sizeof(OcbModeState));
  94. if (NULL == state) {
  95. return ERR_MEMORY;
  96. }
  97. state->cipher = cipher;
  98. result = state->cipher->encrypt(state->cipher, state->checksum, state->L_star, BLOCK_SIZE);
  99. if (result)
  100. return result;
  101. double_L(&state->L_dollar, &state->L_star);
  102. double_L(&state->L[0], &state->L_dollar);
  103. for (i=1; i<=64; i++)
  104. double_L(&state->L[i], &state->L[i-1]);
  105. memcpy(state->offset_P, offset_0, BLOCK_SIZE);
  106. state->counter_A = state->counter_P = 1;
  107. return 0;
  108. }
  109. enum OcbDirection { OCB_ENCRYPT, OCB_DECRYPT };
  110. EXPORT_SYM int OCB_transcrypt(OcbModeState *state,
  111. const uint8_t *in,
  112. uint8_t *out,
  113. size_t in_len,
  114. enum OcbDirection direction)
  115. {
  116. CipherOperation process = NULL;
  117. const uint8_t *checksummed = NULL;
  118. int result;
  119. unsigned i;
  120. if ((NULL == state) || (NULL == out) || (NULL == in))
  121. return ERR_NULL;
  122. assert(OCB_ENCRYPT==direction || OCB_DECRYPT==direction);
  123. checksummed = OCB_ENCRYPT==direction ? in : out;
  124. process = OCB_ENCRYPT==direction ? state->cipher->encrypt : state->cipher->decrypt;
  125. for (;in_len>=BLOCK_SIZE; in_len-=BLOCK_SIZE) {
  126. unsigned idx;
  127. DataBlock pre;
  128. idx = ntz(state->counter_P);
  129. for (i=0; i<BLOCK_SIZE; i++) {
  130. state->offset_P[i] ^= state->L[idx][i];
  131. pre[i] = in[i] ^ state->offset_P[i];
  132. }
  133. if (++state->counter_P == 0)
  134. return ERR_MAX_DATA;
  135. result = process(state->cipher, pre, out, BLOCK_SIZE);
  136. if (result)
  137. return result;
  138. for (i=0; i<BLOCK_SIZE; i++) {
  139. out[i] ^= state->offset_P[i];
  140. state->checksum[i] ^= checksummed[i];
  141. }
  142. in += BLOCK_SIZE;
  143. checksummed += BLOCK_SIZE;
  144. out += BLOCK_SIZE;
  145. }
  146. /** Process last piece (if any) **/
  147. if (in_len>0) {
  148. DataBlock pad;
  149. for (i=0; i<BLOCK_SIZE; i++)
  150. state->offset_P[i] ^= state->L_star[i];
  151. result = state->cipher->encrypt(state->cipher, state->offset_P, pad, BLOCK_SIZE);
  152. if (result)
  153. return result;
  154. for (i=0; i<in_len; i++) {
  155. out[i] = in[i] ^ pad[i];
  156. state->checksum[i] ^= checksummed[i];
  157. }
  158. state->checksum[in_len] ^= 0x80;
  159. }
  160. return 0;
  161. }
  162. /**
  163. * Encrypt a piece of plaintext.
  164. *
  165. * @state The block cipher state.
  166. * @in A pointer to the plaintext. It is aligned to the 16 byte boundary
  167. * unless it is the last block.
  168. * @out A pointer to an output buffer, that will hold the ciphertext.
  169. * The caller must allocate an area of memory as big as the plaintext.
  170. * @in_len The size of the plaintext pointed to by @in.
  171. *
  172. * @return 0 in case of success, otherwise the relevant error code.
  173. */
  174. EXPORT_SYM int OCB_encrypt(OcbModeState *state,
  175. const uint8_t *in,
  176. uint8_t *out,
  177. size_t in_len)
  178. {
  179. return OCB_transcrypt(state, in, out, in_len, OCB_ENCRYPT);
  180. }
  181. /**
  182. * Decrypt a piece of ciphertext.
  183. *
  184. * @state The block cipher state.
  185. * @in A pointer to the ciphertext. It is aligned to the 16 byte boundary
  186. * unless it is the last block.
  187. * @out A pointer to an output buffer, that will hold the plaintext.
  188. * The caller must allocate an area of memory as big as the ciphertext.
  189. * @in_len The size of the ciphertext pointed to by @in.
  190. *
  191. * @return 0 in case of success, otherwise the relevant error code.
  192. */
  193. EXPORT_SYM int OCB_decrypt(OcbModeState *state,
  194. const uint8_t *in,
  195. uint8_t *out,
  196. size_t in_len)
  197. {
  198. return OCB_transcrypt(state, in, out, in_len, OCB_DECRYPT);
  199. }
  200. /**
  201. * Process a piece of authenticated data.
  202. *
  203. * @state The block cipher state.
  204. * @in A pointer to the authenticated data.
  205. * It must be aligned to the 16 byte boundary, unless it is
  206. * the last piece.
  207. * @in_len The size of the authenticated data pointed to by @in.
  208. */
  209. EXPORT_SYM int OCB_update(OcbModeState *state,
  210. const uint8_t *in,
  211. size_t in_len)
  212. {
  213. int result;
  214. unsigned i;
  215. DataBlock pt;
  216. DataBlock ct;
  217. if ((NULL == state) || (NULL == in))
  218. return ERR_NULL;
  219. for (;in_len>=BLOCK_SIZE; in_len-=BLOCK_SIZE) {
  220. unsigned idx;
  221. idx = ntz(state->counter_A);
  222. for (i=0; i<BLOCK_SIZE; i++) {
  223. state->offset_A[i] ^= state->L[idx][i];
  224. pt[i] = in[i] ^ state->offset_A[i];
  225. }
  226. if (++state->counter_A == 0)
  227. return ERR_MAX_DATA;
  228. result = state->cipher->encrypt(state->cipher, pt, ct, BLOCK_SIZE);
  229. if (result)
  230. return result;
  231. for (i=0; i<BLOCK_SIZE; i++)
  232. state->sum[i] ^= ct[i];
  233. in += BLOCK_SIZE;
  234. }
  235. /** Process last piece (if any) **/
  236. if (in_len>0) {
  237. memset(pt, 0, sizeof pt);
  238. memcpy(pt, in, in_len);
  239. pt[in_len] = 0x80;
  240. for (i=0; i<BLOCK_SIZE; i++)
  241. pt[i] ^= state->offset_A[i] ^ state->L_star[i];
  242. result = state->cipher->encrypt(state->cipher, pt, ct, BLOCK_SIZE);
  243. if (result)
  244. return result;
  245. for (i=0; i<BLOCK_SIZE; i++)
  246. state->sum[i] ^= ct[i];
  247. }
  248. return 0;
  249. }
  250. EXPORT_SYM int OCB_digest(OcbModeState *state,
  251. uint8_t *tag,
  252. size_t tag_len)
  253. {
  254. DataBlock pt;
  255. unsigned i;
  256. int result;
  257. if ((NULL == state) || (NULL == tag))
  258. return ERR_NULL;
  259. if (BLOCK_SIZE != tag_len)
  260. return ERR_TAG_SIZE;
  261. for (i=0; i<BLOCK_SIZE; i++)
  262. pt[i] = state->checksum[i] ^ state->offset_P[i] ^ state->L_dollar[i];
  263. result = state->cipher->encrypt(state->cipher, pt, tag, BLOCK_SIZE);
  264. if (result)
  265. return result;
  266. /** state->sum is HASH(K, A) **/
  267. for (i=0; i<BLOCK_SIZE; i++)
  268. tag[i] ^= state->sum[i];
  269. return 0;
  270. }
  271. EXPORT_SYM int OCB_stop_operation(OcbModeState *state)
  272. {
  273. if (NULL == state)
  274. return ERR_NULL;
  275. state->cipher->destructor(state->cipher);
  276. free(state);
  277. return 0;
  278. }