1 /*------------------------------------------------------------------------------
2 *
3 * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4 * The YADIFA TM software product is provided under the BSD 3-clause license:
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of EURid nor the names of its contributors may be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *------------------------------------------------------------------------------
32 *
33 */
34
35 /** @defgroup dnskey DNSSEC keys functions
36 * @ingroup dnsdbdnssec
37 * @brief
38 *
39 * @{
40 */
41 /*------------------------------------------------------------------------------
42 *
43 * USE INCLUDES */
44 #include "dnscore/dnscore-config.h"
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <arpa/inet.h>
48
49 #include <openssl/bn.h>
50 #include <openssl/err.h>
51 #include <openssl/dsa.h>
52 #include <openssl/ssl.h>
53 #include <openssl/engine.h>
54 #include "dnscore/openssl.h"
55
56 #include "dnscore/dnscore.h"
57
58 #include "dnscore/sys_types.h"
59 #include "dnscore/base64.h"
60
61 #include "dnscore/logger.h"
62 #include "dnscore/dnskey.h"
63 #include "dnscore/dnskey_dsa.h"
64 #include "dnscore/dnssec_errors.h"
65 #include "dnscore/zalloc.h"
66
67
68 #define MODULE_MSG_HANDLE g_system_logger
69
70 #define KEYDSA_TAG 0x5f41534459454b
71
72 #ifndef SSL_API
73 #error "SSL_API not defined"
74 #endif
75
76 #if SSL_API_LT_110
77
78 /*
79 * Backward-compatible interface for 0.9.x
80 */
81
82 #define SSL_FIELD_GET(st_,f_) if(f_ != NULL) { *f_ = st_->f_; }
83 #define SSL_FIELD_SET(st_,f_) if(f_ != NULL) { BN_free(st_->f_); st_->f_ = f_; }
84 #define SSL_FIELD_SET_FAIL(st_,f_) (st_->f_ == NULL && f_ == NULL)
85
DSA_get0_pqg(const DSA * d,const BIGNUM ** p,const BIGNUM ** q,const BIGNUM ** g)86 static void DSA_get0_pqg(const DSA *d,
87 const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
88 {
89 SSL_FIELD_GET(d,p)
90 SSL_FIELD_GET(d,q)
91 SSL_FIELD_GET(d,g)
92 }
93
DSA_set0_pqg(DSA * d,BIGNUM * p,BIGNUM * q,BIGNUM * g)94 static int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
95 {
96 if(SSL_FIELD_SET_FAIL(d,p) || SSL_FIELD_SET_FAIL(d,q) || SSL_FIELD_SET_FAIL(d,g))
97 {
98 return 0;
99 }
100 SSL_FIELD_SET(d,p)
101 SSL_FIELD_SET(d,q)
102 SSL_FIELD_SET(d,g)
103 return 1;
104 }
105
DSA_get0_p(const DSA * d)106 const BIGNUM *DSA_get0_p(const DSA *d)
107 {
108 return d->p;
109 }
110
DSA_get0_key(const DSA * d,const BIGNUM ** pub_key,const BIGNUM ** priv_key)111 void DSA_get0_key(const DSA *d,
112 const BIGNUM **pub_key, const BIGNUM **priv_key)
113 {
114 SSL_FIELD_GET(d,pub_key)
115 SSL_FIELD_GET(d,priv_key)
116 }
117
DSA_set0_key(DSA * d,BIGNUM * pub_key,BIGNUM * priv_key)118 int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
119 {
120 if(SSL_FIELD_SET_FAIL(d,pub_key))
121 {
122 return 0;
123 }
124 SSL_FIELD_SET(d,pub_key)
125 SSL_FIELD_SET(d,priv_key)
126 return 1;
127 }
128
DSA_SIG_get0(const DSA_SIG * sig,const BIGNUM ** r,const BIGNUM ** s)129 void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **r, const BIGNUM **s)
130 {
131 SSL_FIELD_GET(sig,r)
132 SSL_FIELD_GET(sig,s)
133 }
134
DSA_SIG_set0(DSA_SIG * sig,BIGNUM * r,BIGNUM * s)135 int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
136 {
137 if(SSL_FIELD_SET_FAIL(sig,r) || SSL_FIELD_SET_FAIL(sig,s))
138 {
139 return 0;
140 }
141 SSL_FIELD_SET(sig,r)
142 SSL_FIELD_SET(sig,s)
143 return 1;
144 }
145 #elif SSL_API_LT_111
DSA_get0_p(const DSA * d)146 const BIGNUM *DSA_get0_p(const DSA *d)
147 {
148 const BIGNUM *p;
149 const BIGNUM *q;
150 const BIGNUM *g;
151 DSA_get0_pqg(d, &p, &q, &g);
152 return p;
153 }
154 #endif
155
156 /*
157 * Intermediary key
158 */
159
160 struct dnskey_dsa
161 {
162 BIGNUM *p,*q,*g,*pub_key,*priv_key;
163 };
164
165 struct dnskey_dsa_const
166 {
167 const BIGNUM *p,*q,*g,*pub_key,*priv_key;
168 };
169
dnskey_dsa_init(struct dnskey_dsa * ydsa)170 static void dnskey_dsa_init(struct dnskey_dsa *ydsa)
171 {
172 memset(ydsa, 0, sizeof(struct dnskey_dsa));
173 }
174
dnskey_dsa_to_dsa(struct dnskey_dsa * ydsa,DSA * dsa)175 static bool dnskey_dsa_to_dsa(struct dnskey_dsa *ydsa, DSA *dsa)
176 {
177 if(DSA_set0_pqg(dsa, ydsa->p, ydsa->q, ydsa->g) != 0)
178 {
179 ydsa->p = NULL;
180 ydsa->q = NULL;
181 ydsa->g = NULL;
182
183 if(DSA_set0_key(dsa, ydsa->pub_key, ydsa->priv_key) != 0)
184 {
185 ydsa->pub_key = NULL;
186 ydsa->priv_key = NULL;
187 return TRUE;
188 }
189 }
190
191 return FALSE;
192 }
193
dnskey_dsa_from_dsa(struct dnskey_dsa_const * ydsa,const DSA * dsa)194 static void dnskey_dsa_from_dsa(struct dnskey_dsa_const *ydsa, const DSA *dsa)
195 {
196 DSA_get0_pqg(dsa, &ydsa->p, &ydsa->q, &ydsa->g);
197 DSA_get0_key(dsa, &ydsa->pub_key, &ydsa->priv_key);
198 }
199
dnskey_dsa_finalize(struct dnskey_dsa * ydsa)200 static void dnskey_dsa_finalize(struct dnskey_dsa *ydsa)
201 {
202 if(ydsa->p != NULL) BN_free(ydsa->p);
203 if(ydsa->q != NULL) BN_free(ydsa->q);
204 if(ydsa->g != NULL) BN_free(ydsa->g);
205 if(ydsa->pub_key != NULL) BN_free(ydsa->pub_key);
206 if(ydsa->priv_key != NULL) BN_free(ydsa->priv_key);
207 dnskey_dsa_init(ydsa);
208 }
209
210 static const struct dnskey_field_access DSA_field_access[] =
211 {
212 {"Prime(p)", offsetof(struct dnskey_dsa,p), STRUCTDESCRIPTOR_BN},
213 {"Subprime(q)", offsetof(struct dnskey_dsa,q), STRUCTDESCRIPTOR_BN},
214 {"Base(g)", offsetof(struct dnskey_dsa,g), STRUCTDESCRIPTOR_BN},
215 {"Private_value(x)", offsetof(struct dnskey_dsa,priv_key), STRUCTDESCRIPTOR_BN},
216 {"Public_value(y)", offsetof(struct dnskey_dsa,pub_key), STRUCTDESCRIPTOR_BN},
217 {"", 0, 0}
218 };
219
220 static int
dnskey_dsa_getnid(u8 algorithm)221 dnskey_dsa_getnid(u8 algorithm)
222 {
223 switch(algorithm)
224 {
225 case DNSKEY_ALGORITHM_DSASHA1_NSEC3:
226 case DNSKEY_ALGORITHM_DSASHA1:
227 {
228 return NID_sha1;
229 }
230 default:
231 {
232 return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
233 }
234 }
235 }
236
237 static DSA*
dnskey_dsa_genkey(u32 size)238 dnskey_dsa_genkey(u32 size)
239 {
240 yassert(size >= DNSSEC_MINIMUM_KEY_SIZE && size <= DNSSEC_MAXIMUM_KEY_SIZE);
241
242 int err;
243 DSA* dsa;
244
245 #if SSL_API_LT_110
246 dsa = DSA_generate_parameters(size, NULL,0, NULL, NULL, NULL, NULL);
247 #else
248 dsa = DSA_new();
249 DSA_generate_parameters_ex(dsa, size,
250 NULL, 0,
251 NULL, NULL,
252 NULL);
253 #endif
254
255 yassert(dsa != NULL);
256
257 err = DSA_generate_key(dsa); /* no callback */
258
259 if(err == 0)
260 {
261 // error
262
263 DSA_free(dsa);
264 dsa = NULL;
265 }
266
267 return dsa;
268 }
269
270 static ya_result
dnskey_dsa_signdigest(const dnssec_key * key,const u8 * digest,u32 digest_len,u8 * output_)271 dnskey_dsa_signdigest(const dnssec_key *key, const u8 *digest, u32 digest_len, u8 *output_)
272 {
273 u8 *output = output_;
274 DSA_SIG *sig = DSA_do_sign(digest, digest_len, key->key.dsa);
275
276 if(sig != NULL)
277 {
278 const BIGNUM *sig_r;
279 const BIGNUM *sig_s;
280
281 const BIGNUM *p;
282 p = DSA_get0_p(key->key.dsa);
283 DSA_SIG_get0(sig, &sig_r, &sig_s);
284 u32 p_size_bytes = BN_num_bytes(p);
285 u32 t = (p_size_bytes - 64) >> 3;
286
287 *output++ = t;
288 const int bn_size = 20;
289
290 int r_size = BN_num_bytes(sig_r);
291 int r_pad = bn_size - r_size;
292 memset(output, 0, r_pad);
293 BN_bn2bin(sig_r, &output[r_pad]);
294 output += bn_size;
295
296 int s_size = BN_num_bytes(sig_s);
297 int s_pad = bn_size - s_size;
298 memset(output, 0, s_pad);
299 BN_bn2bin(sig_s, &output[s_pad]);
300 // output += bn_size;
301
302 DSA_SIG_free(sig);
303
304 //ya_result output_size = (rn << 1) + 1;
305 ya_result output_size = 20 * 2 + 1;
306
307 #if DEBUG
308 if(!key->vtbl->dnssec_key_verify_digest(key, digest, digest_len, output_, output_size))
309 {
310 log_err("CANNOT VERIFY OWN SIGNATURE!");
311 }
312 #endif
313
314 return output_size;
315 }
316 else
317 {
318 unsigned long ssl_err;
319
320 while((ssl_err = ERR_get_error()) != 0)
321 {
322 char buffer[256];
323 ERR_error_string_n(ssl_err, buffer, sizeof(buffer));
324 log_err("dsa: sign: %{dnsname}/%05d: error %08x %s", key->owner_name, key->tag, ssl_err, buffer);
325 }
326
327 ERR_clear_error();
328
329 return DNSSEC_ERROR_DSASIGNATUREFAILED;
330 }
331 }
332
333 static bool
dnskey_dsa_verifydigest(const dnssec_key * key,const u8 * digest,u32 digest_len,const u8 * signature,u32 signature_len)334 dnskey_dsa_verifydigest(const dnssec_key *key, const u8 *digest, u32 digest_len, const u8 *signature, u32 signature_len)
335 {
336 yassert(signature_len <= DNSSEC_MAXIMUM_KEY_SIZE_BYTES);
337
338 #if DEBUG
339 log_debug6("dsa_verifydigest(K%{dnsname}-%03d-%05d, @%p, @%p)", key->owner_name, key->algorithm, key->tag, digest, signature);
340 log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, digest, digest_len, 32);
341 log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, signature, signature_len, 32);
342 #endif
343
344 if(signature_len != 41)
345 {
346 log_warn("DSA signature expected to be 41 bytes long");
347 }
348
349 if((signature_len & 1) == 0)
350 {
351 log_err("DSA signature size expected to be an odd number");
352
353 return FALSE;
354 }
355
356 u8 t = *signature++;
357
358 if(t != 8)
359 {
360 log_warn("DSA T!=8 (%i)", t);
361 }
362
363 signature_len--;
364 signature_len >>= 1;
365
366 DSA_SIG *sig = DSA_SIG_new();
367
368 BIGNUM *sig_r = BN_bin2bn(signature, signature_len, NULL);
369 signature += signature_len;
370 BIGNUM *sig_s = BN_bin2bn(signature, signature_len, NULL);
371 DSA_SIG_set0(sig, sig_r, sig_s);
372
373 int err = DSA_do_verify(digest, digest_len, sig, key->key.dsa);
374
375 DSA_SIG_free(sig);
376
377 if(err != 1)
378 {
379 unsigned long ssl_err;
380
381 while((ssl_err = ERR_get_error()) != 0)
382 {
383 char buffer[256];
384 ERR_error_string_n(ssl_err, buffer, sizeof(buffer));
385
386 log_debug("dsa: verify: %{dnsname}/%05d: error %08x %s", key->owner_name, key->tag, ssl_err, buffer);
387 }
388
389 ERR_clear_error();
390
391 return FALSE;
392 }
393
394 return TRUE;
395 }
396
397 static DSA*
dnskey_dsa_public_load(const u8 * rdata,u16 rdata_size)398 dnskey_dsa_public_load(const u8* rdata, u16 rdata_size)
399 {
400 if(rdata == NULL)
401 {
402 return NULL;
403 }
404
405 const u8 *inptr = rdata;
406 u32 t;
407 t = *inptr;
408
409 u32 pgy_len = 64 + (t << 3);
410
411 if(rdata_size != 1 + 20 + 3 * pgy_len)
412 {
413 return NULL;
414 }
415
416 inptr++;
417
418 BIGNUM* dsa_q;
419 BIGNUM* dsa_p;
420 BIGNUM* dsa_g;
421 BIGNUM* dsa_pub_key;
422
423 dsa_q = BN_bin2bn(inptr, 20, NULL);
424 if(dsa_q == NULL)
425 {
426 log_err("dsa_public_load: NULL q");
427
428 return NULL;
429 }
430 inptr += 20;
431 dsa_p = BN_bin2bn(inptr, pgy_len, NULL);
432 if(dsa_p == NULL)
433 {
434 log_err("dsa_public_load: NULL p");
435 BN_free(dsa_q);
436
437 return NULL;
438 }
439 inptr += pgy_len;
440 dsa_g = BN_bin2bn(inptr, pgy_len, NULL);
441 if(dsa_g == NULL)
442 {
443 log_err("dsa_public_load: NULL g");
444 BN_free(dsa_q);
445 BN_free(dsa_p);
446
447 return NULL;
448 }
449 inptr += pgy_len;
450 dsa_pub_key = BN_bin2bn(inptr, pgy_len, NULL);
451 if(dsa_pub_key == NULL)
452 {
453 log_err("dsa_public_load: NULL y");
454 BN_free(dsa_q);
455 BN_free(dsa_p);
456 BN_free(dsa_g);
457
458 return NULL;
459 }
460
461 DSA* dsa;
462 dsa = DSA_new();
463
464 yassert(dsa != NULL);
465
466 DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g);
467 DSA_set0_key(dsa, dsa_pub_key, NULL);
468
469 return dsa;
470 }
471
472 static u32
dnskey_dsa_public_store(DSA * dsa,u8 * output_buffer,u32 output_buffer_size)473 dnskey_dsa_public_store(DSA* dsa, u8* output_buffer, u32 output_buffer_size)
474 {
475 unsigned char* outptr = output_buffer;
476
477 const BIGNUM* q = NULL;
478 const BIGNUM* p = NULL;
479 const BIGNUM* g = NULL;
480 const BIGNUM* y = NULL;
481
482 DSA_get0_pqg(dsa, &p, &q, &g);
483 DSA_get0_key(dsa, &y, NULL);
484
485 u32 q_n = BN_num_bytes(q);
486
487 if(q_n != 20)
488 {
489 return 0;
490 }
491
492 s32 p_n = BN_num_bytes(p);
493 s32 g_n = BN_num_bytes(g);
494 s32 y_n = BN_num_bytes(y);
495
496 if((abs(p_n - g_n) > 2) || (abs(p_n - y_n) > 2)) /* sometimes, there is one byte difference in storage */
497 {
498 log_err("dnskey_dsa_public_store: DSA key size discrepancy");
499 return 0;
500 }
501
502 s32 t = p_n;
503 t -= 64;
504
505 if(t < 0)
506 {
507 return 0;
508 }
509
510 if((t & 7) != 0)
511 {
512 return 0;
513 }
514
515 t >>= 3;
516
517 if(t + q_n + p_n + g_n + y_n > output_buffer_size)
518 {
519 return 0; // BUFFER_WOULD_OVERFLOW;
520 }
521
522 *outptr++ = t;
523
524 BN_bn2bin(q, outptr);
525 outptr += q_n;
526
527 BN_bn2bin(p, outptr);
528 outptr += p_n;
529
530 BN_bn2bin(g, outptr);
531 outptr += g_n;
532
533 BN_bn2bin(y, outptr);
534 outptr += y_n;
535
536 return outptr - output_buffer;
537 }
538
539 static u32
dnskey_dsa_dnskey_public_store(const dnssec_key * key,u8 * rdata,size_t rdata_size)540 dnskey_dsa_dnskey_public_store(const dnssec_key* key, u8 *rdata, size_t rdata_size)
541 {
542 u32 len;
543
544 SET_U16_AT(rdata[0], key->flags);
545 rdata[2] = DNSKEY_PROTOCOL_FIELD;
546 rdata[3] = key->algorithm;
547
548 len = dnskey_dsa_public_store(key->key.dsa, &rdata[4], rdata_size - 4) + 4;
549
550 return len;
551 }
552
553 static u32
dnskey_dsa_size(const dnssec_key * key)554 dnskey_dsa_size(const dnssec_key* key)
555 {
556 const BIGNUM* y;
557
558 DSA_get0_key(key->key.dsa, &y, NULL);
559
560 u32 y_n = BN_num_bytes(y);
561
562 return y_n << 3;
563 }
564
565 static u32
dnskey_dsa_public_size(const DSA * dsa)566 dnskey_dsa_public_size(const DSA* dsa)
567 {
568 const BIGNUM* p;
569 const BIGNUM* q;
570 const BIGNUM* g;
571 const BIGNUM* y;
572
573 DSA_get0_pqg(dsa, &p, &q, &g);
574 DSA_get0_key(dsa, &y, NULL);
575
576 u32 p_n = BN_num_bytes(p);
577 u32 q_n = BN_num_bytes(q);
578 u32 g_n = BN_num_bytes(g);
579 u32 y_n = BN_num_bytes(y);
580
581 return 1 + p_n + q_n + g_n + y_n;
582 }
583
584 static u32
dnskey_dsa_dnskey_rdatasize(const dnssec_key * key)585 dnskey_dsa_dnskey_rdatasize(const dnssec_key* key)
586 {
587 return dnskey_dsa_public_size(key->key.dsa) + 4;
588 }
589
590 static void
dnskey_dsa_free(dnssec_key * key)591 dnskey_dsa_free(dnssec_key* key)
592 {
593 DSA* dsa = key->key.dsa;
594 DSA_free(dsa);
595
596 key->key.dsa = NULL;
597 }
598
599 static bool
dnskey_dsa_equals(const dnssec_key * key_a,const dnssec_key * key_b)600 dnskey_dsa_equals(const dnssec_key* key_a, const dnssec_key* key_b)
601 {
602 /* DSA, compare modulus and exponent, exponent first (it's the smallest) */
603
604 if(key_a == key_b)
605 {
606 return TRUE;
607 }
608
609 if(dnssec_key_tag_field_set(key_a) && dnssec_key_tag_field_set(key_b))
610 {
611 if(key_a->tag != key_b->tag)
612 {
613 return FALSE;
614 }
615 }
616
617 if((key_a->flags == key_b->flags) && (key_a->algorithm == key_b->algorithm))
618 {
619 if(strcmp(key_a->origin, key_b->origin) == 0)
620 {
621 const DSA* a_dsa = key_a->key.dsa;
622 const DSA* b_dsa = key_b->key.dsa;
623
624 const BIGNUM* a_dsa_q;
625 const BIGNUM* a_dsa_p;
626 const BIGNUM* a_dsa_g;
627 const BIGNUM* b_dsa_q;
628 const BIGNUM* b_dsa_p;
629 const BIGNUM* b_dsa_g;
630
631 DSA_get0_pqg(a_dsa, &a_dsa_p, &a_dsa_q, &a_dsa_g);
632 DSA_get0_pqg(b_dsa, &b_dsa_p, &b_dsa_q, &b_dsa_g);
633
634 if(BN_cmp(a_dsa_q, b_dsa_q) == 0)
635 {
636 if(BN_cmp(a_dsa_p, b_dsa_p) == 0)
637 {
638 if(BN_cmp(a_dsa_g, b_dsa_g) == 0)
639 {
640 const BIGNUM* a_dsa_pub_key;
641 const BIGNUM* a_dsa_priv_key;
642 const BIGNUM* b_dsa_pub_key;
643 const BIGNUM* b_dsa_priv_key;
644
645 DSA_get0_key(a_dsa, &a_dsa_pub_key, &a_dsa_priv_key);
646 DSA_get0_key(b_dsa, &b_dsa_pub_key, &b_dsa_priv_key);
647
648 if(BN_cmp(a_dsa_pub_key, b_dsa_pub_key) == 0)
649 {
650 if(a_dsa_priv_key != NULL)
651 {
652 if(b_dsa_priv_key != NULL)
653 {
654 return BN_cmp(a_dsa_priv_key, b_dsa_priv_key) == 0;
655 }
656 }
657 else
658 {
659 return b_dsa_priv_key == NULL;
660 }
661 }
662 }
663 }
664 }
665 }
666 }
667
668 return FALSE;
669 }
670
671 static ya_result
dnskey_dsa_private_print_fields(dnssec_key * key,output_stream * os)672 dnskey_dsa_private_print_fields(dnssec_key *key, output_stream *os)
673 {
674 struct dnskey_dsa_const ydsa;
675 dnskey_dsa_from_dsa(&ydsa, key->key.dsa);
676
677 ya_result ret = dnskey_field_access_print(DSA_field_access, &ydsa, os);
678
679 return ret;
680 }
681
682 static const dnssec_key_vtbl dsa_vtbl =
683 {
684 dnskey_dsa_signdigest,
685 dnskey_dsa_verifydigest,
686 dnskey_dsa_dnskey_rdatasize,
687 dnskey_dsa_dnskey_public_store,
688 dnskey_dsa_free,
689 dnskey_dsa_equals,
690 dnskey_dsa_private_print_fields,
691 dnskey_dsa_size,
692 "DSA"
693 };
694
695 static ya_result
dnskey_dsa_initinstance(DSA * dsa,u8 algorithm,u16 flags,const char * origin,dnssec_key ** out_key)696 dnskey_dsa_initinstance(DSA* dsa, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key)
697 {
698 int nid;
699
700 u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES]; /* 4096 bits -> 1KB */
701
702 *out_key = NULL;
703
704 if(FAIL(nid = dnskey_dsa_getnid(algorithm)))
705 {
706 return nid;
707 }
708
709 #if DEBUG
710 memset(rdata, 0xff, sizeof(rdata));
711 #endif
712
713 u32 rdata_size = dnskey_dsa_public_size(dsa);
714
715 if(rdata_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES)
716 {
717 return DNSSEC_ERROR_KEYISTOOBIG;
718 }
719
720 SET_U16_AT(rdata[0], flags); // NATIVEFLAGS
721 rdata[2] = DNSKEY_PROTOCOL_FIELD;
722 rdata[3] = algorithm;
723
724 u32 stored_rdata_size = dnskey_dsa_public_store(dsa, &rdata[4], sizeof(rdata) - 4);
725
726 if(stored_rdata_size != rdata_size)
727 {
728 return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */
729 }
730
731 /* Note : + 4 because of the flags,protocol & algorithm bytes
732 * are not taken in account
733 */
734
735 u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_size + 4);
736
737 dnssec_key* key = dnskey_newemptyinstance(algorithm, flags, origin); // RC
738
739 if(key == NULL)
740 {
741 return INVALID_ARGUMENT_ERROR;
742 }
743
744 key->key.dsa = dsa;
745 key->vtbl = &dsa_vtbl;
746 key->tag = tag;
747 key->nid = nid;
748
749 const BIGNUM *dsa_priv_key = NULL;
750 DSA_get0_key(dsa, NULL, &dsa_priv_key);
751
752 if(dsa_priv_key != NULL)
753 {
754 key->status |= DNSKEY_KEY_IS_PRIVATE;
755 }
756
757 *out_key = key;
758
759 return SUCCESS;
760 }
761
762 static ya_result
dnskey_dsa_parse_field(struct dnskey_field_parser * parser,parser_s * p)763 dnskey_dsa_parse_field(struct dnskey_field_parser *parser, parser_s *p)
764 {
765 struct dnskey_dsa *ydsa = (struct dnskey_dsa*)parser->data;
766
767 ya_result ret = dnskey_field_access_parse(DSA_field_access, ydsa, p);
768
769 return ret;
770 }
771
772 static ya_result
dnskey_dsa_parse_set_key(struct dnskey_field_parser * parser,dnssec_key * key)773 dnskey_dsa_parse_set_key(struct dnskey_field_parser *parser, dnssec_key *key)
774 {
775 struct dnskey_dsa *ydsa = (struct dnskey_dsa*)parser->data;
776
777 if(key == NULL)
778 {
779 return UNEXPECTED_NULL_ARGUMENT_ERROR;
780 }
781 switch(key->algorithm)
782 {
783 case DNSKEY_ALGORITHM_DSASHA1_NSEC3:
784 case DNSKEY_ALGORITHM_DSASHA1:
785 break;
786 default:
787 return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
788 }
789
790 if((ydsa->p == NULL) ||
791 (ydsa->q == NULL) ||
792 (ydsa->g == NULL) ||
793 (ydsa->pub_key == NULL))
794 {
795 return DNSSEC_ERROR_INCOMPLETEKEY;
796 }
797
798 int nid;
799
800 if(FAIL(nid = dnskey_dsa_getnid(key->algorithm)))
801 {
802 return nid;
803 }
804
805 bool has_private = ydsa->priv_key != NULL;
806
807 if(key->key.dsa == NULL)
808 {
809 key->key.dsa = DSA_new();
810 key->vtbl = &dsa_vtbl;
811 }
812
813 if(dnskey_dsa_to_dsa(ydsa, key->key.dsa))
814 {
815 // at this point, ydsa has been emptied
816
817 DSA *dsa = key->key.dsa;
818
819 u32 rdata_size = dnskey_dsa_public_size(dsa);
820
821 u16 tag;
822
823 u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES];
824
825 if(rdata_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES)
826 {
827 return DNSSEC_ERROR_KEYISTOOBIG;
828 }
829
830 SET_U16_AT(rdata[0], key->flags);
831 rdata[2] = DNSKEY_PROTOCOL_FIELD;
832 rdata[3] = key->algorithm;
833
834 if(dnskey_dsa_public_store(dsa, &rdata[4], sizeof(rdata) - 4) != rdata_size)
835 {
836 return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */
837 }
838
839 /* Note : + 4 because of the flags,protocol & algorithm bytes
840 * are not taken in account
841 */
842
843 tag = dnskey_get_tag_from_rdata(rdata, rdata_size + 4);
844
845 key->tag = tag;
846 key->nid = nid;
847
848 key->status |= DNSKEY_KEY_IS_VALID;
849
850 if(has_private)
851 {
852 key->status |= DNSKEY_KEY_IS_PRIVATE;
853 }
854
855 return SUCCESS;
856 }
857 else
858 {
859 return DNSSEC_ERROR_INCOMPLETEKEY;
860 }
861 }
862
863 static void
dnskey_dsa_parse_finalize(struct dnskey_field_parser * parser)864 dnskey_dsa_parse_finalize(struct dnskey_field_parser *parser)
865 {
866 struct dnskey_dsa *ydsa = (struct dnskey_dsa*)parser->data;
867
868 if(ydsa != NULL)
869 {
870 dnskey_dsa_finalize(ydsa);
871 ZFREE(ydsa, struct dnskey_dsa);
872 }
873 }
874
875 static const struct dnskey_field_parser_vtbl dsa_field_parser_vtbl =
876 {
877 dnskey_dsa_parse_field,
878 dnskey_dsa_parse_set_key,
879 dnskey_dsa_parse_finalize,
880 "DSA"
881 };
882
883 void
dnskey_dsa_parse_init(dnskey_field_parser * fp)884 dnskey_dsa_parse_init(dnskey_field_parser *fp)
885 {
886 struct dnskey_dsa *ydsa;
887 ZALLOC_OBJECT_OR_DIE(ydsa, struct dnskey_dsa, KEYDSA_TAG);
888 ZEROMEMORY(ydsa, sizeof(struct dnskey_dsa));
889 fp->data = ydsa;
890 fp->vtbl = &dsa_field_parser_vtbl;
891 }
892
893 ya_result
dnskey_dsa_loadpublic(const u8 * rdata,u16 rdata_size,const char * origin,dnssec_key ** out_key)894 dnskey_dsa_loadpublic(const u8 *rdata, u16 rdata_size, const char *origin, dnssec_key** out_key)
895 {
896 *out_key = NULL;
897
898 if(rdata == NULL || rdata_size <= 6 || origin == NULL)
899 {
900 /* bad */
901
902 return UNEXPECTED_NULL_ARGUMENT_ERROR;
903 }
904
905 u16 flags = GET_U16_AT(rdata[0]);
906 u8 algorithm = rdata[3];
907
908 if((algorithm != DNSKEY_ALGORITHM_DSASHA1_NSEC3) && (algorithm != DNSKEY_ALGORITHM_DSASHA1))
909 {
910 return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
911 }
912
913 rdata += 4;
914 rdata_size -= 4;
915
916 ya_result return_value = DNSSEC_ERROR_CANNOT_READ_KEY_FROM_RDATA;
917
918 DSA *dsa = dnskey_dsa_public_load(rdata, rdata_size);
919
920 if(dsa != NULL)
921 {
922 dnssec_key *key;
923
924 if(ISOK(return_value = dnskey_dsa_initinstance(dsa, algorithm, flags, origin, &key)))
925 {
926 *out_key = key;
927
928 return return_value;
929 }
930
931 DSA_free(dsa);
932 }
933
934 return return_value;
935 }
936
937 ya_result
dnskey_dsa_newinstance(u32 size,u8 algorithm,u16 flags,const char * origin,dnssec_key ** out_key)938 dnskey_dsa_newinstance(u32 size, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key)
939 {
940 *out_key = NULL;
941
942 if(size > DNSSEC_MAXIMUM_KEY_SIZE)
943 {
944 return DNSSEC_ERROR_KEYISTOOBIG;
945 }
946
947 if((algorithm != DNSKEY_ALGORITHM_DSASHA1_NSEC3) && (algorithm != DNSKEY_ALGORITHM_DSASHA1))
948 {
949 return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
950 }
951
952 ya_result return_value = DNSSEC_ERROR_KEY_GENERATION_FAILED;
953
954 DSA *dsa = dnskey_dsa_genkey(size);
955
956 if(dsa != NULL)
957 {
958 dnssec_key *key;
959
960 if(ISOK(return_value = dnskey_dsa_initinstance(dsa, algorithm, flags, origin, &key)))
961 {
962 *out_key = key;
963
964 return return_value;
965 }
966
967 DSA_free(dsa);
968 }
969
970 return return_value;
971 }
972
973 /** @} */
974
975