123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- From 059aded0700309308dafd9720b0313ce52f6e189 Mon Sep 17 00:00:00 2001
- From: Simon Kelley <simon@thekelleys.org.uk>
- Date: Thu, 12 Nov 2020 23:09:15 +0000
- Subject: Optimse RR digest calculation in DNSSEC.
- If an RR is of a type which doesn't need canonicalisation,
- bypass the relatively slow canonicalisation code, and insert
- it direct into the digest.
- ---
- src/dnssec.c | 82 +++++++++++++++++++++++++++++++---------------------
- 1 file changed, 49 insertions(+), 33 deletions(-)
- --- a/src/dnssec.c
- +++ b/src/dnssec.c
- @@ -559,7 +559,7 @@ static int validate_rrset(time_t now, st
- hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
- from_wire(keyname);
-
- -#define RRBUFLEN 300 /* Most RRs are smaller than this. */
- +#define RRBUFLEN 128 /* Most RRs are smaller than this. */
-
- for (i = 0; i < rrsetidx; ++i)
- {
- @@ -597,50 +597,66 @@ static int validate_rrset(time_t now, st
- hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name_start);
- hash->update(ctx, 4, p); /* class and type */
- hash->update(ctx, 4, (unsigned char *)&nsigttl);
- -
- - p += 8; /* skip class, type, ttl */
- +
- + p += 8; /* skip type, class, ttl */
- GETSHORT(rdlen, p);
- if (!CHECK_LEN(header, p, plen, rdlen))
- return STAT_BOGUS;
- -
- - /* canonicalise rdata and calculate length of same, use
- - name buffer as workspace for get_rdata. */
- - state.ip = p;
- - state.op = NULL;
- - state.desc = rr_desc;
- - state.buff = name;
- - state.end = p + rdlen;
- -
- - for (j = 0; get_rdata(header, plen, &state); j++)
- - if (j < RRBUFLEN)
- - rrbuf[j] = *state.op;
-
- - len = htons((u16)j);
- - hash->update(ctx, 2, (unsigned char *)&len);
- -
- - /* If the RR is shorter than RRBUFLEN (most of them, in practice)
- - then we can just digest it now. If it exceeds RRBUFLEN we have to
- - go back to the start and do it in chunks. */
- - if (j >= RRBUFLEN)
- + /* Optimisation for RR types which need no cannonicalisation.
- + This includes DNSKEY DS NSEC and NSEC3, which are also long, so
- + it saves lots of calls to get_rdata, and avoids the pessimal
- + segmented insertion, even with a small rrbuf[].
- +
- + If canonicalisation is not needed, a simple insertion into the hash works.
- + */
- + if (*rr_desc == (u16)-1)
- + {
- + len = htons(rdlen);
- + hash->update(ctx, 2, (unsigned char *)&len);
- + hash->update(ctx, rdlen, p);
- + }
- + else
- {
- + /* canonicalise rdata and calculate length of same, use
- + name buffer as workspace for get_rdata. */
- state.ip = p;
- state.op = NULL;
- state.desc = rr_desc;
- -
- + state.buff = name;
- + state.end = p + rdlen;
- +
- for (j = 0; get_rdata(header, plen, &state); j++)
- + if (j < RRBUFLEN)
- + rrbuf[j] = *state.op;
- +
- + len = htons((u16)j);
- + hash->update(ctx, 2, (unsigned char *)&len);
- +
- + /* If the RR is shorter than RRBUFLEN (most of them, in practice)
- + then we can just digest it now. If it exceeds RRBUFLEN we have to
- + go back to the start and do it in chunks. */
- + if (j >= RRBUFLEN)
- {
- - rrbuf[j] = *state.op;
- -
- - if (j == RRBUFLEN - 1)
- - {
- - hash->update(ctx, RRBUFLEN, rrbuf);
- - j = -1;
- - }
- + state.ip = p;
- + state.op = NULL;
- + state.desc = rr_desc;
- +
- + for (j = 0; get_rdata(header, plen, &state); j++)
- + {
- + rrbuf[j] = *state.op;
- +
- + if (j == RRBUFLEN - 1)
- + {
- + hash->update(ctx, RRBUFLEN, rrbuf);
- + j = -1;
- + }
- + }
- }
- +
- + if (j != 0)
- + hash->update(ctx, j, rrbuf);
- }
- -
- - if (j != 0)
- - hash->update(ctx, j, rrbuf);
- }
-
- hash->digest(ctx, hash->digest_size, digest);
|