]> the.earth.li Git - onak.git/blob - sigcheck.c
Set Rules-Requires-Root to no
[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 "build-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 onak_status_t calculate_packet_sighash(struct openpgp_publickey *key,
40                         struct openpgp_packet *packet,
41                         struct openpgp_packet *sig,
42                         uint8_t *hashtype,
43                         uint8_t *hash,
44                         uint8_t **sighash)
45 {
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 HAVE_NETTLE
51         struct ripemd160_ctx ripemd160_context;
52         struct sha224_ctx sha224_context;
53         struct sha256_ctx sha256_context;
54         struct sha384_ctx sha384_context;
55         struct sha512_ctx sha512_context;
56 #endif
57         uint8_t keyheader[5];
58         uint8_t packetheader[5];
59         uint8_t trailer[10];
60         uint8_t *hashdata[8];
61         size_t hashlen[8];
62         int chunks, i;
63         uint64_t keyid;
64         onak_status_t res;
65
66         *hashtype = 0;
67         *sighash = NULL;
68
69         switch (sig->data[0]) {
70         case 2:
71         case 3:
72                 keyheader[0] = 0x99;
73                 keyheader[1] = key->publickey->length >> 8;
74                 keyheader[2] = key->publickey->length & 0xFF;
75                 hashdata[0] = keyheader;
76                 hashlen[0] = 3;
77                 hashdata[1] = key->publickey->data;
78                 hashlen[1] = key->publickey->length;
79                 chunks = 2;
80
81                 *hashtype = sig->data[16];
82
83                 if (packet != NULL) {
84                         if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
85                                 packetheader[0] = 0x99;
86                                 packetheader[1] = packet->length >> 8;
87                                 packetheader[2] = packet->length & 0xFF;
88                                 hashdata[chunks] = packetheader;
89                                 hashlen[chunks] = 3;
90                                 chunks++;
91                         }
92
93                         // TODO: Things other than UIDS/subkeys?
94                         hashdata[chunks] = packet->data;
95                         hashlen[chunks] = packet->length;
96                         chunks++;
97                 }
98
99                 hashdata[chunks] = &sig->data[2];
100                 hashlen[chunks] = 5;
101                 chunks++;
102                 *sighash = &sig->data[17];
103                 break;
104         case 4:
105                 keyheader[0] = 0x99;
106                 keyheader[1] = key->publickey->length >> 8;
107                 keyheader[2] = key->publickey->length & 0xFF;
108                 hashdata[0] = keyheader;
109                 hashlen[0] = 3;
110                 hashdata[1] = key->publickey->data;
111                 hashlen[1] = key->publickey->length;
112                 chunks = 2;
113
114                 /* Check to see if this is an X509 based signature */
115                 if (sig->data[2] == 0 || sig->data[2] == 100) {
116                         size_t len;
117
118                         keyid = 0;
119                         res = parse_subpackets(&sig->data[4],
120                                                 sig->length - 4, &len,
121                                                 &keyid, NULL);
122                         if (res != ONAK_E_OK) {
123                                 return res;
124                         }
125                         if (keyid == 0 &&
126                                         /* No unhashed data */
127                                         sig->data[4 + len] == 0 &&
128                                         sig->data[5 + len] == 0 &&
129                                         /* Dummy 0 checksum */
130                                         sig->data[6 + len] == 0 &&
131                                         sig->data[7 + len] == 0 &&
132                                         /* Dummy MPI of 1 */
133                                         sig->data[8 + len] == 0 &&
134                                         sig->data[9 + len] == 1 &&
135                                         sig->data[10 + len] == 1) {
136                                 return ONAK_E_UNSUPPORTED_FEATURE;
137                         }
138                 }
139
140                 *hashtype = sig->data[3];
141
142                 if (packet != NULL) {
143                         if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
144                                 packetheader[0] = 0x99;
145                                 packetheader[1] = packet->length >> 8;
146                                 packetheader[2] = packet->length & 0xFF;
147                                 hashdata[chunks] = packetheader;
148                                 hashlen[chunks] = 3;
149                                 chunks++;
150                         } else if (packet->tag == OPENPGP_PACKET_UID ||
151                                         packet->tag == OPENPGP_PACKET_UAT) {
152                                 packetheader[0] = (packet->tag ==
153                                         OPENPGP_PACKET_UID) ?  0xB4 : 0xD1;
154                                 packetheader[1] = packet->length >> 24;
155                                 packetheader[2] = (packet->length >> 16) & 0xFF;
156                                 packetheader[3] = (packet->length >> 8) & 0xFF;
157                                 packetheader[4] = packet->length & 0xFF;
158                                 hashdata[chunks] = packetheader;
159                                 hashlen[chunks] = 5;
160                                 chunks++;
161                         }
162                         hashdata[chunks] = packet->data;
163                         hashlen[chunks] = packet->length;
164                         chunks++;
165                 }
166
167                 hashdata[chunks] = sig->data;
168                 hashlen[chunks] = siglen = (sig->data[4] << 8) +
169                         sig->data[5] + 6;;
170                 if (siglen > sig->length) {
171                         /* Signature data exceed packet length, bogus */
172                         return ONAK_E_INVALID_PKT;
173                 }
174                 chunks++;
175
176                 trailer[0] = 4;
177                 trailer[1] = 0xFF;
178                 trailer[2] = siglen >> 24;
179                 trailer[3] = (siglen >> 16) & 0xFF;
180                 trailer[4] = (siglen >> 8) & 0xFF;
181                 trailer[5] = siglen & 0xFF;
182                 hashdata[chunks] = trailer;
183                 hashlen[chunks] = 6;
184                 chunks++;
185
186                 unhashedlen = (sig->data[siglen] << 8) +
187                         sig->data[siglen + 1];
188                 *sighash = &sig->data[siglen + unhashedlen + 2];
189                 break;
190         case 5:
191                 keyheader[0] = 0x9A;
192                 keyheader[1] = 0;
193                 keyheader[2] = 0;
194                 keyheader[3] = key->publickey->length >> 8;
195                 keyheader[4] = key->publickey->length & 0xFF;
196                 hashdata[0] = keyheader;
197                 hashlen[0] = 5;
198                 hashdata[1] = key->publickey->data;
199                 hashlen[1] = key->publickey->length;
200                 chunks = 2;
201
202                 *hashtype = sig->data[3];
203
204                 if (packet != NULL) {
205                         if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
206                                 packetheader[0] = 0x9A;
207                                 packetheader[1] = 0;
208                                 packetheader[2] = 0;
209                                 packetheader[3] = packet->length >> 8;
210                                 packetheader[4] = packet->length & 0xFF;
211                                 hashdata[chunks] = packetheader;
212                                 hashlen[chunks] = 5;
213                                 chunks++;
214                         } else if (packet->tag == OPENPGP_PACKET_UID ||
215                                         packet->tag == OPENPGP_PACKET_UAT) {
216                                 packetheader[0] = (packet->tag ==
217                                         OPENPGP_PACKET_UID) ?  0xB4 : 0xD1;
218                                 packetheader[1] = packet->length >> 24;
219                                 packetheader[2] = (packet->length >> 16) & 0xFF;
220                                 packetheader[3] = (packet->length >> 8) & 0xFF;
221                                 packetheader[4] = packet->length & 0xFF;
222                                 hashdata[chunks] = packetheader;
223                                 hashlen[chunks] = 5;
224                                 chunks++;
225                         }
226                         hashdata[chunks] = packet->data;
227                         hashlen[chunks] = packet->length;
228                         chunks++;
229                 }
230
231                 hashdata[chunks] = sig->data;
232                 hashlen[chunks] = siglen = (sig->data[4] << 8) +
233                         sig->data[5] + 6;;
234                 if (siglen > sig->length) {
235                         /* Signature data exceed packet length, bogus */
236                         return ONAK_E_INVALID_PKT;
237                 }
238                 chunks++;
239
240                 trailer[0] = 5;
241                 trailer[1] = 0xFF;
242                 trailer[2] = 0;
243                 trailer[3] = 0;
244                 trailer[4] = 0;
245                 trailer[5] = 0;
246                 trailer[6] = siglen >> 24;
247                 trailer[7] = (siglen >> 16) & 0xFF;
248                 trailer[8] = (siglen >> 8) & 0xFF;
249                 trailer[9] = siglen & 0xFF;
250                 hashdata[chunks] = trailer;
251                 hashlen[chunks] = 10;
252                 chunks++;
253
254                 unhashedlen = (sig->data[siglen] << 8) +
255                         sig->data[siglen + 1];
256                 *sighash = &sig->data[siglen + unhashedlen + 2];
257                 break;
258         default:
259                 return ONAK_E_UNSUPPORTED_FEATURE;
260         }
261
262         switch (*hashtype) {
263         case OPENPGP_HASH_MD5:
264                 md5_init(&md5_context);
265                 for (i = 0; i < chunks; i++) {
266                         md5_update(&md5_context, hashlen[i], hashdata[i]);
267                 }
268                 md5_digest(&md5_context, MD5_DIGEST_SIZE, hash);
269                 break;
270         case OPENPGP_HASH_SHA1:
271                 sha1_init(&sha1_context);
272                 for (i = 0; i < chunks; i++) {
273                         sha1_update(&sha1_context, hashlen[i], hashdata[i]);
274                 }
275                 sha1_digest(&sha1_context, SHA1_DIGEST_SIZE, hash);
276                 break;
277         case OPENPGP_HASH_SHA1X:
278                 sha1x_init(&sha1x_context);
279                 for (i = 0; i < chunks; i++) {
280                         sha1x_update(&sha1x_context, hashlen[i], hashdata[i]);
281                 }
282                 sha1x_digest(&sha1x_context, SHA1X_DIGEST_SIZE, hash);
283                 break;
284 #ifdef HAVE_NETTLE
285         case OPENPGP_HASH_RIPEMD160:
286                 ripemd160_init(&ripemd160_context);
287                 for (i = 0; i < chunks; i++) {
288                         ripemd160_update(&ripemd160_context, hashlen[i],
289                                 hashdata[i]);
290                 }
291                 ripemd160_digest(&ripemd160_context, RIPEMD160_DIGEST_SIZE,
292                         hash);
293                 break;
294         case OPENPGP_HASH_SHA224:
295                 sha224_init(&sha224_context);
296                 for (i = 0; i < chunks; i++) {
297                         sha224_update(&sha224_context, hashlen[i],
298                                 hashdata[i]);
299                 }
300                 sha224_digest(&sha224_context, SHA224_DIGEST_SIZE, hash);
301                 break;
302         case OPENPGP_HASH_SHA256:
303                 sha256_init(&sha256_context);
304                 for (i = 0; i < chunks; i++) {
305                         sha256_update(&sha256_context, hashlen[i],
306                                 hashdata[i]);
307                 }
308                 sha256_digest(&sha256_context, SHA256_DIGEST_SIZE, hash);
309                 break;
310         case OPENPGP_HASH_SHA384:
311                 sha384_init(&sha384_context);
312                 for (i = 0; i < chunks; i++) {
313                         sha384_update(&sha384_context, hashlen[i],
314                                 hashdata[i]);
315                 }
316                 sha384_digest(&sha384_context, SHA384_DIGEST_SIZE, hash);
317                 break;
318         case OPENPGP_HASH_SHA512:
319                 sha512_init(&sha512_context);
320                 for (i = 0; i < chunks; i++) {
321                         sha512_update(&sha512_context, hashlen[i],
322                                 hashdata[i]);
323                 }
324                 sha512_digest(&sha512_context, SHA512_DIGEST_SIZE, hash);
325                 break;
326 #endif
327         default:
328                 return ONAK_E_UNSUPPORTED_FEATURE;
329         }
330
331         return ONAK_E_OK;
332 }