2 * sigcheck.c - routines to check OpenPGP signatures
4 * Copyright 2012 Jonathan McDowell <noodles@earth.li>
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.
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
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.
23 #include "keystructs.h"
29 #include <nettle/md5.h>
30 #include <nettle/sha.h>
36 int check_packet_sighash(struct openpgp_publickey *key,
37 struct openpgp_packet *packet,
38 struct openpgp_packet *sig)
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;
48 #ifdef NETTLE_WITH_SHA256
49 struct sha256_ctx sha256_context;
51 #ifdef NETTLE_WITH_SHA384
52 struct sha384_ctx sha384_context;
54 #ifdef NETTLE_WITH_SHA512
55 struct sha512_ctx sha512_context;
58 uint8_t packetheader[5];
66 keyheader[1] = key->publickey->length >> 8;
67 keyheader[2] = key->publickey->length & 0xFF;
68 hashdata[0] = keyheader;
70 hashdata[1] = key->publickey->data;
71 hashlen[1] = key->publickey->length;
74 switch (sig->data[0]) {
77 hashtype = sig->data[16];
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;
89 // TODO: Things other than UIDS/subkeys?
90 hashdata[chunks] = packet->data;
91 hashlen[chunks] = packet->length;
95 hashdata[chunks] = &sig->data[2];
98 sighash = &sig->data[17];
101 hashtype = sig->data[3];
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;
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;
123 hashdata[chunks] = packet->data;
124 hashlen[chunks] = packet->length;
128 hashdata[chunks] = sig->data;
129 hashlen[chunks] = siglen = (sig->data[4] << 8) +
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;
143 unhashedlen = (sig->data[siglen] << 8) +
144 sig->data[siglen + 1];
145 sighash = &sig->data[siglen + unhashedlen + 2];
148 logthing(LOGTHING_ERROR, "Unknown signature version %d",
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]);
159 md5_digest(&md5_context, 16, hash);
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]);
166 sha1_digest(&sha1_context, 20, hash);
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],
175 sha224_digest(&sha224_context, SHA224_DIGEST_SIZE, hash);
177 logthing(LOGTHING_INFO, "SHA224 support not available.");
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],
187 sha256_digest(&sha256_context, SHA256_DIGEST_SIZE, hash);
189 logthing(LOGTHING_INFO, "SHA256 support not available.");
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],
199 sha384_digest(&sha384_context, SHA384_DIGEST_SIZE, hash);
201 logthing(LOGTHING_INFO, "SHA384 support not available.");
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],
211 sha512_digest(&sha512_context, SHA512_DIGEST_SIZE, hash);
213 logthing(LOGTHING_INFO, "SHA512 support not available.");
217 logthing(LOGTHING_ERROR, "Unsupported signature hash type %d",
222 logthing(LOGTHING_DEBUG, "Hash type: %d, %d chunks, "
223 "calculated: %02X%02X / actual: %02X%02X\n",
225 hash[0], hash[1], sighash[0], sighash[1]);
227 return (hash[0] == sighash[0] && hash[1] == sighash[1]);