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.
24 #include "keystructs.h"
30 #include <nettle/md5.h>
31 #include <nettle/ripemd160.h>
32 #include <nettle/sha.h>
38 int check_packet_sighash(struct openpgp_publickey *key,
39 struct openpgp_packet *packet,
40 struct openpgp_packet *sig)
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;
50 #ifdef NETTLE_WITH_SHA224
51 struct sha224_ctx sha224_context;
53 #ifdef NETTLE_WITH_SHA256
54 struct sha256_ctx sha256_context;
56 #ifdef NETTLE_WITH_SHA384
57 struct sha384_ctx sha384_context;
59 #ifdef NETTLE_WITH_SHA512
60 struct sha512_ctx sha512_context;
63 uint8_t packetheader[5];
72 keyheader[1] = key->publickey->length >> 8;
73 keyheader[2] = key->publickey->length & 0xFF;
74 hashdata[0] = keyheader;
76 hashdata[1] = key->publickey->data;
77 hashlen[1] = key->publickey->length;
80 switch (sig->data[0]) {
83 hashtype = sig->data[16];
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;
95 // TODO: Things other than UIDS/subkeys?
96 hashdata[chunks] = packet->data;
97 hashlen[chunks] = packet->length;
101 hashdata[chunks] = &sig->data[2];
104 sighash = &sig->data[17];
107 hashtype = sig->data[3];
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;
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;
129 hashdata[chunks] = packet->data;
130 hashlen[chunks] = packet->length;
134 hashdata[chunks] = sig->data;
135 hashlen[chunks] = siglen = (sig->data[4] << 8) +
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;
149 unhashedlen = (sig->data[siglen] << 8) +
150 sig->data[siglen + 1];
151 sighash = &sig->data[siglen + unhashedlen + 2];
154 get_keyid(key, &keyid);
155 logthing(LOGTHING_ERROR,
156 "Unknown signature version %d on 0x%016" PRIX64,
157 sig->data[0], keyid);
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]);
167 md5_digest(&md5_context, 16, hash);
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]);
174 sha1_digest(&sha1_context, 20, hash);
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],
183 ripemd160_digest(&ripemd160_context, RIPEMD160_DIGEST_SIZE,
186 logthing(LOGTHING_INFO, "RIPEMD160 support not available.");
189 case OPENPGP_HASH_SHA224:
190 #ifdef NETTLE_WITH_SHA224
191 sha224_init(&sha224_context);
192 for (i = 0; i < chunks; i++) {
193 sha224_update(&sha224_context, hashlen[i],
196 sha224_digest(&sha224_context, SHA224_DIGEST_SIZE, hash);
199 logthing(LOGTHING_INFO, "SHA224 support not available.");
202 case OPENPGP_HASH_SHA256:
203 #ifdef NETTLE_WITH_SHA256
204 sha256_init(&sha256_context);
205 for (i = 0; i < chunks; i++) {
206 sha256_update(&sha256_context, hashlen[i],
209 sha256_digest(&sha256_context, SHA256_DIGEST_SIZE, hash);
212 logthing(LOGTHING_INFO, "SHA256 support not available.");
215 case OPENPGP_HASH_SHA384:
216 #ifdef NETTLE_WITH_SHA384
217 sha384_init(&sha384_context);
218 for (i = 0; i < chunks; i++) {
219 sha384_update(&sha384_context, hashlen[i],
222 sha384_digest(&sha384_context, SHA384_DIGEST_SIZE, hash);
225 logthing(LOGTHING_INFO, "SHA384 support not available.");
228 case OPENPGP_HASH_SHA512:
229 #ifdef NETTLE_WITH_SHA512
230 sha512_init(&sha512_context);
231 for (i = 0; i < chunks; i++) {
232 sha512_update(&sha512_context, hashlen[i],
235 sha512_digest(&sha512_context, SHA512_DIGEST_SIZE, hash);
238 logthing(LOGTHING_INFO, "SHA512 support not available.");
242 get_keyid(key, &keyid);
243 logthing(LOGTHING_ERROR,
244 "Unsupported signature hash type %d on 0x%016" PRIX64,
250 logthing(LOGTHING_DEBUG, "Hash type: %d, %d chunks, "
251 "calculated: %02X%02X / actual: %02X%02X\n",
253 hash[0], hash[1], sighash[0], sighash[1]);
255 return (hash[0] == sighash[0] && hash[1] == sighash[1]);