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/ripemd160.h>
31 #include <nettle/sha.h>
37 int check_packet_sighash(struct openpgp_publickey *key,
38 struct openpgp_packet *packet,
39 struct openpgp_packet *sig)
43 size_t siglen, unhashedlen;
44 struct sha1_ctx sha1_context;
45 struct md5_ctx md5_context;
46 #ifdef NETTLE_WITH_RIPEMD160
47 struct ripemd160_ctx ripemd160_context;
49 #ifdef NETTLE_WITH_SHA224
50 struct sha224_ctx sha224_context;
52 #ifdef NETTLE_WITH_SHA256
53 struct sha256_ctx sha256_context;
55 #ifdef NETTLE_WITH_SHA384
56 struct sha384_ctx sha384_context;
58 #ifdef NETTLE_WITH_SHA512
59 struct sha512_ctx sha512_context;
62 uint8_t packetheader[5];
70 keyheader[1] = key->publickey->length >> 8;
71 keyheader[2] = key->publickey->length & 0xFF;
72 hashdata[0] = keyheader;
74 hashdata[1] = key->publickey->data;
75 hashlen[1] = key->publickey->length;
78 switch (sig->data[0]) {
81 hashtype = sig->data[16];
84 if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
85 packetheader[0] = 0x99;
86 packetheader[1] = packet->length >> 8;
87 packetheader[2] = packet->length & 0xFF;
88 hashdata[chunks] = packetheader;
93 // TODO: Things other than UIDS/subkeys?
94 hashdata[chunks] = packet->data;
95 hashlen[chunks] = packet->length;
99 hashdata[chunks] = &sig->data[2];
102 sighash = &sig->data[17];
105 hashtype = sig->data[3];
107 if (packet != NULL) {
108 if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
109 packetheader[0] = 0x99;
110 packetheader[1] = packet->length >> 8;
111 packetheader[2] = packet->length & 0xFF;
112 hashdata[chunks] = packetheader;
115 } else if (packet->tag == OPENPGP_PACKET_UID ||
116 packet->tag == OPENPGP_PACKET_UAT) {
117 packetheader[0] = (packet->tag ==
118 OPENPGP_PACKET_UID) ? 0xB4 : 0xD1;
119 packetheader[1] = packet->length >> 24;
120 packetheader[2] = (packet->length >> 16) & 0xFF;
121 packetheader[3] = (packet->length >> 8) & 0xFF;
122 packetheader[4] = packet->length & 0xFF;
123 hashdata[chunks] = packetheader;
127 hashdata[chunks] = packet->data;
128 hashlen[chunks] = packet->length;
132 hashdata[chunks] = sig->data;
133 hashlen[chunks] = siglen = (sig->data[4] << 8) +
139 v4trailer[2] = siglen >> 24;
140 v4trailer[3] = (siglen >> 16) & 0xFF;
141 v4trailer[4] = (siglen >> 8) & 0xFF;
142 v4trailer[5] = siglen & 0xFF;
143 hashdata[chunks] = v4trailer;
147 unhashedlen = (sig->data[siglen] << 8) +
148 sig->data[siglen + 1];
149 sighash = &sig->data[siglen + unhashedlen + 2];
152 logthing(LOGTHING_ERROR, "Unknown signature version %d",
158 case OPENPGP_HASH_MD5:
159 md5_init(&md5_context);
160 for (i = 0; i < chunks; i++) {
161 md5_update(&md5_context, hashlen[i], hashdata[i]);
163 md5_digest(&md5_context, 16, hash);
165 case OPENPGP_HASH_SHA1:
166 sha1_init(&sha1_context);
167 for (i = 0; i < chunks; i++) {
168 sha1_update(&sha1_context, hashlen[i], hashdata[i]);
170 sha1_digest(&sha1_context, 20, hash);
172 case OPENPGP_HASH_RIPEMD160:
173 #ifdef NETTLE_WITH_RIPEMD160
174 ripemd160_init(&ripemd160_context);
175 for (i = 0; i < chunks; i++) {
176 ripemd160_update(&ripemd160_context, hashlen[i],
179 ripemd160_digest(&ripemd160_context, RIPEMD160_DIGEST_SIZE,
182 logthing(LOGTHING_INFO, "RIPEMD160 support not available.");
185 case OPENPGP_HASH_SHA224:
186 #ifdef NETTLE_WITH_SHA224
187 sha224_init(&sha224_context);
188 for (i = 0; i < chunks; i++) {
189 sha224_update(&sha224_context, hashlen[i],
192 sha224_digest(&sha224_context, SHA224_DIGEST_SIZE, hash);
195 logthing(LOGTHING_INFO, "SHA224 support not available.");
198 case OPENPGP_HASH_SHA256:
199 #ifdef NETTLE_WITH_SHA256
200 sha256_init(&sha256_context);
201 for (i = 0; i < chunks; i++) {
202 sha256_update(&sha256_context, hashlen[i],
205 sha256_digest(&sha256_context, SHA256_DIGEST_SIZE, hash);
208 logthing(LOGTHING_INFO, "SHA256 support not available.");
211 case OPENPGP_HASH_SHA384:
212 #ifdef NETTLE_WITH_SHA384
213 sha384_init(&sha384_context);
214 for (i = 0; i < chunks; i++) {
215 sha384_update(&sha384_context, hashlen[i],
218 sha384_digest(&sha384_context, SHA384_DIGEST_SIZE, hash);
221 logthing(LOGTHING_INFO, "SHA384 support not available.");
224 case OPENPGP_HASH_SHA512:
225 #ifdef NETTLE_WITH_SHA512
226 sha512_init(&sha512_context);
227 for (i = 0; i < chunks; i++) {
228 sha512_update(&sha512_context, hashlen[i],
231 sha512_digest(&sha512_context, SHA512_DIGEST_SIZE, hash);
234 logthing(LOGTHING_INFO, "SHA512 support not available.");
238 logthing(LOGTHING_ERROR, "Unsupported signature hash type %d",
243 logthing(LOGTHING_DEBUG, "Hash type: %d, %d chunks, "
244 "calculated: %02X%02X / actual: %02X%02X\n",
246 hash[0], hash[1], sighash[0], sighash[1]);
248 return (hash[0] == sighash[0] && hash[1] == sighash[1]);