]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/decafsigners.cc
updated KSK and ZSK Rollover procedures, small fixes in Algorithm Rollover procedure
[thirdparty/pdns.git] / pdns / decafsigners.cc
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include <decaf.hxx>
5 #include <decaf/eddsa.hxx>
6 #include <decaf/spongerng.hxx>
7
8 #include "dnssecinfra.hh"
9
10 using namespace decaf;
11
12 class DecafED25519DNSCryptoKeyEngine : public DNSCryptoKeyEngine
13 {
14 public:
15 explicit DecafED25519DNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo)
16 {
17
18 }
19 string getName() const override { return "Decaf ED25519"; }
20 void create(unsigned int bits) override;
21 storvector_t convertToISCVector() const override;
22 std::string getPubKeyHash() const override;
23 std::string sign(const std::string& msg) const override;
24 bool verify(const std::string& msg, const std::string& signature) const override;
25 std::string getPublicKeyString() const override;
26 int getBits() const override;
27 void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
28 void fromPublicKeyString(const std::string& content) override;
29
30 static std::unique_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
31 {
32 return make_unique<DecafED25519DNSCryptoKeyEngine>(algorithm);
33 }
34
35 private:
36 unsigned char d_pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES];
37 unsigned char d_seckey[DECAF_EDDSA_25519_PRIVATE_BYTES];
38 };
39
40 void DecafED25519DNSCryptoKeyEngine::create(unsigned int bits)
41 {
42 if(bits != (unsigned int)getBits()) {
43 throw runtime_error("Unsupported key length of "+std::to_string(bits)+" bits requested, DecafED25519 class");
44 }
45
46 SpongeRng rng("/dev/urandom");
47
48 typename EdDSA<IsoEd25519>::PrivateKey priv(rng);
49 typename EdDSA<IsoEd25519>::PublicKey pub(priv);
50
51 priv.serialize_into(d_seckey);
52 pub.serialize_into(d_pubkey);
53 }
54
55 int DecafED25519DNSCryptoKeyEngine::getBits() const
56 {
57 return DECAF_EDDSA_25519_PRIVATE_BYTES << 3;
58 }
59
60 DNSCryptoKeyEngine::storvector_t DecafED25519DNSCryptoKeyEngine::convertToISCVector() const
61 {
62 /*
63 Private-key-format: v1.2
64 Algorithm: 15 (ED25519)
65 PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=
66 */
67
68 auto storvector = storvector_t{
69 {"Algorithm", "15 (ED25519)"},
70 {"PrivateKey", string((char*)d_seckey, DECAF_EDDSA_25519_PRIVATE_BYTES)},
71 };
72
73 return storvector;
74 }
75
76 void DecafED25519DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap )
77 {
78 /*
79 Private-key-format: v1.2
80 Algorithm: 15 (ED25519)
81 PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=
82 */
83
84 pdns::checked_stoi_into(drc.d_algorithm, stormap["algorithm"]);
85 string privateKey = stormap["privatekey"];
86
87 if (privateKey.length() != DECAF_EDDSA_25519_PRIVATE_BYTES)
88 throw runtime_error("Private key size mismatch in ISCMap, DecafED25519 class");
89
90 typename EdDSA<IsoEd25519>::PrivateKey priv(Block((const unsigned char*)privateKey.c_str(), DECAF_EDDSA_25519_PRIVATE_BYTES));
91 typename EdDSA<IsoEd25519>::PublicKey pub(priv);
92
93 priv.serialize_into(d_seckey);
94 pub.serialize_into(d_pubkey);
95 }
96
97 std::string DecafED25519DNSCryptoKeyEngine::getPubKeyHash() const
98 {
99 return this->getPublicKeyString();
100 }
101
102 std::string DecafED25519DNSCryptoKeyEngine::getPublicKeyString() const
103 {
104 return string((char*)d_pubkey, DECAF_EDDSA_25519_PUBLIC_BYTES);
105 }
106
107 void DecafED25519DNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
108 {
109 if (input.length() != DECAF_EDDSA_25519_PUBLIC_BYTES)
110 throw runtime_error("Public key size mismatch, DecafED25519 class");
111
112 memcpy(d_pubkey, input.c_str(), DECAF_EDDSA_25519_PUBLIC_BYTES);
113 }
114
115 std::string DecafED25519DNSCryptoKeyEngine::sign(const std::string& msg) const
116 {
117 typename EdDSA<IsoEd25519>::PrivateKey priv(Block(d_seckey, DECAF_EDDSA_25519_PRIVATE_BYTES));
118
119 SecureBuffer message(msg.begin(), msg.end());
120
121 SecureBuffer sig = priv.sign(message);
122
123 return string(sig.begin(), sig.end());
124 }
125
126 bool DecafED25519DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
127 {
128 if (signature.length() != DECAF_EDDSA_25519_SIGNATURE_BYTES)
129 return false;
130
131 typename EdDSA<IsoEd25519>::PublicKey pub(Block(d_pubkey, DECAF_EDDSA_25519_PUBLIC_BYTES));
132
133 SecureBuffer sig(signature.begin(), signature.end());
134 SecureBuffer message(msg.begin(), msg.end());
135
136 try {
137 pub.verify(sig, message);
138 } catch(const CryptoException& e) {
139 return false;
140 }
141
142 return true;
143 }
144
145
146 class DecafED448DNSCryptoKeyEngine : public DNSCryptoKeyEngine
147 {
148 public:
149 explicit DecafED448DNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo)
150 {
151
152 }
153 string getName() const override { return "Decaf ED448"; }
154 void create(unsigned int bits) override;
155 storvector_t convertToISCVector() const override;
156 std::string getPubKeyHash() const override;
157 std::string sign(const std::string& msg) const override;
158 bool verify(const std::string& msg, const std::string& signature) const override;
159 std::string getPublicKeyString() const override;
160 int getBits() const override;
161 void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
162 void fromPublicKeyString(const std::string& content) override;
163 void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) override
164 {}
165
166 static std::unique_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
167 {
168 return make_unique<DecafED448DNSCryptoKeyEngine>(algorithm);
169 }
170
171 private:
172 unsigned char d_pubkey[DECAF_EDDSA_448_PUBLIC_BYTES];
173 unsigned char d_seckey[DECAF_EDDSA_448_PRIVATE_BYTES];
174 };
175
176 void DecafED448DNSCryptoKeyEngine::create(unsigned int bits)
177 {
178 if(bits != (unsigned int)getBits()) {
179 throw runtime_error("Unsupported key length of "+std::to_string(bits)+" bits requested, DecafED448 class");
180 }
181
182 SpongeRng rng("/dev/urandom");
183
184 typename EdDSA<Ed448Goldilocks>::PrivateKey priv(rng);
185 typename EdDSA<Ed448Goldilocks>::PublicKey pub(priv);
186
187 priv.serialize_into(d_seckey);
188 pub.serialize_into(d_pubkey);
189 }
190
191 int DecafED448DNSCryptoKeyEngine::getBits() const
192 {
193 return DECAF_EDDSA_448_PRIVATE_BYTES << 3;
194 }
195
196 DNSCryptoKeyEngine::storvector_t DecafED448DNSCryptoKeyEngine::convertToISCVector() const
197 {
198 /*
199 Private-key-format: v1.2
200 Algorithm: 16 (ED448)
201 PrivateKey: xZ+5Cgm463xugtkY5B0Jx6erFTXp13rYegst0qRtNsOYnaVpMx0Z/c5EiA9x8wWbDDct/U3FhYWA
202 */
203
204 auto storvector = storvector_t{
205 {"Algorithm", "16 (ED448)"},
206 {"PrivateKey", string((char*)d_seckey, DECAF_EDDSA_448_PRIVATE_BYTES)},
207 };
208
209 return storvector;
210 }
211
212 void DecafED448DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap )
213 {
214 /*
215 Private-key-format: v1.2
216 Algorithm: 16 (ED448)
217 PrivateKey: xZ+5Cgm463xugtkY5B0Jx6erFTXp13rYegst0qRtNsOYnaVpMx0Z/c5EiA9x8wWbDDct/U3FhYWA
218 */
219
220 pdns::checked_stoi_into(drc.d_algorithm, stormap["algorithm"]);
221 string privateKey = stormap["privatekey"];
222
223 if (privateKey.length() != DECAF_EDDSA_448_PRIVATE_BYTES)
224 throw runtime_error("Private key size mismatch in ISCMap, DecafED448 class");
225
226 typename EdDSA<Ed448Goldilocks>::PrivateKey priv(Block((const unsigned char*)privateKey.c_str(), DECAF_EDDSA_448_PRIVATE_BYTES));
227 typename EdDSA<Ed448Goldilocks>::PublicKey pub(priv);
228
229 priv.serialize_into(d_seckey);
230 pub.serialize_into(d_pubkey);
231 }
232
233 std::string DecafED448DNSCryptoKeyEngine::getPubKeyHash() const
234 {
235 return this->getPublicKeyString();
236 }
237
238 std::string DecafED448DNSCryptoKeyEngine::getPublicKeyString() const
239 {
240 return string((char*)d_pubkey, DECAF_EDDSA_448_PUBLIC_BYTES);
241 }
242
243 void DecafED448DNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
244 {
245 if (input.length() != DECAF_EDDSA_448_PUBLIC_BYTES)
246 throw runtime_error("Public key size mismatch, DecafED448 class");
247
248 memcpy(d_pubkey, input.c_str(), DECAF_EDDSA_448_PUBLIC_BYTES);
249 }
250
251 std::string DecafED448DNSCryptoKeyEngine::sign(const std::string& msg) const
252 {
253 typename EdDSA<Ed448Goldilocks>::PrivateKey priv(Block(d_seckey, DECAF_EDDSA_448_PRIVATE_BYTES));
254
255 SecureBuffer message(msg.begin(), msg.end());
256
257 SecureBuffer sig = priv.sign(message);
258
259 return string(sig.begin(), sig.end());
260 }
261
262 bool DecafED448DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
263 {
264 if (signature.length() != DECAF_EDDSA_448_SIGNATURE_BYTES)
265 return false;
266
267 typename EdDSA<Ed448Goldilocks>::PublicKey pub(Block(d_pubkey, DECAF_EDDSA_448_PUBLIC_BYTES));
268
269 SecureBuffer sig(signature.begin(), signature.end());
270 SecureBuffer message(msg.begin(), msg.end());
271
272 try {
273 pub.verify(sig, message);
274 } catch(const CryptoException& e) {
275 return false;
276 }
277
278 return true;
279 }
280
281
282 namespace {
283 struct LoaderDecafStruct
284 {
285 LoaderDecafStruct()
286 {
287 DNSCryptoKeyEngine::report(15, &DecafED25519DNSCryptoKeyEngine::maker, true);
288 DNSCryptoKeyEngine::report(16, &DecafED448DNSCryptoKeyEngine::maker);
289 }
290 } loaderdecaf;
291 }