]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/botansigners.cc
5d7b43b62b5bf071687435832c4c33f1b030fec5
[thirdparty/pdns.git] / pdns / botansigners.cc
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 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include <botan/auto_rng.h>
26 #include <botan/gost_3410.h>
27 #include <botan/gost_3411.h>
28 #include <botan/pubkey.h>
29 #include "dnssecinfra.hh"
30
31 using namespace Botan;
32
33 /* Государственный гимн Российской Федерации
34 (Gosudarstvenny Gimn Rossiyskoy Federatsii)
35 "The National Anthem of the Russian Federation"
36
37 ~ Rossiya - svyashchennaya nasha derzhava, ~
38 ~ Rossiya - lyubimaya nasha strana. ~
39 ~ Moguchaya volya, velikaya slava - ~
40 ~ Tvoyo dostoyanye na vse vremena! ~
41 */
42
43 class GOSTDNSCryptoKeyEngine : public DNSCryptoKeyEngine
44 {
45 public:
46 explicit GOSTDNSCryptoKeyEngine(unsigned int algorithm) : DNSCryptoKeyEngine(algorithm) {}
47 ~GOSTDNSCryptoKeyEngine(){}
48 void create(unsigned int bits) override;
49 string getName() const override { return "Botan 2 GOST"; }
50 storvector_t convertToISCVector() const override;
51 std::string getPubKeyHash() const override;
52 std::string sign(const std::string& msg) const override;
53 std::string hash(const std::string& msg) const override;
54 bool verify(const std::string& msg, const std::string& signature) const override;
55 std::string getPublicKeyString() const override;
56 int getBits() const override;
57 void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& content) override;
58 void fromPublicKeyString(const std::string& content) override;
59 void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) override
60 {}
61
62 static std::shared_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
63 {
64 return std::make_shared<GOSTDNSCryptoKeyEngine>(algorithm);
65 }
66
67 private:
68 static EC_Group getParams()
69 {
70 return EC_Group("gost_256A");
71 }
72
73 shared_ptr<GOST_3410_PrivateKey> d_key;
74 shared_ptr<GOST_3410_PublicKey> d_pubkey;
75 };
76
77 /*
78 ~ Slav'sya, Otechestvo nashe svobodnoye, ~
79 ~ Bratskikh narodov soyuz vekovoy, ~
80 ~ Predkami dannaya mudrost' narodnaya! ~
81 ~ Slav'sya, strana! My gordimsya toboy! ~
82 */
83
84
85 void GOSTDNSCryptoKeyEngine::create(unsigned int bits)
86 {
87 AutoSeeded_RNG rng;
88 d_key = std::make_shared<GOST_3410_PrivateKey>(rng, getParams());
89 }
90
91 int GOSTDNSCryptoKeyEngine::getBits() const
92 {
93 return 256;
94 }
95
96 /*
97 ~ Ot yuzhnykh morey do polyarnogo kraya ~
98 ~ Raskinulis' nashi lesa i polya. ~
99 ~ Odna ty na svete! Odna ty takaya - ~
100 ~ Khranimaya Bogom rodnaya zemlya! ~
101 */
102
103 DNSCryptoKeyEngine::storvector_t GOSTDNSCryptoKeyEngine::convertToISCVector() const
104 {
105 static const unsigned char asn1Prefix[]=
106 {0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02,
107 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07,
108 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x01, 0x04, 0x22, 0x04, 0x20}; // this is DER, fixed for a 32 byte key
109
110 storvector_t storvect;
111 storvect.push_back(make_pair("Algorithm", "12 (ECC-GOST)"));
112
113 auto buffer = BigInt::encode(d_key->private_value());
114 string gostasn1(reinterpret_cast<const char*>(asn1Prefix), sizeof(asn1Prefix));
115 gostasn1.append(buffer.begin(), buffer.end());
116 storvect.push_back(make_pair("GostAsn1", gostasn1));
117 return storvect;
118 }
119
120 /*
121 ~ Slav'sya, Otechestvo nashe svobodnoye, ~
122 ~ Bratskikh narodov soyuz vekovoy, ~
123 ~ Predkami dannaya mudrost' narodnaya! ~
124 ~ Slav'sya, strana! My gordimsya toboy! ~
125 */
126
127 void GOSTDNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap )
128 {
129 drc.d_algorithm = pdns_stou(stormap["algorithm"]);
130 string privateKey=stormap["gostasn1"];
131 //cerr<<"PrivateKey.size() = "<<privateKey.size()<<endl;
132 //cerr<<makeHexDump(string(privateKey.c_str(), 39))<<endl;
133 string rawKey(privateKey.c_str()+39, privateKey.length()-39);
134
135 for(size_t i = 0; i < rawKey.size() / 2; ++i)
136 {
137 std::swap(rawKey[i], rawKey[rawKey.size()-1-i]);
138 }
139
140 BigInt bigint((byte*)rawKey.c_str(), rawKey.size());
141
142 AutoSeeded_RNG rng;
143 d_key=std::make_shared<GOST_3410_PrivateKey>(rng, getParams(), bigint);
144
145 //cerr<<"Is the just imported key on the curve? " << d_key->public_point().on_the_curve()<<endl;
146 //cerr<<"Is the just imported key zero? " << d_key->public_point().is_zero()<<endl;
147
148 const BigInt&x = d_key->private_value();
149 auto buffer = BigInt::encode(x);
150 // cerr<<"And out again! "<<makeHexDump(string((const char*)buffer.begin(), (const char*)buffer.end()))<<endl;
151 }
152 namespace {
153
154 BigInt decode_le(const byte msg[], size_t msg_len)
155 {
156 Botan::secure_vector<byte> msg_le(msg, msg + msg_len);
157
158 for(size_t i = 0; i != msg_le.size() / 2; ++i)
159 std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
160
161 return BigInt(&msg_le[0], msg_le.size());
162 }
163
164 }
165 void GOSTDNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
166 {
167 BigInt x, y;
168
169 x=decode_le((const byte*)input.c_str(), input.length()/2);
170 y=decode_le((const byte*)input.c_str() + input.length()/2, input.length()/2);
171
172 auto params = getParams();
173 PointGFp point(params.get_curve(), x,y);
174 d_pubkey = std::make_shared<GOST_3410_PublicKey>(params, point);
175 d_key.reset();
176 }
177
178 std::string GOSTDNSCryptoKeyEngine::getPubKeyHash() const
179 {
180 const BigInt&x = d_key->private_value();
181 auto buffer = BigInt::encode(x);
182 return string(buffer.begin(), buffer.end());
183 }
184
185 std::string GOSTDNSCryptoKeyEngine::getPublicKeyString() const
186 {
187 std::shared_ptr<GOST_3410_PublicKey> pk = d_pubkey ? d_pubkey : d_key;
188 const BigInt&x =pk->public_point().get_affine_x();
189 const BigInt&y =pk->public_point().get_affine_y();
190
191 size_t part_size = std::max(x.bytes(), y.bytes());
192
193 std::vector<byte> bits(2*part_size);
194
195 x.binary_encode(&bits[part_size - x.bytes()]);
196 y.binary_encode(&bits[2*part_size - y.bytes()]);
197
198 // Keys are stored in little endian format (WTF)
199 for(size_t i = 0; i != part_size / 2; ++i)
200 {
201 std::swap(bits[i], bits[part_size-1-i]);
202 std::swap(bits[part_size+i], bits[2*part_size-1-i]);
203 }
204
205 return string(bits.begin(), bits.end());
206 }
207
208 /*
209 ~ Shirokiy prostor dlya mechty i dlya zhizni. ~
210 ~ Gryadushchiye nam otkryvayut goda. ~
211 ~ Nam silu dayot nasha vernost' Otchizne. ~
212 ~ Tak bylo, tak yest' i tak budet vsegda! ~
213 */
214
215 std::string GOSTDNSCryptoKeyEngine::sign(const std::string& msg) const
216 {
217 AutoSeeded_RNG rng;
218 PK_Signer signer(*d_key, rng, "Raw");
219 signer.update(hash(msg));
220 auto signature = signer.signature(rng);
221 return string(signature.begin(), signature.end());
222 }
223
224 std::string GOSTDNSCryptoKeyEngine::hash(const std::string& orig) const
225 {
226 GOST_34_11 hasher;
227 auto result = hasher.process(orig);
228 return string(result.begin(), result.end());
229 }
230
231
232 bool GOSTDNSCryptoKeyEngine::verify(const std::string& message, const std::string& signature) const
233 {
234 std::shared_ptr<GOST_3410_PublicKey> pk = d_pubkey ? d_pubkey : d_key;
235 PK_Verifier verifier(*pk, "Raw");
236 verifier.update(hash(message));
237 return verifier.check_signature(reinterpret_cast<const uint8_t*>(signature.c_str()), signature.size());
238 }
239
240 /*
241 ~ Slav'sya, Otechestvo nashe svobodnoye, ~
242 ~ Bratskikh narodov soyuz vekovoy, ~
243 ~ Predkami dannaya mudrost' narodnaya! ~
244 ~ Slav'sya, strana! My gordimsya toboy! ~
245 */
246
247
248 //////////////////////////////
249
250 namespace {
251 struct LoaderStruct
252 {
253 LoaderStruct()
254 {
255 DNSCryptoKeyEngine::report(12, &GOSTDNSCryptoKeyEngine::maker);
256 }
257 } loaderBotan2;
258 }