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 "../crypto/test/test_util.h"
25 #include "cavp_test_util.h"
26
27
28 namespace {
29
30 struct TestCtx {
31 bool encrypt;
32 bool padding;
33 };
34
35 } // namespace
36
AESKeyWrap(std::vector<uint8_t> * out,bool encrypt,const std::vector<uint8_t> & key,const std::vector<uint8_t> & in)37 static bool AESKeyWrap(std::vector<uint8_t> *out, bool encrypt,
38 const std::vector<uint8_t> &key,
39 const std::vector<uint8_t> &in) {
40 size_t key_bits = key.size() * 8;
41 if (key_bits != 128 && key_bits != 192 && key_bits != 256) {
42 return false;
43 }
44 AES_KEY aes_key;
45
46 if (encrypt) {
47 out->resize(in.size() + 8);
48 if (AES_set_encrypt_key(key.data(), key_bits, &aes_key) ||
49 AES_wrap_key(&aes_key, nullptr, out->data(), in.data(), in.size()) ==
50 -1) {
51 return false;
52 }
53 } else {
54 out->resize(in.size() - 8);
55 if (AES_set_decrypt_key(key.data(), key_bits, &aes_key) ||
56 AES_unwrap_key(&aes_key, nullptr, out->data(), in.data(), in.size()) ==
57 -1) {
58 return false;
59 }
60 }
61
62 return true;
63 }
64
AESKeyWrapWithPadding(std::vector<uint8_t> * out,bool encrypt,const std::vector<uint8_t> & key,const std::vector<uint8_t> & in)65 static bool AESKeyWrapWithPadding(std::vector<uint8_t> *out, bool encrypt,
66 const std::vector<uint8_t> &key,
67 const std::vector<uint8_t> &in) {
68 const size_t key_bits = key.size() * 8;
69 if (key_bits != 128 && key_bits != 192 && key_bits != 256) {
70 return false;
71 }
72 AES_KEY aes_key;
73
74 size_t out_len;
75 if (encrypt) {
76 out->resize(in.size() + 15);
77 if (AES_set_encrypt_key(key.data(), key_bits, &aes_key) ||
78 !AES_wrap_key_padded(&aes_key, out->data(), &out_len, out->size(),
79 in.data(), in.size())) {
80 return false;
81 }
82 } else {
83 out->resize(in.size());
84 if (AES_set_decrypt_key(key.data(), key_bits, &aes_key) ||
85 !AES_unwrap_key_padded(&aes_key, out->data(), &out_len, out->size(),
86 in.data(), in.size())) {
87 return false;
88 }
89 }
90
91 out->resize(out_len);
92 return true;
93 }
94
TestCipher(FileTest * t,void * arg)95 static bool TestCipher(FileTest *t, void *arg) {
96 TestCtx *ctx = reinterpret_cast<TestCtx *>(arg);
97
98 std::string count, unused, in_label = ctx->encrypt ? "P" : "C",
99 result_label = ctx->encrypt ? "C" : "P";
100 std::vector<uint8_t> key, in, result;
101 // clang-format off
102 if (!t->GetInstruction(&unused, "PLAINTEXT LENGTH") ||
103 !t->GetAttribute(&count, "COUNT") ||
104 !t->GetBytes(&key, "K") ||
105 !t->GetBytes(&in, in_label)) {
106 return false;
107 }
108 // clang-format on
109
110 auto wrap_function = AESKeyWrap;
111 if (ctx->padding) {
112 wrap_function = AESKeyWrapWithPadding;
113 }
114
115 printf("%s", t->CurrentTestToString().c_str());
116 if (!wrap_function(&result, ctx->encrypt, key, in)) {
117 if (ctx->encrypt) {
118 return false;
119 } else {
120 printf("FAIL\r\n\r\n");
121 }
122 } else {
123 printf("%s = %s\r\n\r\n", result_label.c_str(), EncodeHex(result).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