Você não pode selecionar mais de 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.
 
 
 
 
 
 

324 linhas
10 KiB

  1. /* Copyright (c) 2017, 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 <openssl/cipher.h>
  16. #include <openssl/crypto.h>
  17. #include <openssl/err.h>
  18. #include "internal.h"
  19. #if !defined(OPENSSL_SMALL)
  20. #define EVP_AEAD_AES_GCM_SIV_NONCE_LEN 12
  21. #define EVP_AEAD_AES_GCM_SIV_TAG_LEN 16
  22. struct aead_aes_gcm_siv_ctx {
  23. union {
  24. double align;
  25. AES_KEY ks;
  26. } ks;
  27. block128_f kgk_block;
  28. unsigned is_256:1;
  29. };
  30. static int aead_aes_gcm_siv_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
  31. size_t key_len, size_t tag_len) {
  32. const size_t key_bits = key_len * 8;
  33. if (key_bits != 128 && key_bits != 256) {
  34. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
  35. return 0; /* EVP_AEAD_CTX_init should catch this. */
  36. }
  37. if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
  38. tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
  39. }
  40. if (tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
  41. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
  42. return 0;
  43. }
  44. struct aead_aes_gcm_siv_ctx *gcm_siv_ctx =
  45. OPENSSL_malloc(sizeof(struct aead_aes_gcm_siv_ctx));
  46. if (gcm_siv_ctx == NULL) {
  47. return 0;
  48. }
  49. OPENSSL_memset(gcm_siv_ctx, 0, sizeof(struct aead_aes_gcm_siv_ctx));
  50. aes_ctr_set_key(&gcm_siv_ctx->ks.ks, NULL, &gcm_siv_ctx->kgk_block, key,
  51. key_len);
  52. gcm_siv_ctx->is_256 = (key_len == 32);
  53. ctx->aead_state = gcm_siv_ctx;
  54. return 1;
  55. }
  56. static void aead_aes_gcm_siv_cleanup(EVP_AEAD_CTX *ctx) {
  57. struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
  58. OPENSSL_cleanse(gcm_siv_ctx, sizeof(struct aead_aes_gcm_siv_ctx));
  59. OPENSSL_free(gcm_siv_ctx);
  60. }
  61. /* gcm_siv_crypt encrypts (or decrypts—it's the same thing) |in_len| bytes from
  62. * |in| to |out|, using the block function |enc_block| with |key| in counter
  63. * mode, starting at |initial_counter|. This differs from the traditional
  64. * counter mode code in that the counter is handled little-endian, only the
  65. * first four bytes are used and the GCM-SIV tweak to the final byte is
  66. * applied. The |in| and |out| pointers may be equal but otherwise must not
  67. * alias. */
  68. static void gcm_siv_crypt(uint8_t *out, const uint8_t *in, size_t in_len,
  69. const uint8_t initial_counter[AES_BLOCK_SIZE],
  70. block128_f enc_block, const AES_KEY *key) {
  71. union {
  72. uint32_t w[4];
  73. uint8_t c[16];
  74. } counter;
  75. OPENSSL_memcpy(counter.c, initial_counter, AES_BLOCK_SIZE);
  76. counter.c[15] |= 0x80;
  77. for (size_t done = 0; done < in_len;) {
  78. uint8_t keystream[AES_BLOCK_SIZE];
  79. enc_block(counter.c, keystream, key);
  80. counter.w[0]++;
  81. size_t todo = AES_BLOCK_SIZE;
  82. if (in_len - done < todo) {
  83. todo = in_len - done;
  84. }
  85. for (size_t i = 0; i < todo; i++) {
  86. out[done + i] = keystream[i] ^ in[done + i];
  87. }
  88. done += todo;
  89. }
  90. }
  91. /* gcm_siv_polyval evaluates POLYVAL at |auth_key| on the given plaintext and
  92. * AD. The result is written to |out_tag|. */
  93. static void gcm_siv_polyval(
  94. uint8_t out_tag[16], const uint8_t *in, size_t in_len, const uint8_t *ad,
  95. size_t ad_len, const uint8_t auth_key[16],
  96. const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
  97. struct polyval_ctx polyval_ctx;
  98. CRYPTO_POLYVAL_init(&polyval_ctx, auth_key);
  99. CRYPTO_POLYVAL_update_blocks(&polyval_ctx, ad, ad_len & ~15);
  100. uint8_t scratch[16];
  101. if (ad_len & 15) {
  102. OPENSSL_memset(scratch, 0, sizeof(scratch));
  103. OPENSSL_memcpy(scratch, &ad[ad_len & ~15], ad_len & 15);
  104. CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
  105. }
  106. CRYPTO_POLYVAL_update_blocks(&polyval_ctx, in, in_len & ~15);
  107. if (in_len & 15) {
  108. OPENSSL_memset(scratch, 0, sizeof(scratch));
  109. OPENSSL_memcpy(scratch, &in[in_len & ~15], in_len & 15);
  110. CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
  111. }
  112. union {
  113. uint8_t c[16];
  114. struct {
  115. uint64_t ad;
  116. uint64_t in;
  117. } bitlens;
  118. } length_block;
  119. length_block.bitlens.ad = ad_len * 8;
  120. length_block.bitlens.in = in_len * 8;
  121. CRYPTO_POLYVAL_update_blocks(&polyval_ctx, length_block.c,
  122. sizeof(length_block));
  123. CRYPTO_POLYVAL_finish(&polyval_ctx, out_tag);
  124. for (size_t i = 0; i < EVP_AEAD_AES_GCM_SIV_NONCE_LEN; i++) {
  125. out_tag[i] ^= nonce[i];
  126. }
  127. out_tag[15] &= 0x7f;
  128. }
  129. /* gcm_siv_record_keys contains the keys used for a specific GCM-SIV record. */
  130. struct gcm_siv_record_keys {
  131. uint8_t auth_key[16];
  132. union {
  133. double align;
  134. AES_KEY ks;
  135. } enc_key;
  136. block128_f enc_block;
  137. };
  138. /* gcm_siv_keys calculates the keys for a specific GCM-SIV record with the
  139. * given nonce and writes them to |*out_keys|. */
  140. static void gcm_siv_keys(
  141. const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx,
  142. struct gcm_siv_record_keys *out_keys,
  143. const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
  144. const AES_KEY *const key = &gcm_siv_ctx->ks.ks;
  145. uint8_t key_material[(128 /* POLYVAL key */ + 256 /* max AES key */) / 8];
  146. const size_t blocks_needed = gcm_siv_ctx->is_256 ? 6 : 4;
  147. uint8_t counter[AES_BLOCK_SIZE];
  148. OPENSSL_memset(counter, 0, AES_BLOCK_SIZE - EVP_AEAD_AES_GCM_SIV_NONCE_LEN);
  149. OPENSSL_memcpy(counter + AES_BLOCK_SIZE - EVP_AEAD_AES_GCM_SIV_NONCE_LEN,
  150. nonce, EVP_AEAD_AES_GCM_SIV_NONCE_LEN);
  151. for (size_t i = 0; i < blocks_needed; i++) {
  152. counter[0] = i;
  153. uint8_t ciphertext[AES_BLOCK_SIZE];
  154. gcm_siv_ctx->kgk_block(counter, ciphertext, key);
  155. OPENSSL_memcpy(&key_material[i * 8], ciphertext, 8);
  156. }
  157. OPENSSL_memcpy(out_keys->auth_key, key_material, 16);
  158. aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
  159. key_material + 16, gcm_siv_ctx->is_256 ? 32 : 16);
  160. }
  161. static int aead_aes_gcm_siv_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
  162. size_t *out_len, size_t max_out_len,
  163. const uint8_t *nonce, size_t nonce_len,
  164. const uint8_t *in, size_t in_len,
  165. const uint8_t *ad, size_t ad_len) {
  166. const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
  167. const uint64_t in_len_64 = in_len;
  168. const uint64_t ad_len_64 = ad_len;
  169. if (in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN < in_len ||
  170. in_len_64 > (UINT64_C(1) << 36) ||
  171. ad_len_64 >= (UINT64_C(1) << 61)) {
  172. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
  173. return 0;
  174. }
  175. if (max_out_len < in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
  176. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
  177. return 0;
  178. }
  179. if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
  180. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
  181. return 0;
  182. }
  183. struct gcm_siv_record_keys keys;
  184. gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
  185. uint8_t tag[16];
  186. gcm_siv_polyval(tag, in, in_len, ad, ad_len, keys.auth_key, nonce);
  187. keys.enc_block(tag, tag, &keys.enc_key.ks);
  188. gcm_siv_crypt(out, in, in_len, tag, keys.enc_block, &keys.enc_key.ks);
  189. OPENSSL_memcpy(&out[in_len], tag, EVP_AEAD_AES_GCM_SIV_TAG_LEN);
  190. *out_len = in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN;
  191. return 1;
  192. }
  193. static int aead_aes_gcm_siv_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
  194. size_t *out_len, size_t max_out_len,
  195. const uint8_t *nonce, size_t nonce_len,
  196. const uint8_t *in, size_t in_len,
  197. const uint8_t *ad, size_t ad_len) {
  198. const uint64_t ad_len_64 = ad_len;
  199. if (ad_len_64 >= (UINT64_C(1) << 61)) {
  200. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
  201. return 0;
  202. }
  203. const uint64_t in_len_64 = in_len;
  204. if (in_len < EVP_AEAD_AES_GCM_SIV_TAG_LEN ||
  205. in_len_64 > (UINT64_C(1) << 36) + AES_BLOCK_SIZE) {
  206. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
  207. return 0;
  208. }
  209. if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
  210. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
  211. return 0;
  212. }
  213. const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
  214. const size_t plaintext_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN;
  215. if (max_out_len < plaintext_len) {
  216. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
  217. return 0;
  218. }
  219. struct gcm_siv_record_keys keys;
  220. gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
  221. gcm_siv_crypt(out, in, plaintext_len, &in[plaintext_len], keys.enc_block,
  222. &keys.enc_key.ks);
  223. uint8_t expected_tag[EVP_AEAD_AES_GCM_SIV_TAG_LEN];
  224. gcm_siv_polyval(expected_tag, out, plaintext_len, ad, ad_len, keys.auth_key,
  225. nonce);
  226. keys.enc_block(expected_tag, expected_tag, &keys.enc_key.ks);
  227. if (CRYPTO_memcmp(expected_tag, &in[plaintext_len], sizeof(expected_tag)) !=
  228. 0) {
  229. OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
  230. return 0;
  231. }
  232. *out_len = plaintext_len;
  233. return 1;
  234. }
  235. static const EVP_AEAD aead_aes_128_gcm_siv = {
  236. 16, /* key length */
  237. EVP_AEAD_AES_GCM_SIV_NONCE_LEN, /* nonce length */
  238. EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
  239. EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
  240. aead_aes_gcm_siv_init,
  241. NULL /* init_with_direction */,
  242. aead_aes_gcm_siv_cleanup,
  243. aead_aes_gcm_siv_seal,
  244. aead_aes_gcm_siv_open,
  245. NULL /* get_iv */,
  246. };
  247. static const EVP_AEAD aead_aes_256_gcm_siv = {
  248. 32, /* key length */
  249. EVP_AEAD_AES_GCM_SIV_NONCE_LEN, /* nonce length */
  250. EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
  251. EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
  252. aead_aes_gcm_siv_init,
  253. NULL /* init_with_direction */,
  254. aead_aes_gcm_siv_cleanup,
  255. aead_aes_gcm_siv_seal,
  256. aead_aes_gcm_siv_open,
  257. NULL /* get_iv */,
  258. };
  259. const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void) {
  260. return &aead_aes_128_gcm_siv;
  261. }
  262. const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void) {
  263. return &aead_aes_256_gcm_siv;
  264. }
  265. #endif /* !OPENSSL_SMALL */