]> the.earth.li Git - onak.git/blob - sigcheck.c
Assume if we have Nettle it has all the hashes we need
[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 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 HAVE_NETTLE
50         struct ripemd160_ctx ripemd160_context;
51         struct sha224_ctx sha224_context;
52         struct sha256_ctx sha256_context;
53         struct sha384_ctx sha384_context;
54         struct sha512_ctx sha512_context;
55 #endif
56         uint8_t keyheader[3];
57         uint8_t packetheader[5];
58         uint8_t v4trailer[6];
59         uint8_t hash[64];
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         keyheader[0] = 0x99;
67         keyheader[1] = key->publickey->length >> 8;
68         keyheader[2] = key->publickey->length & 0xFF;
69         hashdata[0] = keyheader;
70         hashlen[0] = 3;
71         hashdata[1] = key->publickey->data;
72         hashlen[1] = key->publickey->length;
73         chunks = 2;
74
75         switch (sig->data[0]) {
76         case 2:
77         case 3:
78                 hashtype = sig->data[16];
79
80                 if (packet != NULL) {
81                         if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
82                                 packetheader[0] = 0x99;
83                                 packetheader[1] = packet->length >> 8;
84                                 packetheader[2] = packet->length & 0xFF;
85                                 hashdata[chunks] = packetheader;
86                                 hashlen[chunks] = 3;
87                                 chunks++;
88                         }
89
90                         // TODO: Things other than UIDS/subkeys?
91                         hashdata[chunks] = packet->data;
92                         hashlen[chunks] = packet->length;
93                         chunks++;
94                 }
95
96                 hashdata[chunks] = &sig->data[2];
97                 hashlen[chunks] = 5;
98                 chunks++;
99                 sighash = &sig->data[17];
100                 break;
101         case 4:
102                 hashtype = sig->data[3];
103
104                 /* Check to see if this is an X509 based signature */
105                 if (sig->data[2] == 0 || sig->data[2] == 100) {
106                         size_t len;
107
108                         keyid = 0;
109                         res = parse_subpackets(&sig->data[4],
110                                                 sig->length - 4, &len,
111                                                 &keyid, NULL);
112                         if (res != ONAK_E_OK) {
113                                 /* If it parses badly, reject it */
114                                 return 0;
115                         }
116                         if (keyid == 0 &&
117                                         /* No unhashed data */
118                                         sig->data[4 + len] == 0 &&
119                                         sig->data[5 + len] == 0 &&
120                                         /* Dummy 0 checksum */
121                                         sig->data[6 + len] == 0 &&
122                                         sig->data[7 + len] == 0 &&
123                                         /* Dummy MPI of 1 */
124                                         sig->data[8 + len] == 0 &&
125                                         sig->data[9 + len] == 1 &&
126                                         sig->data[10 + len] == 1) {
127                                 get_keyid(key, &keyid);
128                                 logthing(LOGTHING_DEBUG,
129                                         "Skipping X509 signature on 0x%016"
130                                         PRIX64,
131                                         keyid);
132                                 return -1;
133                         }
134                 }
135
136                 if (packet != NULL) {
137                         if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
138                                 packetheader[0] = 0x99;
139                                 packetheader[1] = packet->length >> 8;
140                                 packetheader[2] = packet->length & 0xFF;
141                                 hashdata[chunks] = packetheader;
142                                 hashlen[chunks] = 3;
143                                 chunks++;
144                         } else if (packet->tag == OPENPGP_PACKET_UID ||
145                                         packet->tag == OPENPGP_PACKET_UAT) {
146                                 packetheader[0] = (packet->tag ==
147                                         OPENPGP_PACKET_UID) ?  0xB4 : 0xD1;
148                                 packetheader[1] = packet->length >> 24;
149                                 packetheader[2] = (packet->length >> 16) & 0xFF;
150                                 packetheader[3] = (packet->length >> 8) & 0xFF;
151                                 packetheader[4] = packet->length & 0xFF;
152                                 hashdata[chunks] = packetheader;
153                                 hashlen[chunks] = 5;
154                                 chunks++;
155                         }
156                         hashdata[chunks] = packet->data;
157                         hashlen[chunks] = packet->length;
158                         chunks++;
159                 }
160
161                 hashdata[chunks] = sig->data;
162                 hashlen[chunks] = siglen = (sig->data[4] << 8) +
163                         sig->data[5] + 6;;
164                 if (siglen > sig->length) {
165                         /* Signature data exceed packet length, bogus */
166                         return 0;
167                 }
168                 chunks++;
169
170                 v4trailer[0] = 4;
171                 v4trailer[1] = 0xFF;
172                 v4trailer[2] = siglen >> 24;
173                 v4trailer[3] = (siglen >> 16) & 0xFF;
174                 v4trailer[4] = (siglen >> 8) & 0xFF;
175                 v4trailer[5] = siglen & 0xFF;
176                 hashdata[chunks] = v4trailer;
177                 hashlen[chunks] = 6;
178                 chunks++;
179
180                 unhashedlen = (sig->data[siglen] << 8) +
181                         sig->data[siglen + 1];
182                 sighash = &sig->data[siglen + unhashedlen + 2];
183                 break;
184         default:
185                 get_keyid(key, &keyid);
186                 logthing(LOGTHING_ERROR,
187                         "Unknown signature version %d on 0x%016" PRIX64,
188                         sig->data[0], keyid);
189                 return -1;
190         }
191
192         switch (hashtype) {
193         case OPENPGP_HASH_MD5:
194                 md5_init(&md5_context);
195                 for (i = 0; i < chunks; i++) {
196                         md5_update(&md5_context, hashlen[i], hashdata[i]);
197                 }
198                 md5_digest(&md5_context, 16, hash);
199                 break;
200         case OPENPGP_HASH_SHA1:
201                 sha1_init(&sha1_context);
202                 for (i = 0; i < chunks; i++) {
203                         sha1_update(&sha1_context, hashlen[i], hashdata[i]);
204                 }
205                 sha1_digest(&sha1_context, 20, hash);
206                 break;
207         case OPENPGP_HASH_SHA1X:
208                 sha1x_init(&sha1x_context);
209                 for (i = 0; i < chunks; i++) {
210                         sha1x_update(&sha1x_context, hashlen[i], hashdata[i]);
211                 }
212                 sha1x_digest(&sha1x_context, 20, hash);
213                 break;
214 #ifdef HAVE_NETTLE
215         case OPENPGP_HASH_RIPEMD160:
216                 ripemd160_init(&ripemd160_context);
217                 for (i = 0; i < chunks; i++) {
218                         ripemd160_update(&ripemd160_context, hashlen[i],
219                                 hashdata[i]);
220                 }
221                 ripemd160_digest(&ripemd160_context, RIPEMD160_DIGEST_SIZE,
222                         hash);
223                 break;
224         case OPENPGP_HASH_SHA224:
225                 sha224_init(&sha224_context);
226                 for (i = 0; i < chunks; i++) {
227                         sha224_update(&sha224_context, hashlen[i],
228                                 hashdata[i]);
229                 }
230                 sha224_digest(&sha224_context, SHA224_DIGEST_SIZE, hash);
231                 break;
232         case OPENPGP_HASH_SHA256:
233                 sha256_init(&sha256_context);
234                 for (i = 0; i < chunks; i++) {
235                         sha256_update(&sha256_context, hashlen[i],
236                                 hashdata[i]);
237                 }
238                 sha256_digest(&sha256_context, SHA256_DIGEST_SIZE, hash);
239                 break;
240         case OPENPGP_HASH_SHA384:
241                 sha384_init(&sha384_context);
242                 for (i = 0; i < chunks; i++) {
243                         sha384_update(&sha384_context, hashlen[i],
244                                 hashdata[i]);
245                 }
246                 sha384_digest(&sha384_context, SHA384_DIGEST_SIZE, hash);
247                 break;
248         case OPENPGP_HASH_SHA512:
249                 sha512_init(&sha512_context);
250                 for (i = 0; i < chunks; i++) {
251                         sha512_update(&sha512_context, hashlen[i],
252                                 hashdata[i]);
253                 }
254                 sha512_digest(&sha512_context, SHA512_DIGEST_SIZE, hash);
255                 break;
256 #endif
257         default:
258                 get_keyid(key, &keyid);
259                 logthing(LOGTHING_ERROR,
260                         "Unsupported signature hash type %d on 0x%016" PRIX64,
261                         hashtype,
262                         keyid);
263                 return -1;
264         }
265
266         logthing(LOGTHING_DEBUG, "Hash type: %d, %d chunks, "
267                 "calculated: %02X%02X / actual: %02X%02X",
268                 hashtype, chunks,
269                 hash[0], hash[1], sighash[0], sighash[1]);
270
271         return (hash[0] == sighash[0] && hash[1] == sighash[1]);
272 }