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 /**
36 * @defgroup dnskey DNSSEC keys functions
37 * @ingroup dnsdbdnssec
38 * @addtogroup dnskey DNSKEY functions
39 * @brief
40 *
41 *
42 * @{
43 */
44 /*------------------------------------------------------------------------------
45 *
46 * USE INCLUDES */
47 #include "dnscore/dnscore-config.h"
48
49 #define DNSCORE_DNSKEY_C 1
50
51 #include <arpa/inet.h>
52 #include <ctype.h>
53 #include <sys/stat.h>
54 #include <dnscore/dns_resource_record.h>
55 #include "dnscore/openssl.h"
56 #include "dnscore/dnsname.h"
57 #include "dnscore/dnskey.h"
58 #include "dnscore/dnskey_rsa.h"
59 #include "dnscore/dnskey_dsa.h"
60 #if HAS_ECDSA_SUPPORT
61 #include "dnscore/dnskey_ecdsa.h"
62 #endif
63 #if HAS_EDDSA_SUPPORT
64 #include "dnscore/dnskey_eddsa.h"
65 #endif
66 #ifdef DNSKEY_ALGORITHM_DUMMY
67 #include "dnscore/dnskey_dummy.h"
68 #endif
69 #include "dnscore/digest.h"
70 #include "dnscore/base64.h"
71 #include "dnscore/string_set.h"
72 #include "dnscore/file_input_stream.h"
73 #include "dnscore/file_output_stream.h"
74 #include "dnscore/buffer_output_stream.h"
75 #include "dnscore/parser.h"
76 #include "dnscore/zalloc.h"
77 #include "dnscore/logger.h"
78 #include "dnscore/fdtools.h"
79 #include "dnscore/mutex.h"
80 #include "dnscore/timeformat.h"
81
82 extern logger_handle* g_system_logger;
83 #define MODULE_MSG_HANDLE g_system_logger
84
85 #define ZDB_DNSKEY_TAG 0x59454b534e44
86 #define ZDB_DNSKEY_NAME_TAG 0x454d414e59454b
87
88 #define ORIGNDUP_TAG 0x5055444e4749524f
89 #define DNSKRAWB_TAG 0x425741524b534e44
90
91 // dumps key acquisition/release
92 #define DUMP_ACQUIRE_RELEASE_STACK_TRACE 0
93
94 static string_set dnssec_key_load_private_keywords_set = STRING_SET_EMPTY;
95
96 #define DNSKEY_FIELD_ALGORITHM 1
97 #define DNSKEY_FIELD_FORMAT 2
98 #define DNSKEY_FIELD_CREATED 3
99 #define DNSKEY_FIELD_PUBLISH 4
100 #define DNSKEY_FIELD_ACTIVATE 5
101
102 #define DNSKEY_FIELD_INACTIVE 7
103 #define DNSKEY_FIELD_DELETE 8
104 #define DNSKEY_FIELD_ENGINE 9
105
106 static value_name_table dnssec_key_load_private_keywords_common_names[] =
107 {
108 {DNSKEY_FIELD_ALGORITHM, "Algorithm"},
109 {DNSKEY_FIELD_FORMAT, "Private-key-format"},
110 {DNSKEY_FIELD_CREATED, "Created"},
111 {DNSKEY_FIELD_PUBLISH, "Publish"},
112 {DNSKEY_FIELD_ACTIVATE, "Activate"},
113
114 {DNSKEY_FIELD_INACTIVE, "Inactive"},
115 {DNSKEY_FIELD_DELETE, "Delete"},
116 {DNSKEY_FIELD_ENGINE, "Engine"},
117 {0, NULL}
118 };
119
120 static group_mutex_t dnskey_rc_mtx = GROUP_MUTEX_INITIALIZER;
121
122 static const char *rsamd5_names[] = {DNSKEY_ALGORITHM_RSAMD5_NAME,"1", NULL};
123 static const char *dsasha1_names[] = {DNSKEY_ALGORITHM_DSASHA1_NAME,"3", NULL};
124 static const char *rsasha1_names[] = {DNSKEY_ALGORITHM_RSASHA1_NAME,"5", NULL};
125 static const char *dsasha1nsec3_names[] = {DNSKEY_ALGORITHM_DSASHA1_NSEC3_NAME,"6", NULL};
126 static const char *rsasha1nsec3_names[] = {DNSKEY_ALGORITHM_RSASHA1_NSEC3_NAME,"7", NULL};
127 static const char *rsasha256_names[] = {DNSKEY_ALGORITHM_RSASHA256_NSEC3_NAME,"8", NULL};
128 static const char *rsasha512_names[] = {DNSKEY_ALGORITHM_RSASHA512_NSEC3_NAME,"10", NULL};
129 #if HAS_ECDSA_SUPPORT
130 static const char *ecdsap256sha256_names[] = {DNSKEY_ALGORITHM_ECDSAP256SHA256_NAME,"13", NULL};
131 static const char *ecdsap384sha384_names[] = {DNSKEY_ALGORITHM_ECDSAP384SHA384_NAME,"14", NULL};
132 #endif
133 #if HAS_EDDSA_SUPPORT
134 static const char *ed25619_names[] = { DNSKEY_ALGORITHM_ED25519_NAME, "15", NULL};
135 static const char *ed448_names[] = { DNSKEY_ALGORITHM_ED448_NAME, "16", NULL};
136 #endif
137 #ifdef DNSKEY_ALGORITHM_DUMMY
138 static const char *dnskey_dummy_names[] = {DNSKEY_ALGORITHM_DUMMY_NAME,"254", NULL};
139 #endif
140 //static const char *empty_names[] = {NULL};
141
142 static const struct dnskey_features dnskey_supported_algorithms[] =
143 {
144 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 0
145 {
146 rsamd5_names,
147 512,4096,
148 2048,
149 1024,
150 1,
151 DNSKEY_ALGORITHM_RSAMD5,
152 DNSKEY_FEATURE_ZONE_NSEC
153 },
154 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 2
155 {
156 dsasha1_names,
157 512,1024,
158 1024,
159 1024,
160 64,
161 DNSKEY_ALGORITHM_DSASHA1,
162 DNSKEY_FEATURE_ZONE_NSEC
163 },
164 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 4
165 {
166 rsasha1_names,
167 512,4096,
168 2048,
169 1024,
170 1,
171 DNSKEY_ALGORITHM_RSASHA1,
172 DNSKEY_FEATURE_ZONE_NSEC
173 },
174 {
175 dsasha1nsec3_names,
176 512,1024,
177 1024,
178 1024,
179 64,
180 DNSKEY_ALGORITHM_DSASHA1_NSEC3,
181 DNSKEY_FEATURE_ZONE_NSEC3
182 },
183 {
184 rsasha1nsec3_names,
185 512,4096,
186 2048,
187 1024,
188 1,
189 DNSKEY_ALGORITHM_RSASHA1_NSEC3,
190 DNSKEY_FEATURE_ZONE_NSEC3
191 },
192 {
193 rsasha256_names,
194 512,4096,
195 2048,
196 1024,
197 1,
198 DNSKEY_ALGORITHM_RSASHA256_NSEC3,
199 DNSKEY_FEATURE_ZONE_MODERN
200 },
201 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 9
202 {
203 rsasha512_names,
204 1024,4096,
205 2048,
206 1024,
207 1,
208 DNSKEY_ALGORITHM_RSASHA512_NSEC3,
209 DNSKEY_FEATURE_ZONE_MODERN
210 },
211 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 11
212 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 12
213 #if HAS_ECDSA_SUPPORT
214 {
215 ecdsap256sha256_names,
216 256,256,
217 256,
218 256,
219 1,
220 DNSKEY_ALGORITHM_ECDSAP256SHA256,
221 DNSKEY_FEATURE_ZONE_MODERN
222 },
223 {
224 ecdsap384sha384_names,
225 384,384,
226 384,
227 384,
228 1,
229 DNSKEY_ALGORITHM_ECDSAP384SHA384,
230 DNSKEY_FEATURE_ZONE_MODERN
231 },
232 #else
233 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 13
234 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 14
235 #endif
236 #if HAS_EDDSA_SUPPORT
237 {
238 ed25619_names,
239 0,0,
240 0,
241 0,
242 1,
243 DNSKEY_ALGORITHM_ED25519,
244 DNSKEY_FEATURE_ZONE_MODERN
245 },
246 {
247 ed448_names,
248 0,0,
249 0,
250 0,
251 1,
252 DNSKEY_ALGORITHM_ED448,
253 DNSKEY_FEATURE_ZONE_MODERN
254 },
255 #else
256 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 15
257 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 16
258 #endif
259 #ifdef DNSKEY_ALGORITHM_DUMMY
260 {
261 dnskey_dummy_names,
262 16,16,
263 16,
264 16,
265 16,
266 DNSKEY_ALGORITHM_DUMMY,
267 DNSKEY_FEATURE_ZONE_MODERN
268 },
269 #endif
270 /*
271 { // terminator
272 empty_names,
273 0,0,
274 0,
275 0,
276 0,
277 0
278 }*/
279 };
280
281 static const char *
dnskey_get_algorithm_name_from_value(int alg)282 dnskey_get_algorithm_name_from_value(int alg)
283 {
284 switch(alg)
285 {
286 case DNSKEY_ALGORITHM_RSAMD5:
287 return "RSAMD5";
288 case DNSKEY_ALGORITHM_DIFFIE_HELLMAN:
289 return "DH";
290 case DNSKEY_ALGORITHM_DSASHA1:
291 return "DSASHA1";
292 case DNSKEY_ALGORITHM_RSASHA1:
293 return "RSASHA1";
294 case DNSKEY_ALGORITHM_DSASHA1_NSEC3:
295 return "NSEC3DSA";
296 case DNSKEY_ALGORITHM_RSASHA1_NSEC3:
297 return "NSEC3RSASHA1";
298 case DNSKEY_ALGORITHM_RSASHA256_NSEC3:
299 return "RSASHA256";
300 case DNSKEY_ALGORITHM_RSASHA512_NSEC3:
301 return "RSASHA512";
302 case DNSKEY_ALGORITHM_GOST:
303 return "ECCGOST";
304 case DNSKEY_ALGORITHM_ECDSAP256SHA256:
305 return "ECDSAP256SHA256";
306 case DNSKEY_ALGORITHM_ECDSAP384SHA384:
307 return "ECDSAP384SHA384";
308 case DNSKEY_ALGORITHM_ED25519:
309 return "ED25519";
310 case DNSKEY_ALGORITHM_ED448:
311 return "ED448";
312 #ifdef DNSKEY_ALGORITHM_DUMMY
313 case DNSKEY_ALGORITHM_DUMMY:
314 return "DUMMY";
315 #endif
316 default:
317 return "?";
318 }
319 }
320
321 static ya_result
dnskey_field_parser_dummy_parse_field(struct dnskey_field_parser * parser,struct parser_s * p)322 dnskey_field_parser_dummy_parse_field(struct dnskey_field_parser *parser, struct parser_s *p)
323 {
324 (void)parser;
325 (void)p;
326 return FEATURE_NOT_IMPLEMENTED_ERROR;
327 }
328
329 static ya_result
dnskey_field_parser_dummy_set_key(struct dnskey_field_parser * parser,dnssec_key * key)330 dnskey_field_parser_dummy_set_key(struct dnskey_field_parser *parser, dnssec_key *key)
331 {
332 (void)parser;
333 (void)key;
334 return FEATURE_NOT_IMPLEMENTED_ERROR;
335 }
336
337 static void
dnskey_field_parser_dummy_finalize_method(struct dnskey_field_parser * parser)338 dnskey_field_parser_dummy_finalize_method(struct dnskey_field_parser *parser)
339 {
340 (void)parser;
341 }
342
343 struct dnskey_field_parser_vtbl dnskey_field_dummy_parser =
344 {
345 dnskey_field_parser_dummy_parse_field,
346 dnskey_field_parser_dummy_set_key,
347 dnskey_field_parser_dummy_finalize_method,
348 "DUMMY"
349 };
350
351 ya_result
dnskey_field_access_parse(const struct dnskey_field_access * sd,void * base,parser_s * p)352 dnskey_field_access_parse(const struct dnskey_field_access *sd, void *base, parser_s *p)
353 {
354 ya_result ret = INVALID_STATE_ERROR;
355
356 u32 label_len = parser_text_length(p);
357 const char *label = parser_text(p);
358 bool parsed_it = FALSE;
359 u8 tmp_out[DNSSEC_MAXIMUM_KEY_SIZE_BYTES];
360
361 for(; sd->type != STRUCTDESCRIPTOR_NONE; sd++)
362 {
363 switch(sd->type)
364 {
365 case STRUCTDESCRIPTOR_BN:
366 {
367 if(memcmp(label, sd->name, label_len) == 0)
368 {
369 BIGNUM **bnp = (BIGNUM**)(((u8*)base) + sd->relative);
370
371 ret = parser_next_word(p);
372
373 if((*bnp != NULL) || FAIL(ret))
374 {
375 return ret;
376 }
377
378 u32 word_len = parser_text_length(p);
379 const char *word = parser_text(p);
380
381 ya_result n = base64_decode(word, word_len, tmp_out);
382
383 if(FAIL(n))
384 {
385 log_err("dnskey: unable to decode field %s", sd->name);
386 return n;
387 }
388
389 *bnp = BN_bin2bn(tmp_out, n, NULL);
390
391 if(*bnp == NULL)
392 {
393 log_err("dnskey: unable to get big number from field %s", sd->name);
394 return DNSSEC_ERROR_BNISNULL;
395 }
396
397 parsed_it = TRUE;
398
399 goto dnskey_field_access_parse_loop_exit;
400 }
401
402 break;
403 }
404 case STRUCTDESCRIPTOR_RAW:
405 {
406 if(memcmp(label, sd->name, label_len) == 0)
407 {
408 dnskey_raw_field_t *raw = (dnskey_raw_field_t*)(((u8*)base) + sd->relative);
409
410 ret = parser_next_word(p);
411
412 if((raw->buffer != NULL) || FAIL(ret))
413 {
414 return ret;
415 }
416
417 u32 word_len = parser_text_length(p);
418 const char *word = parser_text(p);
419
420 ya_result n = base64_decode(word, word_len, tmp_out);
421
422 if(FAIL(n))
423 {
424 log_err("dnskey: unable to decode field %s", sd->name);
425 return n;
426 }
427
428 ZALLOC_OBJECT_ARRAY_OR_DIE(raw->buffer, u8, n, DNSKRAWB_TAG);
429 memcpy(raw->buffer, tmp_out, n);
430 raw->size = n;
431
432 parsed_it = TRUE;
433
434 goto dnskey_field_access_parse_loop_exit;
435 }
436 break;
437 }
438 }
439 } /* for each possible field */
440 dnskey_field_access_parse_loop_exit:
441 if(!parsed_it)
442 {
443 return SUCCESS; // unknown keyword (ignore)
444 }
445
446 return ret;
447 }
448
449 ya_result
dnskey_field_access_print(const struct dnskey_field_access * sd,const void * base,output_stream * os)450 dnskey_field_access_print(const struct dnskey_field_access *sd, const void *base, output_stream *os)
451 {
452 ya_result ret = SUCCESS;
453
454 for(; sd->type != STRUCTDESCRIPTOR_NONE; sd++)
455 {
456 switch(sd->type)
457 {
458 case STRUCTDESCRIPTOR_BN:
459 {
460 const u8 *bn_ptr_ptr = (((const u8*)base) + sd->relative);
461 const BIGNUM **bn = (const BIGNUM**)bn_ptr_ptr;
462
463 if(bn != NULL)
464 {
465 osformat(os, "%s: ", sd->name);
466 dnskey_write_bignum_as_base64_to_stream(*bn, os);
467 osprintln(os, "");
468 }
469 break;
470 }
471 case STRUCTDESCRIPTOR_RAW:
472 {
473 const u8 *bn_ptr_ptr = (((const u8*)base) + sd->relative);
474 const dnskey_raw_field_t *raw = (const dnskey_raw_field_t *)bn_ptr_ptr;
475
476 osformat(os, "%s: ", sd->name);
477
478 char buffer[1024];
479 u32 encoded_size = BASE64_ENCODED_SIZE(raw->size);
480 if(encoded_size > sizeof(buffer))
481 {
482 return BUFFER_WOULD_OVERFLOW;
483 }
484 u32 n = base64_encode(raw->buffer, raw->size, buffer);
485 output_stream_write(os, buffer, n);
486 osprintln(os, "");
487 break;
488 }
489 case STRUCTDESCRIPTOR_U16:
490 {
491 const u8 *bn_ptr_ptr = (((const u8*)base) + sd->relative);
492 const u16 *valuep = (const u16 *)bn_ptr_ptr;
493 osformat(os, "%s: %hu", sd->name, *valuep);
494 break;
495 }
496 }
497 }
498
499 return ret;
500 }
501
502 /*
503
504 unsigned long ac; * assumed to be 32 bits or larger *
505 int i; * loop index *
506
507 for ( ac = 0, i = 0; i < keysize; ++i )
508 ac += (i & 1) ? key[i] : key[i] << 8;
509 ac += (ac >> 16) & 0xFFFF;
510 return ac & 0xFFFF;
511
512 =>
513
514 s=0;
515 s+=key[0]
516 s+=key[1]<<8
517 s+=key[2]
518 s+=key[3]<<8
519
520 Basically it's a sum of little-endian unsigned 16 bits words
521 And the reference implementation does not match the definition.
522
523 "ignoring any carry bits" Yes ? So this is wrong : ac += (i & 1) ? key[i] : key[i] << 8;
524 The least significant byte will have the add carry bit carried to the most signiticant byte.
525
526 */
527
528 /**
529 * Generates a key tag from the DNSKEY RDATA wire
530 *
531 * @param dnskey_rdata
532 * @param dnskey_rdata_size
533 * @return
534 */
535
536 u16
dnskey_get_tag_from_rdata(const u8 * dnskey_rdata,u32 dnskey_rdata_size)537 dnskey_get_tag_from_rdata(const u8* dnskey_rdata, u32 dnskey_rdata_size)
538 {
539 u32 sum = 0;
540 u32 sumh = 0;
541 while(dnskey_rdata_size > 1)
542 {
543 sumh += *dnskey_rdata++;
544 sum += *dnskey_rdata++;
545 dnskey_rdata_size -= 2;
546 }
547 if(dnskey_rdata_size != 0)
548 {
549 sumh += *dnskey_rdata++;
550 }
551 sum += sumh << 8;
552 sum += sum >> 16;
553
554 return (u16)sum;
555 }
556
557
558
559 /**
560 * Initialises the context for a key algorithm.
561 *
562 * @param ctx
563 * @param algorithm
564 * @return
565 */
566
567 ya_result
dnskey_digest_init(digest_s * ctx,u8 algorithm)568 dnskey_digest_init(digest_s *ctx, u8 algorithm)
569 {
570 switch(algorithm)
571 {
572 case DNSKEY_ALGORITHM_DSASHA1:
573 case DNSKEY_ALGORITHM_RSASHA1:
574 case DNSKEY_ALGORITHM_DSASHA1_NSEC3:
575 case DNSKEY_ALGORITHM_RSASHA1_NSEC3:
576 digest_sha1_init(ctx);
577 break;
578 case DNSKEY_ALGORITHM_RSASHA256_NSEC3:
579 case DNSKEY_ALGORITHM_ECDSAP256SHA256:
580 digest_sha256_init(ctx);
581 break;
582 case DNSKEY_ALGORITHM_ECDSAP384SHA384:
583 digest_sha384_init(ctx);
584 break;
585 case DNSKEY_ALGORITHM_RSASHA512_NSEC3:
586 digest_sha512_init(ctx);
587 break;
588 #if HAS_EDDSA_SUPPORT
589 case DNSKEY_ALGORITHM_ED25519:
590 case DNSKEY_ALGORITHM_ED448:
591 digest_rawdata_init(ctx);
592 break;
593 #endif
594 #ifdef DNSKEY_ALGORITHM_DUMMY
595 case DNSKEY_ALGORITHM_DUMMY:
596 break;
597 #endif
598 default:
599 return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
600 }
601
602 return SUCCESS;
603 }
604
605 /**
606 * Generate the RDATA of a DS records using the RDATA from a DSNKEY record
607 *
608 * @param digest_type the type of DS
609 * @param dnskey_fqdn the domain of the record
610 * @param dnskey_rdata the rdata of the DNSKEY
611 * @param dnskey_rdata_size the size of the rdata of the DNSKEY
612 * @param out_rdata the output buffer that has to be the right size (known given digest_type)
613 * @return
614 */
615
616 ya_result
dnskey_generate_ds_rdata(u8 digest_type,const u8 * dnskey_fqdn,const u8 * dnskey_rdata,u16 dnskey_rdata_size,u8 * out_rdata)617 dnskey_generate_ds_rdata(u8 digest_type, const u8 *dnskey_fqdn, const u8 *dnskey_rdata,u16 dnskey_rdata_size, u8 *out_rdata)
618 {
619 digest_s ctx;
620
621 s32 digest_size;
622
623 switch(digest_type)
624 {
625 case DS_DIGEST_SHA1:
626 digest_sha1_init(&ctx);
627 break;
628 case DS_DIGEST_SHA256:
629 digest_sha256_init(&ctx);
630 break;
631 default:
632 return DNSSEC_ERROR_UNSUPPORTEDDIGESTALGORITHM;
633 }
634
635 digest_size = digest_get_size(&ctx);
636
637 u16 tag = dnskey_get_tag_from_rdata(dnskey_rdata, dnskey_rdata_size);
638 u8 algorithm = dnskey_rdata[3];
639
640 digest_update(&ctx, dnskey_fqdn, dnsname_len(dnskey_fqdn));
641 digest_update(&ctx, dnskey_rdata, dnskey_rdata_size);
642
643 out_rdata[0] = tag >> 8;
644 out_rdata[1] = tag;
645 out_rdata[2] = algorithm;
646 out_rdata[3] = digest_type;
647
648 digest_final_copy_bytes(&ctx, &out_rdata[4], digest_size); // generates DS record : safe use
649
650 return 4 + digest_size;
651 }
652
653 /**
654 * Sanitises an text origin and returns a zallocated copy of it
655 *
656 * @param origin
657 * @return a sanitized zallocated copy of origin
658 */
659
660 static char*
dnskey_origin_zdup_sanitize(const char * origin)661 dnskey_origin_zdup_sanitize(const char* origin)
662 {
663 char* ret;
664
665 if(origin == NULL)
666 {
667 ZALLOC_OBJECT_ARRAY_OR_DIE(ret, char, 2, ORIGNDUP_TAG);
668 ret[0] = '.';
669 ret[1] = '\0';
670 return ret;
671 }
672
673 int origin_len = strlen(origin);
674
675 if(origin_len == 0)
676 {
677 ZALLOC_OBJECT_ARRAY_OR_DIE(ret, char, 2, ORIGNDUP_TAG);
678 ret[0] = '.';
679 ret[1] = '\0';
680 return ret;
681 }
682
683 if(origin[origin_len - 1] == '.')
684 {
685 origin_len++;
686 ZALLOC_OBJECT_ARRAY_OR_DIE(ret, char, origin_len, ORIGNDUP_TAG);
687 //MEMCOPY(ret, origin, origin_len);
688 for(int i = 0; i < origin_len; i++)
689 {
690 ret[i] = tolower(origin[i]);
691 }
692 }
693 else
694 {
695 ZALLOC_OBJECT_ARRAY_OR_DIE(ret, char, (origin_len + 2), ORIGNDUP_TAG);
696 //MEMCOPY(ret, origin, origin_len);
697 for(int i = 0; i < origin_len; i++)
698 {
699 ret[i] = tolower(origin[i]);
700 }
701 ret[origin_len++] = '.'; // VS false positive (nonsense)
702 ret[origin_len] = '\0';
703 }
704
705 return ret;
706 }
707
708 /**
709 * Initialises an empty instance of a DNSKEY
710 * No cryptographic content is put in the key.
711 * Needs further setup.
712 *
713 * @param algorithm the algorithm of the key.
714 * @param flags the flags of the key
715 * @param origin the origin of the key
716 *
717 * @return a pointer to an empty instance (no real key attached) of a key.
718 */
719
720 dnssec_key*
dnskey_newemptyinstance(u8 algorithm,u16 flags,const char * origin)721 dnskey_newemptyinstance(u8 algorithm, u16 flags, const char *origin)
722 {
723 yassert(origin != NULL);
724
725 char *origin_copy = dnskey_origin_zdup_sanitize(origin);
726
727 u8 *owner_name = dnsname_zdup_from_name(origin_copy);
728 if(owner_name == NULL)
729 {
730 log_err("dnskey_newemptyinstance(%hhu, %hx, %s = '%s'): origin parameter is not a domain name", algorithm, flags, origin, origin_copy);
731 ZFREE_ARRAY(origin_copy, strlen(origin_copy) + 1);
732 return NULL;
733 }
734
735 dnssec_key* key;
736
737 ZALLOC_OBJECT_OR_DIE( key, dnssec_key, ZDB_DNSKEY_TAG);
738 ZEROMEMORY(key, sizeof(dnssec_key));
739
740 key->origin = origin_copy;
741
742 /* origin is allocated with ZALLOC using ZALLOC_STRING_OR_DIE
743 * In this mode, the byte before the pointer is the size of the string.
744 */
745
746 key->owner_name = owner_name;
747
748 key->rc = 1;
749
750 key->epoch_created = 0;
751 key->epoch_publish = 0;
752 key->epoch_activate = 0;
753
754 /*
755 key->epoch_inactive = 0;
756 key->epoch_delete = 0;
757 */
758 key->flags = flags;
759 key->algorithm = algorithm;
760 /*key->status = 0;*/
761 /*key->key.X=....*/
762 /*key->tag=00000*/
763 /*key->is_private=TRUE;*/
764
765 log_debug("dnskey_newemptyinstance: %{dnsname} +%03d+-----/%d status=%x rc=%i (%p)", dnskey_get_domain(key), key->algorithm, ntohs(key->flags), key->status, key->rc, key);
766
767 return key;
768 }
769
770 /**
771 * Increases the reference count on a dnssec_key
772 *
773 * @param key
774 */
775
776 #if DUMP_ACQUIRE_RELEASE_STACK_TRACE
dnskey_acquire_debug()777 static void dnskey_acquire_debug()
778 {
779 stacktrace st = debug_stacktrace_get();
780 debug_stacktrace_log_with_prefix(MODULE_MSG_HANDLE, MSG_DEBUG, st, "dnskey_acquire: ");
781 }
782
dnskey_release_debug()783 static void dnskey_release_debug()
784 {
785 stacktrace st = debug_stacktrace_get();
786 debug_stacktrace_log_with_prefix(MODULE_MSG_HANDLE, MSG_DEBUG, st, "dnskey_release: ");
787 }
788 #endif
789
790 void
dnskey_acquire(dnssec_key * key)791 dnskey_acquire(dnssec_key *key)
792 {
793 yassert(key->rc > 0);
794 log_debug("dnskey_acquire: %{dnsname} +%03d+%05d/%d status=%x rc=%i (%p)", dnskey_get_domain(key), key->algorithm, key->tag, ntohs(key->flags), key->status, key->rc + 1, key);
795 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
796 ++key->rc;
797 #if DUMP_ACQUIRE_RELEASE_STACK_TRACE
798 dnskey_acquire_debug();
799 #endif
800 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
801 }
802
803 /**
804 * Releases the reference count on a dnssec_key.
805 * If the reference count reaches zero, destroys the key.
806 *
807 * @param a
808 * @param b
809 */
810
811 void
dnskey_release(dnssec_key * key)812 dnskey_release(dnssec_key *key)
813 {
814 yassert(key != NULL && key->rc > 0);
815
816 log_debug("dnskey_release: %{dnsname} +%03d+%05d/%d status=%x rc=%i (%p)", dnskey_get_domain(key), key->algorithm, key->tag, ntohs(key->flags), key->status, key->rc - 1, key);
817
818 #if DUMP_ACQUIRE_RELEASE_STACK_TRACE
819 dnskey_release_debug();
820 #endif
821
822 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
823 if(--key->rc == 0)
824 {
825 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
826
827 #if DEBUG
828 if(key->next != NULL)
829 {
830 // log_err("dnskey_release(%p): a key should be detached from its list before destruction", key);
831 logger_flush();
832 abort();
833 }
834 #endif
835
836 if(key->vtbl != NULL)
837 {
838 key->vtbl->dnssec_key_free(key);
839 }
840
841 ZFREE_ARRAY(key->origin, strlen(key->origin) + 1); // +1 because the 0 has to be taken in account too (duh!)
842 dnsname_zfree(key->owner_name);
843 #if DEBUG
844 memset(key, 0xfe, sizeof(dnssec_key));
845 #endif
846 ZFREE(key, dnssec_key);
847 }
848 else
849 {
850 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
851 }
852 }
853
854 /**
855 * Generate a (public) key using the RDATA
856 *
857 * RC ok
858 *
859 * @param rdata
860 * @param rdata_size
861 * @param origin
862 * @param out_key points to a pointer for the instantiated key
863 *
864 * @return an error code (success or error)
865 */
866
867 ya_result
dnskey_new_from_rdata(const u8 * rdata,u16 rdata_size,const u8 * fqdn,dnssec_key ** out_key)868 dnskey_new_from_rdata(const u8 *rdata, u16 rdata_size, const u8 *fqdn, dnssec_key **out_key)
869 {
870 if(out_key == NULL)
871 {
872 return UNEXPECTED_NULL_ARGUMENT_ERROR;
873 }
874
875 ya_result return_value;
876 u8 algorithm = rdata[3];
877 char origin[MAX_DOMAIN_LENGTH];
878
879 dnsname_to_cstr(origin, fqdn);
880
881 *out_key = NULL;
882
883 switch(algorithm)
884 {
885 case DNSKEY_ALGORITHM_RSASHA1:
886 case DNSKEY_ALGORITHM_RSASHA1_NSEC3:
887 case DNSKEY_ALGORITHM_RSASHA256_NSEC3:
888 case DNSKEY_ALGORITHM_RSASHA512_NSEC3:
889 return_value = dnskey_rsa_loadpublic(rdata, rdata_size, origin, out_key); // RC
890 break;
891
892 case DNSKEY_ALGORITHM_DSASHA1:
893 case DNSKEY_ALGORITHM_DSASHA1_NSEC3:
894 return_value = dnskey_dsa_loadpublic(rdata, rdata_size, origin, out_key); // RC
895 break;
896 #if HAS_ECDSA_SUPPORT
897 case DNSKEY_ALGORITHM_ECDSAP256SHA256:
898 case DNSKEY_ALGORITHM_ECDSAP384SHA384:
899 return_value = dnskey_ecdsa_loadpublic(rdata, rdata_size, origin, out_key); // RC
900 break;
901 #endif
902 #if HAS_EDDSA_SUPPORT
903 case DNSKEY_ALGORITHM_ED25519:
904 case DNSKEY_ALGORITHM_ED448:
905 return_value = dnskey_eddsa_loadpublic(rdata, rdata_size, origin, out_key); // RC
906 break;
907 #endif
908 #ifdef DNSKEY_ALGORITHM_DUMMY
909 case DNSKEY_ALGORITHM_DUMMY:
910 return_value = dnskey_dummy_loadpublic(rdata, rdata_size, origin, out_key);
911 break;
912 #endif
913 default:
914 return_value = DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
915 break;
916 }
917
918 return return_value;
919 }
920
921 /**
922 * Writes a BIGNUM integer to a stream
923 */
924
925 ya_result
dnskey_write_bignum_as_base64_to_stream(const BIGNUM * num,output_stream * os)926 dnskey_write_bignum_as_base64_to_stream(const BIGNUM *num, output_stream *os)
927 {
928 u8 *buffer;
929 char *buffer2;
930 u8 buffer_[4096];
931 char buffer2_[4096];
932
933 if(num == NULL)
934 {
935 return DNSSEC_ERROR_BNISNULL;
936 }
937
938 u32 n = BN_num_bytes(num);
939 u32 m = BASE64_ENCODED_SIZE(n);
940
941 if(n <= sizeof(buffer_))
942 {
943 buffer = buffer_;
944 }
945 else
946 {
947 MALLOC_OBJECT_ARRAY_OR_DIE(buffer, u8, n, TMPBUFFR_TAG);
948 //buffer = (u8*)malloc(n);
949 }
950
951 if(m <= sizeof(buffer2_))
952 {
953 buffer2 = buffer2_;
954 }
955 else
956 {
957 MALLOC_OBJECT_ARRAY_OR_DIE(buffer2, char, m, TMPBUFFR_TAG);
958 //buffer2 = (char*)malloc(m);
959 }
960
961 BN_bn2bin(num, buffer);
962
963 u32 o = base64_encode(buffer,n,buffer2);
964
965 yassert(o <= m);
966
967 output_stream_write(os, buffer2, o);
968
969 if(buffer != buffer_) free(buffer);
970 if(buffer2 != buffer2_) free(buffer2);
971
972 return SUCCESS;
973 }
974
975 /**
976 * Returns the most relevant publication time.
977 *
978 * publish > activate > created > now
979 *
980 * @param key
981 * @return
982 */
983
984 time_t
dnskey_get_publish_epoch(const dnssec_key * key)985 dnskey_get_publish_epoch(const dnssec_key *key)
986 {
987 u32 ret;
988
989 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
990
991 if(key->epoch_publish != 0)
992 {
993 ret = key->epoch_publish;
994 }
995 else if(key->epoch_activate != 0)
996 {
997 ret = key->epoch_activate;
998 }
999 else if(key->epoch_created != 0)
1000 {
1001 ret = key->epoch_created;
1002 }
1003 else
1004 {
1005 ret = 0; // of course, the last if/else could be replaced by ret = key->epoch_created
1006 }
1007
1008 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
1009
1010 return ret;
1011 }
1012
1013 void
dnskey_set_created_epoch(dnssec_key * key,time_t t)1014 dnskey_set_created_epoch(dnssec_key *key, time_t t)
1015 {
1016 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1017 key->epoch_created = t;
1018 key->status |= DNSKEY_KEY_HAS_SMART_FIELD_CREATED;
1019 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1020 }
1021
1022 void
dnskey_set_publish_epoch(dnssec_key * key,time_t t)1023 dnskey_set_publish_epoch(dnssec_key *key, time_t t)
1024 {
1025 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1026 key->epoch_publish = t;
1027 key->status |= DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH;
1028 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1029 }
1030
1031 /**
1032 * Returns the most relevant activation time.
1033 *
1034 * activate > publish > created > now
1035 *
1036 * @param key
1037 * @return
1038 */
1039
1040 time_t
dnskey_get_activate_epoch(const dnssec_key * key)1041 dnskey_get_activate_epoch(const dnssec_key *key)
1042 {
1043 u32 ret;
1044
1045 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1046
1047 if(key->epoch_activate != 0)
1048 {
1049 ret = key->epoch_activate;
1050 }
1051 else if(key->epoch_publish != 0)
1052 {
1053 ret = key->epoch_publish;
1054 }
1055 else if(key->epoch_created != 0)
1056 {
1057 ret = key->epoch_created;
1058 }
1059 else
1060 {
1061 ret = 0;
1062 }
1063
1064 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1065
1066 return ret;
1067 }
1068
1069 void
dnskey_set_activate_epoch(dnssec_key * key,time_t t)1070 dnskey_set_activate_epoch(dnssec_key *key, time_t t)
1071 {
1072 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1073 key->epoch_activate = t;
1074 key->status |= DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE;
1075 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1076 }
1077
1078
1079
1080
1081 /**
1082 * Returns the most relevant inactivation time.
1083 *
1084 * inactive > delete > never
1085 *
1086 * @param key
1087 * @return
1088 */
1089
1090 time_t
dnskey_get_inactive_epoch(const dnssec_key * key)1091 dnskey_get_inactive_epoch(const dnssec_key *key)
1092 {
1093 u32 ret;
1094
1095 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1096
1097 if(key->epoch_inactive != 0)
1098 {
1099 ret = key->epoch_inactive;
1100 }
1101 else if(key->epoch_activate != 0)
1102 {
1103 // if activation was a lie, inactivation is one too anyway
1104 if((key->epoch_created != 0) && (key->epoch_delete > key->epoch_created))
1105 {
1106 s64 leniency = (key->epoch_delete - key->epoch_created) / 4;
1107
1108 if(leniency > 86400)
1109 {
1110 leniency = 86400;
1111 }
1112
1113 s64 inactive_epoch = key->epoch_delete - leniency;
1114
1115 if(inactive_epoch > MAX_S32) inactive_epoch = MAX_S32;
1116 ret = (s32)inactive_epoch;
1117 }
1118 else
1119 {
1120 ret = MAX_S32;
1121 }
1122 }
1123 else
1124 {
1125 ret = MAX_S32; // don't use MAX_U32 here
1126 }
1127
1128 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1129
1130 return ret;
1131 }
1132
1133 void
dnskey_set_inactive_epoch(dnssec_key * key,time_t t)1134 dnskey_set_inactive_epoch(dnssec_key *key, time_t t)
1135 {
1136 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1137 key->epoch_inactive = t;
1138 key->status |= DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE;
1139 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1140 }
1141
1142 /**
1143 * Returns the most relevant delete time.
1144 *
1145 * delete > inactive > never
1146 *
1147 * @param key
1148 * @return
1149 */
1150
1151 time_t
dnskey_get_delete_epoch(const dnssec_key * key)1152 dnskey_get_delete_epoch(const dnssec_key *key)
1153 {
1154 u32 ret;
1155
1156 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
1157
1158 if(key->epoch_delete != 0)
1159 {
1160 ret = key->epoch_delete;
1161 }
1162 else if(key->epoch_publish == 0)
1163 {
1164 // if publication was a lie, delete is one too anyway
1165 if((key->epoch_created != 0) && (key->epoch_inactive > key->epoch_activate))
1166 {
1167 s64 leniency = (key->epoch_inactive - key->epoch_activate) / 4;
1168
1169 if(leniency > 86400)
1170 {
1171 leniency = 86400;
1172 }
1173
1174 s64 delete_epoch = key->epoch_inactive + leniency;
1175
1176 if(delete_epoch > MAX_S32) delete_epoch = MAX_S32;
1177 ret = (s32)delete_epoch;
1178 }
1179 else
1180 {
1181 ret = MAX_S32;
1182 }
1183 }
1184 else
1185 {
1186 ret = MAX_S32; // don't use MAX_U32 here
1187 }
1188
1189 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
1190
1191 return ret;
1192 }
1193
1194 void
dnskey_set_delete_epoch(dnssec_key * key,time_t t)1195 dnskey_set_delete_epoch(dnssec_key *key, time_t t)
1196 {
1197 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1198 key->epoch_delete= t;
1199 key->status |= DNSKEY_KEY_HAS_SMART_FIELD_DELETE;
1200 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1201 }
1202
1203 /**
1204 *
1205 * Compares two keys for equality on a cryptographic point of view
1206 * Uses the tag, flags, algorithm, origin and key content.
1207 *
1208 * @param a
1209 * @param b
1210 *
1211 * @return TRUE iff the keys are the same.
1212 */
1213
1214 bool
dnskey_equals(const dnssec_key * a,const dnssec_key * b)1215 dnskey_equals(const dnssec_key* a, const dnssec_key* b)
1216 {
1217 if(a == b)
1218 {
1219 return TRUE;
1220 }
1221
1222 if(dnssec_key_tag_field_set(a) && dnssec_key_tag_field_set(b))
1223 {
1224 if(a->tag != b->tag)
1225 {
1226 return FALSE;
1227 }
1228 }
1229
1230 if((a->flags == b->flags) && (a->algorithm == b->algorithm))
1231 {
1232 /* Compare the origin */
1233
1234 if(strcmp(a->origin, b->origin) == 0)
1235 {
1236 /* Compare the content of the key */
1237
1238 return a->vtbl->dnssec_key_equals(a, b);
1239 }
1240 }
1241
1242 return FALSE;
1243 }
1244
1245 /**
1246 *
1247 * Compares two keys for equality on a cryptographic point of view
1248 * Uses the tag, flags, algorithm, origin and public key content.
1249 *
1250 * @param a
1251 * @param b
1252 *
1253 * @return TRUE iff the keys are the same.
1254 */
1255
1256 bool
dnskey_public_equals(const dnssec_key * a,const dnssec_key * b)1257 dnskey_public_equals(const dnssec_key *a, const dnssec_key *b)
1258 {
1259 if(a == b)
1260 {
1261 return TRUE;
1262 }
1263
1264 if(dnssec_key_tag_field_set(a) && dnssec_key_tag_field_set(b))
1265 {
1266 if(a->tag != b->tag)
1267 {
1268 return FALSE;
1269 }
1270 }
1271
1272 if((a->flags == b->flags) && (a->algorithm == b->algorithm))
1273 {
1274 /* Compare the origin */
1275
1276 if(strcmp(a->origin, b->origin) == 0)
1277 {
1278 /* Compare the content of the key */
1279
1280 u8 rdata_a[4096];
1281 u8 rdata_b[4096];
1282
1283 u32 rdata_a_size = a->vtbl->dnssec_key_writerdata(a, rdata_a, sizeof(rdata_a));
1284 u32 rdata_b_size = b->vtbl->dnssec_key_writerdata(b, rdata_b, sizeof(rdata_b));
1285
1286 if(rdata_a_size == rdata_b_size)
1287 {
1288 bool ret = (memcmp(rdata_a, rdata_b, rdata_a_size) == 0);
1289 return ret;
1290 }
1291 }
1292 }
1293
1294 return FALSE;
1295 }
1296
1297 /**
1298 * Returns TRUE if the tag and algorithm of the rdata are matching the ones of the key.
1299 *
1300 * @param key
1301 * @param rdata
1302 * @param rdata_size
1303 * @return
1304 */
1305
1306 bool
dnskey_matches_rdata(const dnssec_key * key,const u8 * rdata,u16 rdata_size)1307 dnskey_matches_rdata(const dnssec_key *key, const u8 *rdata, u16 rdata_size)
1308 {
1309 if(dnskey_get_algorithm(key) == rdata[3])
1310 {
1311 u16 key_tag = dnskey_get_tag_const(key);
1312 u16 rdata_tag = dnskey_get_tag_from_rdata(rdata, rdata_size);
1313
1314 return key_tag == rdata_tag;
1315 }
1316
1317 return FALSE;
1318 }
1319
1320 u16
dnskey_get_tag(dnssec_key * key)1321 dnskey_get_tag(dnssec_key *key)
1322 {
1323 if((dnskey_state_get(key) & DNSKEY_KEY_TAG_SET) == 0)
1324 {
1325 u8 rdata[2048];
1326
1327 u32 rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, sizeof(rdata));
1328
1329 yassert(rdata_size <= 2048);
1330
1331 u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_size);
1332
1333 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1334 key->tag = tag;
1335 key->status |= DNSKEY_KEY_TAG_SET;
1336 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
1337 }
1338
1339 return key->tag;
1340 }
1341
1342 u16
dnskey_get_tag_const(const dnssec_key * key)1343 dnskey_get_tag_const(const dnssec_key *key)
1344 {
1345 u16 tag;
1346
1347 if(key->status & DNSKEY_KEY_TAG_SET)
1348 {
1349 tag = key->tag;
1350 }
1351 else
1352 {
1353 u8 rdata[2048];
1354
1355 u32 rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, sizeof(rdata));
1356
1357 yassert(rdata_size <= 2048);
1358
1359 tag = dnskey_get_tag_from_rdata(rdata, rdata_size);
1360 }
1361
1362 return tag;
1363 }
1364
1365 u8
dnskey_get_algorithm(const dnssec_key * key)1366 dnskey_get_algorithm(const dnssec_key *key)
1367 {
1368 return key->algorithm;
1369 }
1370
1371 const u8 *
dnskey_get_domain(const dnssec_key * key)1372 dnskey_get_domain(const dnssec_key *key)
1373 {
1374 if(key != NULL)
1375 {
1376 return key->owner_name;
1377 }
1378 else
1379 {
1380 return (const u8*)"\004NULL";
1381 }
1382 }
1383
1384 bool
dnskey_is_private(const dnssec_key * key)1385 dnskey_is_private(const dnssec_key *key)
1386 {
1387 return (key->status & DNSKEY_KEY_IS_PRIVATE) != 0;
1388 }
1389
1390 /**
1391 * Adds/Remove a key from a key chain.
1392 * The 'next' field of the key is used.
1393 * A key can only be in one chain at a time.
1394 * This is meant to be used in the keystore.
1395 *
1396 * RC ok
1397 *
1398 * @param keyp
1399 */
1400
1401 void
dnskey_add_to_chain(dnssec_key * key,dnssec_key ** prevp)1402 dnskey_add_to_chain(dnssec_key *key, dnssec_key **prevp)
1403 {
1404 yassert(key->next == NULL);
1405
1406 u16 key_tag = dnskey_get_tag(key);
1407
1408 while(*prevp != NULL)
1409 {
1410 if(dnskey_get_tag(*prevp) > key_tag)
1411 {
1412 key->next = *prevp;
1413 *prevp = key;
1414 dnskey_acquire(key);
1415 return;
1416 }
1417
1418 prevp = &((*prevp)->next);
1419 }
1420
1421 // append
1422
1423 *prevp = key;
1424
1425 dnskey_acquire(key);
1426
1427 key->next = NULL;
1428 }
1429
1430 /**
1431 * Adds/Remove a key from a key chain.
1432 * The 'next' field of the key is used.
1433 * A key can only be in one chain at a time.
1434 * This is meant to be used in the keystore.
1435 *
1436 * RC ok
1437 *
1438 * @param keyp
1439 */
1440
1441 void
dnskey_remove_from_chain(dnssec_key * key,dnssec_key ** prevp)1442 dnskey_remove_from_chain(dnssec_key *key, dnssec_key **prevp)
1443 {
1444 u16 key_tag = dnskey_get_tag(key);
1445
1446 while(*prevp != NULL)
1447 {
1448 u16 tag;
1449 if((tag = dnskey_get_tag(*prevp)) >= key_tag)
1450 {
1451 if(tag == key_tag)
1452 {
1453 dnssec_key *key_to_release = *prevp;
1454 *prevp = (*prevp)->next;
1455 // now (and only now) the next field can (and must) be cleared
1456 key_to_release->next = NULL;
1457 dnskey_release(key_to_release);
1458 }
1459
1460 break;
1461 }
1462
1463 prevp = &((*prevp)->next);
1464 }
1465 }
1466
1467 ya_result
dnskey_new_public_key_from_stream(input_stream * is,dnssec_key ** keyp)1468 dnskey_new_public_key_from_stream(input_stream *is, dnssec_key** keyp)
1469 {
1470 parser_s parser;
1471 ya_result ret;
1472 u16 rclass;
1473 u16 rtype;
1474 u16 flags;
1475 u16 rdata_size;
1476 char origin[MAX_DOMAIN_LENGTH + 1];
1477 u8 fqdn[MAX_DOMAIN_LENGTH];
1478 u8 rdata[1024 + 4];
1479
1480 parser_init(&parser, "\"\"''", "()", ";#", "\040\t\r", "\\");
1481 parser.close_last_stream = FALSE;
1482 parser_push_stream(&parser, is);
1483
1484 for(;;)
1485 {
1486 if(ISOK(ret = parser_next_token(&parser)))
1487 {
1488 if(!(ret & PARSER_WORD))
1489 {
1490 if(ret & (PARSER_COMMENT|PARSER_EOL))
1491 {
1492 continue;
1493 }
1494
1495 if(ret & PARSER_EOF)
1496 {
1497 input_stream *completed_stream = parser_pop_stream(&parser);
1498 input_stream_close(completed_stream);
1499 ret = UNEXPECTED_EOF;
1500 break;
1501 }
1502 continue;
1503 }
1504 }
1505
1506 const char *text = parser_text(&parser);
1507 u32 text_len = parser_text_length(&parser);
1508 memcpy(origin, text, text_len);
1509 origin[text_len] = '\0';
1510
1511 if(FAIL(ret = cstr_to_dnsname_with_check_len(fqdn, text, text_len)))
1512 {
1513 break;
1514 }
1515
1516 if(FAIL(ret = parser_copy_next_class(&parser, &rclass)))
1517 {
1518 break;
1519 }
1520
1521 if(rclass != CLASS_IN)
1522 {
1523 // not IN
1524 ret = DNSSEC_ERROR_EXPECTED_CLASS_IN;
1525 break;
1526 }
1527
1528 if(FAIL(ret = parser_copy_next_type(&parser, &rtype)))
1529 {
1530 break;
1531 }
1532
1533 if(rtype != TYPE_DNSKEY)
1534 {
1535 // not DNSKEY
1536 ret = DNSSEC_ERROR_EXPECTED_TYPE_DNSKEY;
1537 break;
1538 }
1539
1540 if(FAIL(ret = parser_copy_next_u16(&parser, &flags)))
1541 {
1542 break;
1543 }
1544
1545 flags = htons(flags); // need to fix the endianness
1546 SET_U16_AT_P(rdata, flags);
1547
1548 // protocol (8 bits integer)
1549
1550 if(FAIL(ret = parser_copy_next_u8(&parser, &rdata[2])))
1551 {
1552 break;
1553 }
1554
1555 // algorithm (8 bits integer)
1556
1557 if(FAIL(ret = parser_copy_next_u8(&parser, &rdata[3])))
1558 {
1559 break;
1560 }
1561
1562 // key (base64)
1563
1564 if(FAIL(ret = parser_concat_next_tokens_nospace(&parser)))
1565 {
1566 break;
1567 }
1568
1569 if(BASE64_DECODED_SIZE(ret) > (int)sizeof(rdata) - 4)
1570 {
1571 // overflow
1572 ret = DNSSEC_ERROR_UNEXPECTEDKEYSIZE;
1573 break;
1574 }
1575
1576 if(FAIL(ret = base64_decode(parser_text(&parser), parser_text_length(&parser), &rdata[4])))
1577 {
1578 break;
1579 }
1580
1581 if(ret > 1024)
1582 {
1583 ret = DNSSEC_ERROR_KEYISTOOBIG;
1584 break;
1585 }
1586
1587 rdata_size = 4 + ret;
1588
1589 ret = dnskey_new_from_rdata(rdata, rdata_size, fqdn, keyp); // RC
1590
1591 break;
1592 }
1593
1594 parser_finalize(&parser);
1595
1596 return ret;
1597 }
1598
1599 /**
1600 * Loads a public key from a file.
1601 *
1602 * ie: Keu.+007+12345.key
1603 *
1604 * RC ok
1605 *
1606 * @param filename
1607 * @param keyp
1608 * @return
1609 */
1610
1611 ya_result
dnskey_new_public_key_from_file(const char * filename,dnssec_key ** keyp)1612 dnskey_new_public_key_from_file(const char *filename, dnssec_key** keyp)
1613 {
1614 input_stream is;
1615 ya_result ret;
1616
1617
1618 if(keyp == NULL)
1619 {
1620 return UNEXPECTED_NULL_ARGUMENT_ERROR;
1621 }
1622
1623 *keyp = NULL;
1624
1625 if(ISOK(ret = file_input_stream_open(&is, filename)))
1626 {
1627 ret = dnskey_new_public_key_from_stream(&is, keyp);
1628 input_stream_close(&is);
1629 }
1630
1631 return ret;
1632 }
1633
1634 ya_result
dnskey_add_private_key_from_stream(input_stream * is,dnssec_key * key,const char * path,u8 algorithm)1635 dnskey_add_private_key_from_stream(input_stream *is, dnssec_key *key, const char* path, u8 algorithm)
1636 {
1637 dnskey_field_parser dnskey_parser = {NULL, &dnskey_field_dummy_parser};
1638 parser_s parser;
1639 s64 timestamp;
1640 u32 smart_fields = 0;
1641 ya_result ret;
1642 u8 parsed_algorithm;
1643
1644 if(path == NULL)
1645 {
1646 path = "";
1647 }
1648
1649 // in case of error, the timestamp is set to 0
1650
1651 fd_mtime(fd_input_stream_get_filedescriptor(is), ×tamp);
1652
1653 if(ISOK(ret = parser_init(&parser,
1654 "", // by 2
1655 "", // by 2
1656 "#;", // by 1
1657 " \t\r:", // by 1
1658 "" // by 1
1659 )))
1660 {
1661 parser.close_last_stream = FALSE;
1662
1663 parser_push_stream(&parser, is);
1664
1665 for(;;)
1666 {
1667 // get the next token
1668
1669 if(ISOK(ret = parser_next_token(&parser)))
1670 {
1671 if(!(ret & PARSER_WORD))
1672 {
1673 if(ret & (PARSER_COMMENT|PARSER_EOL))
1674 {
1675 continue;
1676 }
1677 }
1678 if(ret & PARSER_EOF)
1679 {
1680 break;
1681 }
1682 }
1683
1684 // u32 label_len = parser_text_length(&parser);
1685 const char *label = parser_text(&parser);
1686 // makes the word asciiz (need to be undone)
1687 parser_text_asciiz(&parser);
1688 #if DEBUG
1689 log_debug("dnskey: parsing %s::%s", path, label);
1690 #endif
1691 string_node *node = string_set_find(&dnssec_key_load_private_keywords_set, label);
1692 // makes the word asciiz (need to be undone)
1693 parser_text_unasciiz(&parser);
1694
1695 if(node != NULL)
1696 {
1697 // push to management
1698
1699 // parse next word
1700
1701 if(FAIL(ret = parser_next_word(&parser)))
1702 {
1703 break;
1704 }
1705
1706 u32 word_len = parser_text_length(&parser);
1707 const char *word = parser_text(&parser);
1708
1709 switch(node->value)
1710 {
1711 case DNSKEY_FIELD_ALGORITHM:
1712 {
1713 if(ISOK(ret = parser_get_u8(word, word_len, &parsed_algorithm)))
1714 {
1715 if(algorithm == 0)
1716 {
1717 algorithm = parsed_algorithm;
1718 }
1719 else if(parsed_algorithm != algorithm)
1720 {
1721 log_err("dnssec: error parsing %s: expected algorithm version %i, got %i", path, algorithm, parsed_algorithm);
1722 ret = DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
1723 }
1724
1725 parser_expect_eol(&parser);
1726 }
1727 break;
1728 }
1729 case DNSKEY_FIELD_FORMAT:
1730 {
1731 ret = DNSSEC_ERROR_FILE_FORMAT_VERSION;
1732
1733 if(word[0] == 'v')
1734 {
1735 if(word[1] == '1')
1736 {
1737 if(word[2] == '.')
1738 {
1739 // let's assume all 1.x are compatible
1740 ret = SUCCESS;
1741 break;
1742 }
1743 }
1744 }
1745
1746 // makes the word asciiz (need to be undone)
1747 parser_text_asciiz(&parser);
1748 log_err("dnssec: error parsing %s: expected format v1.x, got %s", path, word);
1749 parser_text_unasciiz(&parser);
1750 break;
1751 }
1752 case DNSKEY_FIELD_CREATED:
1753 {
1754 if(ISOK(ret = parse_yyyymmddhhmmss_check_range_len(word, word_len, &key->epoch_created)))
1755 {
1756 smart_fields |= DNSKEY_KEY_HAS_SMART_FIELD_CREATED;
1757 }
1758 break;
1759 }
1760 case DNSKEY_FIELD_PUBLISH:
1761 {
1762 if(ISOK(ret = parse_yyyymmddhhmmss_check_range_len(word, word_len, &key->epoch_publish)))
1763 {
1764 smart_fields |= DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH;
1765 }
1766 break;
1767 }
1768 case DNSKEY_FIELD_ACTIVATE:
1769 {
1770 if(ISOK(ret = parse_yyyymmddhhmmss_check_range_len(word, word_len, &key->epoch_activate)))
1771 {
1772 smart_fields |= DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE;
1773 }
1774 break;
1775 }
1776
1777 case DNSKEY_FIELD_INACTIVE:
1778 {
1779 if(ISOK(ret = parse_yyyymmddhhmmss_check_range_len(word, word_len, &key->epoch_inactive)))
1780 {
1781 smart_fields |= DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE;
1782 }
1783 break;
1784 }
1785 case DNSKEY_FIELD_DELETE:
1786 {
1787 if(ISOK(ret = parse_yyyymmddhhmmss_check_range_len(word, word_len, &key->epoch_delete)))
1788 {
1789 smart_fields |= DNSKEY_KEY_HAS_SMART_FIELD_DELETE;
1790 }
1791 break;
1792 }
1793 case DNSKEY_FIELD_ENGINE:
1794 {
1795 // a base64 encoded null-terminated engine name (ie: "pkcs11")
1796
1797 break;
1798 }
1799 default:
1800 {
1801 log_err("dnssec: internal error: %s set as %i defined but not handled", node->key, node->value);
1802 ret = DNSSEC_ERROR_FIELD_NOT_HANDLED;
1803 }
1804 }
1805
1806 if(FAIL(ret))
1807 {
1808 if(ret != /**/ ERROR)
1809 {
1810 log_err("dnssec: error parsing %s: failed to parse value of field %s: %r", path, node->key, ret);
1811 }
1812 break;
1813 }
1814
1815 while(FAIL(parser_expect_eol(&parser)))
1816 {
1817 log_warn("dnssec: expected end of line");
1818 }
1819 }
1820 else
1821 {
1822 if(dnskey_parser.data == NULL)
1823 {
1824 switch(algorithm)
1825 {
1826 case DNSKEY_ALGORITHM_RSASHA1:
1827 case DNSKEY_ALGORITHM_RSASHA1_NSEC3:
1828 case DNSKEY_ALGORITHM_RSASHA256_NSEC3:
1829 case DNSKEY_ALGORITHM_RSASHA512_NSEC3:
1830 {
1831 dnskey_rsa_parse_init(&dnskey_parser);
1832 break;
1833 }
1834 case DNSKEY_ALGORITHM_DSASHA1:
1835 case DNSKEY_ALGORITHM_DSASHA1_NSEC3:
1836 {
1837 dnskey_dsa_parse_init(&dnskey_parser);
1838 break;
1839 }
1840 #if HAS_ECDSA_SUPPORT
1841 case DNSKEY_ALGORITHM_ECDSAP256SHA256:
1842 case DNSKEY_ALGORITHM_ECDSAP384SHA384:
1843 {
1844 dnskey_ecdsa_parse_init(&dnskey_parser);
1845 break;
1846 }
1847 #endif
1848 #if HAS_EDDSA_SUPPORT
1849 case DNSKEY_ALGORITHM_ED25519:
1850 case DNSKEY_ALGORITHM_ED448:
1851 {
1852 dnskey_eddsa_parse_init(&dnskey_parser);
1853 break;
1854 }
1855 #endif
1856 #ifdef DNSKEY_ALGORITHM_DUMMY
1857 case DNSKEY_ALGORITHM_DUMMY:
1858 {
1859 dnskey_dummy_parse_init(&dnskey_parser);
1860 break;
1861 }
1862 #endif
1863 default:
1864 {
1865 ret = DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
1866 goto dnskey_new_private_key_from_file_failure; /// *** GOTO *** ///
1867 // break;
1868 }
1869 }
1870 }
1871
1872 ret = dnskey_parser.vtbl->parse_field(&dnskey_parser, &parser);
1873
1874 if(FAIL(ret))
1875 {
1876 log_err("dnssec: error parsing key %s: %r", path, ret);
1877 break;
1878 }
1879
1880 while(FAIL(parser_expect_eol(&parser)))
1881 {
1882 log_warn("dnssec: expected end of line");
1883 }
1884 }
1885
1886 // if failed push to expected algorithm
1887 // else issue a warning
1888 // note the last modification time of the file, for management
1889 // close
1890 } // for(;;)
1891
1892 if(ISOK(ret))
1893 {
1894 if(FAIL(ret = dnskey_parser.vtbl->set_key(&dnskey_parser, key)))
1895 {
1896 log_err("dnssec: %s cannot be read as a private key", path);
1897 }
1898
1899 key->status |= smart_fields;
1900
1901 switch(smart_fields & (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE))
1902 {
1903 case DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH:
1904 {
1905 key->epoch_activate = key->epoch_publish;
1906 break;
1907 }
1908 case DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE:
1909 {
1910 key->epoch_publish = key->epoch_activate;
1911 break;
1912 }
1913 }
1914 }
1915
1916 dnskey_new_private_key_from_file_failure:
1917
1918 dnskey_parser.vtbl->finalise(&dnskey_parser);
1919 parser_finalize(&parser); // also closes the stream
1920
1921 if(ISOK(ret))
1922 {
1923 if(!dnskey_is_private(key))
1924 {
1925 log_err("dnssec: %s is not a valid private key", path);
1926 ret = DNSSEC_ERROR_KEYRING_KEY_IS_NOT_PRIVATE;
1927 }
1928 }
1929
1930 if(ISOK(ret))
1931 {
1932 key->timestamp = timestamp;
1933 }
1934 else
1935 {
1936 dnskey_release(key);
1937 key = NULL;
1938 }
1939 }
1940
1941 return ret;
1942 }
1943
1944 /**
1945 * Loads a private key from a file.
1946 *
1947 * ie: Keu.+007+12345.private
1948 *
1949 * The public key must be in the same folder as the private key.
1950 *
1951 * ie: Keu.+007+12345.key
1952 *
1953 * RC ok
1954 *
1955 * @param filename
1956 * @param keyp
1957 * @return
1958 */
1959
1960 ya_result
dnskey_new_private_key_from_file(const char * filename,dnssec_key ** keyp)1961 dnskey_new_private_key_from_file(const char *filename, dnssec_key **keyp)
1962 {
1963 dnssec_key *key;
1964
1965 ya_result ret;
1966 //u32 smart_fields = 0;
1967 int path_len;
1968 int algorithm = -1;
1969 int tag;
1970 //u8 parsed_algorithm;
1971 //bool ext_is_private;
1972 char extension[16];
1973 char domain[256];
1974 u8 origin[256];
1975 char path[PATH_MAX];
1976
1977 if(keyp == NULL)
1978 {
1979 return INVALID_ARGUMENT_ERROR;
1980 }
1981
1982 const char *name = strrchr(filename,'/');
1983 if(name == NULL)
1984 {
1985 name = filename;
1986 }
1987 else
1988 {
1989 ++name;
1990 }
1991
1992 if(sscanf(name, "K%255[^+]+%03d+%05d.%15s", domain, &algorithm, &tag, extension) != 4)
1993 {
1994 log_err("dnssec: don't know how to parse key file name: '%s'", filename);
1995 return PARSESTRING_ERROR;
1996 }
1997
1998 if(FAIL(ret = cstr_to_dnsname_with_check(origin, domain)))
1999 {
2000 log_err("dnssec: could not parse domain name from file name: '%s': %r", filename, ret);
2001 return ret;
2002 }
2003
2004 path_len = strlen(filename);
2005
2006 if(memcmp(extension, "private", 7) == 0)
2007 {
2008 //ext_is_private = TRUE;
2009 path_len -= 7;
2010 }
2011 else if(memcmp(extension, "key", 3) == 0)
2012 {
2013 //ext_is_private = FALSE;
2014 path_len -= 3;
2015 }
2016 else
2017 {
2018 log_err("dnssec: expected .private or .key extension for the file: '%s'", filename);
2019 return INVALID_STATE_ERROR;
2020 }
2021
2022 memcpy(path, filename, path_len);
2023
2024 // first open the public key file, to get the flags
2025
2026 memcpy(&path[path_len], "key", 4);
2027 if(FAIL(ret = dnskey_new_public_key_from_file(path, &key))) // RC
2028 {
2029 return ret;
2030 }
2031
2032 // then open the private key file
2033
2034 key->nid = 0; // else it will not be editable // scan-build false positive. key cannot be NULL.
2035
2036 memcpy(&path[path_len], "private", 8);
2037
2038 // open parser
2039 input_stream is;
2040 if(ISOK(ret = file_input_stream_open(&is, filename)))
2041 {
2042 ret = dnskey_add_private_key_from_stream(&is, key, path, algorithm);
2043 input_stream_close(&is);
2044 }
2045
2046 *keyp = key;
2047
2048 return ret;
2049 }
2050
2051 /**
2052 *
2053 * Save the private part of a key to a stream
2054 *
2055 * @param key
2056 * @param filename
2057 * @return
2058 */
2059
2060 void
dnskey_store_private_key_to_stream(dnssec_key * key,output_stream * os)2061 dnskey_store_private_key_to_stream(dnssec_key *key, output_stream *os)
2062 {
2063 yassert(os != NULL);
2064 yassert(key != NULL);
2065
2066 const char *key_algorithm_name = dnskey_get_algorithm_name_from_value(key->algorithm);
2067
2068 // basic fields
2069
2070 osformatln(os, "Private-key-format: v1.3");
2071 osformatln(os, "Algorithm: %i (%s)", key->algorithm, key_algorithm_name);
2072
2073 // internal fields
2074
2075 key->vtbl->dnssec_key_print_fields(key, os);
2076
2077 // time fields : all are stored as an UTC YYYYMMDDhhmmss
2078
2079 format_writer epoch = {packedepoch_format_handler_method, NULL};
2080
2081 if(key->epoch_created != 0)
2082 {
2083 epoch.value = (void*)(intptr)key->epoch_created;
2084 osformatln(os, "Created: %w", &epoch);
2085 }
2086
2087 if(key->epoch_publish != 0)
2088 {
2089 epoch.value = (void*)(intptr)key->epoch_publish;
2090 osformatln(os, "Publish: %w", &epoch);
2091 }
2092
2093 if(key->epoch_activate != 0)
2094 {
2095 epoch.value = (void*)(intptr)key->epoch_activate;
2096 osformatln(os, "Activate: %w", &epoch);
2097 }
2098
2099 if(key->epoch_inactive != 0)
2100 {
2101 epoch.value = (void*)(intptr)key->epoch_inactive;
2102 osformatln(os, "Inactive: %w", &epoch);
2103 }
2104
2105 if(key->epoch_delete != 0)
2106 {
2107 epoch.value = (void*)(intptr)key->epoch_delete;
2108 osformatln(os, "Delete: %w", &epoch);
2109 }
2110
2111 }
2112
2113 /**
2114 *
2115 * Save the private part of a key to a file with the given name
2116 *
2117 * @param key
2118 * @param filename
2119 * @return
2120 */
2121
2122 ya_result
dnskey_store_private_key_to_file(dnssec_key * key,const char * filename)2123 dnskey_store_private_key_to_file(dnssec_key *key, const char *filename)
2124 {
2125 yassert(filename != NULL);
2126 yassert(key != NULL);
2127
2128 output_stream os;
2129 ya_result ret;
2130
2131 if(ISOK(ret = file_output_stream_create(&os, filename, 0644)))
2132 {
2133 buffer_output_stream_init(&os, &os, 4096);
2134
2135 dnskey_store_private_key_to_stream(key, &os);
2136
2137 output_stream_close(&os);
2138
2139 ret = SUCCESS;
2140 }
2141
2142 return ret;
2143 }
2144
2145 /**
2146 *
2147 * Save the public part of a key to a stream
2148 *
2149 * @param key
2150 * @param filename
2151 * @return
2152 */
2153
2154 ya_result
dnskey_store_public_key_to_stream(dnssec_key * key,output_stream * os)2155 dnskey_store_public_key_to_stream(dnssec_key *key, output_stream *os)
2156 {
2157 u8 rdata[2048];
2158
2159 if(key->vtbl->dnssec_key_rdatasize(key) < sizeof(rdata))
2160 {
2161 int rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, sizeof(rdata));
2162 rdata_desc dnskeyrdata = {TYPE_DNSKEY, rdata_size, rdata};
2163
2164 osformatln(os, "; This is a key, keyid %d, for domain %{dnsname}", dnskey_get_tag(key), key->owner_name);
2165 osformatln(os, "%{dnsname} IN %{typerdatadesc}", key->owner_name, &dnskeyrdata);
2166
2167 return SUCCESS;
2168 }
2169 else
2170 {
2171 return BUFFER_WOULD_OVERFLOW;
2172 }
2173 }
2174
2175 /**
2176 *
2177 * Save the public part of a key to a file with the given name
2178 *
2179 * @param key
2180 * @param filename
2181 * @return
2182 */
2183
2184 ya_result
dnskey_store_public_key_to_file(dnssec_key * key,const char * filename)2185 dnskey_store_public_key_to_file(dnssec_key *key, const char *filename)
2186 {
2187 ya_result ret;
2188
2189 if(key->vtbl->dnssec_key_rdatasize(key) < 2048)
2190 {
2191 output_stream os;
2192
2193 if(ISOK(ret = file_output_stream_create(&os, filename, 0644)))
2194 {
2195 if(FAIL(ret = dnskey_store_public_key_to_stream(key, &os)))
2196 {
2197 unlink(filename);
2198 }
2199 output_stream_close(&os);
2200 }
2201 }
2202 else
2203 {
2204 ret = DNSSEC_ERROR_KEYISTOOBIG; // key too big (should never happen)
2205 }
2206
2207 return ret;
2208 }
2209
2210 /**
2211 * Save the private part of a key to a dir
2212 *
2213 * @param key
2214 * @param dirname
2215 * @return
2216 */
2217
2218 ya_result
dnskey_store_private_key_to_dir(dnssec_key * key,const char * dirname)2219 dnskey_store_private_key_to_dir(dnssec_key *key, const char *dirname)
2220 {
2221 ya_result ret;
2222 char filename[PATH_MAX];
2223
2224 if(ISOK(ret = snformat(filename, sizeof(filename), "%s/K%{dnsname}+%03d+%05d.private",
2225 dirname,
2226 key->owner_name,
2227 key->algorithm,
2228 dnskey_get_tag(key)
2229 )))
2230 {
2231 ret = file_exists(filename);
2232
2233 if(ret == 0)
2234 {
2235 ret = dnskey_store_private_key_to_file(key, filename);
2236 }
2237 else
2238 {
2239 // cannot create the file because it exists already or the path is not accessible
2240 ret = DNSSEC_ERROR_CANNOT_WRITE_NEW_FILE;
2241 }
2242 }
2243
2244 return ret;
2245 }
2246
2247 /**
2248 *
2249 * Saves the public part of the key in a dir
2250 *
2251 * @param key
2252 * @param dirname
2253 * @return
2254 */
2255
2256 ya_result
dnskey_store_public_key_to_dir(dnssec_key * key,const char * dirname)2257 dnskey_store_public_key_to_dir(dnssec_key *key, const char *dirname)
2258 {
2259 ya_result ret;
2260 char filename[PATH_MAX];
2261
2262 if(ISOK(ret = snformat(filename, sizeof(filename), "%s/K%{dnsname}+%03d+%05d.key",
2263 dirname,
2264 key->owner_name,
2265 key->algorithm,
2266 dnskey_get_tag(key)
2267 )))
2268 {
2269 ret = file_exists(filename);
2270
2271 if(ret == 0)
2272 {
2273 ret = dnskey_store_public_key_to_file(key, filename);
2274 }
2275 else
2276 {
2277 // cannot create the file because it exists already or the path is not accessible
2278 ret = DNSSEC_ERROR_CANNOT_WRITE_NEW_FILE;
2279 }
2280 }
2281
2282 return ret;
2283 }
2284
2285 /**
2286 * Save both parts of the key to the directory.
2287 *
2288 * @param key
2289 * @param dir
2290 *
2291 * @return an error code
2292 */
2293
2294 ya_result
dnskey_store_keypair_to_dir(dnssec_key * key,const char * dir)2295 dnskey_store_keypair_to_dir(dnssec_key *key, const char *dir)
2296 {
2297 ya_result ret;
2298
2299 if(ISOK(ret = dnskey_store_public_key_to_dir(key, dir)))
2300 {
2301 ret = dnskey_store_private_key_to_dir(key, dir);
2302 }
2303
2304 return ret;
2305 }
2306
2307 ya_result
dnskey_delete_public_key_from_dir(dnssec_key * key,const char * dirname)2308 dnskey_delete_public_key_from_dir(dnssec_key *key, const char *dirname)
2309 {
2310 ya_result ret;
2311 char filename[PATH_MAX];
2312
2313 if(ISOK(ret = snformat(filename, sizeof(filename), "%s/K%{dnsname}+%03d+%05d.key",
2314 dirname,
2315 key->owner_name,
2316 key->algorithm,
2317 dnskey_get_tag(key)
2318 )))
2319 {
2320 unlink(filename);
2321 ret = ERRNO_ERROR;
2322 }
2323
2324 return ret;
2325 }
2326
2327 ya_result
dnskey_delete_private_key_from_dir(dnssec_key * key,const char * dirname)2328 dnskey_delete_private_key_from_dir(dnssec_key *key, const char *dirname)
2329 {
2330 ya_result ret;
2331 char filename[PATH_MAX];
2332
2333 if(ISOK(ret = snformat(filename, sizeof(filename), "%s/K%{dnsname}+%03d+%05d.private",
2334 dirname,
2335 key->owner_name,
2336 key->algorithm,
2337 dnskey_get_tag(key)
2338 )))
2339 {
2340 unlink(filename);
2341 ret = ERRNO_ERROR;
2342 }
2343
2344 return ret;
2345 }
2346
2347 ya_result
dnskey_delete_keypair_from_dir(dnssec_key * key,const char * dirname)2348 dnskey_delete_keypair_from_dir(dnssec_key *key, const char *dirname)
2349 {
2350 ya_result ret1 = dnskey_delete_public_key_from_dir(key, dirname);
2351 ya_result ret2 = dnskey_delete_private_key_from_dir(key, dirname);
2352 if((ret1 != MAKE_ERRNO_ERROR(EACCES)) && (ret2 != MAKE_ERRNO_ERROR(EACCES)))
2353 {
2354 return SUCCESS;
2355 }
2356 else
2357 {
2358 return MAKE_ERRNO_ERROR(EACCES);
2359 }
2360 }
2361
2362 bool
dnskey_is_expired(const dnssec_key * key,time_t now)2363 dnskey_is_expired(const dnssec_key *key, time_t now)
2364 {
2365 return (key->epoch_delete != 0 && key->epoch_delete < now) || (key->epoch_inactive != 0 && key->epoch_inactive < now);
2366 }
2367
2368 bool
dnskey_is_expired_now(const dnssec_key * key)2369 dnskey_is_expired_now(const dnssec_key *key)
2370 {
2371 time_t now = time(NULL);
2372 bool ret = dnskey_is_expired(key, now);
2373 return ret;
2374 }
2375
2376 int
dnskey_get_size(const dnssec_key * key)2377 dnskey_get_size(const dnssec_key *key)
2378 {
2379 int bits_size = key->vtbl->dnssec_key_size(key);
2380 return bits_size;
2381 }
2382
2383 u16
dnskey_get_flags(const dnssec_key * key)2384 dnskey_get_flags(const dnssec_key *key)
2385 {
2386 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
2387 u16 flags = key->flags;
2388 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
2389 return flags;
2390 }
2391
2392 void
dnskey_state_enable(dnssec_key * key,u32 status)2393 dnskey_state_enable(dnssec_key *key, u32 status)
2394 {
2395 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
2396 key->status |= status;
2397 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
2398 }
2399
2400 void
dnskey_state_disable(dnssec_key * key,u32 status)2401 dnskey_state_disable(dnssec_key *key, u32 status)
2402 {
2403 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
2404 key->status &= ~status;
2405 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
2406 }
2407
2408 u32
dnskey_state_get(const dnssec_key * key)2409 dnskey_state_get(const dnssec_key *key)
2410 {
2411 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
2412 u32 state = key->status;
2413 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
2414 return state;
2415 }
2416
2417 /**
2418 * Initialises internal info.
2419 */
2420
2421 void
dnskey_init()2422 dnskey_init()
2423 {
2424 if(dnssec_key_load_private_keywords_set == STRING_SET_EMPTY)
2425 {
2426 for(int i = 0; dnssec_key_load_private_keywords_common_names[i].data != NULL; i++)
2427 {
2428 string_node *node = string_set_insert(&dnssec_key_load_private_keywords_set, dnssec_key_load_private_keywords_common_names[i].data);
2429 node->value = dnssec_key_load_private_keywords_common_names[i].id;
2430 }
2431 }
2432 }
2433
2434 void
dnskey_finalize()2435 dnskey_finalize()
2436 {
2437 string_set_destroy(&dnssec_key_load_private_keywords_set);
2438 }
2439
2440 /**
2441 * Returns true if the key is supposed to have been added in the zone at the chosen time already.
2442 *
2443 * @param key
2444 * @param t
2445 * @return
2446 */
2447
2448 bool
dnskey_is_published(const dnssec_key * key,time_t t)2449 dnskey_is_published(const dnssec_key *key, time_t t)
2450 {
2451 // there is a publish time and it has occurred
2452
2453 if(dnskey_has_explicit_publish(key) && (key->epoch_publish <= t))
2454 {
2455 bool ret = !dnskey_is_unpublished(key, t);
2456 return ret;
2457 }
2458
2459 // there is no publish time
2460
2461 return !dnskey_is_unpublished(key, t);
2462 }
2463
2464 /**
2465 * Returns true if the key is supposed to have been removed from the zone at the chosen time already.
2466 *
2467 * @param key
2468 * @param t
2469 * @return
2470 */
2471
2472 bool
dnskey_is_unpublished(const dnssec_key * key,time_t t)2473 dnskey_is_unpublished(const dnssec_key *key, time_t t)
2474 {
2475 // true if and only if there is a removal time that occurred already
2476
2477 return dnskey_has_explicit_delete(key) && (key->epoch_delete <= t);
2478 }
2479
2480 /**
2481 * Returns true if the key is supposed to be used for signatures.
2482 *
2483 * @param key
2484 * @param t
2485 * @return
2486 */
2487
2488 bool
dnskey_is_activated(const dnssec_key * key,time_t t)2489 dnskey_is_activated(const dnssec_key *key, time_t t)
2490 {
2491 // there is a active time and it has occurred
2492
2493 if(dnskey_has_explicit_activate(key))
2494 {
2495 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
2496 time_t epoch_activate = key->epoch_activate;
2497 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
2498 if(epoch_activate <= t) // activation time passed
2499 {
2500 bool ret = !dnskey_is_deactivated(key, t); // not deactivated yet ?
2501 return ret;
2502 }
2503
2504 return FALSE; // not active yet
2505 }
2506 else
2507 {
2508 // no activation defined : active at publication time but only until deactivation
2509
2510 return dnskey_is_published(key, t) && !dnskey_is_deactivated(key, t);
2511 }
2512 }
2513
2514 /**
2515 * Assumes we are in 'leniency' seconds in the future for activation (and in the present for deactivation)
2516 */
2517
2518 bool
dnskey_is_activated_lenient(const dnssec_key * key,time_t t,u32 leniency)2519 dnskey_is_activated_lenient(const dnssec_key *key, time_t t, u32 leniency)
2520 {
2521 // there is a active time and it has occurred
2522
2523 if(dnskey_has_explicit_activate(key))
2524 {
2525 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
2526 time_t epoch_activate = key->epoch_activate;
2527 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
2528 if(epoch_activate <= t + leniency) // activation time passed
2529 {
2530 bool ret = !dnskey_is_deactivated(key, t); // not deactivated yet ?
2531 return ret;
2532 }
2533
2534 return FALSE; // not active yet
2535 }
2536 else
2537 {
2538 // no activation defined : active at publication time but only until deactivation
2539
2540 return dnskey_is_published(key, t) && !dnskey_is_deactivated(key, t);
2541 }
2542 }
2543
2544 /**
2545 * Returns true if the key must not be used for signatures anymore.
2546 *
2547 * @param key
2548 * @param t
2549 * @return
2550 */
2551
2552 bool
dnskey_is_deactivated(const dnssec_key * key,time_t t)2553 dnskey_is_deactivated(const dnssec_key *key, time_t t)
2554 {
2555 // there is a inactive time and it has occurred
2556
2557 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
2558 time_t epoch_inactive = key->epoch_inactive;
2559 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ);
2560
2561 if(epoch_inactive > 0)
2562 {
2563 return (epoch_inactive <= t);
2564 }
2565 else
2566 {
2567 // the key has to be activated and not deleted
2568
2569 return dnskey_is_unpublished(key, t);
2570 }
2571 }
2572
2573 bool
dnskey_has_explicit_publish(const dnssec_key * key)2574 dnskey_has_explicit_publish(const dnssec_key *key)
2575 {
2576 return (dnskey_state_get(key) & DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH) != 0;
2577 }
2578
2579 bool
dnskey_has_explicit_delete(const dnssec_key * key)2580 dnskey_has_explicit_delete(const dnssec_key *key)
2581 {
2582 return (dnskey_state_get(key) & DNSKEY_KEY_HAS_SMART_FIELD_DELETE) != 0;
2583 }
2584
2585 bool
dnskey_has_explicit_publish_or_delete(const dnssec_key * key)2586 dnskey_has_explicit_publish_or_delete(const dnssec_key *key)
2587 {
2588 return (dnskey_state_get(key) & (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE)) != 0;
2589 }
2590
2591 bool
dnskey_has_explicit_publish_and_delete(const dnssec_key * key)2592 dnskey_has_explicit_publish_and_delete(const dnssec_key *key)
2593 {
2594 return (dnskey_state_get(key) & (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE)) == (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE);
2595 }
2596
2597 bool
dnskey_has_explicit_activate(const dnssec_key * key)2598 dnskey_has_explicit_activate(const dnssec_key *key)
2599 {
2600 return (dnskey_state_get(key) & DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE) != 0;
2601 }
2602
2603 bool
dnskey_has_explicit_deactivate(const dnssec_key * key)2604 dnskey_has_explicit_deactivate(const dnssec_key *key)
2605 {
2606 return (dnskey_state_get(key) & DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE) != 0;
2607 }
2608
2609 bool
dnskey_has_activate_and_deactivate(const dnssec_key * key)2610 dnskey_has_activate_and_deactivate(const dnssec_key *key)
2611 {
2612 return (dnskey_state_get(key) & (DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE)) == (DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE);
2613 }
2614
2615 bool
dnskey_has_activate_or_deactivate(const dnssec_key * key)2616 dnskey_has_activate_or_deactivate(const dnssec_key *key)
2617 {
2618 return (dnskey_state_get(key) & (DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE)) != 0;
2619 }
2620
2621 u8
dnskey_supported_algorithm_count()2622 dnskey_supported_algorithm_count()
2623 {
2624 return sizeof(dnskey_supported_algorithms)/sizeof(dnskey_supported_algorithms[0]);
2625 }
2626
2627 const dnskey_features*
dnskey_supported_algorithm_by_index(u8 index)2628 dnskey_supported_algorithm_by_index(u8 index)
2629 {
2630 if(index < dnskey_supported_algorithm_count())
2631 {
2632 const dnskey_features* ret = &dnskey_supported_algorithms[index];
2633 return ret;
2634 }
2635
2636 return NULL;
2637 }
2638
2639 const dnskey_features*
dnskey_supported_algorithm(u8 algorithm)2640 dnskey_supported_algorithm(u8 algorithm)
2641 {
2642 for(int i = 0; i < dnskey_supported_algorithm_count(); ++i)
2643 {
2644 const dnskey_features* ret = &dnskey_supported_algorithms[i];
2645 if(ret->algorithm == algorithm)
2646 {
2647 return ret;
2648 }
2649 }
2650
2651 return NULL;
2652 }
2653
dnskey_newinstance(u32 size,u8 algorithm,u16 flags,const char * origin,dnssec_key ** out_key)2654 ya_result dnskey_newinstance(u32 size, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key)
2655 {
2656 if(size > DNSSEC_MAXIMUM_KEY_SIZE)
2657 {
2658 return DNSSEC_ERROR_KEYISTOOBIG;
2659 }
2660
2661 ya_result ret;
2662
2663 switch(algorithm)
2664 {
2665 case DNSKEY_ALGORITHM_RSASHA1:
2666 case DNSKEY_ALGORITHM_RSASHA1_NSEC3:
2667 case DNSKEY_ALGORITHM_RSASHA256_NSEC3:
2668 case DNSKEY_ALGORITHM_RSASHA512_NSEC3:
2669 ret = dnskey_rsa_newinstance(size, algorithm, flags, origin, out_key);
2670 break;
2671 case DNSKEY_ALGORITHM_DSASHA1:
2672 case DNSKEY_ALGORITHM_DSASHA1_NSEC3:
2673 ret = dnskey_dsa_newinstance(size, algorithm, flags, origin, out_key);
2674 break;
2675 #if HAS_ECDSA_SUPPORT
2676 case DNSKEY_ALGORITHM_ECDSAP256SHA256:
2677 case DNSKEY_ALGORITHM_ECDSAP384SHA384:
2678 ret = dnskey_ecdsa_newinstance(size, algorithm, flags, origin, out_key);
2679 break;
2680 #endif
2681 #if HAS_EDDSA_SUPPORT
2682 case DNSKEY_ALGORITHM_ED25519:
2683 case DNSKEY_ALGORITHM_ED448:
2684 ret = dnskey_eddsa_newinstance(size, algorithm, flags, origin, out_key);
2685 break;
2686 #endif
2687 #ifdef DNSKEY_ALGORITHM_DUMMY
2688 case DNSKEY_ALGORITHM_DUMMY:
2689 ret = dnskey_dummy_newinstance(size, algorithm, flags, origin, out_key);
2690 break;
2691 #endif
2692 default:
2693 ret = DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
2694 break;
2695 }
2696
2697 if(ISOK(ret))
2698 {
2699 time_t now = time(NULL);
2700 group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
2701 (*out_key)->epoch_created = now;
2702 (*out_key)->status |= DNSKEY_KEY_HAS_SMART_FIELD_CREATED;
2703 group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE);
2704 }
2705
2706 return ret;
2707 }
2708
2709 void
dnskey_init_dns_resource_record(dnssec_key * key,s32 ttl,dns_resource_record * rr)2710 dnskey_init_dns_resource_record(dnssec_key *key, s32 ttl, dns_resource_record *rr)
2711 {
2712 u8 rdata[8191];
2713 u32 rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, sizeof(rdata));
2714 dns_resource_record_init_record(rr, dnskey_get_domain(key), TYPE_DNSKEY, CLASS_IN, ttl, rdata_size, rdata);
2715 }
2716
2717 /** @} */
2718