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