dnsmasq: Backport some security updates
[openwrt/openwrt.git] / package / network / services / dnsmasq / patches / 0105-Optimse-RR-digest-calculation-in-DNSSEC.patch
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.
5
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.
9 ---
10 src/dnssec.c | 82 +++++++++++++++++++++++++++++++---------------------
11 1 file changed, 49 insertions(+), 33 deletions(-)
12
13 --- a/src/dnssec.c
14 +++ b/src/dnssec.c
15 @@ -559,7 +559,7 @@ static int validate_rrset(time_t now, st
16 hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
17 from_wire(keyname);
18
19 -#define RRBUFLEN 300 /* Most RRs are smaller than this. */
20 +#define RRBUFLEN 128 /* Most RRs are smaller than this. */
21
22 for (i = 0; i < rrsetidx; ++i)
23 {
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);
28 -
29 - p += 8; /* skip class, type, ttl */
30 +
31 + p += 8; /* skip type, class, ttl */
32 GETSHORT(rdlen, p);
33 if (!CHECK_LEN(header, p, plen, rdlen))
34 return STAT_BOGUS;
35 -
36 - /* canonicalise rdata and calculate length of same, use
37 - name buffer as workspace for get_rdata. */
38 - state.ip = p;
39 - state.op = NULL;
40 - state.desc = rr_desc;
41 - state.buff = name;
42 - state.end = p + rdlen;
43 -
44 - for (j = 0; get_rdata(header, plen, &state); j++)
45 - if (j < RRBUFLEN)
46 - rrbuf[j] = *state.op;
47
48 - len = htons((u16)j);
49 - hash->update(ctx, 2, (unsigned char *)&len);
50 -
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. */
54 - if (j >= RRBUFLEN)
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[].
59 +
60 + If canonicalisation is not needed, a simple insertion into the hash works.
61 + */
62 + if (*rr_desc == (u16)-1)
63 + {
64 + len = htons(rdlen);
65 + hash->update(ctx, 2, (unsigned char *)&len);
66 + hash->update(ctx, rdlen, p);
67 + }
68 + else
69 {
70 + /* canonicalise rdata and calculate length of same, use
71 + name buffer as workspace for get_rdata. */
72 state.ip = p;
73 state.op = NULL;
74 state.desc = rr_desc;
75 -
76 + state.buff = name;
77 + state.end = p + rdlen;
78 +
79 for (j = 0; get_rdata(header, plen, &state); j++)
80 + if (j < RRBUFLEN)
81 + rrbuf[j] = *state.op;
82 +
83 + len = htons((u16)j);
84 + hash->update(ctx, 2, (unsigned char *)&len);
85 +
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. */
89 + if (j >= RRBUFLEN)
90 {
91 - rrbuf[j] = *state.op;
92 -
93 - if (j == RRBUFLEN - 1)
94 - {
95 - hash->update(ctx, RRBUFLEN, rrbuf);
96 - j = -1;
97 - }
98 + state.ip = p;
99 + state.op = NULL;
100 + state.desc = rr_desc;
101 +
102 + for (j = 0; get_rdata(header, plen, &state); j++)
103 + {
104 + rrbuf[j] = *state.op;
105 +
106 + if (j == RRBUFLEN - 1)
107 + {
108 + hash->update(ctx, RRBUFLEN, rrbuf);
109 + j = -1;
110 + }
111 + }
112 }
113 +
114 + if (j != 0)
115 + hash->update(ctx, j, rrbuf);
116 }
117 -
118 - if (j != 0)
119 - hash->update(ctx, j, rrbuf);
120 }
121
122 hash->digest(ctx, hash->digest_size, digest);