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