Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

311 рядки
8.6 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 <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <openssl/aead.h>
  19. #include <openssl/crypto.h>
  20. /* This program tests an AEAD against a series of test vectors from a file. The
  21. * test vector file consists of key-value lines where the key and value are
  22. * separated by a colon and optional whitespace. The keys are listed in
  23. * |NAMES|, below. The values are hex-encoded data.
  24. *
  25. * After a number of key-value lines, a blank line or EOF indicates the end of
  26. * the test case.
  27. *
  28. * For example, here's a valid test case:
  29. *
  30. * KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4
  31. * NONCE: 978105dfce667bf4
  32. * IN: 6a4583908d
  33. * AD: b654574932
  34. * CT: 5294265a60
  35. * TAG: 1d45758621762e061368e68868e2f929
  36. */
  37. #define BUF_MAX 512
  38. /* These are the different types of line that are found in the input file. */
  39. enum {
  40. KEY = 0, /* hex encoded key. */
  41. NONCE, /* hex encoded nonce. */
  42. IN, /* hex encoded plaintext. */
  43. AD, /* hex encoded additional data. */
  44. CT, /* hex encoded ciphertext (not including the authenticator,
  45. which is next). */
  46. TAG, /* hex encoded authenticator. */
  47. NUM_TYPES,
  48. };
  49. static const char NAMES[6][NUM_TYPES] = {
  50. "KEY", "NONCE", "IN", "AD", "CT", "TAG",
  51. };
  52. static unsigned char hex_digit(char h) {
  53. if (h >= '0' && h <= '9') {
  54. return h - '0';
  55. } else if (h >= 'a' && h <= 'f') {
  56. return h - 'a' + 10;
  57. } else if (h >= 'A' && h <= 'F') {
  58. return h - 'A' + 10;
  59. } else {
  60. return 16;
  61. }
  62. }
  63. static int run_test_case(const EVP_AEAD *aead,
  64. unsigned char bufs[NUM_TYPES][BUF_MAX],
  65. const unsigned int lengths[NUM_TYPES],
  66. unsigned int line_no) {
  67. EVP_AEAD_CTX ctx;
  68. size_t ciphertext_len, plaintext_len;
  69. unsigned char out[BUF_MAX + EVP_AEAD_MAX_OVERHEAD], out2[BUF_MAX];
  70. if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
  71. NULL)) {
  72. fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
  73. return 0;
  74. }
  75. if (!EVP_AEAD_CTX_seal(&ctx, out, &ciphertext_len, sizeof(out), bufs[NONCE],
  76. lengths[NONCE], bufs[IN], lengths[IN], bufs[AD],
  77. lengths[AD])) {
  78. fprintf(stderr, "Failed to run AEAD on line %u\n", line_no);
  79. return 0;
  80. }
  81. if (ciphertext_len != lengths[CT] + lengths[TAG]) {
  82. fprintf(stderr, "Bad output length on line %u: %u vs %u\n", line_no,
  83. (unsigned)ciphertext_len, (unsigned)(lengths[CT] + lengths[TAG]));
  84. return 0;
  85. }
  86. if (memcmp(out, bufs[CT], lengths[CT]) != 0) {
  87. fprintf(stderr, "Bad output on line %u\n", line_no);
  88. return 0;
  89. }
  90. if (memcmp(out + lengths[CT], bufs[TAG], lengths[TAG]) != 0) {
  91. fprintf(stderr, "Bad tag on line %u\n", line_no);
  92. return 0;
  93. }
  94. /* The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
  95. * reset after each operation. */
  96. EVP_AEAD_CTX_cleanup(&ctx);
  97. if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
  98. NULL)) {
  99. fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
  100. return 0;
  101. }
  102. if (!EVP_AEAD_CTX_open(&ctx, out2, &plaintext_len, lengths[IN], bufs[NONCE],
  103. lengths[NONCE], out, ciphertext_len, bufs[AD],
  104. lengths[AD])) {
  105. fprintf(stderr, "Failed to decrypt on line %u\n", line_no);
  106. return 0;
  107. }
  108. if (plaintext_len != lengths[IN]) {
  109. fprintf(stderr, "Bad decrypt on line %u: %u\n", line_no,
  110. (unsigned)ciphertext_len);
  111. return 0;
  112. }
  113. /* The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
  114. * reset after each operation. */
  115. EVP_AEAD_CTX_cleanup(&ctx);
  116. if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
  117. NULL)) {
  118. fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
  119. return 0;
  120. }
  121. out[0] ^= 0x80;
  122. if (EVP_AEAD_CTX_open(&ctx, out2, &plaintext_len, lengths[IN], bufs[NONCE],
  123. lengths[NONCE], out, ciphertext_len, bufs[AD],
  124. lengths[AD])) {
  125. fprintf(stderr, "Decrypted bad data on line %u\n", line_no);
  126. return 0;
  127. }
  128. EVP_AEAD_CTX_cleanup(&ctx);
  129. return 1;
  130. }
  131. int main(int argc, char **argv) {
  132. FILE *f;
  133. const EVP_AEAD *aead = NULL;
  134. unsigned int line_no = 0, num_tests = 0, j;
  135. unsigned char bufs[NUM_TYPES][BUF_MAX];
  136. unsigned int lengths[NUM_TYPES];
  137. CRYPTO_library_init();
  138. if (argc != 3) {
  139. fprintf(stderr, "%s <aead> <test file.txt>\n", argv[0]);
  140. return 1;
  141. }
  142. if (strcmp(argv[1], "aes-128-gcm") == 0) {
  143. aead = EVP_aead_aes_128_gcm();
  144. } else if (strcmp(argv[1], "aes-256-gcm") == 0) {
  145. aead = EVP_aead_aes_256_gcm();
  146. } else if (strcmp(argv[1], "chacha20-poly1305") == 0) {
  147. aead = EVP_aead_chacha20_poly1305();
  148. } else if (strcmp(argv[1], "rc4-md5") == 0) {
  149. aead = EVP_aead_rc4_md5_tls();
  150. } else if (strcmp(argv[1], "aes-128-key-wrap") == 0) {
  151. aead = EVP_aead_aes_128_key_wrap();
  152. } else if (strcmp(argv[1], "aes-256-key-wrap") == 0) {
  153. aead = EVP_aead_aes_256_key_wrap();
  154. } else {
  155. fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
  156. return 2;
  157. }
  158. f = fopen(argv[2], "r");
  159. if (f == NULL) {
  160. perror("failed to open input");
  161. return 1;
  162. }
  163. for (j = 0; j < NUM_TYPES; j++) {
  164. lengths[j] = 0;
  165. }
  166. for (;;) {
  167. char line[4096];
  168. unsigned int i, type_len = 0;
  169. unsigned char *buf = NULL;
  170. unsigned int *buf_len = NULL;
  171. if (!fgets(line, sizeof(line), f)) {
  172. line[0] = 0;
  173. }
  174. line_no++;
  175. if (line[0] == '#') {
  176. continue;
  177. }
  178. if (line[0] == '\n' || line[0] == 0) {
  179. /* Run a test, if possible. */
  180. char any_values_set = 0;
  181. for (j = 0; j < NUM_TYPES; j++) {
  182. if (lengths[j] != 0) {
  183. any_values_set = 1;
  184. break;
  185. }
  186. }
  187. if (any_values_set) {
  188. if (!run_test_case(aead, bufs, lengths, line_no)) {
  189. return 4;
  190. }
  191. for (j = 0; j < NUM_TYPES; j++) {
  192. lengths[j] = 0;
  193. }
  194. num_tests++;
  195. }
  196. if (line[0] == 0) {
  197. break;
  198. }
  199. continue;
  200. }
  201. /* Each line looks like:
  202. * TYPE: 0123abc
  203. * Where "TYPE" is the type of the data on the line,
  204. * e.g. "KEY". */
  205. for (i = 0; line[i] != 0 && line[i] != '\n'; i++) {
  206. if (line[i] == ':') {
  207. type_len = i;
  208. break;
  209. }
  210. }
  211. i++;
  212. if (type_len == 0) {
  213. fprintf(stderr, "Parse error on line %u\n", line_no);
  214. return 3;
  215. }
  216. /* After the colon, there's optional whitespace. */
  217. for (; line[i] != 0 && line[i] != '\n'; i++) {
  218. if (line[i] != ' ' && line[i] != '\t') {
  219. break;
  220. }
  221. }
  222. line[type_len] = 0;
  223. for (j = 0; j < NUM_TYPES; j++) {
  224. if (strcmp(line, NAMES[j]) != 0) {
  225. continue;
  226. }
  227. if (lengths[j] != 0) {
  228. fprintf(stderr, "Duplicate value on line %u\n", line_no);
  229. return 3;
  230. }
  231. buf = bufs[j];
  232. buf_len = &lengths[j];
  233. }
  234. if (buf == NULL) {
  235. fprintf(stderr, "Unknown line type on line %u\n", line_no);
  236. return 3;
  237. }
  238. j = 0;
  239. for (; line[i] != 0 && line[i] != '\n'; i++) {
  240. unsigned char v, v2;
  241. v = hex_digit(line[i++]);
  242. if (line[i] == 0 || line[i] == '\n') {
  243. fprintf(stderr, "Odd-length hex data on line %u\n", line_no);
  244. return 3;
  245. }
  246. v2 = hex_digit(line[i]);
  247. if (v > 15 || v2 > 15) {
  248. fprintf(stderr, "Invalid hex char on line %u\n", line_no);
  249. return 3;
  250. }
  251. v <<= 4;
  252. v |= v2;
  253. if (j == BUF_MAX) {
  254. fprintf(stderr, "Too much hex data on line %u (max is %u bytes)\n",
  255. line_no, (unsigned)BUF_MAX);
  256. return 3;
  257. }
  258. buf[j++] = v;
  259. *buf_len = *buf_len + 1;
  260. }
  261. }
  262. printf("Completed %u test cases\n", num_tests);
  263. printf("PASS\n");
  264. fclose(f);
  265. return 0;
  266. }