Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

312 linhas
11 KiB

  1. /* Copyright (c) 2014, Google Inc.
  2. *
  3. * Permission to use, copy, modify, and/or distribute this software for any
  4. * purpose with or without fee is hereby granted, provided that the above
  5. * copyright notice and this permission notice appear in all copies.
  6. *
  7. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. #include <openssl/aead.h>
  15. #include <string.h>
  16. #include <openssl/chacha.h>
  17. #include <openssl/cipher.h>
  18. #include <openssl/err.h>
  19. #include <openssl/mem.h>
  20. #include <openssl/poly1305.h>
  21. #include "internal.h"
  22. #define POLY1305_TAG_LEN 16
  23. struct aead_chacha20_poly1305_ctx {
  24. unsigned char key[32];
  25. unsigned char tag_len;
  26. };
  27. static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
  28. size_t key_len, size_t tag_len) {
  29. struct aead_chacha20_poly1305_ctx *c20_ctx;
  30. if (tag_len == 0) {
  31. tag_len = POLY1305_TAG_LEN;
  32. }
  33. if (tag_len > POLY1305_TAG_LEN) {
  34. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
  35. return 0;
  36. }
  37. if (key_len != sizeof(c20_ctx->key)) {
  38. return 0; /* internal error - EVP_AEAD_CTX_init should catch this. */
  39. }
  40. c20_ctx = OPENSSL_malloc(sizeof(struct aead_chacha20_poly1305_ctx));
  41. if (c20_ctx == NULL) {
  42. return 0;
  43. }
  44. memcpy(c20_ctx->key, key, key_len);
  45. c20_ctx->tag_len = tag_len;
  46. ctx->aead_state = c20_ctx;
  47. return 1;
  48. }
  49. static void aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx) {
  50. struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
  51. OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key));
  52. OPENSSL_free(c20_ctx);
  53. }
  54. static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) {
  55. uint8_t length_bytes[8];
  56. unsigned i;
  57. for (i = 0; i < sizeof(length_bytes); i++) {
  58. length_bytes[i] = data_len;
  59. data_len >>= 8;
  60. }
  61. CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
  62. }
  63. #if defined(__arm__)
  64. #define ALIGNED __attribute__((aligned(16)))
  65. #else
  66. #define ALIGNED
  67. #endif
  68. typedef void (*aead_poly1305_update)(poly1305_state *ctx, const uint8_t *ad,
  69. size_t ad_len, const uint8_t *ciphertext,
  70. size_t ciphertext_len);
  71. /* aead_poly1305 fills |tag| with the authentication tag for the given
  72. * inputs, using |update| to control the order and format that the inputs are
  73. * signed/authenticated. */
  74. static void aead_poly1305(aead_poly1305_update update,
  75. uint8_t tag[POLY1305_TAG_LEN],
  76. const struct aead_chacha20_poly1305_ctx *c20_ctx,
  77. const uint8_t nonce[12], const uint8_t *ad,
  78. size_t ad_len, const uint8_t *ciphertext,
  79. size_t ciphertext_len) {
  80. uint8_t poly1305_key[32] ALIGNED;
  81. memset(poly1305_key, 0, sizeof(poly1305_key));
  82. CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
  83. c20_ctx->key, nonce, 0);
  84. poly1305_state ctx;
  85. CRYPTO_poly1305_init(&ctx, poly1305_key);
  86. update(&ctx, ad, ad_len, ciphertext, ciphertext_len);
  87. CRYPTO_poly1305_finish(&ctx, tag);
  88. }
  89. static int seal_impl(aead_poly1305_update poly1305_update,
  90. const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
  91. size_t max_out_len, const uint8_t nonce[12],
  92. const uint8_t *in, size_t in_len, const uint8_t *ad,
  93. size_t ad_len) {
  94. const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
  95. const uint64_t in_len_64 = in_len;
  96. /* |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
  97. * individual operations that work on more than 256GB at a time.
  98. * |in_len_64| is needed because, on 32-bit platforms, size_t is only
  99. * 32-bits and this produces a warning because it's always false.
  100. * Casting to uint64_t inside the conditional is not sufficient to stop
  101. * the warning. */
  102. if (in_len_64 >= (1ull << 32) * 64 - 64) {
  103. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
  104. return 0;
  105. }
  106. if (in_len + c20_ctx->tag_len < in_len) {
  107. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
  108. return 0;
  109. }
  110. if (max_out_len < in_len + c20_ctx->tag_len) {
  111. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
  112. return 0;
  113. }
  114. CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
  115. uint8_t tag[POLY1305_TAG_LEN] ALIGNED;
  116. aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, out, in_len);
  117. memcpy(out + in_len, tag, c20_ctx->tag_len);
  118. *out_len = in_len + c20_ctx->tag_len;
  119. return 1;
  120. }
  121. static int open_impl(aead_poly1305_update poly1305_update,
  122. const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
  123. size_t max_out_len, const uint8_t nonce[12],
  124. const uint8_t *in, size_t in_len, const uint8_t *ad,
  125. size_t ad_len) {
  126. const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
  127. size_t plaintext_len;
  128. const uint64_t in_len_64 = in_len;
  129. if (in_len < c20_ctx->tag_len) {
  130. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
  131. return 0;
  132. }
  133. /* |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
  134. * individual operations that work on more than 256GB at a time.
  135. * |in_len_64| is needed because, on 32-bit platforms, size_t is only
  136. * 32-bits and this produces a warning because it's always false.
  137. * Casting to uint64_t inside the conditional is not sufficient to stop
  138. * the warning. */
  139. if (in_len_64 >= (1ull << 32) * 64 - 64) {
  140. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
  141. return 0;
  142. }
  143. plaintext_len = in_len - c20_ctx->tag_len;
  144. uint8_t tag[POLY1305_TAG_LEN] ALIGNED;
  145. aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, in,
  146. plaintext_len);
  147. if (CRYPTO_memcmp(tag, in + plaintext_len, c20_ctx->tag_len) != 0) {
  148. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
  149. return 0;
  150. }
  151. CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, nonce, 1);
  152. *out_len = plaintext_len;
  153. return 1;
  154. }
  155. static void poly1305_update_padded_16(poly1305_state *poly1305,
  156. const uint8_t *data, size_t data_len) {
  157. static const uint8_t padding[16] = { 0 }; /* Padding is all zeros. */
  158. CRYPTO_poly1305_update(poly1305, data, data_len);
  159. if (data_len % 16 != 0) {
  160. CRYPTO_poly1305_update(poly1305, padding, sizeof(padding) - (data_len % 16));
  161. }
  162. }
  163. static void poly1305_update(poly1305_state *ctx, const uint8_t *ad,
  164. size_t ad_len, const uint8_t *ciphertext,
  165. size_t ciphertext_len) {
  166. poly1305_update_padded_16(ctx, ad, ad_len);
  167. poly1305_update_padded_16(ctx, ciphertext, ciphertext_len);
  168. poly1305_update_length(ctx, ad_len);
  169. poly1305_update_length(ctx, ciphertext_len);
  170. }
  171. static int aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
  172. size_t *out_len, size_t max_out_len,
  173. const uint8_t *nonce, size_t nonce_len,
  174. const uint8_t *in, size_t in_len,
  175. const uint8_t *ad, size_t ad_len) {
  176. if (nonce_len != 12) {
  177. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
  178. return 0;
  179. }
  180. return seal_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
  181. in_len, ad, ad_len);
  182. }
  183. static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
  184. size_t *out_len, size_t max_out_len,
  185. const uint8_t *nonce, size_t nonce_len,
  186. const uint8_t *in, size_t in_len,
  187. const uint8_t *ad, size_t ad_len) {
  188. if (nonce_len != 12) {
  189. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
  190. return 0;
  191. }
  192. return open_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
  193. in_len, ad, ad_len);
  194. }
  195. static const EVP_AEAD aead_chacha20_poly1305 = {
  196. 32, /* key len */
  197. 12, /* nonce len */
  198. POLY1305_TAG_LEN, /* overhead */
  199. POLY1305_TAG_LEN, /* max tag length */
  200. aead_chacha20_poly1305_init,
  201. NULL, /* init_with_direction */
  202. aead_chacha20_poly1305_cleanup,
  203. aead_chacha20_poly1305_seal,
  204. aead_chacha20_poly1305_open,
  205. NULL, /* get_rc4_state */
  206. NULL, /* get_iv */
  207. };
  208. const EVP_AEAD *EVP_aead_chacha20_poly1305_rfc7539(void) {
  209. return &aead_chacha20_poly1305;
  210. }
  211. static void poly1305_update_old(poly1305_state *ctx, const uint8_t *ad,
  212. size_t ad_len, const uint8_t *ciphertext,
  213. size_t ciphertext_len) {
  214. CRYPTO_poly1305_update(ctx, ad, ad_len);
  215. poly1305_update_length(ctx, ad_len);
  216. CRYPTO_poly1305_update(ctx, ciphertext, ciphertext_len);
  217. poly1305_update_length(ctx, ciphertext_len);
  218. }
  219. static int aead_chacha20_poly1305_old_seal(
  220. const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len,
  221. const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len,
  222. const uint8_t *ad, size_t ad_len) {
  223. if (nonce_len != 8) {
  224. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
  225. return 0;
  226. }
  227. uint8_t nonce_96[12];
  228. memset(nonce_96, 0, 4);
  229. memcpy(nonce_96 + 4, nonce, 8);
  230. return seal_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
  231. nonce_96, in, in_len, ad, ad_len);
  232. }
  233. static int aead_chacha20_poly1305_old_open(
  234. const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len,
  235. const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len,
  236. const uint8_t *ad, size_t ad_len) {
  237. if (nonce_len != 8) {
  238. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
  239. return 0;
  240. }
  241. uint8_t nonce_96[12];
  242. memset(nonce_96, 0, 4);
  243. memcpy(nonce_96 + 4, nonce, 8);
  244. return open_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
  245. nonce_96, in, in_len, ad, ad_len);
  246. }
  247. static const EVP_AEAD aead_chacha20_poly1305_old = {
  248. 32, /* key len */
  249. 8, /* nonce len */
  250. POLY1305_TAG_LEN, /* overhead */
  251. POLY1305_TAG_LEN, /* max tag length */
  252. aead_chacha20_poly1305_init,
  253. NULL, /* init_with_direction */
  254. aead_chacha20_poly1305_cleanup,
  255. aead_chacha20_poly1305_old_seal,
  256. aead_chacha20_poly1305_old_open,
  257. NULL, /* get_rc4_state */
  258. NULL, /* get_iv */
  259. };
  260. const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void) {
  261. return &aead_chacha20_poly1305_old;
  262. }
  263. const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
  264. return &aead_chacha20_poly1305_old;
  265. }