]> the.earth.li Git - onak.git/blob - sigcheck.c
Skip signature hash verification for X509 signatures
[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, write to the Free Software Foundation, Inc., 51
17  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <stdint.h>
21
22 #include "config.h"
23 #include "decodekey.h"
24 #include "keyid.h"
25 #include "keystructs.h"
26 #include "log.h"
27 #include "openpgp.h"
28 #include "sigcheck.h"
29
30 #ifdef HAVE_NETTLE
31 #include <nettle/md5.h>
32 #include <nettle/ripemd160.h>
33 #include <nettle/sha.h>
34 #else
35 #include "md5.h"
36 #include "sha1.h"
37 #endif
38 #include "sha1x.h"
39
40 int check_packet_sighash(struct openpgp_publickey *key,
41                         struct openpgp_packet *packet,
42                         struct openpgp_packet *sig)
43 {
44         uint8_t hashtype;
45         uint8_t *sighash;
46         size_t siglen, unhashedlen;
47         struct sha1_ctx sha1_context;
48         struct sha1x_ctx sha1x_context;
49         struct md5_ctx md5_context;
50 #ifdef NETTLE_WITH_RIPEMD160
51         struct ripemd160_ctx ripemd160_context;
52 #endif
53 #ifdef NETTLE_WITH_SHA224
54         struct sha224_ctx sha224_context;
55 #endif
56 #ifdef NETTLE_WITH_SHA256
57         struct sha256_ctx sha256_context;
58 #endif
59 #ifdef NETTLE_WITH_SHA384
60         struct sha384_ctx sha384_context;
61 #endif
62 #ifdef NETTLE_WITH_SHA512
63         struct sha512_ctx sha512_context;
64 #endif
65         uint8_t keyheader[3];
66         uint8_t packetheader[5];
67         uint8_t v4trailer[6];
68         uint8_t hash[64];
69         uint8_t *hashdata[8];
70         size_t hashlen[8];
71         int chunks, i;
72         uint64_t keyid;
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                         len = parse_subpackets(&sig->data[4], &keyid, NULL);
118                         if (keyid == 0 &&
119                                         /* No unhashed data */
120                                         sig->data[4 + len] == 0 &&
121                                         sig->data[5 + len] == 0 &&
122                                         /* Dummy 0 checksum */
123                                         sig->data[6 + len] == 0 &&
124                                         sig->data[7 + len] == 0 &&
125                                         /* Dummy MPI of 1 */
126                                         sig->data[8 + len] == 0 &&
127                                         sig->data[9 + len] == 1 &&
128                                         sig->data[10 + len] == 1) {
129                                 get_keyid(key, &keyid);
130                                 logthing(LOGTHING_DEBUG,
131                                         "Skipping X509 signature on 0x%016"
132                                         PRIX64,
133                                         keyid);
134                                 return -1;
135                         }
136                 }
137
138                 if (packet != NULL) {
139                         if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
140                                 packetheader[0] = 0x99;
141                                 packetheader[1] = packet->length >> 8;
142                                 packetheader[2] = packet->length & 0xFF;
143                                 hashdata[chunks] = packetheader;
144                                 hashlen[chunks] = 3;
145                                 chunks++;
146                         } else if (packet->tag == OPENPGP_PACKET_UID ||
147                                         packet->tag == OPENPGP_PACKET_UAT) {
148                                 packetheader[0] = (packet->tag ==
149                                         OPENPGP_PACKET_UID) ?  0xB4 : 0xD1;
150                                 packetheader[1] = packet->length >> 24;
151                                 packetheader[2] = (packet->length >> 16) & 0xFF;
152                                 packetheader[3] = (packet->length >> 8) & 0xFF;
153                                 packetheader[4] = packet->length & 0xFF;
154                                 hashdata[chunks] = packetheader;
155                                 hashlen[chunks] = 5;
156                                 chunks++;
157                         }
158                         hashdata[chunks] = packet->data;
159                         hashlen[chunks] = packet->length;
160                         chunks++;
161                 }
162
163                 hashdata[chunks] = sig->data;
164                 hashlen[chunks] = siglen = (sig->data[4] << 8) +
165                         sig->data[5] + 6;;
166                 chunks++;
167
168                 v4trailer[0] = 4;
169                 v4trailer[1] = 0xFF;
170                 v4trailer[2] = siglen >> 24;
171                 v4trailer[3] = (siglen >> 16) & 0xFF;
172                 v4trailer[4] = (siglen >> 8) & 0xFF;
173                 v4trailer[5] = siglen & 0xFF;
174                 hashdata[chunks] = v4trailer;
175                 hashlen[chunks] = 6;
176                 chunks++;
177
178                 unhashedlen = (sig->data[siglen] << 8) +
179                         sig->data[siglen + 1];
180                 sighash = &sig->data[siglen + unhashedlen + 2];
181                 break;
182         default:
183                 get_keyid(key, &keyid);
184                 logthing(LOGTHING_ERROR,
185                         "Unknown signature version %d on 0x%016" PRIX64,
186                         sig->data[0], keyid);
187                 return -1;
188         }
189
190         switch (hashtype) {
191         case OPENPGP_HASH_MD5:
192                 md5_init(&md5_context);
193                 for (i = 0; i < chunks; i++) {
194                         md5_update(&md5_context, hashlen[i], hashdata[i]);
195                 }
196                 md5_digest(&md5_context, 16, hash);
197                 break;
198         case OPENPGP_HASH_SHA1:
199                 sha1_init(&sha1_context);
200                 for (i = 0; i < chunks; i++) {
201                         sha1_update(&sha1_context, hashlen[i], hashdata[i]);
202                 }
203                 sha1_digest(&sha1_context, 20, hash);
204                 break;
205         case OPENPGP_HASH_RIPEMD160:
206 #ifdef NETTLE_WITH_RIPEMD160
207                 ripemd160_init(&ripemd160_context);
208                 for (i = 0; i < chunks; i++) {
209                         ripemd160_update(&ripemd160_context, hashlen[i],
210                                 hashdata[i]);
211                 }
212                 ripemd160_digest(&ripemd160_context, RIPEMD160_DIGEST_SIZE,
213                         hash);
214                 break;
215 #else
216                 logthing(LOGTHING_INFO, "RIPEMD160 support not available.");
217                 return -1;
218 #endif
219         case OPENPGP_HASH_SHA1X:
220                 sha1x_init(&sha1x_context);
221                 for (i = 0; i < chunks; i++) {
222                         sha1x_update(&sha1x_context, hashlen[i], hashdata[i]);
223                 }
224                 sha1x_digest(&sha1x_context, 20, hash);
225                 break;
226         case OPENPGP_HASH_SHA224:
227 #ifdef NETTLE_WITH_SHA224
228                 sha224_init(&sha224_context);
229                 for (i = 0; i < chunks; i++) {
230                         sha224_update(&sha224_context, hashlen[i],
231                                 hashdata[i]);
232                 }
233                 sha224_digest(&sha224_context, SHA224_DIGEST_SIZE, hash);
234                 break;
235 #else
236                 logthing(LOGTHING_INFO, "SHA224 support not available.");
237                 return -1;
238 #endif
239         case OPENPGP_HASH_SHA256:
240 #ifdef NETTLE_WITH_SHA256
241                 sha256_init(&sha256_context);
242                 for (i = 0; i < chunks; i++) {
243                         sha256_update(&sha256_context, hashlen[i],
244                                 hashdata[i]);
245                 }
246                 sha256_digest(&sha256_context, SHA256_DIGEST_SIZE, hash);
247                 break;
248 #else
249                 logthing(LOGTHING_INFO, "SHA256 support not available.");
250                 return -1;
251 #endif
252         case OPENPGP_HASH_SHA384:
253 #ifdef NETTLE_WITH_SHA384
254                 sha384_init(&sha384_context);
255                 for (i = 0; i < chunks; i++) {
256                         sha384_update(&sha384_context, hashlen[i],
257                                 hashdata[i]);
258                 }
259                 sha384_digest(&sha384_context, SHA384_DIGEST_SIZE, hash);
260                 break;
261 #else
262                 logthing(LOGTHING_INFO, "SHA384 support not available.");
263                 return -1;
264 #endif
265         case OPENPGP_HASH_SHA512:
266 #ifdef NETTLE_WITH_SHA512
267                 sha512_init(&sha512_context);
268                 for (i = 0; i < chunks; i++) {
269                         sha512_update(&sha512_context, hashlen[i],
270                                 hashdata[i]);
271                 }
272                 sha512_digest(&sha512_context, SHA512_DIGEST_SIZE, hash);
273                 break;
274 #else
275                 logthing(LOGTHING_INFO, "SHA512 support not available.");
276                 return -1;
277 #endif
278         default:
279                 get_keyid(key, &keyid);
280                 logthing(LOGTHING_ERROR,
281                         "Unsupported signature hash type %d on 0x%016" PRIX64,
282                         hashtype,
283                         keyid);
284                 return -1;
285         }
286
287         logthing(LOGTHING_DEBUG, "Hash type: %d, %d chunks, "
288                 "calculated: %02X%02X / actual: %02X%02X",
289                 hashtype, chunks,
290                 hash[0], hash[1], sighash[0], sighash[1]);
291
292         return (hash[0] == sighash[0] && hash[1] == sighash[1]);
293 }