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 dnscorednssec
38  *  @addtogroup dnskey DNSKEY functions
39  *  @brief
40  *
41  *
42  * @{
43  */
44 
45 #include "dnscore/dnskey-signature.h"
46 #include "dnscore/dnskey.h"
47 #include "dnscore/logger.h"
48 
49 #define MODULE_MSG_HANDLE g_system_logger
50 
51 #define DEBUG_CRYPTO_INTERNALS 0
52 
53 #if DEBUG_CRYPTO_INTERNALS
54 #pragma message("WARNING: DEBUG_CRYPTO_INTERNALS is not set to 0")
55 #endif
56 
57 #if DEBUG_CRYPTO_INTERNALS
58 #define DNSKEY_SIGN_TIME_LENIENCY 0
59 #else
60 #define DNSKEY_SIGN_TIME_LENIENCY 86400
61 #endif
62 
63 struct dnskey_signature_header
64 {
65     // this part MUST match the 18 bytes of wire image of an RRSIG
66 
67     u16 type_covered;
68     u8 algorithm;
69     u8 labels;
70     s32 original_ttl;
71 
72     u32 expiration;
73     u32 inception;          // 16 bytes
74     u16 tag;                // 18
75     u8 fqdn_signature[];
76 };
77 
78 union dnskey_signature_header_storage
79 {
80     u8 rdata[RRSIG_RDATA_HEADER_LEN + 256 + 2048];
81     struct dnskey_signature_header header;
82 };
83 
84 struct dnskey_signature_tctr
85 {
86     u16 rtype;
87     u16 rclass;
88     s32 ttl;
89     u16 rdata_size;
90 };
91 
92 static int
dnskey_signature_canonize_sort_record_view_rdata_compare(const void * a,const void * b,void * c)93 dnskey_signature_canonize_sort_record_view_rdata_compare(const void *a, const void *b, void *c)
94 {
95     const u8* ptr_a = (const u8*)a;
96     const u8* ptr_b = (const u8*)b;
97     resource_record_view *view = (resource_record_view*)c;
98 
99     u16 rr_a_size = view->vtbl->get_rdata_size(view->data, ptr_a);
100     u16 rr_b_size = view->vtbl->get_rdata_size(view->data, ptr_b);
101 
102     int ret;
103 
104     int diff_len = rr_a_size;
105     diff_len -= rr_b_size;
106 
107     const u8 *rr_a_rdata = view->vtbl->get_rdata(view->data, ptr_a);
108     const u8 *rr_b_rdata = view->vtbl->get_rdata(view->data, ptr_b);
109 
110     if(diff_len != 0)
111     {
112         u16 len = MIN(rr_a_size, rr_b_size);
113 
114         ret = memcmp(rr_a_rdata, rr_b_rdata, len);
115 
116         if(ret == 0)
117         {
118             ret = diff_len;
119         }
120     }
121     else
122     {
123         ret = memcmp(rr_a_rdata, rr_b_rdata, rr_a_size);
124     }
125 
126     return ret;
127 }
128 
129 void
dnskey_signature_init(dnskey_signature * ds)130 dnskey_signature_init(dnskey_signature *ds)
131 {
132     ZEROMEMORY(ds, sizeof(*ds));
133 }
134 
dnskey_signature_set_validity(dnskey_signature * ds,time_t from,time_t to)135 void dnskey_signature_set_validity(dnskey_signature *ds, time_t from, time_t to)
136 {
137     if(from != ds->inception)
138     {
139         ds->inception = (u32)from;
140         ds->has_digest = 0;
141         ds->inception_set = 1;
142     }
143     if(to != ds->expiration)
144     {
145         ds->expiration = (u32)to;
146         ds->has_digest = 0;
147         ds->expiration_set = 1;
148     }
149 }
150 
151 void
dnskey_signature_set_view(dnskey_signature * ds,resource_record_view * view)152 dnskey_signature_set_view(dnskey_signature *ds, resource_record_view *view)
153 {
154     ds->rr_view = view;
155     ds->is_canonised = 0;
156     ds->has_digest = 0;
157 }
158 
159 void
dnskey_signature_set_rrset_reference(dnskey_signature * ds,ptr_vector * rrset)160 dnskey_signature_set_rrset_reference(dnskey_signature *ds, ptr_vector *rrset)
161 {
162     ds->rrset_reference = rrset;
163     ds->is_canonised = 0;
164     ds->has_digest = 0;
165 }
166 
167 void
dnskey_signature_set_canonised(dnskey_signature * ds,bool canonised)168 dnskey_signature_set_canonised(dnskey_signature *ds, bool canonised)
169 {
170     ds->is_canonised = canonised?1:0;
171 }
172 
173 /**
174  * out_rrsig_rr points to a mallocated dns_resource_record
175  */
176 
177 ya_result
dnskey_signature_sign(dnskey_signature * ds,const dnssec_key * key,void ** out_rrsig_rr)178 dnskey_signature_sign(dnskey_signature *ds, const dnssec_key *key, void **out_rrsig_rr)
179 {
180     u8 *signature;
181     const void *rr0;
182     const u8 *fqdn;
183     size_t fqdn_len;
184     const u8* owner_fqdn;
185     size_t owner_fqdn_len;
186     digest_s *ctx_ptr = &ds->digest_ctx;
187     ya_result ret;
188     struct dnskey_signature_tctr tctr;
189     u8 fqdn_buffer[256];
190 
191     union dnskey_signature_header_storage hdr;
192 
193     if(key == NULL)
194     {
195         return INVALID_ARGUMENT_ERROR;   // no key
196     }
197 
198     if(!dnskey_is_private(key))
199     {
200         return DNSSEC_ERROR_KEYRING_KEY_IS_NOT_PRIVATE; // not private
201     }
202 
203     if((ds->rrset_reference == NULL) || (ptr_vector_size(ds->rrset_reference) == 0))
204     {
205         return INVALID_ARGUMENT_ERROR;   // empty set
206     }
207 
208 #if DEBUG || DEBUG_CRYPTO_INTERNALS
209     memset(&hdr, 0xf5, sizeof(hdr));
210 #endif
211 
212     time_t inception = ds->inception;
213     time_t expiration = ds->expiration/*dnskey_get_inactive_epoch(key)*/;
214 
215     u8 key_algorithm = dnskey_get_algorithm(key);
216 
217     if(key_algorithm != ds->key_algorithm)
218     {
219         ds->has_digest = 0;
220     }
221 
222     ptr_vector *rrset = ds->rrset_reference;
223     const resource_record_view_vtbl *view_vtbl = ds->rr_view->vtbl;
224     void *data = ds->rr_view->data;
225 
226     if(!ds->has_digest)
227     {
228         if(FAIL(ret = dnskey_digest_init(ctx_ptr, key_algorithm)))
229         {
230             return ret;
231         }
232 
233         rr0 = ptr_vector_get(rrset, 0);
234 
235         fqdn_len = dnsname_canonize(view_vtbl->get_fqdn(data, rr0), fqdn_buffer);
236         fqdn = fqdn_buffer;
237         //dnsname_len(fqdn);
238         hdr.header.labels = 0;
239 
240         if((fqdn[0] == 1) && (fqdn[1] == (u8)'*'))
241         {
242             fqdn += *fqdn + 1;
243         }
244 
245         while(fqdn[0] != 0)
246         {
247             ++hdr.header.labels;
248             fqdn += *fqdn + 1;
249         }
250 
251         fqdn = fqdn_buffer;
252 
253         owner_fqdn = dnskey_get_domain(key);
254         owner_fqdn_len = dnsname_len(owner_fqdn);
255 
256         if(!ds->is_canonised)
257         {
258             ptr_vector_qsort_r(rrset, dnskey_signature_canonize_sort_record_view_rdata_compare, ds->rr_view);
259             ds->is_canonised = 1;
260         }
261 
262         hdr.header.type_covered = view_vtbl->get_type(data, rr0);
263         hdr.header.algorithm = dnskey_get_algorithm(key);
264         // hdr.header.labels has already been set
265         hdr.header.original_ttl = htonl(view_vtbl->get_ttl(data, rr0));
266         hdr.header.expiration = ntohl(expiration);
267         hdr.header.inception = ntohl(inception);
268         hdr.header.tag = htons(dnskey_get_tag_const(key));
269         memcpy(&hdr.header.fqdn_signature[0], owner_fqdn, owner_fqdn_len); // VS false positive: more than enough room has been allocated on the stack
270         signature = &hdr.header.fqdn_signature[owner_fqdn_len];
271 
272         tctr.rtype = hdr.header.type_covered;
273         tctr.rclass = view_vtbl->get_class(data, rr0);
274         tctr.ttl = hdr.header.original_ttl;
275 
276         size_t hdr_size = signature - (u8*)&hdr;
277 
278 #if DEBUG_CRYPTO_INTERNALS
279         log_debug("dnskey_signature_sign: digest for %{dnsname} %{dnstype} and key tag %i", owner_fqdn, &hdr.header.type_covered, dnskey_get_tag_const(key));
280         log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, &hdr, hdr_size, 32);
281 #endif
282 
283         digest_update(ctx_ptr, &hdr, hdr_size);
284 
285         for(int i = 0; i <= ptr_vector_last_index(rrset); ++i)
286         {
287             const void *rr = ptr_vector_get(rrset, i);
288             digest_update(ctx_ptr, fqdn, fqdn_len);
289 
290             u16 rdata_size = view_vtbl->get_rdata_size(data, rr);
291             tctr.rdata_size = htons(rdata_size);
292 
293             const void *rdata = view_vtbl->get_rdata(data, rr);
294 
295 #if DEBUG_CRYPTO_INTERNALS
296             rdata_desc rdd = {tctr.rtype, rdata_size, rdata};
297             log_debug("dnskey_signature_sign: #%i: %{dnsname} %i %{dnsclass} %{typerdatadesc}",
298                     i, fqdn, ntohl(tctr.ttl), &tctr.rclass, &rdd);
299             log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, fqdn, fqdn_len, 32);
300             log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, &tctr, 2 + 2 + 4 + 2, 32);
301             log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, rdata, rdata_size, 32);
302 #endif
303             digest_update(ctx_ptr, &tctr, 2 + 2 + 4 + 2);
304             digest_update(ctx_ptr, rdata, rdata_size);
305         }
306 
307         s32 digest_size = digest_get_size(ctx_ptr);
308 
309         //digest_final_copy_bytes(ctx_ptr, ds->digest_buffer, sizeof(ds->digest_buffer));
310         digest_final(ctx_ptr);
311 
312 #if DEBUG_CRYPTO_INTERNALS
313         log_debug("dnskey_signature_sign: digest value");
314         log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, digest_get_digest_ptr(ctx_ptr), digest_size, 32);
315 #endif
316 
317         ds->digest_size = digest_size;
318         ds->has_digest = 1;
319     }
320     else
321     {
322         // digest has already been computed, only need to ready the signature,
323         // the rr0 and the fqdn
324 
325 #if DEBUG_CRYPTO_INTERNALS
326         log_debug("dnskey_signature_sign: digest already computed");
327         log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, digest_get_digest_ptr(ctx_ptr), ds->digest_size, 32);
328 #endif
329 
330         owner_fqdn = dnskey_get_domain(key);
331         owner_fqdn_len = dnsname_len(owner_fqdn);
332         signature = &hdr.header.fqdn_signature[owner_fqdn_len];
333         rr0 = ptr_vector_get(rrset, 0);
334         fqdn = view_vtbl->get_fqdn(data, rr0);
335 
336         tctr.rtype = view_vtbl->get_type(data, rr0);
337         tctr.rclass = view_vtbl->get_class(data, rr0);
338         tctr.ttl = htonl(view_vtbl->get_ttl(data, rr0));
339     }
340 
341     void *digest_ptr;
342     digest_get_digest(ctx_ptr, &digest_ptr);
343     s32 signature_size = key->vtbl->dnssec_key_sign_digest(key, digest_ptr, ds->digest_size, signature);
344 
345     if(ISOK(signature_size))
346     {
347 #if DEBUG_CRYPTO_INTERNALS
348         log_debug("dnskey_signature_sign: signature value");
349         log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, signature, signature_size, 32);
350 #endif
351 
352         u16 rrsig_rdata_size = RRSIG_RDATA_HEADER_LEN + owner_fqdn_len + signature_size;
353 
354         void *rrsig_rr = view_vtbl->new_instance(data, fqdn, TYPE_RRSIG, tctr.rclass, view_vtbl->get_ttl(data, rr0), rrsig_rdata_size, hdr.rdata);
355 
356         *out_rrsig_rr = rrsig_rr;
357 
358         return rrsig_rdata_size;
359     }
360     else
361     {
362         return signature_size;
363     }
364 }
365 
366 
367 ya_result
dnskey_signature_verify(dnskey_signature * ds,const dnssec_key * key,void * in_rrsig_rr)368 dnskey_signature_verify(dnskey_signature *ds, const dnssec_key *key, void *in_rrsig_rr) // not tested
369 {
370     const void *rr0;
371     const u8 *fqdn;
372     size_t fqdn_len;
373     const u8* owner_fqdn;
374     size_t owner_fqdn_len;
375     digest_s *ctx_ptr = &ds->digest_ctx;
376     ya_result ret;
377     struct dnskey_signature_tctr tctr;
378     u8 fqdn_buffer[256];
379 
380     union dnskey_signature_header_storage hdr;
381 
382     if(key == NULL)
383     {
384         return INVALID_ARGUMENT_ERROR;   // no key
385     }
386 
387     if((ds->rrset_reference == NULL) || (ptr_vector_size(ds->rrset_reference) == 0))
388     {
389         return INVALID_ARGUMENT_ERROR;   // empty set
390     }
391 
392     u8 key_algorithm = dnskey_get_algorithm(key);
393 
394     if(key_algorithm != ds->key_algorithm)
395     {
396         ds->has_digest = 0;
397     }
398 
399     ptr_vector *rrset = ds->rrset_reference;
400     const resource_record_view_vtbl *view_vtbl = ds->rr_view->vtbl;
401     void *data = ds->rr_view->data;
402 
403     if(!ds->has_digest)
404     {
405         if(FAIL(ret = dnskey_digest_init(ctx_ptr, key_algorithm)))
406         {
407             return ret;
408         }
409 
410         rr0 = ptr_vector_get(rrset, 0);
411 
412         fqdn_len = dnsname_canonize(view_vtbl->get_fqdn(data, rr0), fqdn_buffer);
413         fqdn = fqdn_buffer;
414         //dnsname_len(fqdn);
415         hdr.header.labels = 0;
416 
417         if((fqdn[0] == 1) && (fqdn[1] == (u8)'*'))
418         {
419             fqdn += *fqdn + 1;
420         }
421 
422         while(fqdn[0] != 0)
423         {
424             ++hdr.header.labels;
425             fqdn += *fqdn + 1;
426         }
427 
428         fqdn = fqdn_buffer;
429 
430         owner_fqdn = dnskey_get_domain(key);
431         owner_fqdn_len = dnsname_len(owner_fqdn);
432 
433         if(!ds->is_canonised)
434         {
435             ptr_vector_qsort_r(rrset, dnskey_signature_canonize_sort_record_view_rdata_compare, ds->rr_view);
436             ds->is_canonised = 1;
437         }
438 
439         const u8 *rrsig_rdata = view_vtbl->get_rdata(data, in_rrsig_rr);
440         /*u16 rrsig_rdata_size = */ view_vtbl->get_rdata_size(data, in_rrsig_rr);
441         size_t hdr_size = &hdr.header.fqdn_signature[owner_fqdn_len] - (u8*)&hdr;
442 
443         memcpy(hdr.rdata, rrsig_rdata, hdr_size);
444         /*
445         hdr.header.type_covered = htons(rrsig_get_type_covered_from_rdata(rrsig_rdata, rrsig_rdata_size));
446         hdr.header.algorithm = rrsig_get_algorithm_from_rdata(rrsig_rdata, rrsig_rdata_size);
447         // hdr.header.labels has already been set
448         hdr.header.original_ttl = htonl(rrsig_get_original_ttl_from_rdata(rrsig_rdata, rrsig_rdata_size));
449         hdr.header.expiration = ntohl(rrsig_get_valid_until_from_rdata(rrsig_rdata, rrsig_rdata_size));
450         hdr.header.inception = ntohl(rrsig_get_valid_from_from_rdata(rrsig_rdata, rrsig_rdata_size));
451         hdr.header.tag = htons(rrsig_get_key_tag_from_rdata(rrsig_rdata, rrsig_rdata_size));
452         memcpy(&hdr.header.fqdn_signature[0], owner_fqdn, owner_fqdn_len);
453         */
454         tctr.rtype = hdr.header.type_covered;
455         tctr.rclass = view_vtbl->get_class(data, rr0);
456         tctr.ttl = hdr.header.original_ttl;
457 
458 #if DEBUG_CRYPTO_INTERNALS
459         log_debug("dnskey_signature_verify: digest for %{dnsname} %{dnstype} and key tag %i", owner_fqdn, &hdr.header.type_covered, dnskey_get_tag_const(key));
460         log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, &hdr, hdr_size, 32);
461 #endif
462 
463         digest_update(ctx_ptr, &hdr, hdr_size);
464 
465         for(int i = 0; i <= ptr_vector_last_index(rrset); ++i)
466         {
467             const void *rr = ptr_vector_get(rrset, i);
468             digest_update(ctx_ptr, fqdn, fqdn_len);
469 
470             u16 rdata_size = view_vtbl->get_rdata_size(data, rr);
471             tctr.rdata_size = htons(rdata_size);
472 
473             const void *rdata = view_vtbl->get_rdata(data, rr);
474 
475 #if DEBUG_CRYPTO_INTERNALS
476             rdata_desc rdd = {tctr.rtype, rdata_size, rdata};
477             log_debug("dnskey_signature_verify: #%i: %{dnsname} %i %{dnsclass} %{typerdatadesc}",
478                       i, fqdn, ntohl(tctr.ttl), &tctr.rclass, &rdd);
479             log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, fqdn, fqdn_len, 32);
480             log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, &tctr, 2 + 2 + 4 + 2, 32);
481             log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, rdata, rdata_size, 32);
482 #endif
483             digest_update(ctx_ptr, &tctr, 2 + 2 + 4 + 2);
484             digest_update(ctx_ptr, rdata, rdata_size);
485         }
486 
487         s32 digest_size = digest_get_size(ctx_ptr);
488 
489         //digest_final_copy_bytes(ctx_ptr, ds->digest_buffer, sizeof(ds->digest_buffer));
490         digest_final(ctx_ptr);
491 
492 #if DEBUG_CRYPTO_INTERNALS
493         log_debug("dnskey_signature_verify: digest value");
494         log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, digest_get_digest_ptr(ctx_ptr), digest_size, 32);
495 #endif
496 
497         ds->digest_size = digest_size;
498         ds->has_digest = 1;
499     }
500     else
501     {
502         // digest has already been computed, only need to ready the signature,
503         // the rr0 and the fqdn
504 
505 #if DEBUG_CRYPTO_INTERNALS
506         log_debug("dnskey_signature_verify: digest already computed");
507         log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, digest_get_digest_ptr(ctx_ptr), ds->digest_size, 32);
508 #endif
509         /// @TODO 20210218 edf -- add optional signature verification")
510         // owner_fqdn = dnskey_get_domain(key); // never read
511         // owner_fqdn_len = dnsname_len(owner_fqdn); // never read
512         //signature = &hdr.header.fqdn_signature[owner_fqdn_len];
513         // rr0 = ptr_vector_get(rrset, 0); // never read
514         // fqdn = view_vtbl->get_fqdn(data, rr0); // never read
515     }
516 
517     const u8 *signature_rdata = view_vtbl->get_rdata(ds->rr_view->data, in_rrsig_rr);
518     u16 signature_rdata_size = view_vtbl->get_rdata_size(ds->rr_view->data, in_rrsig_rr);
519 
520     u32 rrsig_signer_name_len = dnsname_len(rrsig_get_signer_name_from_rdata(signature_rdata, signature_rdata_size));
521     u32 rrsig_header_len = RRSIG_RDATA_HEADER_LEN + rrsig_signer_name_len;
522     u16 signature_size = signature_rdata_size - rrsig_header_len;
523 
524     const u8 *signature = &signature_rdata[rrsig_header_len];
525 
526 #if DEBUG_CRYPTO_INTERNALS
527     log_debug("dnskey_signature_verify: signature value");
528     log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, signature, signature_size, 32);
529 #endif
530 
531     void *digest_ptr;
532     digest_get_digest(ctx_ptr, &digest_ptr);
533     bool verified = key->vtbl->dnssec_key_verify_digest(key, digest_ptr, ds->digest_size, signature, signature_size);
534 
535 #if DEBUG_CRYPTO_INTERNALS
536     log_debug("dnskey_signature_verify: %s", (verified)?"verified":"wrong");
537 #endif
538 
539     return (verified)?SUCCESS:ERROR;
540 }
541 
542 void
dnskey_signature_finalize(dnskey_signature * ds)543 dnskey_signature_finalize(dnskey_signature *ds)
544 {
545     (void)ds;
546 }
547 
548 ya_result
dnskey_sign_rrset_with_maxinterval(const dnssec_key * key,ptr_vector * rrset,bool canonize,resource_record_view * view,s32 maxinterval,void ** out_rrsig_rr)549 dnskey_sign_rrset_with_maxinterval(const dnssec_key *key, ptr_vector *rrset, bool canonize, resource_record_view *view,
550                                    s32 maxinterval, void **out_rrsig_rr)
551 {
552     if(dnskey_is_private(key))
553     {
554         dnskey_signature ds;
555         dnskey_signature_init(&ds);
556 
557         s32 from_epoch = MAX(time(NULL) - 86400, 0);
558         s32 to_epoch = dnskey_get_inactive_epoch(key);
559 
560         // if the key will be inactive well after the maxinterval, use maxinterval to the life-time of the signature
561 
562         if(to_epoch - from_epoch > maxinterval + DNSKEY_SIGN_TIME_LENIENCY) // + 86400 : don't limit down for a small period of overhead
563         {
564             if(((s64)from_epoch + (s64)maxinterval) <= MAX_S32)
565             {
566                 to_epoch = from_epoch + maxinterval;
567             }
568             else
569             {
570                 log_warn("dnskey_sign_rrset_with_maxinterval(%{dnsname}, ..., %i, %p)", dnskey_get_domain(key), maxinterval, out_rrsig_rr);
571                 to_epoch = MAX_S32;
572             }
573         }
574         // else limit to the expiration time of the signature
575 
576         from_epoch -= DNSKEY_SIGN_TIME_LENIENCY;    // give some leniency for the validity start
577 
578         dnskey_signature_set_validity(&ds, from_epoch, to_epoch);
579         dnskey_signature_set_view(&ds, view);
580         dnskey_signature_set_rrset_reference(&ds, rrset);
581         dnskey_signature_set_canonised(&ds, !canonize);
582         ya_result ret = dnskey_signature_sign(&ds, key, out_rrsig_rr);
583         dnskey_signature_finalize(&ds);
584 
585         return ret;
586     }
587     else
588     {
589         return DNSSEC_ERROR_KEYRING_KEY_IS_NOT_PRIVATE;
590     }
591 }
592 
593 /*
594 ya_result
595 dnskey_signature_rrset_verify(dnskey_signature *ds, const dnssec_key *key, ptr_vector *rrset, resource_record_view *view)
596 {
597 }
598 */
599 /**
600  * @}
601  */
602