1 /* Copyright (c) 2018, 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 "./wycheproof_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 #include "./file_test.h"
23 
24 
GetWycheproofResult(FileTest * t,WycheproofResult * out)25 bool GetWycheproofResult(FileTest *t, WycheproofResult *out) {
26   std::string result;
27   if (!t->GetAttribute(&result, "result")) {
28     return false;
29   }
30   if (result == "valid") {
31     *out = WycheproofResult::kValid;
32   } else if (result == "invalid") {
33     *out = WycheproofResult::kInvalid;
34   } else if (result == "acceptable") {
35     *out = WycheproofResult::kAcceptable;
36   } else {
37     t->PrintLine("Bad result string '%s'", result.c_str());
38     return false;
39   }
40   return true;
41 }
42 
GetWycheproofDigest(FileTest * t,const char * key,bool instruction)43 const EVP_MD *GetWycheproofDigest(FileTest *t, const char *key,
44                                   bool instruction) {
45   std::string name;
46   bool ok =
47       instruction ? t->GetInstruction(&name, key) : t->GetAttribute(&name, key);
48   if (!ok) {
49     return nullptr;
50   }
51   if (name == "SHA-1") {
52     return EVP_sha1();
53   }
54   if (name == "SHA-224") {
55     return EVP_sha224();
56   }
57   if (name == "SHA-256") {
58     return EVP_sha256();
59   }
60   if (name == "SHA-384") {
61     return EVP_sha384();
62   }
63   if (name == "SHA-512") {
64     return EVP_sha512();
65   }
66   t->PrintLine("Unknown digest '%s'", name.c_str());
67   return nullptr;
68 }
69 
GetWycheproofCurve(FileTest * t,const char * key,bool instruction)70 bssl::UniquePtr<EC_GROUP> GetWycheproofCurve(FileTest *t, const char *key,
71                                              bool instruction) {
72   std::string name;
73   bool ok =
74       instruction ? t->GetInstruction(&name, key) : t->GetAttribute(&name, key);
75   if (!ok) {
76     return nullptr;
77   }
78   int nid;
79   if (name == "secp224r1") {
80     nid = NID_secp224r1;
81   } else if (name == "secp256r1") {
82     nid = NID_X9_62_prime256v1;
83   } else if (name == "secp384r1") {
84     nid = NID_secp384r1;
85   } else if (name == "secp521r1") {
86     nid = NID_secp521r1;
87   } else {
88     t->PrintLine("Unknown curve '%s'", name.c_str());
89     return nullptr;
90   }
91   return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(nid));
92 }
93 
GetWycheproofBIGNUM(FileTest * t,const char * key,bool instruction)94 bssl::UniquePtr<BIGNUM> GetWycheproofBIGNUM(FileTest *t, const char *key,
95                                             bool instruction) {
96   std::string value;
97   bool ok = instruction ? t->GetInstruction(&value, key)
98                         : t->GetAttribute(&value, key);
99   if (!ok) {
100     return nullptr;
101   }
102   BIGNUM *bn = nullptr;
103   if (BN_hex2bn(&bn, value.c_str()) != static_cast<int>(value.size())) {
104     BN_free(bn);
105     t->PrintLine("Could not decode value '%s'", value.c_str());
106     return nullptr;
107   }
108   bssl::UniquePtr<BIGNUM> ret(bn);
109   if (!value.empty()) {
110     // If the high bit is one, this is a negative number in Wycheproof.
111     // Wycheproof's tests generally mimic Java APIs, including all their
112     // mistakes. See
113     // https://github.com/google/wycheproof/blob/0329f5b751ef102bd6b7b7181b6e049522a887f5/java/com/google/security/wycheproof/JsonUtil.java#L62.
114     if ('0' > value[0] || value[0] > '7') {
115       bssl::UniquePtr<BIGNUM> tmp(BN_new());
116       if (!tmp ||
117           !BN_set_bit(tmp.get(), value.size() * 4) ||
118           !BN_sub(ret.get(), ret.get(), tmp.get())) {
119         return nullptr;
120       }
121     }
122   }
123   return ret;
124 }
125