You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

228 rivejä
6.2 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. // cavp_aes_test processes a NIST CAVP AES test vector request file and emits
  15. // the corresponding response.
  16. #include <stdlib.h>
  17. #include <openssl/cipher.h>
  18. #include <openssl/crypto.h>
  19. #include <openssl/err.h>
  20. #include "../crypto/test/file_test.h"
  21. #include "cavp_test_util.h"
  22. namespace {
  23. struct TestCtx {
  24. const EVP_CIPHER *cipher;
  25. bool has_iv;
  26. enum Mode {
  27. kKAT, // Known Answer Test
  28. kMCT, // Monte Carlo Test
  29. };
  30. Mode mode;
  31. };
  32. }
  33. static bool MonteCarlo(const TestCtx *ctx, FileTest *t,
  34. const EVP_CIPHER *cipher, std::vector<uint8_t> *out,
  35. bool encrypt, std::vector<uint8_t> key,
  36. std::vector<uint8_t> iv, std::vector<uint8_t> in) {
  37. const std::string in_label = encrypt ? "PLAINTEXT" : "CIPHERTEXT",
  38. result_label = encrypt ? "CIPHERTEXT" : "PLAINTEXT";
  39. std::vector<uint8_t> prev_result, result, prev_in;
  40. for (int i = 0; i < 100; i++) {
  41. printf("COUNT = %d\r\nKEY = %s\r\n", i,
  42. EncodeHex(key.data(), key.size()).c_str());
  43. if (ctx->has_iv) {
  44. printf("IV = %s\r\n", EncodeHex(iv.data(), iv.size()).c_str());
  45. }
  46. printf("%s = %s\r\n", in_label.c_str(),
  47. EncodeHex(in.data(), in.size()).c_str());
  48. if (!ctx->has_iv) { // ECB mode
  49. for (int j = 0; j < 1000; j++) {
  50. prev_result = result;
  51. if (!CipherOperation(cipher, &result, encrypt, key, iv, in)) {
  52. return false;
  53. }
  54. in = result;
  55. }
  56. } else {
  57. for (int j = 0; j < 1000; j++) {
  58. prev_result = result;
  59. if (j > 0) {
  60. if (encrypt) {
  61. iv = result;
  62. } else {
  63. iv = prev_in;
  64. }
  65. }
  66. if (!CipherOperation(cipher, &result, encrypt, key, iv, in)) {
  67. return false;
  68. }
  69. prev_in = in;
  70. if (j == 0) {
  71. in = iv;
  72. } else {
  73. in = prev_result;
  74. }
  75. }
  76. }
  77. printf("%s = %s\r\n\r\n", result_label.c_str(),
  78. EncodeHex(result.data(), result.size()).c_str());
  79. const size_t key_len = key.size() * 8;
  80. if (key_len == 128) {
  81. for (size_t k = 0; k < key.size(); k++) {
  82. key[k] ^= result[k];
  83. }
  84. } else if (key_len == 192) {
  85. for (size_t k = 0; k < key.size(); k++) {
  86. // Key[i+1] = Key[i] xor (last 64-bits of CT[j-1] || CT[j])
  87. if (k < 8) {
  88. key[k] ^= prev_result[prev_result.size() - 8 + k];
  89. } else {
  90. key[k] ^= result[k - 8];
  91. }
  92. }
  93. } else { // key_len == 256
  94. for (size_t k = 0; k < key.size(); k++) {
  95. // Key[i+1] = Key[i] xor (CT[j-1] || CT[j])
  96. if (k < 16) {
  97. key[k] ^= prev_result[k];
  98. } else {
  99. key[k] ^= result[k - 16];
  100. }
  101. }
  102. }
  103. if (ctx->has_iv) {
  104. iv = result;
  105. in = prev_result;
  106. } else {
  107. in = result;
  108. }
  109. }
  110. return true;
  111. }
  112. static bool TestCipher(FileTest *t, void *arg) {
  113. TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
  114. if (t->HasInstruction("ENCRYPT") == t->HasInstruction("DECRYPT")) {
  115. t->PrintLine("Want either ENCRYPT or DECRYPT");
  116. return false;
  117. }
  118. enum {
  119. kEncrypt,
  120. kDecrypt,
  121. } operation = t->HasInstruction("ENCRYPT") ? kEncrypt : kDecrypt;
  122. std::string count;
  123. std::vector<uint8_t> key, iv, in, result;
  124. if (!t->GetAttribute(&count, "COUNT") ||
  125. !t->GetBytes(&key, "KEY") ||
  126. (ctx->has_iv && !t->GetBytes(&iv, "IV"))) {
  127. return false;
  128. }
  129. const EVP_CIPHER *cipher = ctx->cipher;
  130. if (operation == kEncrypt) {
  131. if (!t->GetBytes(&in, "PLAINTEXT")) {
  132. return false;
  133. }
  134. } else { // operation == kDecrypt
  135. if (!t->GetBytes(&in, "CIPHERTEXT")) {
  136. return false;
  137. }
  138. }
  139. if (ctx->mode == TestCtx::kKAT) {
  140. if (!CipherOperation(cipher, &result, operation == kEncrypt, key, iv, in)) {
  141. return false;
  142. }
  143. const std::string label =
  144. operation == kEncrypt ? "CIPHERTEXT" : "PLAINTEXT";
  145. printf("%s%s = %s\r\n\r\n", t->CurrentTestToString().c_str(), label.c_str(),
  146. EncodeHex(result.data(), result.size()).c_str());
  147. } else { // ctx->mode == kMCT
  148. const std::string op_label =
  149. operation == kEncrypt ? "[ENCRYPT]" : "[DECRYPT]";
  150. printf("%s\r\n\r\n", op_label.c_str());
  151. if (!MonteCarlo(ctx, t, cipher, &result, operation == kEncrypt, key, iv,
  152. in)) {
  153. return false;
  154. }
  155. if (operation == kEncrypt) {
  156. // MCT tests contain a stray blank line after the ENCRYPT section.
  157. printf("\r\n");
  158. }
  159. }
  160. return true;
  161. }
  162. static int usage(char *arg) {
  163. fprintf(stderr, "usage: %s (kat|mct) <cipher> <test file>\n", arg);
  164. return 1;
  165. }
  166. int cavp_aes_test_main(int argc, char **argv) {
  167. if (argc != 4) {
  168. return usage(argv[0]);
  169. }
  170. const std::string tm(argv[1]);
  171. enum TestCtx::Mode test_mode;
  172. if (tm == "kat") {
  173. test_mode = TestCtx::kKAT;
  174. } else if (tm == "mct") {
  175. test_mode = TestCtx::kMCT;
  176. } else {
  177. fprintf(stderr, "invalid test_mode: %s\n", tm.c_str());
  178. return usage(argv[0]);
  179. }
  180. const std::string cipher_name(argv[2]);
  181. const EVP_CIPHER *cipher = GetCipher(argv[2]);
  182. if (cipher == nullptr) {
  183. fprintf(stderr, "invalid cipher: %s\n", argv[2]);
  184. return 1;
  185. }
  186. const bool has_iv =
  187. (cipher_name != "aes-128-ecb" &&
  188. cipher_name != "aes-192-ecb" &&
  189. cipher_name != "aes-256-ecb");
  190. TestCtx ctx = {cipher, has_iv, test_mode};
  191. FileTest::Options opts;
  192. opts.path = argv[3];
  193. opts.callback = TestCipher;
  194. opts.arg = &ctx;
  195. opts.silent = true;
  196. opts.comment_callback = EchoComment;
  197. return FileTestMain(opts);
  198. }