dnsmasq: Backport some security updates
[librecmc/librecmc.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);