]> the.earth.li Git - onak.git/blob - sigcheck.c
Add ability to drop overly large packets
[onak.git] / sigcheck.c
1 /*
2  * sigcheck.c - routines to check OpenPGP signatures
3  *
4  * Copyright 2012 Jonathan McDowell <noodles@earth.li>
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program.  If not, see <https://www.gnu.org/licenses/>.
17  */
18
19 #include <stdint.h>
20
21 #include "config.h"
22 #include "decodekey.h"
23 #include "keyid.h"
24 #include "keystructs.h"
25 #include "log.h"
26 #include "openpgp.h"
27 #include "sigcheck.h"
28
29 #ifdef HAVE_NETTLE
30 #include <nettle/md5.h>
31 #include <nettle/ripemd160.h>
32 #include <nettle/sha.h>
33 #else
34 #include "md5.h"
35 #include "sha1.h"
36 #endif
37 #include "sha1x.h"
38
39 int check_packet_sighash(struct openpgp_publickey *key,
40                         struct openpgp_packet *packet,
41                         struct openpgp_packet *sig)
42 {
43         uint8_t hashtype;
44         uint8_t *sighash;
45         size_t siglen, unhashedlen;
46         struct sha1_ctx sha1_context;
47         struct sha1x_ctx sha1x_context;
48         struct md5_ctx md5_context;
49 #ifdef NETTLE_WITH_RIPEMD160
50         struct ripemd160_ctx ripemd160_context;
51 #endif
52 #ifdef NETTLE_WITH_SHA224
53         struct sha224_ctx sha224_context;
54 #endif
55 #ifdef NETTLE_WITH_SHA256
56         struct sha256_ctx sha256_context;
57 #endif
58 #ifdef NETTLE_WITH_SHA384
59         struct sha384_ctx sha384_context;
60 #endif
61 #ifdef NETTLE_WITH_SHA512
62         struct sha512_ctx sha512_context;
63 #endif
64         uint8_t keyheader[3];
65         uint8_t packetheader[5];
66         uint8_t v4trailer[6];
67         uint8_t hash[64];
68         uint8_t *hashdata[8];
69         size_t hashlen[8];
70         int chunks, i;
71         uint64_t keyid;
72         onak_status_t res;
73
74         keyheader[0] = 0x99;
75         keyheader[1] = key->publickey->length >> 8;
76         keyheader[2] = key->publickey->length & 0xFF;
77         hashdata[0] = keyheader;
78         hashlen[0] = 3;
79         hashdata[1] = key->publickey->data;
80         hashlen[1] = key->publickey->length;
81         chunks = 2;
82
83         switch (sig->data[0]) {
84         case 2:
85         case 3:
86                 hashtype = sig->data[16];
87
88                 if (packet != NULL) {
89                         if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
90                                 packetheader[0] = 0x99;
91                                 packetheader[1] = packet->length >> 8;
92                                 packetheader[2] = packet->length & 0xFF;
93                                 hashdata[chunks] = packetheader;
94                                 hashlen[chunks] = 3;
95                                 chunks++;
96                         }
97
98                         // TODO: Things other than UIDS/subkeys?
99                         hashdata[chunks] = packet->data;
100                         hashlen[chunks] = packet->length;
101                         chunks++;
102                 }
103
104                 hashdata[chunks] = &sig->data[2];
105                 hashlen[chunks] = 5;
106                 chunks++;
107                 sighash = &sig->data[17];
108                 break;
109         case 4:
110                 hashtype = sig->data[3];
111
112                 /* Check to see if this is an X509 based signature */
113                 if (sig->data[2] == 0 || sig->data[2] == 100) {
114                         size_t len;
115
116                         keyid = 0;
117                         res = parse_subpackets(&sig->data[4],
118                                                 sig->length - 4, &len,
119                                                 &keyid, NULL);
120                         if (res != ONAK_E_OK) {
121                                 /* If it parses badly, reject it */
122                                 return 0;
123                         }
124                         if (keyid == 0 &&
125                                         /* No unhashed data */
126                                         sig->data[4 + len] == 0 &&
127                                         sig->data[5 + len] == 0 &&
128                                         /* Dummy 0 checksum */
129                                         sig->data[6 + len] == 0 &&
130                                         sig->data[7 + len] == 0 &&
131                                         /* Dummy MPI of 1 */
132                                         sig->data[8 + len] == 0 &&
133                                         sig->data[9 + len] == 1 &&
134                                         sig->data[10 + len] == 1) {
135                                 get_keyid(key, &keyid);
136                                 logthing(LOGTHING_DEBUG,
137                                         "Skipping X509 signature on 0x%016"
138                                         PRIX64,
139                                         keyid);
140                                 return -1;
141                         }
142                 }
143
144                 if (packet != NULL) {
145                         if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
146                                 packetheader[0] = 0x99;
147                                 packetheader[1] = packet->length >> 8;
148                                 packetheader[2] = packet->length & 0xFF;
149                                 hashdata[chunks] = packetheader;
150                                 hashlen[chunks] = 3;
151                                 chunks++;
152                         } else if (packet->tag == OPENPGP_PACKET_UID ||
153                                         packet->tag == OPENPGP_PACKET_UAT) {
154                                 packetheader[0] = (packet->tag ==
155                                         OPENPGP_PACKET_UID) ?  0xB4 : 0xD1;
156                                 packetheader[1] = packet->length >> 24;
157                                 packetheader[2] = (packet->length >> 16) & 0xFF;
158                                 packetheader[3] = (packet->length >> 8) & 0xFF;
159                                 packetheader[4] = packet->length & 0xFF;
160                                 hashdata[chunks] = packetheader;
161                                 hashlen[chunks] = 5;
162                                 chunks++;
163                         }
164                         hashdata[chunks] = packet->data;
165                         hashlen[chunks] = packet->length;
166                         chunks++;
167                 }
168
169                 hashdata[chunks] = sig->data;
170                 hashlen[chunks] = siglen = (sig->data[4] << 8) +
171                         sig->data[5] + 6;;
172                 if (siglen > sig->length) {
173                         /* Signature data exceed packet length, bogus */
174                         return 0;
175                 }
176                 chunks++;
177
178                 v4trailer[0] = 4;
179                 v4trailer[1] = 0xFF;
180                 v4trailer[2] = siglen >> 24;
181                 v4trailer[3] = (siglen >> 16) & 0xFF;
182                 v4trailer[4] = (siglen >> 8) & 0xFF;
183                 v4trailer[5] = siglen & 0xFF;
184                 hashdata[chunks] = v4trailer;
185                 hashlen[chunks] = 6;
186                 chunks++;
187
188                 unhashedlen = (sig->data[siglen] << 8) +
189                         sig->data[siglen + 1];
190                 sighash = &sig->data[siglen + unhashedlen + 2];
191                 break;
192         default:
193                 get_keyid(key, &keyid);
194                 logthing(LOGTHING_ERROR,
195                         "Unknown signature version %d on 0x%016" PRIX64,
196                         sig->data[0], keyid);
197                 return -1;
198         }
199
200         switch (hashtype) {
201         case OPENPGP_HASH_MD5:
202                 md5_init(&md5_context);
203                 for (i = 0; i < chunks; i++) {
204                         md5_update(&md5_context, hashlen[i], hashdata[i]);
205                 }
206                 md5_digest(&md5_context, 16, hash);
207                 break;
208         case OPENPGP_HASH_SHA1:
209                 sha1_init(&sha1_context);
210                 for (i = 0; i < chunks; i++) {
211                         sha1_update(&sha1_context, hashlen[i], hashdata[i]);
212                 }
213                 sha1_digest(&sha1_context, 20, hash);
214                 break;
215         case OPENPGP_HASH_RIPEMD160:
216 #ifdef NETTLE_WITH_RIPEMD160
217                 ripemd160_init(&ripemd160_context);
218                 for (i = 0; i < chunks; i++) {
219                         ripemd160_update(&ripemd160_context, hashlen[i],
220                                 hashdata[i]);
221                 }
222                 ripemd160_digest(&ripemd160_context, RIPEMD160_DIGEST_SIZE,
223                         hash);
224                 break;
225 #else
226                 logthing(LOGTHING_INFO, "RIPEMD160 support not available.");
227                 return -1;
228 #endif
229         case OPENPGP_HASH_SHA1X:
230                 sha1x_init(&sha1x_context);
231                 for (i = 0; i < chunks; i++) {
232                         sha1x_update(&sha1x_context, hashlen[i], hashdata[i]);
233                 }
234                 sha1x_digest(&sha1x_context, 20, hash);
235                 break;
236         case OPENPGP_HASH_SHA224:
237 #ifdef NETTLE_WITH_SHA224
238                 sha224_init(&sha224_context);
239                 for (i = 0; i < chunks; i++) {
240                         sha224_update(&sha224_context, hashlen[i],
241                                 hashdata[i]);
242                 }
243                 sha224_digest(&sha224_context, SHA224_DIGEST_SIZE, hash);
244                 break;
245 #else
246                 logthing(LOGTHING_INFO, "SHA224 support not available.");
247                 return -1;
248 #endif
249         case OPENPGP_HASH_SHA256:
250 #ifdef NETTLE_WITH_SHA256
251                 sha256_init(&sha256_context);
252                 for (i = 0; i < chunks; i++) {
253                         sha256_update(&sha256_context, hashlen[i],
254                                 hashdata[i]);
255                 }
256                 sha256_digest(&sha256_context, SHA256_DIGEST_SIZE, hash);
257                 break;
258 #else
259                 logthing(LOGTHING_INFO, "SHA256 support not available.");
260                 return -1;
261 #endif
262         case OPENPGP_HASH_SHA384:
263 #ifdef NETTLE_WITH_SHA384
264                 sha384_init(&sha384_context);
265                 for (i = 0; i < chunks; i++) {
266                         sha384_update(&sha384_context, hashlen[i],
267                                 hashdata[i]);
268                 }
269                 sha384_digest(&sha384_context, SHA384_DIGEST_SIZE, hash);
270                 break;
271 #else
272                 logthing(LOGTHING_INFO, "SHA384 support not available.");
273                 return -1;
274 #endif
275         case OPENPGP_HASH_SHA512:
276 #ifdef NETTLE_WITH_SHA512
277                 sha512_init(&sha512_context);
278                 for (i = 0; i < chunks; i++) {
279                         sha512_update(&sha512_context, hashlen[i],
280                                 hashdata[i]);
281                 }
282                 sha512_digest(&sha512_context, SHA512_DIGEST_SIZE, hash);
283                 break;
284 #else
285                 logthing(LOGTHING_INFO, "SHA512 support not available.");
286                 return -1;
287 #endif
288         default:
289                 get_keyid(key, &keyid);
290                 logthing(LOGTHING_ERROR,
291                         "Unsupported signature hash type %d on 0x%016" PRIX64,
292                         hashtype,
293                         keyid);
294                 return -1;
295         }
296
297         logthing(LOGTHING_DEBUG, "Hash type: %d, %d chunks, "
298                 "calculated: %02X%02X / actual: %02X%02X",
299                 hashtype, chunks,
300                 hash[0], hash[1], sighash[0], sighash[1]);
301
302         return (hash[0] == sighash[0] && hash[1] == sighash[1]);
303 }