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_keywrap_test processes a NIST CAVP AES test vector request file and
16 // emits the corresponding response.
17
18 #include <stdlib.h>
19
20 #include <openssl/aes.h>
21 #include <openssl/crypto.h>
22
23 #include "../crypto/test/file_test.h"
24 #include "cavp_test_util.h"
25
26
27 namespace {
28
29 struct TestCtx {
30 bool encrypt;
31 bool padding;
32 };
33
34 } // namespace
35
AESKeyWrap(std::vector<uint8_t> * out,bool encrypt,const std::vector<uint8_t> & key,const std::vector<uint8_t> & in)36 static bool AESKeyWrap(std::vector<uint8_t> *out, bool encrypt,
37 const std::vector<uint8_t> &key,
38 const std::vector<uint8_t> &in) {
39 size_t key_bits = key.size() * 8;
40 if (key_bits != 128 && key_bits != 192 && key_bits != 256) {
41 return false;
42 }
43 AES_KEY aes_key;
44
45 if (encrypt) {
46 out->resize(in.size() + 8);
47 if (AES_set_encrypt_key(key.data(), key_bits, &aes_key) ||
48 AES_wrap_key(&aes_key, nullptr, out->data(), in.data(), in.size()) ==
49 -1) {
50 return false;
51 }
52 } else {
53 out->resize(in.size() - 8);
54 if (AES_set_decrypt_key(key.data(), key_bits, &aes_key) ||
55 AES_unwrap_key(&aes_key, nullptr, out->data(), in.data(), in.size()) ==
56 -1) {
57 return false;
58 }
59 }
60
61 return true;
62 }
63
AESKeyWrapWithPadding(std::vector<uint8_t> * out,bool encrypt,const std::vector<uint8_t> & key,const std::vector<uint8_t> & in)64 static bool AESKeyWrapWithPadding(std::vector<uint8_t> *out, bool encrypt,
65 const std::vector<uint8_t> &key,
66 const std::vector<uint8_t> &in) {
67 const size_t key_bits = key.size() * 8;
68 if (key_bits != 128 && key_bits != 192 && key_bits != 256) {
69 return false;
70 }
71 AES_KEY aes_key;
72
73 size_t out_len;
74 if (encrypt) {
75 out->resize(in.size() + 15);
76 if (AES_set_encrypt_key(key.data(), key_bits, &aes_key) ||
77 !AES_wrap_key_padded(&aes_key, out->data(), &out_len, out->size(),
78 in.data(), in.size())) {
79 return false;
80 }
81 } else {
82 out->resize(in.size());
83 if (AES_set_decrypt_key(key.data(), key_bits, &aes_key) ||
84 !AES_unwrap_key_padded(&aes_key, out->data(), &out_len, out->size(),
85 in.data(), in.size())) {
86 return false;
87 }
88 }
89
90 out->resize(out_len);
91 return true;
92 }
93
TestCipher(FileTest * t,void * arg)94 static bool TestCipher(FileTest *t, void *arg) {
95 TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
96
97 std::string count, unused, in_label = ctx->encrypt ? "P" : "C",
98 result_label = ctx->encrypt ? "C" : "P";
99 std::vector<uint8_t> key, in, result;
100 // clang-format off
101 if (!t->GetInstruction(&unused, "PLAINTEXT LENGTH") ||
102 !t->GetAttribute(&count, "COUNT") ||
103 !t->GetBytes(&key, "K") ||
104 !t->GetBytes(&in, in_label)) {
105 return false;
106 }
107 // clang-format on
108
109 auto wrap_function = AESKeyWrap;
110 if (ctx->padding) {
111 wrap_function = AESKeyWrapWithPadding;
112 }
113
114 printf("%s", t->CurrentTestToString().c_str());
115 if (!wrap_function(&result, ctx->encrypt, key, in)) {
116 if (ctx->encrypt) {
117 return false;
118 } else {
119 printf("FAIL\r\n\r\n");
120 }
121 } else {
122 printf("%s = %s\r\n\r\n", result_label.c_str(),
123 EncodeHex(result.data(), result.size()).c_str());
124 }
125
126 return true;
127 }
128
usage(char * arg)129 static int usage(char *arg) {
130 fprintf(
131 stderr,
132 "usage: %s (enc|dec|enc-pad|dec-pad) (128|192|256) <test file>\n",
133 arg);
134 return 1;
135 }
136
cavp_keywrap_test_main(int argc,char ** argv)137 int cavp_keywrap_test_main(int argc, char **argv) {
138 if (argc != 4) {
139 return usage(argv[0]);
140 }
141
142 const std::string op(argv[1]);
143 bool encrypt = false;
144 bool padding = false;
145 if (op == "enc") {
146 encrypt = true;
147 } else if (op == "dec") {
148 } else if (op == "enc-pad") {
149 encrypt = true;
150 padding = true;
151 } else if (op == "dec-pad") {
152 padding = true;
153 } else {
154 return usage(argv[0]);
155 }
156
157 TestCtx ctx = {encrypt, padding};
158
159 FileTest::Options opts;
160 opts.path = argv[3];
161 opts.callback = TestCipher;
162 opts.arg = &ctx;
163 opts.silent = true;
164 opts.comment_callback = EchoComment;
165 return FileTestMain(opts);
166 }
167