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];
66 switch (sig->data[0]) {
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 *hashtype = sig->data[16];
81 if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
82 packetheader[0] = 0x99;
83 packetheader[1] = packet->length >> 8;
84 packetheader[2] = packet->length & 0xFF;
85 hashdata[chunks] = packetheader;
90 // TODO: Things other than UIDS/subkeys?
91 hashdata[chunks] = packet->data;
92 hashlen[chunks] = packet->length;
96 hashdata[chunks] = &sig->data[2];
99 *sighash = &sig->data[17];
103 keyheader[1] = key->publickey->length >> 8;
104 keyheader[2] = key->publickey->length & 0xFF;
105 hashdata[0] = keyheader;
107 hashdata[1] = key->publickey->data;
108 hashlen[1] = key->publickey->length;
111 *hashtype = sig->data[3];
113 /* Check to see if this is an X509 based signature */
114 if (sig->data[2] == 0 || sig->data[2] == 100) {
118 res = parse_subpackets(&sig->data[4],
119 sig->length - 4, &len,
121 if (res != ONAK_E_OK) {
125 /* No unhashed data */
126 sig->data[4 + len] == 0 &&
127 sig->data[5 + len] == 0 &&
128 /* Dummy 0 checksum */
129 sig->data[6 + len] == 0 &&
130 sig->data[7 + len] == 0 &&
132 sig->data[8 + len] == 0 &&
133 sig->data[9 + len] == 1 &&
134 sig->data[10 + len] == 1) {
135 return ONAK_E_UNSUPPORTED_FEATURE;
139 if (packet != NULL) {
140 if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
141 packetheader[0] = 0x99;
142 packetheader[1] = packet->length >> 8;
143 packetheader[2] = packet->length & 0xFF;
144 hashdata[chunks] = packetheader;
147 } else if (packet->tag == OPENPGP_PACKET_UID ||
148 packet->tag == OPENPGP_PACKET_UAT) {
149 packetheader[0] = (packet->tag ==
150 OPENPGP_PACKET_UID) ? 0xB4 : 0xD1;
151 packetheader[1] = packet->length >> 24;
152 packetheader[2] = (packet->length >> 16) & 0xFF;
153 packetheader[3] = (packet->length >> 8) & 0xFF;
154 packetheader[4] = packet->length & 0xFF;
155 hashdata[chunks] = packetheader;
159 hashdata[chunks] = packet->data;
160 hashlen[chunks] = packet->length;
164 hashdata[chunks] = sig->data;
165 hashlen[chunks] = siglen = (sig->data[4] << 8) +
167 if (siglen > sig->length) {
168 /* Signature data exceed packet length, bogus */
169 return ONAK_E_INVALID_PKT;
175 trailer[2] = siglen >> 24;
176 trailer[3] = (siglen >> 16) & 0xFF;
177 trailer[4] = (siglen >> 8) & 0xFF;
178 trailer[5] = siglen & 0xFF;
179 hashdata[chunks] = trailer;
183 unhashedlen = (sig->data[siglen] << 8) +
184 sig->data[siglen + 1];
185 *sighash = &sig->data[siglen + unhashedlen + 2];
191 keyheader[3] = key->publickey->length >> 8;
192 keyheader[4] = key->publickey->length & 0xFF;
193 hashdata[0] = keyheader;
195 hashdata[1] = key->publickey->data;
196 hashlen[1] = key->publickey->length;
199 *hashtype = sig->data[3];
201 if (packet != NULL) {
202 if (packet->tag == OPENPGP_PACKET_PUBLICSUBKEY) {
203 packetheader[0] = 0x9A;
206 packetheader[3] = packet->length >> 8;
207 packetheader[4] = packet->length & 0xFF;
208 hashdata[chunks] = packetheader;
211 } else if (packet->tag == OPENPGP_PACKET_UID ||
212 packet->tag == OPENPGP_PACKET_UAT) {
213 packetheader[0] = (packet->tag ==
214 OPENPGP_PACKET_UID) ? 0xB4 : 0xD1;
215 packetheader[1] = packet->length >> 24;
216 packetheader[2] = (packet->length >> 16) & 0xFF;
217 packetheader[3] = (packet->length >> 8) & 0xFF;
218 packetheader[4] = packet->length & 0xFF;
219 hashdata[chunks] = packetheader;
223 hashdata[chunks] = packet->data;
224 hashlen[chunks] = packet->length;
228 hashdata[chunks] = sig->data;
229 hashlen[chunks] = siglen = (sig->data[4] << 8) +
231 if (siglen > sig->length) {
232 /* Signature data exceed packet length, bogus */
233 return ONAK_E_INVALID_PKT;
243 trailer[6] = siglen >> 24;
244 trailer[7] = (siglen >> 16) & 0xFF;
245 trailer[8] = (siglen >> 8) & 0xFF;
246 trailer[9] = siglen & 0xFF;
247 hashdata[chunks] = trailer;
248 hashlen[chunks] = 10;
251 unhashedlen = (sig->data[siglen] << 8) +
252 sig->data[siglen + 1];
253 *sighash = &sig->data[siglen + unhashedlen + 2];
256 return ONAK_E_UNSUPPORTED_FEATURE;
260 case OPENPGP_HASH_MD5:
261 md5_init(&md5_context);
262 for (i = 0; i < chunks; i++) {
263 md5_update(&md5_context, hashlen[i], hashdata[i]);
265 md5_digest(&md5_context, 16, hash);
267 case OPENPGP_HASH_SHA1:
268 sha1_init(&sha1_context);
269 for (i = 0; i < chunks; i++) {
270 sha1_update(&sha1_context, hashlen[i], hashdata[i]);
272 sha1_digest(&sha1_context, 20, hash);
274 case OPENPGP_HASH_SHA1X:
275 sha1x_init(&sha1x_context);
276 for (i = 0; i < chunks; i++) {
277 sha1x_update(&sha1x_context, hashlen[i], hashdata[i]);
279 sha1x_digest(&sha1x_context, 20, hash);
282 case OPENPGP_HASH_RIPEMD160:
283 ripemd160_init(&ripemd160_context);
284 for (i = 0; i < chunks; i++) {
285 ripemd160_update(&ripemd160_context, hashlen[i],
288 ripemd160_digest(&ripemd160_context, RIPEMD160_DIGEST_SIZE,
291 case OPENPGP_HASH_SHA224:
292 sha224_init(&sha224_context);
293 for (i = 0; i < chunks; i++) {
294 sha224_update(&sha224_context, hashlen[i],
297 sha224_digest(&sha224_context, SHA224_DIGEST_SIZE, hash);
299 case OPENPGP_HASH_SHA256:
300 sha256_init(&sha256_context);
301 for (i = 0; i < chunks; i++) {
302 sha256_update(&sha256_context, hashlen[i],
305 sha256_digest(&sha256_context, SHA256_DIGEST_SIZE, hash);
307 case OPENPGP_HASH_SHA384:
308 sha384_init(&sha384_context);
309 for (i = 0; i < chunks; i++) {
310 sha384_update(&sha384_context, hashlen[i],
313 sha384_digest(&sha384_context, SHA384_DIGEST_SIZE, hash);
315 case OPENPGP_HASH_SHA512:
316 sha512_init(&sha512_context);
317 for (i = 0; i < chunks; i++) {
318 sha512_update(&sha512_context, hashlen[i],
321 sha512_digest(&sha512_context, SHA512_DIGEST_SIZE, hash);
325 return ONAK_E_UNSUPPORTED_FEATURE;