cavp_aes_test.cc
Go to the documentation of this file.
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 
15 // cavp_aes_test processes a NIST CAVP AES test vector request file and emits
16 // the corresponding response.
17 
18 #include <stdlib.h>
19 
20 #include <openssl/cipher.h>
21 #include <openssl/crypto.h>
22 #include <openssl/err.h>
23 
24 #include "../crypto/test/file_test.h"
25 #include "../crypto/test/test_util.h"
26 #include "cavp_test_util.h"
27 
28 
29 namespace {
30 
31 struct TestCtx {
32  const EVP_CIPHER *cipher;
33  bool has_iv;
34  enum Mode {
35  kKAT, // Known Answer Test
36  kMCT, // Monte Carlo Test
37  };
38  Mode mode;
39 };
40 
41 }
42 
43 static bool MonteCarlo(const TestCtx *ctx, FileTest *t,
44  const EVP_CIPHER *cipher, std::vector<uint8_t> *out,
45  bool encrypt, std::vector<uint8_t> key,
46  std::vector<uint8_t> iv, std::vector<uint8_t> in) {
47  const std::string in_label = encrypt ? "PLAINTEXT" : "CIPHERTEXT",
48  result_label = encrypt ? "CIPHERTEXT" : "PLAINTEXT";
49  std::vector<uint8_t> prev_result, result, prev_in;
50  for (int i = 0; i < 100; i++) {
51  printf("COUNT = %d\r\nKEY = %s\r\n", i, EncodeHex(key).c_str());
52  if (ctx->has_iv) {
53  printf("IV = %s\r\n", EncodeHex(iv).c_str());
54  }
55  printf("%s = %s\r\n", in_label.c_str(), EncodeHex(in).c_str());
56 
57  if (!ctx->has_iv) { // ECB mode
58  for (int j = 0; j < 1000; j++) {
59  prev_result = result;
60  if (!CipherOperation(cipher, &result, encrypt, key, iv, in)) {
61  return false;
62  }
63  in = result;
64  }
65  } else {
66  for (int j = 0; j < 1000; j++) {
67  prev_result = result;
68  if (j > 0) {
69  if (encrypt) {
70  iv = result;
71  } else {
72  iv = prev_in;
73  }
74  }
75 
76  if (!CipherOperation(cipher, &result, encrypt, key, iv, in)) {
77  return false;
78  }
79 
80  prev_in = in;
81 
82  if (j == 0) {
83  in = iv;
84  } else {
85  in = prev_result;
86  }
87  }
88  }
89 
90  printf("%s = %s\r\n\r\n", result_label.c_str(), EncodeHex(result).c_str());
91 
92  const size_t key_len = key.size() * 8;
93  if (key_len == 128) {
94  for (size_t k = 0; k < key.size(); k++) {
95  key[k] ^= result[k];
96  }
97  } else if (key_len == 192) {
98  for (size_t k = 0; k < key.size(); k++) {
99  // Key[i+1] = Key[i] xor (last 64-bits of CT[j-1] || CT[j])
100  if (k < 8) {
101  key[k] ^= prev_result[prev_result.size() - 8 + k];
102  } else {
103  key[k] ^= result[k - 8];
104  }
105  }
106  } else { // key_len == 256
107  for (size_t k = 0; k < key.size(); k++) {
108  // Key[i+1] = Key[i] xor (CT[j-1] || CT[j])
109  if (k < 16) {
110  key[k] ^= prev_result[k];
111  } else {
112  key[k] ^= result[k - 16];
113  }
114  }
115  }
116 
117  if (ctx->has_iv) {
118  iv = result;
119  in = prev_result;
120  } else {
121  in = result;
122  }
123  }
124 
125  return true;
126 }
127 
128 static bool TestCipher(FileTest *t, void *arg) {
129  TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
130 
131  if (t->HasInstruction("ENCRYPT") == t->HasInstruction("DECRYPT")) {
132  t->PrintLine("Want either ENCRYPT or DECRYPT");
133  return false;
134  }
135  enum {
136  kEncrypt,
137  kDecrypt,
138  } operation = t->HasInstruction("ENCRYPT") ? kEncrypt : kDecrypt;
139 
141  std::vector<uint8_t> key, iv, in, result;
142  if (!t->GetAttribute(&count, "COUNT") ||
143  !t->GetBytes(&key, "KEY") ||
144  (ctx->has_iv && !t->GetBytes(&iv, "IV"))) {
145  return false;
146  }
147 
148  const EVP_CIPHER *cipher = ctx->cipher;
149  if (operation == kEncrypt) {
150  if (!t->GetBytes(&in, "PLAINTEXT")) {
151  return false;
152  }
153  } else { // operation == kDecrypt
154  if (!t->GetBytes(&in, "CIPHERTEXT")) {
155  return false;
156  }
157  }
158 
159  if (ctx->mode == TestCtx::kKAT) {
160  if (!CipherOperation(cipher, &result, operation == kEncrypt, key, iv, in)) {
161  return false;
162  }
163  const std::string label =
164  operation == kEncrypt ? "CIPHERTEXT" : "PLAINTEXT";
165  printf("%s%s = %s\r\n\r\n", t->CurrentTestToString().c_str(), label.c_str(),
166  EncodeHex(result).c_str());
167  } else { // ctx->mode == kMCT
168  const std::string op_label =
169  operation == kEncrypt ? "[ENCRYPT]" : "[DECRYPT]";
170  printf("%s\r\n\r\n", op_label.c_str());
171  if (!MonteCarlo(ctx, t, cipher, &result, operation == kEncrypt, key, iv,
172  in)) {
173  return false;
174  }
175  if (operation == kEncrypt) {
176  // MCT tests contain a stray blank line after the ENCRYPT section.
177  printf("\r\n");
178  }
179  }
180 
181  return true;
182 }
183 
184 static int usage(char *arg) {
185  fprintf(stderr, "usage: %s (kat|mct) <cipher> <test file>\n", arg);
186  return 1;
187 }
188 
189 int cavp_aes_test_main(int argc, char **argv) {
190  if (argc != 4) {
191  return usage(argv[0]);
192  }
193 
194  const std::string tm(argv[1]);
195  enum TestCtx::Mode test_mode;
196  if (tm == "kat") {
197  test_mode = TestCtx::kKAT;
198  } else if (tm == "mct") {
199  test_mode = TestCtx::kMCT;
200  } else {
201  fprintf(stderr, "invalid test_mode: %s\n", tm.c_str());
202  return usage(argv[0]);
203  }
204 
205  const std::string cipher_name(argv[2]);
206  const EVP_CIPHER *cipher = GetCipher(argv[2]);
207  if (cipher == nullptr) {
208  fprintf(stderr, "invalid cipher: %s\n", argv[2]);
209  return 1;
210  }
211  const bool has_iv =
212  (cipher_name != "aes-128-ecb" &&
213  cipher_name != "aes-192-ecb" &&
214  cipher_name != "aes-256-ecb");
215 
216  TestCtx ctx = {cipher, has_iv, test_mode};
217 
219  opts.path = argv[3];
220  opts.callback = TestCipher;
221  opts.arg = &ctx;
222  opts.silent = true;
223  opts.comment_callback = EchoComment;
224  return FileTestMain(opts);
225 }
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
ctx
Definition: benchmark-async.c:30
FileTestMain
int FileTestMain(FileTestFunc run_test, void *arg, const char *path)
Definition: file_test.cc:399
cavp_aes_test_main
int cavp_aes_test_main(int argc, char **argv)
Definition: cavp_aes_test.cc:189
printf
_Use_decl_annotations_ int __cdecl printf(const char *_Format,...)
Definition: cs_driver.c:91
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
cstest_report.opts
opts
Definition: cstest_report.py:81
mode
const char int mode
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
ctx
static struct test_ctx ctx
Definition: test-ipc-send-recv.c:65
setup.k
k
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
in
const char * in
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:391
evp_cipher_st
Definition: cipher.h:585
TestCipher
static bool TestCipher(FileTest *t, void *arg)
Definition: cavp_aes_test.cc:128
gen_synthetic_protos.label
label
Definition: gen_synthetic_protos.py:102
gen_stats_data.c_str
def c_str(s, encoding='ascii')
Definition: gen_stats_data.py:38
cavp_test_util.h
EncodeHex
std::string EncodeHex(bssl::Span< const uint8_t > in)
Definition: boringssl-with-bazel/src/crypto/test/test_util.cc:75
FileTest
Definition: file_test.h:90
err.h
crypto.h
cipher.h
arg
Definition: cmdline.cc:40
EchoComment
void EchoComment(const std::string &comment)
Definition: cavp_test_util.cc:218
CipherOperation
bool CipherOperation(const EVP_CIPHER *cipher, std::vector< uint8_t > *out, bool encrypt, const std::vector< uint8_t > &key, const std::vector< uint8_t > &iv, const std::vector< uint8_t > &in)
Definition: cavp_test_util.cc:68
tm
static uv_timer_t tm
Definition: test-tcp-open.c:41
key
const char * key
Definition: hpack_parser_table.cc:164
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
arg
struct arg arg
FileTest::Options
Definition: file_test.h:104
usage
static int usage(char *arg)
Definition: cavp_aes_test.cc:184
MonteCarlo
static bool MonteCarlo(const TestCtx *ctx, FileTest *t, const EVP_CIPHER *cipher, std::vector< uint8_t > *out, bool encrypt, std::vector< uint8_t > key, std::vector< uint8_t > iv, std::vector< uint8_t > in)
Definition: cavp_aes_test.cc:43
GetCipher
static const EVP_CIPHER * GetCipher(const std::string &name)
Definition: cipher_test.cc:78
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
test_mode
static test_mode_t test_mode
Definition: test-poll.c:78


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:52