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