1 /* 2 * Written by Dr Stephen N Henson (steve (at) 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 (at) 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 69 OPENSSL_MSVC_PRAGMA(warning(pop)) 70 71 #include <gtest/gtest.h> 72 73 #include <openssl/bytestring.h> 74 #include <openssl/crypto.h> 75 #include <openssl/digest.h> 76 #include <openssl/err.h> 77 #include <openssl/rsa.h> 78 79 #include "../test/file_test.h" 80 #include "../test/test_util.h" 81 82 83 // evp_test dispatches between multiple test types. PrivateKey tests take a key 84 // name parameter and single block, decode it as a PEM private key, and save it 85 // under that key name. Decrypt, Sign, and Verify tests take a previously 86 // imported key name as parameter and test their respective operations. 87 88 static const EVP_MD *GetDigest(FileTest *t, const std::string &name) { 89 if (name == "MD5") { 90 return EVP_md5(); 91 } else if (name == "SHA1") { 92 return EVP_sha1(); 93 } else if (name == "SHA224") { 94 return EVP_sha224(); 95 } else if (name == "SHA256") { 96 return EVP_sha256(); 97 } else if (name == "SHA384") { 98 return EVP_sha384(); 99 } else if (name == "SHA512") { 100 return EVP_sha512(); 101 } 102 ADD_FAILURE() << "Unknown digest: " << name; 103 return nullptr; 104 } 105 106 static int GetKeyType(FileTest *t, const std::string &name) { 107 if (name == "RSA") { 108 return EVP_PKEY_RSA; 109 } 110 if (name == "EC") { 111 return EVP_PKEY_EC; 112 } 113 if (name == "DSA") { 114 return EVP_PKEY_DSA; 115 } 116 if (name == "Ed25519") { 117 return EVP_PKEY_ED25519; 118 } 119 ADD_FAILURE() << "Unknown key type: " << name; 120 return EVP_PKEY_NONE; 121 } 122 123 static int GetRSAPadding(FileTest *t, int *out, const std::string &name) { 124 if (name == "PKCS1") { 125 *out = RSA_PKCS1_PADDING; 126 return true; 127 } 128 if (name == "PSS") { 129 *out = RSA_PKCS1_PSS_PADDING; 130 return true; 131 } 132 if (name == "OAEP") { 133 *out = RSA_PKCS1_OAEP_PADDING; 134 return true; 135 } 136 ADD_FAILURE() << "Unknown RSA padding mode: " << name; 137 return false; 138 } 139 140 using KeyMap = std::map<std::string, bssl::UniquePtr<EVP_PKEY>>; 141 142 static bool ImportKey(FileTest *t, KeyMap *key_map, 143 EVP_PKEY *(*parse_func)(CBS *cbs), 144 int (*marshal_func)(CBB *cbb, const EVP_PKEY *key)) { 145 std::vector<uint8_t> input; 146 if (!t->GetBytes(&input, "Input")) { 147 return false; 148 } 149 150 CBS cbs; 151 CBS_init(&cbs, input.data(), input.size()); 152 bssl::UniquePtr<EVP_PKEY> pkey(parse_func(&cbs)); 153 if (!pkey) { 154 return false; 155 } 156 157 std::string key_type; 158 if (!t->GetAttribute(&key_type, "Type")) { 159 return false; 160 } 161 EXPECT_EQ(GetKeyType(t, key_type), EVP_PKEY_id(pkey.get())); 162 163 // The key must re-encode correctly. 164 bssl::ScopedCBB cbb; 165 uint8_t *der; 166 size_t der_len; 167 if (!CBB_init(cbb.get(), 0) || 168 !marshal_func(cbb.get(), pkey.get()) || 169 !CBB_finish(cbb.get(), &der, &der_len)) { 170 return false; 171 } 172 bssl::UniquePtr<uint8_t> free_der(der); 173 174 std::vector<uint8_t> output = input; 175 if (t->HasAttribute("Output") && 176 !t->GetBytes(&output, "Output")) { 177 return false; 178 } 179 EXPECT_EQ(Bytes(output), Bytes(der, der_len)) << "Re-encoding the key did not match."; 180 181 // Save the key for future tests. 182 const std::string &key_name = t->GetParameter(); 183 EXPECT_EQ(0u, key_map->count(key_name)) << "Duplicate key: " << key_name; 184 (*key_map)[key_name] = std::move(pkey); 185 return true; 186 } 187 188 // SetupContext configures |ctx| based on attributes in |t|, with the exception 189 // of the signing digest which must be configured externally. 190 static bool SetupContext(FileTest *t, EVP_PKEY_CTX *ctx) { 191 if (t->HasAttribute("RSAPadding")) { 192 int padding; 193 if (!GetRSAPadding(t, &padding, t->GetAttributeOrDie("RSAPadding")) || 194 !EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) { 195 return false; 196 } 197 } 198 if (t->HasAttribute("PSSSaltLength") && 199 !EVP_PKEY_CTX_set_rsa_pss_saltlen( 200 ctx, atoi(t->GetAttributeOrDie("PSSSaltLength").c_str()))) { 201 return false; 202 } 203 if (t->HasAttribute("MGF1Digest")) { 204 const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("MGF1Digest")); 205 if (digest == nullptr || !EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, digest)) { 206 return false; 207 } 208 } 209 return true; 210 } 211 212 static bool TestEVP(FileTest *t, KeyMap *key_map) { 213 if (t->GetType() == "PrivateKey") { 214 return ImportKey(t, key_map, EVP_parse_private_key, 215 EVP_marshal_private_key); 216 } 217 218 if (t->GetType() == "PublicKey") { 219 return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key); 220 } 221 222 int (*key_op_init)(EVP_PKEY_CTX *ctx) = nullptr; 223 int (*key_op)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len, 224 const uint8_t *in, size_t in_len) = nullptr; 225 int (*md_op_init)(EVP_MD_CTX * ctx, EVP_PKEY_CTX * *pctx, const EVP_MD *type, 226 ENGINE *e, EVP_PKEY *pkey) = nullptr; 227 bool is_verify = false; 228 if (t->GetType() == "Decrypt") { 229 key_op_init = EVP_PKEY_decrypt_init; 230 key_op = EVP_PKEY_decrypt; 231 } else if (t->GetType() == "Sign") { 232 key_op_init = EVP_PKEY_sign_init; 233 key_op = EVP_PKEY_sign; 234 } else if (t->GetType() == "Verify") { 235 key_op_init = EVP_PKEY_verify_init; 236 is_verify = true; 237 } else if (t->GetType() == "SignMessage") { 238 md_op_init = EVP_DigestSignInit; 239 } else if (t->GetType() == "VerifyMessage") { 240 md_op_init = EVP_DigestVerifyInit; 241 is_verify = true; 242 } else { 243 ADD_FAILURE() << "Unknown test " << t->GetType(); 244 return false; 245 } 246 247 // Load the key. 248 const std::string &key_name = t->GetParameter(); 249 if (key_map->count(key_name) == 0) { 250 ADD_FAILURE() << "Could not find key " << key_name; 251 return false; 252 } 253 EVP_PKEY *key = (*key_map)[key_name].get(); 254 255 const EVP_MD *digest = nullptr; 256 if (t->HasAttribute("Digest")) { 257 digest = GetDigest(t, t->GetAttributeOrDie("Digest")); 258 if (digest == nullptr) { 259 return false; 260 } 261 } 262 263 // For verify tests, the "output" is the signature. Read it now so that, for 264 // tests which expect a failure in SetupContext, the attribute is still 265 // consumed. 266 std::vector<uint8_t> input, actual, output; 267 if (!t->GetBytes(&input, "Input") || 268 (is_verify && !t->GetBytes(&output, "Output"))) { 269 return false; 270 } 271 272 if (md_op_init) { 273 bssl::ScopedEVP_MD_CTX ctx; 274 EVP_PKEY_CTX *pctx; 275 if (!md_op_init(ctx.get(), &pctx, digest, nullptr, key) || 276 !SetupContext(t, pctx)) { 277 return false; 278 } 279 280 if (is_verify) { 281 return !!EVP_DigestVerify(ctx.get(), output.data(), output.size(), 282 input.data(), input.size()); 283 } 284 285 size_t len; 286 if (!EVP_DigestSign(ctx.get(), nullptr, &len, input.data(), input.size())) { 287 return false; 288 } 289 actual.resize(len); 290 if (!EVP_DigestSign(ctx.get(), actual.data(), &len, input.data(), 291 input.size()) || 292 !t->GetBytes(&output, "Output")) { 293 return false; 294 } 295 actual.resize(len); 296 EXPECT_EQ(Bytes(output), Bytes(actual)); 297 return true; 298 } 299 300 bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr)); 301 if (!ctx || 302 !key_op_init(ctx.get()) || 303 (digest != nullptr && 304 !EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) || 305 !SetupContext(t, ctx.get())) { 306 return false; 307 } 308 309 if (is_verify) { 310 return !!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), 311 input.data(), input.size()); 312 } 313 314 size_t len; 315 if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) { 316 return false; 317 } 318 actual.resize(len); 319 if (!key_op(ctx.get(), actual.data(), &len, input.data(), input.size()) || 320 !t->GetBytes(&output, "Output")) { 321 return false; 322 } 323 actual.resize(len); 324 EXPECT_EQ(Bytes(output), Bytes(actual)); 325 return true; 326 } 327 328 TEST(EVPTest, TestVectors) { 329 KeyMap key_map; 330 FileTestGTest("crypto/evp/evp_tests.txt", [&](FileTest *t) { 331 bool result = TestEVP(t, &key_map); 332 if (t->HasAttribute("Error")) { 333 ASSERT_FALSE(result) << "Operation unexpectedly succeeded."; 334 uint32_t err = ERR_peek_error(); 335 EXPECT_EQ(t->GetAttributeOrDie("Error"), ERR_reason_error_string(err)); 336 } else if (!result) { 337 ADD_FAILURE() << "Operation unexpectedly failed."; 338 ERR_print_errors_fp(stdout); 339 } 340 }); 341 } 342