aes-ccm.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * Counter with CBC-MAC (CCM) with AES
  3. *
  4. * Copyright (c) 2010-2012, Jouni Malinen <j@w1.fi>
  5. *
  6. * This software may be distributed under the terms of the BSD license.
  7. * See README for more details.
  8. */
  9. #include <string.h>
  10. #include "aes.h"
  11. #define PUT_BE16(a, val) \
  12. do { \
  13. (a)[0] = ((u16) (val)) >> 8; \
  14. (a)[1] = ((u16) (val)) & 0xff; \
  15. } while (0)
  16. static void xor_aes_block(u8 *dst, const u8 *src)
  17. {
  18. #ifdef HAVE_ALIGNED_MEM_OPERATION
  19. u32 *d = (u32 *) dst;
  20. u32 *s = (u32 *) src;
  21. *d++ ^= *s++;
  22. *d++ ^= *s++;
  23. *d++ ^= *s++;
  24. *d++ ^= *s++;
  25. #else /* HAVE_ALIGNED_MEM_OPERATION */
  26. u32 i;
  27. for (i = 0; i < 16; i++)
  28. {
  29. *dst++ ^= *src++;
  30. }
  31. #endif /* HAVE_ALIGNED_MEM_OPERATION */
  32. }
  33. static void aes_ccm_auth_start(void *aes, size_t M, size_t L, const u8 *nonce,
  34. const u8 *aad, size_t aad_len, size_t plain_len,
  35. u8 *x)
  36. {
  37. u8 aad_buf[2 * AES_BLOCK_SIZE];
  38. u8 b[AES_BLOCK_SIZE];
  39. /* Authentication */
  40. /* B_0: Flags | Nonce N | l(m) */
  41. b[0] = aad_len ? 0x40 : 0 /* Adata */;
  42. b[0] |= (((M - 2) / 2) /* M' */ << 3);
  43. b[0] |= (L - 1) /* L' */;
  44. memcpy(&b[1], nonce, 15 - L);
  45. PUT_BE16(&b[AES_BLOCK_SIZE - L], plain_len);
  46. aes_encrypt(aes, b, x); /* X_1 = E(K, B_0) */
  47. if (!aad_len)
  48. return;
  49. PUT_BE16(aad_buf, aad_len);
  50. memcpy(aad_buf + 2, aad, aad_len);
  51. memset(aad_buf + 2 + aad_len, 0, sizeof(aad_buf) - 2 - aad_len);
  52. xor_aes_block(aad_buf, x);
  53. aes_encrypt(aes, aad_buf, x); /* X_2 = E(K, X_1 XOR B_1) */
  54. if (aad_len > AES_BLOCK_SIZE - 2) {
  55. xor_aes_block(&aad_buf[AES_BLOCK_SIZE], x);
  56. /* X_3 = E(K, X_2 XOR B_2) */
  57. aes_encrypt(aes, &aad_buf[AES_BLOCK_SIZE], x);
  58. }
  59. }
  60. static void aes_ccm_auth(void *aes, const u8 *data, size_t len, u8 *x)
  61. {
  62. size_t last = len % AES_BLOCK_SIZE;
  63. size_t i;
  64. for (i = 0; i < len / AES_BLOCK_SIZE; i++) {
  65. /* X_i+1 = E(K, X_i XOR B_i) */
  66. xor_aes_block(x, data);
  67. data += AES_BLOCK_SIZE;
  68. aes_encrypt(aes, x, x);
  69. }
  70. if (last) {
  71. /* XOR zero-padded last block */
  72. for (i = 0; i < last; i++)
  73. x[i] ^= *data++;
  74. aes_encrypt(aes, x, x);
  75. }
  76. }
  77. static void aes_ccm_encr_start(size_t L, const u8 *nonce, u8 *a)
  78. {
  79. /* A_i = Flags | Nonce N | Counter i */
  80. a[0] = L - 1; /* Flags = L' */
  81. memcpy(&a[1], nonce, 15 - L);
  82. }
  83. static void aes_ccm_encr(void *aes, size_t L, const u8 *in, size_t len, u8 *out,
  84. u8 *a)
  85. {
  86. size_t last = len % AES_BLOCK_SIZE;
  87. size_t i;
  88. /* crypt = msg XOR (S_1 | S_2 | ... | S_n) */
  89. for (i = 1; i <= len / AES_BLOCK_SIZE; i++) {
  90. PUT_BE16(&a[AES_BLOCK_SIZE - 2], i);
  91. /* S_i = E(K, A_i) */
  92. aes_encrypt(aes, a, out);
  93. xor_aes_block(out, in);
  94. out += AES_BLOCK_SIZE;
  95. in += AES_BLOCK_SIZE;
  96. }
  97. #if 0
  98. if (last) {
  99. PUT_BE16(&a[AES_BLOCK_SIZE - 2], i);
  100. aes_encrypt(aes, a, out);
  101. /* XOR zero-padded last block */
  102. for (i = 0; i < last; i++)
  103. *out++ ^= *in++;
  104. }
  105. #else /* 0 */
  106. if (last) {
  107. u8 tout[AES_BLOCK_SIZE];
  108. PUT_BE16(&a[AES_BLOCK_SIZE - 2], i);
  109. aes_encrypt(aes, a, tout);
  110. /* XOR zero-padded last block */
  111. for (i = 0; i < last; i++)
  112. *out++ = tout[i] ^ *in++;
  113. }
  114. #endif /* 0 */
  115. }
  116. static void aes_ccm_encr_auth(void *aes, size_t M, u8 *x, u8 *a, u8 *auth)
  117. {
  118. size_t i;
  119. u8 tmp[AES_BLOCK_SIZE];
  120. /* U = T XOR S_0; S_0 = E(K, A_0) */
  121. PUT_BE16(&a[AES_BLOCK_SIZE - 2], 0);
  122. aes_encrypt(aes, a, tmp);
  123. for (i = 0; i < M; i++)
  124. auth[i] = x[i] ^ tmp[i];
  125. }
  126. static void aes_ccm_decr_auth(void *aes, size_t M, u8 *a, const u8 *auth, u8 *t)
  127. {
  128. size_t i;
  129. u8 tmp[AES_BLOCK_SIZE];
  130. /* U = T XOR S_0; S_0 = E(K, A_0) */
  131. PUT_BE16(&a[AES_BLOCK_SIZE - 2], 0);
  132. aes_encrypt(aes, a, tmp);
  133. for (i = 0; i < M; i++)
  134. t[i] = auth[i] ^ tmp[i];
  135. }
  136. /* AES-CCM with fixed L=2 and aad_len <= 30 assumption */
  137. int aes_ccm_ae(const u8 *key, size_t key_len, const u8 *nonce,
  138. size_t M, const u8 *plain, size_t plain_len,
  139. const u8 *aad, size_t aad_len, u8 *crypt, u8 *auth)
  140. {
  141. const size_t L = 2;
  142. void *aes;
  143. u8 x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE];
  144. if (aad_len > 30 || M > AES_BLOCK_SIZE)
  145. return -1;
  146. aes = aes_encrypt_init(key, key_len);
  147. if (aes == NULL)
  148. return -1;
  149. aes_ccm_auth_start(aes, M, L, nonce, aad, aad_len, plain_len, x);
  150. aes_ccm_auth(aes, plain, plain_len, x);
  151. /* Encryption */
  152. aes_ccm_encr_start(L, nonce, a);
  153. aes_ccm_encr(aes, L, plain, plain_len, crypt, a);
  154. aes_ccm_encr_auth(aes, M, x, a, auth);
  155. aes_encrypt_deinit(aes);
  156. return 0;
  157. }
  158. /* AES-CCM with fixed L=2 and aad_len <= 30 assumption */
  159. int aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce,
  160. size_t M, const u8 *crypt, size_t crypt_len,
  161. const u8 *aad, size_t aad_len, const u8 *auth, u8 *plain)
  162. {
  163. const size_t L = 2;
  164. void *aes;
  165. u8 x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE];
  166. u8 t[AES_BLOCK_SIZE];
  167. if (aad_len > 30 || M > AES_BLOCK_SIZE)
  168. return -1;
  169. aes = aes_encrypt_init(key, key_len);
  170. if (aes == NULL)
  171. return -1;
  172. /* Decryption */
  173. aes_ccm_encr_start(L, nonce, a);
  174. aes_ccm_decr_auth(aes, M, a, auth, t);
  175. /* plaintext = msg XOR (S_1 | S_2 | ... | S_n) */
  176. aes_ccm_encr(aes, L, crypt, crypt_len, plain, a);
  177. aes_ccm_auth_start(aes, M, L, nonce, aad, aad_len, crypt_len, x);
  178. aes_ccm_auth(aes, plain, crypt_len, x);
  179. aes_encrypt_deinit(aes);
  180. if (memcmp(x, t, M) != 0) {
  181. return -1;
  182. }
  183. return 0;
  184. }