1 /*
2  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  */
53 
54 #include <openssl/evp.h>
55 
56 #include <stdio.h>
57 #include <stdint.h>
58 #include <stdlib.h>
59 #include <string.h>
60 
61 OPENSSL_MSVC_PRAGMA(warning(push))
62 OPENSSL_MSVC_PRAGMA(warning(disable: 4702))
63 
64 #include <map>
65 #include <string>
66 #include <utility>
67 #include <vector>
68 
OPENSSL_MSVC_PRAGMA(warning (pop)) const69 OPENSSL_MSVC_PRAGMA(warning(pop))
70 
71 #include <openssl/bytestring.h>
72 #include <openssl/crypto.h>
73 #include <openssl/digest.h>
74 #include <openssl/err.h>
75 #include <openssl/rsa.h>
76 
77 #include "../test/file_test.h"
78 
79 
80 // evp_test dispatches between multiple test types. PrivateKey tests take a key
81 // name parameter and single block, decode it as a PEM private key, and save it
82 // under that key name. Decrypt, Sign, and Verify tests take a previously
83 // imported key name as parameter and test their respective operations.
84 
85 static const EVP_MD *GetDigest(FileTest *t, const std::string &name) {
86   if (name == "MD5") {
87     return EVP_md5();
88   } else if (name == "SHA1") {
89     return EVP_sha1();
90   } else if (name == "SHA224") {
91     return EVP_sha224();
92   } else if (name == "SHA256") {
93     return EVP_sha256();
94   } else if (name == "SHA384") {
95     return EVP_sha384();
96   } else if (name == "SHA512") {
97     return EVP_sha512();
98   }
99   t->PrintLine("Unknown digest: '%s'", name.c_str());
100   return nullptr;
101 }
102 
GetKeyType(FileTest * t,const std::string & name)103 static int GetKeyType(FileTest *t, const std::string &name) {
104   if (name == "RSA") {
105     return EVP_PKEY_RSA;
106   }
107   if (name == "EC") {
108     return EVP_PKEY_EC;
109   }
110   if (name == "DSA") {
111     return EVP_PKEY_DSA;
112   }
113   t->PrintLine("Unknown key type: '%s'", name.c_str());
114   return EVP_PKEY_NONE;
115 }
116 
GetRSAPadding(FileTest * t,int * out,const std::string & name)117 static int GetRSAPadding(FileTest *t, int *out, const std::string &name) {
118   if (name == "PKCS1") {
119     *out = RSA_PKCS1_PADDING;
120     return true;
121   }
122   if (name == "PSS") {
123     *out = RSA_PKCS1_PSS_PADDING;
124     return true;
125   }
126   if (name == "OAEP") {
127     *out = RSA_PKCS1_OAEP_PADDING;
128     return true;
129   }
130   t->PrintLine("Unknown RSA padding mode: '%s'", name.c_str());
131   return false;
132 }
133 
134 using KeyMap = std::map<std::string, bssl::UniquePtr<EVP_PKEY>>;
135 
ImportKey(FileTest * t,KeyMap * key_map,EVP_PKEY * (* parse_func)(CBS * cbs),int (* marshal_func)(CBB * cbb,const EVP_PKEY * key))136 static bool ImportKey(FileTest *t, KeyMap *key_map,
137                       EVP_PKEY *(*parse_func)(CBS *cbs),
138                       int (*marshal_func)(CBB *cbb, const EVP_PKEY *key)) {
139   std::vector<uint8_t> input;
140   if (!t->GetBytes(&input, "Input")) {
141     return false;
142   }
143 
144   CBS cbs;
145   CBS_init(&cbs, input.data(), input.size());
146   bssl::UniquePtr<EVP_PKEY> pkey(parse_func(&cbs));
147   if (!pkey) {
148     return false;
149   }
150 
151   std::string key_type;
152   if (!t->GetAttribute(&key_type, "Type")) {
153     return false;
154   }
155   if (EVP_PKEY_id(pkey.get()) != GetKeyType(t, key_type)) {
156     t->PrintLine("Bad key type.");
157     return false;
158   }
159 
160   // The key must re-encode correctly.
161   bssl::ScopedCBB cbb;
162   uint8_t *der;
163   size_t der_len;
164   if (!CBB_init(cbb.get(), 0) ||
165       !marshal_func(cbb.get(), pkey.get()) ||
166       !CBB_finish(cbb.get(), &der, &der_len)) {
167     return false;
168   }
169   bssl::UniquePtr<uint8_t> free_der(der);
170 
171   std::vector<uint8_t> output = input;
172   if (t->HasAttribute("Output") &&
173       !t->GetBytes(&output, "Output")) {
174     return false;
175   }
176   if (!t->ExpectBytesEqual(output.data(), output.size(), der, der_len)) {
177     t->PrintLine("Re-encoding the key did not match.");
178     return false;
179   }
180 
181   // Save the key for future tests.
182   const std::string &key_name = t->GetParameter();
183   if (key_map->count(key_name) > 0) {
184     t->PrintLine("Duplicate key '%s'.", key_name.c_str());
185     return false;
186   }
187   (*key_map)[key_name] = std::move(pkey);
188   return true;
189 }
190 
TestEVP(FileTest * t,void * arg)191 static bool TestEVP(FileTest *t, void *arg) {
192   KeyMap *key_map = reinterpret_cast<KeyMap*>(arg);
193   if (t->GetType() == "PrivateKey") {
194     return ImportKey(t, key_map, EVP_parse_private_key,
195                      EVP_marshal_private_key);
196   }
197 
198   if (t->GetType() == "PublicKey") {
199     return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key);
200   }
201 
202   int (*key_op_init)(EVP_PKEY_CTX *ctx);
203   int (*key_op)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len,
204                 const uint8_t *in, size_t in_len);
205   if (t->GetType() == "Decrypt") {
206     key_op_init = EVP_PKEY_decrypt_init;
207     key_op = EVP_PKEY_decrypt;
208   } else if (t->GetType() == "Sign") {
209     key_op_init = EVP_PKEY_sign_init;
210     key_op = EVP_PKEY_sign;
211   } else if (t->GetType() == "Verify") {
212     key_op_init = EVP_PKEY_verify_init;
213     key_op = nullptr;  // EVP_PKEY_verify is handled differently.
214   } else {
215     t->PrintLine("Unknown test '%s'", t->GetType().c_str());
216     return false;
217   }
218 
219   // Load the key.
220   const std::string &key_name = t->GetParameter();
221   if (key_map->count(key_name) == 0) {
222     t->PrintLine("Could not find key '%s'.", key_name.c_str());
223     return false;
224   }
225   EVP_PKEY *key = (*key_map)[key_name].get();
226 
227   std::vector<uint8_t> input;
228   if (!t->GetBytes(&input, "Input")) {
229     return false;
230   }
231 
232   // Set up the EVP_PKEY_CTX.
233   bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
234   if (!ctx || !key_op_init(ctx.get())) {
235     return false;
236   }
237   if (t->HasAttribute("Digest")) {
238     const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("Digest"));
239     if (digest == nullptr ||
240         !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) {
241       return false;
242     }
243   }
244   if (t->HasAttribute("RSAPadding")) {
245     int padding;
246     if (!GetRSAPadding(t, &padding, t->GetAttributeOrDie("RSAPadding")) ||
247         !EVP_PKEY_CTX_set_rsa_padding(ctx.get(), padding)) {
248       return false;
249     }
250   }
251   if (t->HasAttribute("PSSSaltLength") &&
252       !EVP_PKEY_CTX_set_rsa_pss_saltlen(
253           ctx.get(), atoi(t->GetAttributeOrDie("PSSSaltLength").c_str()))) {
254     return false;
255   }
256   if (t->HasAttribute("MGF1Digest")) {
257     const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("MGF1Digest"));
258     if (digest == nullptr ||
259         !EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.get(), digest)) {
260       return false;
261     }
262   }
263 
264   if (t->GetType() == "Verify") {
265     std::vector<uint8_t> output;
266     if (!t->GetBytes(&output, "Output") ||
267         !EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(),
268                          input.size())) {
269       // ECDSA sometimes doesn't push an error code. Push one on the error queue
270       // so it's distinguishable from other errors.
271       OPENSSL_PUT_ERROR(USER, ERR_R_EVP_LIB);
272       return false;
273     }
274     return true;
275   }
276 
277   size_t len;
278   std::vector<uint8_t> actual, output;
279   if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) {
280     return false;
281   }
282   actual.resize(len);
283   if (!key_op(ctx.get(), actual.data(), &len, input.data(), input.size())) {
284     return false;
285   }
286   actual.resize(len);
287   if (!t->GetBytes(&output, "Output") ||
288       !t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) {
289     return false;
290   }
291   return true;
292 }
293 
main(int argc,char * argv[])294 int main(int argc, char *argv[]) {
295   CRYPTO_library_init();
296   if (argc != 2) {
297     fprintf(stderr, "%s <test file.txt>\n", argv[0]);
298     return 1;
299   }
300 
301   KeyMap map;
302   return FileTestMain(TestEVP, &map, argv[1]);
303 }
304