ccm.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /* ====================================================================
  2. * Copyright (c) 2011 The OpenSSL Project. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in
  13. * the documentation and/or other materials provided with the
  14. * distribution.
  15. *
  16. * 3. All advertising materials mentioning features or use of this
  17. * software must display the following acknowledgment:
  18. * "This product includes software developed by the OpenSSL Project
  19. * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  20. *
  21. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  22. * endorse or promote products derived from this software without
  23. * prior written permission. For written permission, please contact
  24. * openssl-core@openssl.org.
  25. *
  26. * 5. Products derived from this software may not be called "OpenSSL"
  27. * nor may "OpenSSL" appear in their names without prior written
  28. * permission of the OpenSSL Project.
  29. *
  30. * 6. Redistributions of any form whatsoever must retain the following
  31. * acknowledgment:
  32. * "This product includes software developed by the OpenSSL Project
  33. * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  34. *
  35. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  36. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  38. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  41. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  42. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  44. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  45. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  46. * OF THE POSSIBILITY OF SUCH DAMAGE.
  47. * ====================================================================
  48. */
  49. #include <assert.h>
  50. #include <string.h>
  51. #include <openssl/cpu.h>
  52. #include <openssl/mem.h>
  53. #include "../../internal.h"
  54. #include "internal.h"
  55. struct ccm128_state {
  56. union {
  57. uint64_t u[2];
  58. uint8_t c[16];
  59. } nonce, cmac;
  60. };
  61. int CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, const void *key, block128_f block,
  62. ctr128_f ctr, unsigned M, unsigned L) {
  63. if (M < 4 || M > 16 || (M & 1) != 0 || L < 2 || L > 8) {
  64. return 0;
  65. }
  66. ctx->block = block;
  67. ctx->ctr = ctr;
  68. ctx->M = M;
  69. ctx->L = L;
  70. return 1;
  71. }
  72. size_t CRYPTO_ccm128_max_input(const CCM128_CONTEXT *ctx) {
  73. return ctx->L >= sizeof(size_t) ? (size_t)-1
  74. : (((size_t)1) << (ctx->L * 8)) - 1;
  75. }
  76. static int ccm128_init_state(const CCM128_CONTEXT *ctx,
  77. struct ccm128_state *state, const void *key,
  78. const uint8_t *nonce, size_t nonce_len,
  79. const uint8_t *aad, size_t aad_len,
  80. size_t plaintext_len) {
  81. const block128_f block = ctx->block;
  82. const unsigned M = ctx->M;
  83. const unsigned L = ctx->L;
  84. // |L| determines the expected |nonce_len| and the limit for |plaintext_len|.
  85. if (plaintext_len > CRYPTO_ccm128_max_input(ctx) ||
  86. nonce_len != 15 - L) {
  87. return 0;
  88. }
  89. // Assemble the first block for computing the MAC.
  90. OPENSSL_memset(state, 0, sizeof(*state));
  91. state->nonce.c[0] = (uint8_t)((L - 1) | ((M - 2) / 2) << 3);
  92. if (aad_len != 0) {
  93. state->nonce.c[0] |= 0x40; // Set AAD Flag
  94. }
  95. OPENSSL_memcpy(&state->nonce.c[1], nonce, nonce_len);
  96. for (unsigned i = 0; i < L; i++) {
  97. state->nonce.c[15 - i] = (uint8_t)(plaintext_len >> (8 * i));
  98. }
  99. (*block)(state->nonce.c, state->cmac.c, key);
  100. size_t blocks = 1;
  101. if (aad_len != 0) {
  102. unsigned i;
  103. // Cast to u64 to avoid the compiler complaining about invalid shifts.
  104. uint64_t aad_len_u64 = aad_len;
  105. if (aad_len_u64 < 0x10000 - 0x100) {
  106. state->cmac.c[0] ^= (uint8_t)(aad_len_u64 >> 8);
  107. state->cmac.c[1] ^= (uint8_t)aad_len_u64;
  108. i = 2;
  109. } else if (aad_len_u64 <= 0xffffffff) {
  110. state->cmac.c[0] ^= 0xff;
  111. state->cmac.c[1] ^= 0xfe;
  112. state->cmac.c[2] ^= (uint8_t)(aad_len_u64 >> 24);
  113. state->cmac.c[3] ^= (uint8_t)(aad_len_u64 >> 16);
  114. state->cmac.c[4] ^= (uint8_t)(aad_len_u64 >> 8);
  115. state->cmac.c[5] ^= (uint8_t)aad_len_u64;
  116. i = 6;
  117. } else {
  118. state->cmac.c[0] ^= 0xff;
  119. state->cmac.c[1] ^= 0xff;
  120. state->cmac.c[2] ^= (uint8_t)(aad_len_u64 >> 56);
  121. state->cmac.c[3] ^= (uint8_t)(aad_len_u64 >> 48);
  122. state->cmac.c[4] ^= (uint8_t)(aad_len_u64 >> 40);
  123. state->cmac.c[5] ^= (uint8_t)(aad_len_u64 >> 32);
  124. state->cmac.c[6] ^= (uint8_t)(aad_len_u64 >> 24);
  125. state->cmac.c[7] ^= (uint8_t)(aad_len_u64 >> 16);
  126. state->cmac.c[8] ^= (uint8_t)(aad_len_u64 >> 8);
  127. state->cmac.c[9] ^= (uint8_t)aad_len_u64;
  128. i = 10;
  129. }
  130. do {
  131. for (; i < 16 && aad_len != 0; i++) {
  132. state->cmac.c[i] ^= *aad;
  133. aad++;
  134. aad_len--;
  135. }
  136. (*block)(state->cmac.c, state->cmac.c, key);
  137. blocks++;
  138. i = 0;
  139. } while (aad_len != 0);
  140. }
  141. // Per RFC 3610, section 2.6, the total number of block cipher operations done
  142. // must not exceed 2^61. There are two block cipher operations remaining per
  143. // message block, plus one block at the end to encrypt the MAC.
  144. size_t remaining_blocks = 2 * ((plaintext_len + 15) / 16) + 1;
  145. if (plaintext_len + 15 < plaintext_len ||
  146. remaining_blocks + blocks < blocks ||
  147. (uint64_t) remaining_blocks + blocks > UINT64_C(1) << 61) {
  148. return 0;
  149. }
  150. // Assemble the first block for encrypting and decrypting. The bottom |L|
  151. // bytes are replaced with a counter and all bit the encoding of |L| is
  152. // cleared in the first byte.
  153. state->nonce.c[0] &= 7;
  154. return 1;
  155. }
  156. static int ccm128_encrypt(const CCM128_CONTEXT *ctx, struct ccm128_state *state,
  157. const void *key, uint8_t *out, const uint8_t *in,
  158. size_t len) {
  159. // The counter for encryption begins at one.
  160. for (unsigned i = 0; i < ctx->L; i++) {
  161. state->nonce.c[15 - i] = 0;
  162. }
  163. state->nonce.c[15] = 1;
  164. uint8_t partial_buf[16];
  165. unsigned num = 0;
  166. if (ctx->ctr != NULL) {
  167. CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, state->nonce.c, partial_buf,
  168. &num, ctx->ctr);
  169. } else {
  170. CRYPTO_ctr128_encrypt(in, out, len, key, state->nonce.c, partial_buf, &num,
  171. ctx->block);
  172. }
  173. return 1;
  174. }
  175. static int ccm128_compute_mac(const CCM128_CONTEXT *ctx,
  176. struct ccm128_state *state, const void *key,
  177. uint8_t *out_tag, size_t tag_len,
  178. const uint8_t *in, size_t len) {
  179. block128_f block = ctx->block;
  180. if (tag_len != ctx->M) {
  181. return 0;
  182. }
  183. // Incorporate |in| into the MAC.
  184. union {
  185. uint64_t u[2];
  186. uint8_t c[16];
  187. } tmp;
  188. while (len >= 16) {
  189. OPENSSL_memcpy(tmp.c, in, 16);
  190. state->cmac.u[0] ^= tmp.u[0];
  191. state->cmac.u[1] ^= tmp.u[1];
  192. (*block)(state->cmac.c, state->cmac.c, key);
  193. in += 16;
  194. len -= 16;
  195. }
  196. if (len > 0) {
  197. for (size_t i = 0; i < len; i++) {
  198. state->cmac.c[i] ^= in[i];
  199. }
  200. (*block)(state->cmac.c, state->cmac.c, key);
  201. }
  202. // Encrypt the MAC with counter zero.
  203. for (unsigned i = 0; i < ctx->L; i++) {
  204. state->nonce.c[15 - i] = 0;
  205. }
  206. (*block)(state->nonce.c, tmp.c, key);
  207. state->cmac.u[0] ^= tmp.u[0];
  208. state->cmac.u[1] ^= tmp.u[1];
  209. OPENSSL_memcpy(out_tag, state->cmac.c, tag_len);
  210. return 1;
  211. }
  212. int CRYPTO_ccm128_encrypt(const CCM128_CONTEXT *ctx, const void *key,
  213. uint8_t *out, uint8_t *out_tag, size_t tag_len,
  214. const uint8_t *nonce, size_t nonce_len,
  215. const uint8_t *in, size_t len, const uint8_t *aad,
  216. size_t aad_len) {
  217. struct ccm128_state state;
  218. return ccm128_init_state(ctx, &state, key, nonce, nonce_len, aad, aad_len,
  219. len) &&
  220. ccm128_compute_mac(ctx, &state, key, out_tag, tag_len, in, len) &&
  221. ccm128_encrypt(ctx, &state, key, out, in, len);
  222. }
  223. int CRYPTO_ccm128_decrypt(const CCM128_CONTEXT *ctx, const void *key,
  224. uint8_t *out, uint8_t *out_tag, size_t tag_len,
  225. const uint8_t *nonce, size_t nonce_len,
  226. const uint8_t *in, size_t len, const uint8_t *aad,
  227. size_t aad_len) {
  228. struct ccm128_state state;
  229. return ccm128_init_state(ctx, &state, key, nonce, nonce_len, aad, aad_len,
  230. len) &&
  231. ccm128_encrypt(ctx, &state, key, out, in, len) &&
  232. ccm128_compute_mac(ctx, &state, key, out_tag, tag_len, out, len);
  233. }