]>
Commit | Line | Data |
---|---|---|
12471842 PL |
1 | /* |
2 | * This file is part of PowerDNS or dnsdist. | |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
870a0fe4 AT |
22 | #ifdef HAVE_CONFIG_H |
23 | #include "config.h" | |
24 | #endif | |
00f1924b | 25 | #include <botan/auto_rng.h> |
f7982887 | 26 | #include <botan/gost_3410.h> |
224778b0 | 27 | #include <botan/gost_3411.h> |
13f34f2e | 28 | #include <botan/pubkey.h> |
07402f63 | 29 | #include <botan/version.h> |
022e5e0b BH |
30 | #include "dnssecinfra.hh" |
31 | ||
32 | using namespace Botan; | |
33 | ||
f7982887 BH |
34 | /* Государственный гимн Российской Федерации |
35 | (Gosudarstvenny Gimn Rossiyskoy Federatsii) | |
36 | "The National Anthem of the Russian Federation" | |
37 | ||
224778b0 | 38 | ~ Rossiya - svyashchennaya nasha derzhava, ~ |
f7982887 BH |
39 | ~ Rossiya - lyubimaya nasha strana. ~ |
40 | ~ Moguchaya volya, velikaya slava - ~ | |
41 | ~ Tvoyo dostoyanye na vse vremena! ~ | |
42 | */ | |
43 | ||
8d9f38f2 | 44 | class GOSTDNSCryptoKeyEngine : public DNSCryptoKeyEngine |
f7982887 BH |
45 | { |
46 | public: | |
189bb9d2 | 47 | explicit GOSTDNSCryptoKeyEngine(unsigned int algorithm) : DNSCryptoKeyEngine(algorithm) {} |
3a168083 | 48 | ~GOSTDNSCryptoKeyEngine(){} |
e69c2dac | 49 | void create(unsigned int bits) override; |
13f34f2e | 50 | string getName() const override { return "Botan 2 GOST"; } |
e69c2dac RG |
51 | storvector_t convertToISCVector() const override; |
52 | std::string getPubKeyHash() const override; | |
13f34f2e RG |
53 | std::string sign(const std::string& msg) const override; |
54 | std::string hash(const std::string& msg) const override; | |
55 | bool verify(const std::string& msg, const std::string& signature) const override; | |
e69c2dac RG |
56 | std::string getPublicKeyString() const override; |
57 | int getBits() const override; | |
58 | void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& content) override; | |
59 | void fromPublicKeyString(const std::string& content) override; | |
60 | void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) override | |
f7982887 BH |
61 | {} |
62 | ||
e69c2dac | 63 | static std::shared_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm) |
f7982887 | 64 | { |
e69c2dac | 65 | return std::make_shared<GOSTDNSCryptoKeyEngine>(algorithm); |
f7982887 BH |
66 | } |
67 | ||
68 | private: | |
13f34f2e RG |
69 | static EC_Group getParams() |
70 | { | |
71 | return EC_Group("gost_256A"); | |
72 | } | |
13f34f2e | 73 | |
f7982887 | 74 | shared_ptr<GOST_3410_PrivateKey> d_key; |
aa65a832 | 75 | shared_ptr<GOST_3410_PublicKey> d_pubkey; |
f7982887 BH |
76 | }; |
77 | ||
78 | /* | |
79 | ~ Slav'sya, Otechestvo nashe svobodnoye, ~ | |
80 | ~ Bratskikh narodov soyuz vekovoy, ~ | |
81 | ~ Predkami dannaya mudrost' narodnaya! ~ | |
82 | ~ Slav'sya, strana! My gordimsya toboy! ~ | |
83 | */ | |
84 | ||
85 | ||
8d9f38f2 | 86 | void GOSTDNSCryptoKeyEngine::create(unsigned int bits) |
f7982887 BH |
87 | { |
88 | AutoSeeded_RNG rng; | |
13f34f2e | 89 | d_key = std::make_shared<GOST_3410_PrivateKey>(rng, getParams()); |
f7982887 BH |
90 | } |
91 | ||
8d9f38f2 | 92 | int GOSTDNSCryptoKeyEngine::getBits() const |
f7982887 BH |
93 | { |
94 | return 256; | |
95 | } | |
96 | ||
97 | /* | |
98 | ~ Ot yuzhnykh morey do polyarnogo kraya ~ | |
99 | ~ Raskinulis' nashi lesa i polya. ~ | |
100 | ~ Odna ty na svete! Odna ty takaya - ~ | |
101 | ~ Khranimaya Bogom rodnaya zemlya! ~ | |
102 | */ | |
103 | ||
c99573a5 | 104 | DNSCryptoKeyEngine::storvector_t GOSTDNSCryptoKeyEngine::convertToISCVector() const |
f7982887 | 105 | { |
13f34f2e | 106 | static const unsigned char asn1Prefix[]= |
f7982887 BH |
107 | {0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, |
108 | 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, | |
109 | 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x01, 0x04, 0x22, 0x04, 0x20}; // this is DER, fixed for a 32 byte key | |
110 | ||
13f34f2e RG |
111 | storvector_t storvect; |
112 | storvect.push_back(make_pair("Algorithm", "12 (ECC-GOST)")); | |
113 | ||
114 | auto buffer = BigInt::encode(d_key->private_value()); | |
115 | string gostasn1(reinterpret_cast<const char*>(asn1Prefix), sizeof(asn1Prefix)); | |
116 | gostasn1.append(buffer.begin(), buffer.end()); | |
c99573a5 BH |
117 | storvect.push_back(make_pair("GostAsn1", gostasn1)); |
118 | return storvect; | |
f7982887 BH |
119 | } |
120 | ||
121 | /* | |
122 | ~ Slav'sya, Otechestvo nashe svobodnoye, ~ | |
123 | ~ Bratskikh narodov soyuz vekovoy, ~ | |
124 | ~ Predkami dannaya mudrost' narodnaya! ~ | |
125 | ~ Slav'sya, strana! My gordimsya toboy! ~ | |
126 | */ | |
127 | ||
8d9f38f2 | 128 | void GOSTDNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap ) |
f7982887 | 129 | { |
335da0ba | 130 | drc.d_algorithm = pdns_stou(stormap["algorithm"]); |
f309dacd | 131 | string privateKey=stormap["gostasn1"]; |
f7982887 BH |
132 | //cerr<<"PrivateKey.size() = "<<privateKey.size()<<endl; |
133 | //cerr<<makeHexDump(string(privateKey.c_str(), 39))<<endl; | |
134 | string rawKey(privateKey.c_str()+39, privateKey.length()-39); | |
135 | ||
136 | for(size_t i = 0; i < rawKey.size() / 2; ++i) | |
137 | { | |
138 | std::swap(rawKey[i], rawKey[rawKey.size()-1-i]); | |
139 | } | |
140 | ||
141 | BigInt bigint((byte*)rawKey.c_str(), rawKey.size()); | |
142 | ||
a11fe644 | 143 | AutoSeeded_RNG rng; |
13f34f2e | 144 | d_key=std::make_shared<GOST_3410_PrivateKey>(rng, getParams(), bigint); |
f7982887 BH |
145 | |
146 | //cerr<<"Is the just imported key on the curve? " << d_key->public_point().on_the_curve()<<endl; | |
147 | //cerr<<"Is the just imported key zero? " << d_key->public_point().is_zero()<<endl; | |
148 | ||
149 | const BigInt&x = d_key->private_value(); | |
13f34f2e | 150 | auto buffer = BigInt::encode(x); |
f7982887 BH |
151 | // cerr<<"And out again! "<<makeHexDump(string((const char*)buffer.begin(), (const char*)buffer.end()))<<endl; |
152 | } | |
aa65a832 BH |
153 | namespace { |
154 | ||
155 | BigInt decode_le(const byte msg[], size_t msg_len) | |
156 | { | |
13f34f2e | 157 | Botan::secure_vector<byte> msg_le(msg, msg + msg_len); |
aa65a832 BH |
158 | |
159 | for(size_t i = 0; i != msg_le.size() / 2; ++i) | |
160 | std::swap(msg_le[i], msg_le[msg_le.size()-1-i]); | |
161 | ||
162 | return BigInt(&msg_le[0], msg_le.size()); | |
163 | } | |
164 | ||
165 | } | |
189bb9d2 | 166 | void GOSTDNSCryptoKeyEngine::fromPublicKeyString(const std::string& input) |
aa65a832 BH |
167 | { |
168 | BigInt x, y; | |
169 | ||
170 | x=decode_le((const byte*)input.c_str(), input.length()/2); | |
171 | y=decode_le((const byte*)input.c_str() + input.length()/2, input.length()/2); | |
172 | ||
13f34f2e | 173 | auto params = getParams(); |
07402f63 | 174 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,5,0) |
aa65a832 | 175 | PointGFp point(params.get_curve(), x,y); |
07402f63 RG |
176 | #else |
177 | PointGFp point(params.point(x,y)); | |
178 | #endif | |
13f34f2e | 179 | d_pubkey = std::make_shared<GOST_3410_PublicKey>(params, point); |
a39da654 | 180 | d_key.reset(); |
aa65a832 | 181 | } |
f7982887 | 182 | |
8d9f38f2 | 183 | std::string GOSTDNSCryptoKeyEngine::getPubKeyHash() const |
f7982887 BH |
184 | { |
185 | const BigInt&x = d_key->private_value(); | |
13f34f2e RG |
186 | auto buffer = BigInt::encode(x); |
187 | return string(buffer.begin(), buffer.end()); | |
f7982887 BH |
188 | } |
189 | ||
8d9f38f2 | 190 | std::string GOSTDNSCryptoKeyEngine::getPublicKeyString() const |
f7982887 | 191 | { |
87557ae2 RG |
192 | std::shared_ptr<GOST_3410_PublicKey> pk = d_pubkey ? d_pubkey : d_key; |
193 | const BigInt&x =pk->public_point().get_affine_x(); | |
194 | const BigInt&y =pk->public_point().get_affine_y(); | |
f7982887 BH |
195 | |
196 | size_t part_size = std::max(x.bytes(), y.bytes()); | |
197 | ||
13f34f2e | 198 | std::vector<byte> bits(2*part_size); |
13f34f2e | 199 | |
f7982887 BH |
200 | x.binary_encode(&bits[part_size - x.bytes()]); |
201 | y.binary_encode(&bits[2*part_size - y.bytes()]); | |
202 | ||
203 | // Keys are stored in little endian format (WTF) | |
204 | for(size_t i = 0; i != part_size / 2; ++i) | |
205 | { | |
206 | std::swap(bits[i], bits[part_size-1-i]); | |
207 | std::swap(bits[part_size+i], bits[2*part_size-1-i]); | |
208 | } | |
209 | ||
13f34f2e | 210 | return string(bits.begin(), bits.end()); |
f7982887 BH |
211 | } |
212 | ||
213 | /* | |
214 | ~ Shirokiy prostor dlya mechty i dlya zhizni. ~ | |
215 | ~ Gryadushchiye nam otkryvayut goda. ~ | |
216 | ~ Nam silu dayot nasha vernost' Otchizne. ~ | |
217 | ~ Tak bylo, tak yest' i tak budet vsegda! ~ | |
218 | */ | |
219 | ||
8d9f38f2 | 220 | std::string GOSTDNSCryptoKeyEngine::sign(const std::string& msg) const |
f7982887 | 221 | { |
f7982887 | 222 | AutoSeeded_RNG rng; |
13f34f2e RG |
223 | PK_Signer signer(*d_key, rng, "Raw"); |
224 | signer.update(hash(msg)); | |
225 | auto signature = signer.signature(rng); | |
226 | return string(signature.begin(), signature.end()); | |
f7982887 BH |
227 | } |
228 | ||
8d9f38f2 | 229 | std::string GOSTDNSCryptoKeyEngine::hash(const std::string& orig) const |
224778b0 | 230 | { |
224778b0 | 231 | GOST_34_11 hasher; |
13f34f2e RG |
232 | auto result = hasher.process(orig); |
233 | return string(result.begin(), result.end()); | |
224778b0 BH |
234 | } |
235 | ||
aa65a832 | 236 | |
8d9f38f2 | 237 | bool GOSTDNSCryptoKeyEngine::verify(const std::string& message, const std::string& signature) const |
f7982887 | 238 | { |
13f34f2e | 239 | std::shared_ptr<GOST_3410_PublicKey> pk = d_pubkey ? d_pubkey : d_key; |
13f34f2e RG |
240 | PK_Verifier verifier(*pk, "Raw"); |
241 | verifier.update(hash(message)); | |
242 | return verifier.check_signature(reinterpret_cast<const uint8_t*>(signature.c_str()), signature.size()); | |
f7982887 BH |
243 | } |
244 | ||
245 | /* | |
246 | ~ Slav'sya, Otechestvo nashe svobodnoye, ~ | |
247 | ~ Bratskikh narodov soyuz vekovoy, ~ | |
248 | ~ Predkami dannaya mudrost' narodnaya! ~ | |
249 | ~ Slav'sya, strana! My gordimsya toboy! ~ | |
250 | */ | |
251 | ||
252 | ||
253 | ////////////////////////////// | |
254 | ||
022e5e0b BH |
255 | namespace { |
256 | struct LoaderStruct | |
257 | { | |
258 | LoaderStruct() | |
259 | { | |
8d9f38f2 | 260 | DNSCryptoKeyEngine::report(12, &GOSTDNSCryptoKeyEngine::maker); |
022e5e0b | 261 | } |
e11963ce | 262 | } loaderBotan2; |
022e5e0b | 263 | } |