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 #include "cavp_test_util.h"
16
17 #include <openssl/bn.h>
18 #include <openssl/digest.h>
19 #include <openssl/ec.h>
20 #include <openssl/nid.h>
21
22
GetCipher(const std::string & name)23 const EVP_CIPHER *GetCipher(const std::string &name) {
24 if (name == "des-cbc") {
25 return EVP_des_cbc();
26 } else if (name == "des-ecb") {
27 return EVP_des_ecb();
28 } else if (name == "des-ede") {
29 return EVP_des_ede();
30 } else if (name == "des-ede3") {
31 return EVP_des_ede3();
32 } else if (name == "des-ede-cbc") {
33 return EVP_des_ede_cbc();
34 } else if (name == "des-ede3-cbc") {
35 return EVP_des_ede3_cbc();
36 } else if (name == "rc4") {
37 return EVP_rc4();
38 } else if (name == "aes-128-ecb") {
39 return EVP_aes_128_ecb();
40 } else if (name == "aes-256-ecb") {
41 return EVP_aes_256_ecb();
42 } else if (name == "aes-128-cbc") {
43 return EVP_aes_128_cbc();
44 } else if (name == "aes-128-gcm") {
45 return EVP_aes_128_gcm();
46 } else if (name == "aes-128-ofb") {
47 return EVP_aes_128_ofb();
48 } else if (name == "aes-192-cbc") {
49 return EVP_aes_192_cbc();
50 } else if (name == "aes-192-ctr") {
51 return EVP_aes_192_ctr();
52 } else if (name == "aes-192-ecb") {
53 return EVP_aes_192_ecb();
54 } else if (name == "aes-256-cbc") {
55 return EVP_aes_256_cbc();
56 } else if (name == "aes-128-ctr") {
57 return EVP_aes_128_ctr();
58 } else if (name == "aes-256-ctr") {
59 return EVP_aes_256_ctr();
60 } else if (name == "aes-256-gcm") {
61 return EVP_aes_256_gcm();
62 } else if (name == "aes-256-ofb") {
63 return EVP_aes_256_ofb();
64 }
65 return nullptr;
66 }
67
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)68 bool CipherOperation(const EVP_CIPHER *cipher, std::vector<uint8_t> *out,
69 bool encrypt, const std::vector<uint8_t> &key,
70 const std::vector<uint8_t> &iv,
71 const std::vector<uint8_t> &in) {
72 bssl::ScopedEVP_CIPHER_CTX ctx;
73 if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr,
74 encrypt ? 1 : 0)) {
75 return false;
76 }
77 if (!iv.empty() && iv.size() != EVP_CIPHER_CTX_iv_length(ctx.get())) {
78 return false;
79 }
80
81 int result_len1 = 0, result_len2;
82 *out = std::vector<uint8_t>(in.size());
83 if (!EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size()) ||
84 !EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key.data(), iv.data(),
85 -1) ||
86 !EVP_CIPHER_CTX_set_padding(ctx.get(), 0) ||
87 !EVP_CipherUpdate(ctx.get(), out->data(), &result_len1, in.data(),
88 in.size()) ||
89 !EVP_CipherFinal_ex(ctx.get(), out->data() + result_len1, &result_len2)) {
90 return false;
91 }
92 out->resize(result_len1 + result_len2);
93
94 return true;
95 }
96
AEADEncrypt(const EVP_AEAD * aead,std::vector<uint8_t> * ct,std::vector<uint8_t> * tag,size_t tag_len,const std::vector<uint8_t> & key,const std::vector<uint8_t> & pt,const std::vector<uint8_t> & aad,const std::vector<uint8_t> & iv)97 bool AEADEncrypt(const EVP_AEAD *aead, std::vector<uint8_t> *ct,
98 std::vector<uint8_t> *tag, size_t tag_len,
99 const std::vector<uint8_t> &key,
100 const std::vector<uint8_t> &pt,
101 const std::vector<uint8_t> &aad,
102 const std::vector<uint8_t> &iv) {
103 bssl::ScopedEVP_AEAD_CTX ctx;
104 if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key.size(), tag_len,
105 nullptr)) {
106 return false;
107 }
108
109 std::vector<uint8_t> out;
110 out.resize(pt.size() + EVP_AEAD_max_overhead(aead));
111 size_t out_len;
112 if (!EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(), iv.data(),
113 iv.size(), pt.data(), pt.size(), aad.data(),
114 aad.size())) {
115 return false;
116 }
117 out.resize(out_len);
118
119 ct->assign(out.begin(), out.end() - tag_len);
120 tag->assign(out.end() - tag_len, out.end());
121
122 return true;
123 }
124
AEADDecrypt(const EVP_AEAD * aead,std::vector<uint8_t> * pt,size_t pt_len,const std::vector<uint8_t> & key,const std::vector<uint8_t> & aad,const std::vector<uint8_t> & ct,const std::vector<uint8_t> & tag,const std::vector<uint8_t> & iv)125 bool AEADDecrypt(const EVP_AEAD *aead, std::vector<uint8_t> *pt, size_t pt_len,
126 const std::vector<uint8_t> &key,
127 const std::vector<uint8_t> &aad,
128 const std::vector<uint8_t> &ct,
129 const std::vector<uint8_t> &tag,
130 const std::vector<uint8_t> &iv) {
131 bssl::ScopedEVP_AEAD_CTX ctx;
132 if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
133 tag.size(), evp_aead_open)) {
134 return false;
135 }
136 std::vector<uint8_t> in = ct;
137 in.reserve(ct.size() + tag.size());
138 in.insert(in.end(), tag.begin(), tag.end());
139
140 pt->resize(pt_len);
141 size_t out_pt_len;
142 if (!EVP_AEAD_CTX_open(ctx.get(), pt->data(), &out_pt_len, pt->size(),
143 iv.data(), iv.size(), in.data(), in.size(), aad.data(),
144 aad.size()) ||
145 out_pt_len != pt_len) {
146 return false;
147 }
148 return true;
149 }
150
HexToBIGNUM(bssl::UniquePtr<BIGNUM> * out,const char * in)151 static int HexToBIGNUM(bssl::UniquePtr<BIGNUM> *out, const char *in) {
152 BIGNUM *raw = NULL;
153 int ret = BN_hex2bn(&raw, in);
154 out->reset(raw);
155 return ret;
156 }
157
GetBIGNUM(FileTest * t,const char * attribute)158 bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *attribute) {
159 std::string hex;
160 if (!t->GetAttribute(&hex, attribute)) {
161 return nullptr;
162 }
163
164 bssl::UniquePtr<BIGNUM> ret;
165 if (HexToBIGNUM(&ret, hex.c_str()) != static_cast<int>(hex.size())) {
166 t->PrintLine("Could not decode '%s'.", hex.c_str());
167 return nullptr;
168 }
169 return ret;
170 }
171
GetECGroupNIDFromInstruction(FileTest * t,const char ** out_str)172 int GetECGroupNIDFromInstruction(FileTest *t, const char **out_str) {
173 const char *dummy;
174 if (out_str == nullptr) {
175 out_str = &dummy;
176 }
177
178 if (t->HasInstruction("P-224")) {
179 *out_str = "P-224";
180 return NID_secp224r1;
181 }
182 if (t->HasInstruction("P-256")) {
183 *out_str = "P-256";
184 return NID_X9_62_prime256v1;
185 }
186 if (t->HasInstruction("P-384")) {
187 *out_str = "P-384";
188 return NID_secp384r1;
189 }
190 if (t->HasInstruction("P-521")) {
191 *out_str = "P-521";
192 return NID_secp521r1;
193 }
194 t->PrintLine("No supported group specified.");
195 return NID_undef;
196 }
197
GetDigestFromInstruction(FileTest * t)198 const EVP_MD *GetDigestFromInstruction(FileTest *t) {
199 if (t->HasInstruction("SHA-1")) {
200 return EVP_sha1();
201 }
202 if (t->HasInstruction("SHA-224")) {
203 return EVP_sha224();
204 }
205 if (t->HasInstruction("SHA-256")) {
206 return EVP_sha256();
207 }
208 if (t->HasInstruction("SHA-384")) {
209 return EVP_sha384();
210 }
211 if (t->HasInstruction("SHA-512")) {
212 return EVP_sha512();
213 }
214 t->PrintLine("No supported digest function specified.");
215 return nullptr;
216 }
217
EchoComment(const std::string & comment)218 void EchoComment(const std::string& comment) {
219 fwrite(comment.c_str(), comment.size(), 1, stdout);
220 }
221