1 From 059aded0700309308dafd9720b0313ce52f6e189 Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Thu, 12 Nov 2020 23:09:15 +0000
4 Subject: Optimse RR digest calculation in DNSSEC.
6 If an RR is of a type which doesn't need canonicalisation,
7 bypass the relatively slow canonicalisation code, and insert
8 it direct into the digest.
10 src/dnssec.c | 82 +++++++++++++++++++++++++++++++---------------------
11 1 file changed, 49 insertions(+), 33 deletions(-)
15 @@ -559,7 +559,7 @@ static int validate_rrset(time_t now, st
16 hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
19 -#define RRBUFLEN 300 /* Most RRs are smaller than this. */
20 +#define RRBUFLEN 128 /* Most RRs are smaller than this. */
22 for (i = 0; i < rrsetidx; ++i)
24 @@ -597,50 +597,66 @@ static int validate_rrset(time_t now, st
25 hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name_start);
26 hash->update(ctx, 4, p); /* class and type */
27 hash->update(ctx, 4, (unsigned char *)&nsigttl);
29 - p += 8; /* skip class, type, ttl */
31 + p += 8; /* skip type, class, ttl */
33 if (!CHECK_LEN(header, p, plen, rdlen))
36 - /* canonicalise rdata and calculate length of same, use
37 - name buffer as workspace for get_rdata. */
40 - state.desc = rr_desc;
42 - state.end = p + rdlen;
44 - for (j = 0; get_rdata(header, plen, &state); j++)
46 - rrbuf[j] = *state.op;
48 - len = htons((u16)j);
49 - hash->update(ctx, 2, (unsigned char *)&len);
51 - /* If the RR is shorter than RRBUFLEN (most of them, in practice)
52 - then we can just digest it now. If it exceeds RRBUFLEN we have to
53 - go back to the start and do it in chunks. */
55 + /* Optimisation for RR types which need no cannonicalisation.
56 + This includes DNSKEY DS NSEC and NSEC3, which are also long, so
57 + it saves lots of calls to get_rdata, and avoids the pessimal
58 + segmented insertion, even with a small rrbuf[].
60 + If canonicalisation is not needed, a simple insertion into the hash works.
62 + if (*rr_desc == (u16)-1)
65 + hash->update(ctx, 2, (unsigned char *)&len);
66 + hash->update(ctx, rdlen, p);
70 + /* canonicalise rdata and calculate length of same, use
71 + name buffer as workspace for get_rdata. */
77 + state.end = p + rdlen;
79 for (j = 0; get_rdata(header, plen, &state); j++)
81 + rrbuf[j] = *state.op;
83 + len = htons((u16)j);
84 + hash->update(ctx, 2, (unsigned char *)&len);
86 + /* If the RR is shorter than RRBUFLEN (most of them, in practice)
87 + then we can just digest it now. If it exceeds RRBUFLEN we have to
88 + go back to the start and do it in chunks. */
91 - rrbuf[j] = *state.op;
93 - if (j == RRBUFLEN - 1)
95 - hash->update(ctx, RRBUFLEN, rrbuf);
100 + state.desc = rr_desc;
102 + for (j = 0; get_rdata(header, plen, &state); j++)
104 + rrbuf[j] = *state.op;
106 + if (j == RRBUFLEN - 1)
108 + hash->update(ctx, RRBUFLEN, rrbuf);
115 + hash->update(ctx, j, rrbuf);
119 - hash->update(ctx, j, rrbuf);
122 hash->digest(ctx, hash->digest_size, digest);