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, see <https://www.gnu.org/licenses/>.
21 #include "build-config.h"
22 #include "decodekey.h"
24 #include "keystructs.h"
30 #include <nettle/md5.h>
31 #include <nettle/ripemd160.h>
32 #include <nettle/sha.h>
39 onak_status_t calculate_packet_sighash(struct openpgp_publickey *key,
40 struct openpgp_packet *packet,
41 struct openpgp_packet *sig,
46 size_t siglen, unhashedlen;
47 struct sha1_ctx sha1_context;
48 struct sha1x_ctx sha1x_context;
49 struct md5_ctx md5_context;
51 struct ripemd160_ctx ripemd160_context;
52 struct sha224_ctx sha224_context;
53 struct sha256_ctx sha256_context;
54 struct sha384_ctx sha384_context;
55 struct sha512_ctx sha512_context;
58 uint8_t packetheader[5];
69 switch (sig->data[0]) {
73 keyheader[1] = key->publickey->length >> 8;
74 keyheader[2] = key->publickey->length & 0xFF;
75 hashdata[0] = keyheader;
77 hashdata[1] = key->publickey->data;
78 hashlen[1] = key->publickey->length;
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];
106 keyheader[1] = key->publickey->length >> 8;
107 keyheader[2] = key->publickey->length & 0xFF;
108 hashdata[0] = keyheader;
110 hashdata[1] = key->publickey->data;
111 hashlen[1] = key->publickey->length;
114 /* Check to see if this is an X509 based signature */
115 if (sig->data[2] == 0 || sig->data[2] == 100) {
119 res = parse_subpackets(&sig->data[4],
120 sig->length - 4, &len,
122 if (res != ONAK_E_OK) {
126 /* No unhashed data */
127 sig->data[4 + len] == 0 &&
128 sig->data[5 + len] == 0 &&
129 /* Dummy 0 checksum */
130 sig->data[6 + len] == 0 &&
131 sig->data[7 + len] == 0 &&
133 sig->data[8 + len] == 0 &&
134 sig->data[9 + len] == 1 &&
135 sig->data[10 + len] == 1) {
136 return ONAK_E_UNSUPPORTED_FEATURE;
140 *hashtype = sig->data[3];
142 if (packet != NULL) {
143 if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
144 packetheader[0] = 0x99;
145 packetheader[1] = packet->length >> 8;
146 packetheader[2] = packet->length & 0xFF;
147 hashdata[chunks] = packetheader;
150 } else if (packet->tag == OPENPGP_PACKET_UID ||
151 packet->tag == OPENPGP_PACKET_UAT) {
152 packetheader[0] = (packet->tag ==
153 OPENPGP_PACKET_UID) ? 0xB4 : 0xD1;
154 packetheader[1] = packet->length >> 24;
155 packetheader[2] = (packet->length >> 16) & 0xFF;
156 packetheader[3] = (packet->length >> 8) & 0xFF;
157 packetheader[4] = packet->length & 0xFF;
158 hashdata[chunks] = packetheader;
162 hashdata[chunks] = packet->data;
163 hashlen[chunks] = packet->length;
167 hashdata[chunks] = sig->data;
168 hashlen[chunks] = siglen = (sig->data[4] << 8) +
170 if (siglen > sig->length) {
171 /* Signature data exceed packet length, bogus */
172 return ONAK_E_INVALID_PKT;
178 trailer[2] = siglen >> 24;
179 trailer[3] = (siglen >> 16) & 0xFF;
180 trailer[4] = (siglen >> 8) & 0xFF;
181 trailer[5] = siglen & 0xFF;
182 hashdata[chunks] = trailer;
186 unhashedlen = (sig->data[siglen] << 8) +
187 sig->data[siglen + 1];
188 *sighash = &sig->data[siglen + unhashedlen + 2];
194 keyheader[3] = key->publickey->length >> 8;
195 keyheader[4] = key->publickey->length & 0xFF;
196 hashdata[0] = keyheader;
198 hashdata[1] = key->publickey->data;
199 hashlen[1] = key->publickey->length;
202 *hashtype = sig->data[3];
204 if (packet != NULL) {
205 if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
206 packetheader[0] = 0x9A;
209 packetheader[3] = packet->length >> 8;
210 packetheader[4] = packet->length & 0xFF;
211 hashdata[chunks] = packetheader;
214 } else if (packet->tag == OPENPGP_PACKET_UID ||
215 packet->tag == OPENPGP_PACKET_UAT) {
216 packetheader[0] = (packet->tag ==
217 OPENPGP_PACKET_UID) ? 0xB4 : 0xD1;
218 packetheader[1] = packet->length >> 24;
219 packetheader[2] = (packet->length >> 16) & 0xFF;
220 packetheader[3] = (packet->length >> 8) & 0xFF;
221 packetheader[4] = packet->length & 0xFF;
222 hashdata[chunks] = packetheader;
226 hashdata[chunks] = packet->data;
227 hashlen[chunks] = packet->length;
231 hashdata[chunks] = sig->data;
232 hashlen[chunks] = siglen = (sig->data[4] << 8) +
234 if (siglen > sig->length) {
235 /* Signature data exceed packet length, bogus */
236 return ONAK_E_INVALID_PKT;
246 trailer[6] = siglen >> 24;
247 trailer[7] = (siglen >> 16) & 0xFF;
248 trailer[8] = (siglen >> 8) & 0xFF;
249 trailer[9] = siglen & 0xFF;
250 hashdata[chunks] = trailer;
251 hashlen[chunks] = 10;
254 unhashedlen = (sig->data[siglen] << 8) +
255 sig->data[siglen + 1];
256 *sighash = &sig->data[siglen + unhashedlen + 2];
259 return ONAK_E_UNSUPPORTED_FEATURE;
263 case OPENPGP_HASH_MD5:
264 md5_init(&md5_context);
265 for (i = 0; i < chunks; i++) {
266 md5_update(&md5_context, hashlen[i], hashdata[i]);
268 md5_digest(&md5_context, MD5_DIGEST_SIZE, hash);
270 case OPENPGP_HASH_SHA1:
271 sha1_init(&sha1_context);
272 for (i = 0; i < chunks; i++) {
273 sha1_update(&sha1_context, hashlen[i], hashdata[i]);
275 sha1_digest(&sha1_context, SHA1_DIGEST_SIZE, hash);
277 case OPENPGP_HASH_SHA1X:
278 sha1x_init(&sha1x_context);
279 for (i = 0; i < chunks; i++) {
280 sha1x_update(&sha1x_context, hashlen[i], hashdata[i]);
282 sha1x_digest(&sha1x_context, SHA1X_DIGEST_SIZE, hash);
285 case OPENPGP_HASH_RIPEMD160:
286 ripemd160_init(&ripemd160_context);
287 for (i = 0; i < chunks; i++) {
288 ripemd160_update(&ripemd160_context, hashlen[i],
291 ripemd160_digest(&ripemd160_context, RIPEMD160_DIGEST_SIZE,
294 case OPENPGP_HASH_SHA224:
295 sha224_init(&sha224_context);
296 for (i = 0; i < chunks; i++) {
297 sha224_update(&sha224_context, hashlen[i],
300 sha224_digest(&sha224_context, SHA224_DIGEST_SIZE, hash);
302 case OPENPGP_HASH_SHA256:
303 sha256_init(&sha256_context);
304 for (i = 0; i < chunks; i++) {
305 sha256_update(&sha256_context, hashlen[i],
308 sha256_digest(&sha256_context, SHA256_DIGEST_SIZE, hash);
310 case OPENPGP_HASH_SHA384:
311 sha384_init(&sha384_context);
312 for (i = 0; i < chunks; i++) {
313 sha384_update(&sha384_context, hashlen[i],
316 sha384_digest(&sha384_context, SHA384_DIGEST_SIZE, hash);
318 case OPENPGP_HASH_SHA512:
319 sha512_init(&sha512_context);
320 for (i = 0; i < chunks; i++) {
321 sha512_update(&sha512_context, hashlen[i],
324 sha512_digest(&sha512_context, SHA512_DIGEST_SIZE, hash);
328 return ONAK_E_UNSUPPORTED_FEATURE;