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