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.
 
 
 
 
 
 

363 linhas
13 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 <stdint.h>
  15. #include <string.h>
  16. #include <vector>
  17. #include <openssl/aead.h>
  18. #include <openssl/crypto.h>
  19. #include <openssl/err.h>
  20. #include "../test/file_test.h"
  21. #include "../test/scoped_types.h"
  22. // This program tests an AEAD against a series of test vectors from a file,
  23. // using the FileTest format. As an example, here's a valid test case:
  24. //
  25. // KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4
  26. // NONCE: 978105dfce667bf4
  27. // IN: 6a4583908d
  28. // AD: b654574932
  29. // CT: 5294265a60
  30. // TAG: 1d45758621762e061368e68868e2f929
  31. static bool TestAEAD(FileTest *t, void *arg) {
  32. const EVP_AEAD *aead = reinterpret_cast<const EVP_AEAD*>(arg);
  33. std::vector<uint8_t> key, nonce, in, ad, ct, tag;
  34. if (!t->GetBytes(&key, "KEY") ||
  35. !t->GetBytes(&nonce, "NONCE") ||
  36. !t->GetBytes(&in, "IN") ||
  37. !t->GetBytes(&ad, "AD") ||
  38. !t->GetBytes(&ct, "CT") ||
  39. !t->GetBytes(&tag, "TAG")) {
  40. return false;
  41. }
  42. ScopedEVP_AEAD_CTX ctx;
  43. if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
  44. tag.size(), evp_aead_seal)) {
  45. t->PrintLine("Failed to init AEAD.");
  46. return false;
  47. }
  48. std::vector<uint8_t> out(in.size() + EVP_AEAD_max_overhead(aead));
  49. if (!t->HasAttribute("NO_SEAL")) {
  50. size_t out_len;
  51. if (!EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
  52. nonce.data(), nonce.size(), in.data(), in.size(),
  53. ad.data(), ad.size())) {
  54. t->PrintLine("Failed to run AEAD.");
  55. return false;
  56. }
  57. out.resize(out_len);
  58. if (out.size() != ct.size() + tag.size()) {
  59. t->PrintLine("Bad output length: %u vs %u.", (unsigned)out_len,
  60. (unsigned)(ct.size() + tag.size()));
  61. return false;
  62. }
  63. if (!t->ExpectBytesEqual(ct.data(), ct.size(), out.data(), ct.size()) ||
  64. !t->ExpectBytesEqual(tag.data(), tag.size(), out.data() + ct.size(),
  65. tag.size())) {
  66. return false;
  67. }
  68. } else {
  69. out.resize(ct.size() + tag.size());
  70. memcpy(out.data(), ct.data(), ct.size());
  71. memcpy(out.data() + ct.size(), tag.data(), tag.size());
  72. }
  73. // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
  74. // reset after each operation.
  75. ctx.Reset();
  76. if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
  77. tag.size(), evp_aead_open)) {
  78. t->PrintLine("Failed to init AEAD.");
  79. return false;
  80. }
  81. std::vector<uint8_t> out2(out.size());
  82. size_t out2_len;
  83. int ret = EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
  84. nonce.data(), nonce.size(), out.data(),
  85. out.size(), ad.data(), ad.size());
  86. if (t->HasAttribute("FAILS")) {
  87. if (ret) {
  88. t->PrintLine("Decrypted bad data.");
  89. return false;
  90. }
  91. ERR_clear_error();
  92. return true;
  93. }
  94. if (!ret) {
  95. t->PrintLine("Failed to decrypt.");
  96. return false;
  97. }
  98. out2.resize(out2_len);
  99. if (!t->ExpectBytesEqual(in.data(), in.size(), out2.data(), out2.size())) {
  100. return false;
  101. }
  102. // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
  103. // reset after each operation.
  104. ctx.Reset();
  105. if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
  106. tag.size(), evp_aead_open)) {
  107. t->PrintLine("Failed to init AEAD.");
  108. return false;
  109. }
  110. // Garbage at the end isn't ignored.
  111. out.push_back(0);
  112. out2.resize(out.size());
  113. if (EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
  114. nonce.data(), nonce.size(), out.data(), out.size(),
  115. ad.data(), ad.size())) {
  116. t->PrintLine("Decrypted bad data with trailing garbage.");
  117. return false;
  118. }
  119. ERR_clear_error();
  120. // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
  121. // reset after each operation.
  122. ctx.Reset();
  123. if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
  124. tag.size(), evp_aead_open)) {
  125. t->PrintLine("Failed to init AEAD.");
  126. return false;
  127. }
  128. // Verify integrity is checked.
  129. out[0] ^= 0x80;
  130. out.resize(out.size() - 1);
  131. out2.resize(out.size());
  132. if (EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
  133. nonce.data(), nonce.size(), out.data(), out.size(),
  134. ad.data(), ad.size())) {
  135. t->PrintLine("Decrypted bad data with corrupted byte.");
  136. return false;
  137. }
  138. ERR_clear_error();
  139. return true;
  140. }
  141. static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
  142. EVP_AEAD_CTX ctx;
  143. uint8_t key[128];
  144. memset(key, 0, sizeof(key));
  145. const size_t key_len = EVP_AEAD_key_length(aead);
  146. if (key_len > sizeof(key)) {
  147. fprintf(stderr, "Key length of AEAD too long.\n");
  148. return 0;
  149. }
  150. if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len,
  151. 9999 /* a silly tag length to trigger an error */,
  152. NULL /* ENGINE */) != 0) {
  153. fprintf(stderr, "A silly tag length didn't trigger an error!\n");
  154. return 0;
  155. }
  156. ERR_clear_error();
  157. /* Running a second, failed _init should not cause a memory leak. */
  158. if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len,
  159. 9999 /* a silly tag length to trigger an error */,
  160. NULL /* ENGINE */) != 0) {
  161. fprintf(stderr, "A silly tag length didn't trigger an error!\n");
  162. return 0;
  163. }
  164. ERR_clear_error();
  165. /* Calling _cleanup on an |EVP_AEAD_CTX| after a failed _init should be a
  166. * no-op. */
  167. EVP_AEAD_CTX_cleanup(&ctx);
  168. return 1;
  169. }
  170. static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
  171. const size_t key_len = EVP_AEAD_key_length(aead);
  172. const size_t nonce_len = EVP_AEAD_nonce_length(aead);
  173. const size_t max_overhead = EVP_AEAD_max_overhead(aead);
  174. std::vector<uint8_t> key(key_len, 'a');
  175. ScopedEVP_AEAD_CTX ctx;
  176. if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key_len,
  177. EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
  178. return false;
  179. }
  180. static const uint8_t kPlaintext[260] =
  181. "testing123456testing123456testing123456testing123456testing123456testing"
  182. "123456testing123456testing123456testing123456testing123456testing123456t"
  183. "esting123456testing123456testing123456testing123456testing123456testing1"
  184. "23456testing123456testing123456testing12345";
  185. const std::vector<size_t> offsets = {
  186. 0, 1, 2, 8, 15, 16, 17, 31, 32, 33, 63,
  187. 64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257,
  188. };
  189. std::vector<uint8_t> nonce(nonce_len, 'b');
  190. std::vector<uint8_t> valid_encryption(sizeof(kPlaintext) + max_overhead);
  191. size_t valid_encryption_len;
  192. if (!EVP_AEAD_CTX_seal(
  193. ctx.get(), valid_encryption.data(), &valid_encryption_len,
  194. sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len,
  195. kPlaintext, sizeof(kPlaintext), nullptr, 0)) {
  196. fprintf(stderr, "EVP_AEAD_CTX_seal failed with disjoint buffers.\n");
  197. return false;
  198. }
  199. // Test with out != in which we expect to fail.
  200. std::vector<uint8_t> buffer(2 + valid_encryption_len);
  201. uint8_t *in = buffer.data() + 1;
  202. uint8_t *out1 = buffer.data();
  203. uint8_t *out2 = buffer.data() + 2;
  204. memcpy(in, kPlaintext, sizeof(kPlaintext));
  205. size_t out_len;
  206. if (EVP_AEAD_CTX_seal(ctx.get(), out1, &out_len,
  207. sizeof(kPlaintext) + max_overhead, nonce.data(),
  208. nonce_len, in, sizeof(kPlaintext), nullptr, 0) ||
  209. EVP_AEAD_CTX_seal(ctx.get(), out2, &out_len,
  210. sizeof(kPlaintext) + max_overhead, nonce.data(),
  211. nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
  212. fprintf(stderr, "EVP_AEAD_CTX_seal unexpectedly succeeded.\n");
  213. return false;
  214. }
  215. ERR_clear_error();
  216. memcpy(in, valid_encryption.data(), valid_encryption_len);
  217. if (EVP_AEAD_CTX_open(ctx.get(), out1, &out_len, valid_encryption_len,
  218. nonce.data(), nonce_len, in, valid_encryption_len,
  219. nullptr, 0) ||
  220. EVP_AEAD_CTX_open(ctx.get(), out2, &out_len, valid_encryption_len,
  221. nonce.data(), nonce_len, in, valid_encryption_len,
  222. nullptr, 0)) {
  223. fprintf(stderr, "EVP_AEAD_CTX_open unexpectedly succeeded.\n");
  224. return false;
  225. }
  226. ERR_clear_error();
  227. // Test with out == in, which we expect to work.
  228. memcpy(in, kPlaintext, sizeof(kPlaintext));
  229. if (!EVP_AEAD_CTX_seal(ctx.get(), in, &out_len,
  230. sizeof(kPlaintext) + max_overhead, nonce.data(),
  231. nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
  232. fprintf(stderr, "EVP_AEAD_CTX_seal failed in-place.\n");
  233. return false;
  234. }
  235. if (out_len != valid_encryption_len ||
  236. memcmp(in, valid_encryption.data(), out_len) != 0) {
  237. fprintf(stderr, "EVP_AEAD_CTX_seal produced bad output in-place.\n");
  238. return false;
  239. }
  240. memcpy(in, valid_encryption.data(), valid_encryption_len);
  241. if (!EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len,
  242. nonce.data(), nonce_len, in, valid_encryption_len,
  243. nullptr, 0)) {
  244. fprintf(stderr, "EVP_AEAD_CTX_open failed in-place.\n");
  245. return false;
  246. }
  247. if (out_len != sizeof(kPlaintext) ||
  248. memcmp(in, kPlaintext, out_len) != 0) {
  249. fprintf(stderr, "EVP_AEAD_CTX_open produced bad output in-place.\n");
  250. return false;
  251. }
  252. return true;
  253. }
  254. struct KnownAEAD {
  255. const char name[40];
  256. const EVP_AEAD *(*func)(void);
  257. // limited_implementation indicates that tests that assume a generic AEAD
  258. // interface should not be performed. For example, the key-wrap AEADs only
  259. // handle inputs that are a multiple of eight bytes in length and the
  260. // SSLv3/TLS AEADs have the concept of “direction”.
  261. bool limited_implementation;
  262. };
  263. static const struct KnownAEAD kAEADs[] = {
  264. { "aes-128-gcm", EVP_aead_aes_128_gcm, false },
  265. { "aes-256-gcm", EVP_aead_aes_256_gcm, false },
  266. { "chacha20-poly1305", EVP_aead_chacha20_poly1305, false },
  267. { "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old, false },
  268. { "rc4-md5-tls", EVP_aead_rc4_md5_tls, true },
  269. { "rc4-sha1-tls", EVP_aead_rc4_sha1_tls, true },
  270. { "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true },
  271. { "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true },
  272. { "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true },
  273. { "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true },
  274. { "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true },
  275. { "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true },
  276. { "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true },
  277. { "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true },
  278. { "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true },
  279. { "rc4-md5-ssl3", EVP_aead_rc4_md5_ssl3, true },
  280. { "rc4-sha1-ssl3", EVP_aead_rc4_sha1_ssl3, true },
  281. { "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true },
  282. { "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true },
  283. { "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true },
  284. { "aes-128-key-wrap", EVP_aead_aes_128_key_wrap, true },
  285. { "aes-256-key-wrap", EVP_aead_aes_256_key_wrap, true },
  286. { "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false },
  287. { "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false },
  288. { "", NULL, false },
  289. };
  290. int main(int argc, char **argv) {
  291. CRYPTO_library_init();
  292. if (argc != 3) {
  293. fprintf(stderr, "%s <aead> <test file.txt>\n", argv[0]);
  294. return 1;
  295. }
  296. const struct KnownAEAD *known_aead;
  297. for (unsigned i = 0;; i++) {
  298. known_aead = &kAEADs[i];
  299. if (known_aead->func == NULL) {
  300. fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
  301. return 2;
  302. }
  303. if (strcmp(known_aead->name, argv[1]) == 0) {
  304. break;
  305. }
  306. }
  307. const EVP_AEAD *const aead = known_aead->func();
  308. if (!TestCleanupAfterInitFailure(aead)) {
  309. return 1;
  310. }
  311. if (!known_aead->limited_implementation && !TestWithAliasedBuffers(aead)) {
  312. fprintf(stderr, "Aliased buffers test failed for %s.\n", known_aead->name);
  313. return 1;
  314. }
  315. return FileTestMain(TestAEAD, const_cast<EVP_AEAD*>(aead), argv[2]);
  316. }