1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
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);
|