]> git.sommitrealweird.co.uk Git - onak.git/blob - sigcheck.c
fc046266248df3d8dd98d6f127758a1c6d163189
[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 #else
177                 logthing(LOGTHING_INFO, "SHA224 support not available.");
178 #endif
179                 break;
180         case OPENPGP_HASH_SHA256:
181 #ifdef NETTLE_WITH_SHA256
182                 sha256_init(&sha256_context);
183                 for (i = 0; i < chunks; i++) {
184                         sha256_update(&sha256_context, hashlen[i],
185                                 hashdata[i]);
186                 }
187                 sha256_digest(&sha256_context, SHA256_DIGEST_SIZE, hash);
188 #else
189                 logthing(LOGTHING_INFO, "SHA256 support not available.");
190 #endif
191                 break;
192         case OPENPGP_HASH_SHA384:
193 #ifdef NETTLE_WITH_SHA384
194                 sha384_init(&sha384_context);
195                 for (i = 0; i < chunks; i++) {
196                         sha384_update(&sha384_context, hashlen[i],
197                                 hashdata[i]);
198                 }
199                 sha384_digest(&sha384_context, SHA384_DIGEST_SIZE, hash);
200 #else
201                 logthing(LOGTHING_INFO, "SHA384 support not available.");
202 #endif
203                 break;
204         case OPENPGP_HASH_SHA512:
205 #ifdef NETTLE_WITH_SHA512
206                 sha512_init(&sha512_context);
207                 for (i = 0; i < chunks; i++) {
208                         sha512_update(&sha512_context, hashlen[i],
209                                 hashdata[i]);
210                 }
211                 sha512_digest(&sha512_context, SHA512_DIGEST_SIZE, hash);
212 #else
213                 logthing(LOGTHING_INFO, "SHA512 support not available.");
214 #endif
215                 break;
216         default:
217                 logthing(LOGTHING_ERROR, "Unsupported signature hash type %d",
218                                 hashtype);
219                 return -1;
220         }
221
222         logthing(LOGTHING_DEBUG, "Hash type: %d, %d chunks, "
223                 "calculated: %02X%02X / actual: %02X%02X\n",
224                 hashtype, chunks,
225                 hash[0], hash[1], sighash[0], sighash[1]);
226
227         return (hash[0] == sighash[0] && hash[1] == sighash[1]);
228 }