1 /*-
2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@NetBSD.org)
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*
30 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31 * All rights reserved.
32 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33 * their moral rights under the UK Copyright Design and Patents Act 1988 to
34 * be recorded as the authors of this copyright work.
35 *
36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37 * use this file except in compliance with the License.
38 *
39 * You may obtain a copy of the License at
40 * http://www.apache.org/licenses/LICENSE-2.0
41 *
42 * Unless required by applicable law or agreed to in writing, software
43 * distributed under the License is distributed on an "AS IS" BASIS,
44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
45 *
46 * See the License for the specific language governing permissions and
47 * limitations under the License.
48 */
49 #include "config.h"
50
51 #ifdef HAVE_SYS_CDEFS_H
52 #include <sys/cdefs.h>
53 #endif
54
55 #if defined(__NetBSD__)
56 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
57 __RCSID("$NetBSD: validate.c,v 1.44 2012/03/05 02:20:18 christos Exp $");
58 #endif
59
60 #include <sys/types.h>
61 #include <sys/param.h>
62 #include <sys/stat.h>
63
64 #include <string.h>
65 #include <stdio.h>
66
67 #ifdef HAVE_UNISTD_H
68 #include <unistd.h>
69 #endif
70
71 #ifdef HAVE_FCNTL_H
72 #include <fcntl.h>
73 #endif
74
75 #include "packet-parse.h"
76 #include "packet-show.h"
77 #include "keyring.h"
78 #include "signature.h"
79 #include "netpgpsdk.h"
80 #include "readerwriter.h"
81 #include "netpgpdefs.h"
82 #include "memory.h"
83 #include "packet.h"
84 #include "crypto.h"
85 #include "validate.h"
86
87 #ifdef HAVE_FCNTL_H
88 #include <fcntl.h>
89 #endif
90
91
92 static int
keydata_reader(pgp_stream_t * stream,void * dest,size_t length,pgp_error_t ** errors,pgp_reader_t * readinfo,pgp_cbdata_t * cbinfo)93 keydata_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors,
94 pgp_reader_t *readinfo,
95 pgp_cbdata_t *cbinfo)
96 {
97 validate_reader_t *reader = pgp_reader_get_arg(readinfo);
98
99 __PGP_USED(stream);
100 __PGP_USED(errors);
101 __PGP_USED(cbinfo);
102 if (reader->offset == reader->key->packets[reader->packet].length) {
103 reader->packet += 1;
104 reader->offset = 0;
105 }
106 if (reader->packet == reader->key->packetc) {
107 return 0;
108 }
109
110 /*
111 * we should never be asked to cross a packet boundary in a single
112 * read
113 */
114 if (reader->key->packets[reader->packet].length <
115 reader->offset + length) {
116 (void) fprintf(stderr, "keydata_reader: weird length\n");
117 return 0;
118 }
119
120 (void) memcpy(dest,
121 &reader->key->packets[reader->packet].raw[reader->offset],
122 length);
123 reader->offset += (unsigned)length;
124
125 return (int)length;
126 }
127
128 static void
free_sig_info(pgp_sig_info_t * sig)129 free_sig_info(pgp_sig_info_t *sig)
130 {
131 free(sig->v4_hashed);
132 free(sig);
133 }
134
135 static void
copy_sig_info(pgp_sig_info_t * dst,const pgp_sig_info_t * src)136 copy_sig_info(pgp_sig_info_t *dst, const pgp_sig_info_t *src)
137 {
138 (void) memcpy(dst, src, sizeof(*src));
139 if ((dst->v4_hashed = calloc(1, src->v4_hashlen)) == NULL) {
140 (void) fprintf(stderr, "copy_sig_info: bad alloc\n");
141 } else {
142 (void) memcpy(dst->v4_hashed, src->v4_hashed, src->v4_hashlen);
143 }
144 }
145
146 static int
add_sig_to_list(const pgp_sig_info_t * sig,pgp_sig_info_t ** sigs,unsigned * count)147 add_sig_to_list(const pgp_sig_info_t *sig, pgp_sig_info_t **sigs,
148 unsigned *count)
149 {
150 pgp_sig_info_t *newsigs;
151
152 if (*count == 0) {
153 newsigs = calloc(*count + 1, sizeof(pgp_sig_info_t));
154 } else {
155 newsigs = realloc(*sigs,
156 (*count + 1) * sizeof(pgp_sig_info_t));
157 }
158 if (newsigs == NULL) {
159 (void) fprintf(stderr, "add_sig_to_list: alloc failure\n");
160 return 0;
161 }
162 *sigs = newsigs;
163 copy_sig_info(&(*sigs)[*count], sig);
164 *count += 1;
165 return 1;
166 }
167
168 /*
169 The hash value is calculated by the following method:
170 + hash the data using the given digest algorithm
171 + hash the hash value onto the end
172 + hash the trailer - 6 bytes
173 [PGP_V4][0xff][len >> 24][len >> 16][len >> 8][len & 0xff]
174 to give the final hash value that is checked against the one in the signature
175 */
176
177 /* Does the signed hash match the given hash? */
178 unsigned
check_binary_sig(const uint8_t * data,const unsigned len,const pgp_sig_t * sig,const pgp_pubkey_t * signer)179 check_binary_sig(const uint8_t *data,
180 const unsigned len,
181 const pgp_sig_t *sig,
182 const pgp_pubkey_t *signer)
183 {
184 unsigned hashedlen;
185 pgp_hash_t hash;
186 unsigned n;
187 uint8_t hashout[PGP_MAX_HASH_SIZE];
188 uint8_t trailer[6];
189
190 pgp_hash_any(&hash, sig->info.hash_alg);
191 if (!hash.init(&hash)) {
192 (void) fprintf(stderr, "check_binary_sig: bad hash init\n");
193 return 0;
194 }
195 hash.add(&hash, data, len);
196 switch (sig->info.version) {
197 case PGP_V3:
198 trailer[0] = sig->info.type;
199 trailer[1] = (unsigned)(sig->info.birthtime) >> 24;
200 trailer[2] = (unsigned)(sig->info.birthtime) >> 16;
201 trailer[3] = (unsigned)(sig->info.birthtime) >> 8;
202 trailer[4] = (uint8_t)(sig->info.birthtime);
203 hash.add(&hash, trailer, 5);
204 break;
205
206 case PGP_V4:
207 if (pgp_get_debug_level(__FILE__)) {
208 hexdump(stderr, "v4 hash", sig->info.v4_hashed,
209 sig->info.v4_hashlen);
210 }
211 hash.add(&hash, sig->info.v4_hashed, (unsigned)sig->info.v4_hashlen);
212 trailer[0] = 0x04; /* version */
213 trailer[1] = 0xFF;
214 hashedlen = (unsigned)sig->info.v4_hashlen;
215 trailer[2] = (uint8_t)(hashedlen >> 24);
216 trailer[3] = (uint8_t)(hashedlen >> 16);
217 trailer[4] = (uint8_t)(hashedlen >> 8);
218 trailer[5] = (uint8_t)(hashedlen);
219 hash.add(&hash, trailer, 6);
220 break;
221
222 default:
223 (void) fprintf(stderr, "Invalid signature version %d\n",
224 sig->info.version);
225 return 0;
226 }
227
228 n = hash.finish(&hash, hashout);
229 if (pgp_get_debug_level(__FILE__)) {
230 hexdump(stdout, "hash out", hashout, n);
231 }
232 return pgp_check_sig(hashout, n, sig, signer);
233 }
234
235 pgp_cb_ret_t
pgp_validate_key_cb(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)236 pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
237 {
238 const pgp_contents_t *content = &pkt->u;
239 const pgp_key_t *signer;
240 validate_key_cb_t *key;
241 pgp_pubkey_t *sigkey;
242 pgp_error_t **errors;
243 pgp_io_t *io;
244 unsigned from;
245 unsigned valid = 0;
246
247 io = cbinfo->io;
248 if (pgp_get_debug_level(__FILE__)) {
249 (void) fprintf(io->errs, "%s\n",
250 pgp_show_packet_tag(pkt->tag));
251 }
252 key = pgp_callback_arg(cbinfo);
253 errors = pgp_callback_errors(cbinfo);
254 switch (pkt->tag) {
255 case PGP_PTAG_CT_PUBLIC_KEY:
256 if (key->pubkey.version != 0) {
257 (void) fprintf(io->errs,
258 "pgp_validate_key_cb: version bad\n");
259 return PGP_FINISHED;
260 }
261 key->pubkey = content->pubkey;
262 return PGP_KEEP_MEMORY;
263
264 case PGP_PTAG_CT_PUBLIC_SUBKEY:
265 if (key->subkey.version) {
266 pgp_pubkey_free(&key->subkey);
267 }
268 key->subkey = content->pubkey;
269 return PGP_KEEP_MEMORY;
270
271 case PGP_PTAG_CT_SECRET_KEY:
272 key->seckey = content->seckey;
273 key->pubkey = key->seckey.pubkey;
274 return PGP_KEEP_MEMORY;
275
276 case PGP_PTAG_CT_USER_ID:
277 if (key->userid) {
278 pgp_userid_free(&key->userid);
279 }
280 key->userid = content->userid;
281 key->last_seen = ID;
282 return PGP_KEEP_MEMORY;
283
284 case PGP_PTAG_CT_USER_ATTR:
285 if (content->userattr.len == 0) {
286 (void) fprintf(io->errs,
287 "pgp_validate_key_cb: user attribute length 0");
288 return PGP_FINISHED;
289 }
290 (void) fprintf(io->outs, "user attribute, length=%d\n",
291 (int) content->userattr.len);
292 if (key->userattr.len) {
293 pgp_data_free(&key->userattr);
294 }
295 key->userattr = content->userattr;
296 key->last_seen = ATTRIBUTE;
297 return PGP_KEEP_MEMORY;
298
299 case PGP_PTAG_CT_SIGNATURE: /* V3 sigs */
300 case PGP_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */
301 from = 0;
302 signer = pgp_getkeybyid(io, key->keyring,
303 content->sig.info.signer_id,
304 &from, &sigkey);
305 if (!signer) {
306 if (!add_sig_to_list(&content->sig.info,
307 &key->result->unknown_sigs,
308 &key->result->unknownc)) {
309 (void) fprintf(io->errs,
310 "pgp_validate_key_cb: user attribute length 0");
311 return PGP_FINISHED;
312 }
313 break;
314 }
315 if (sigkey == &signer->enckey) {
316 (void) fprintf(io->errs,
317 "WARNING: signature made with encryption key\n");
318 }
319 switch (content->sig.info.type) {
320 case PGP_CERT_GENERIC:
321 case PGP_CERT_PERSONA:
322 case PGP_CERT_CASUAL:
323 case PGP_CERT_POSITIVE:
324 case PGP_SIG_REV_CERT:
325 valid = (key->last_seen == ID) ?
326 pgp_check_useridcert_sig(&key->pubkey,
327 key->userid,
328 &content->sig,
329 pgp_get_pubkey(signer),
330 key->reader->key->packets[
331 key->reader->packet].raw) :
332 pgp_check_userattrcert_sig(&key->pubkey,
333 &key->userattr,
334 &content->sig,
335 pgp_get_pubkey(signer),
336 key->reader->key->packets[
337 key->reader->packet].raw);
338 break;
339
340 case PGP_SIG_SUBKEY:
341 /*
342 * XXX: we should also check that the signer is the
343 * key we are validating, I think.
344 */
345 valid = pgp_check_subkey_sig(&key->pubkey,
346 &key->subkey,
347 &content->sig,
348 pgp_get_pubkey(signer),
349 key->reader->key->packets[
350 key->reader->packet].raw);
351 break;
352
353 case PGP_SIG_DIRECT:
354 valid = pgp_check_direct_sig(&key->pubkey,
355 &content->sig,
356 pgp_get_pubkey(signer),
357 key->reader->key->packets[
358 key->reader->packet].raw);
359 break;
360
361 case PGP_SIG_STANDALONE:
362 case PGP_SIG_PRIMARY:
363 case PGP_SIG_REV_KEY:
364 case PGP_SIG_REV_SUBKEY:
365 case PGP_SIG_TIMESTAMP:
366 case PGP_SIG_3RD_PARTY:
367 PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED,
368 "Sig Verification type 0x%02x not done yet\n",
369 content->sig.info.type);
370 break;
371
372 default:
373 PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED,
374 "Unexpected signature type 0x%02x\n",
375 content->sig.info.type);
376 }
377
378 if (valid) {
379 if (!add_sig_to_list(&content->sig.info,
380 &key->result->valid_sigs,
381 &key->result->validc)) {
382 PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, "%s",
383 "Can't add good sig to list\n");
384 }
385 } else {
386 PGP_ERROR_1(errors, PGP_E_V_BAD_SIGNATURE, "%s",
387 "Bad Sig");
388 if (!add_sig_to_list(&content->sig.info,
389 &key->result->invalid_sigs,
390 &key->result->invalidc)) {
391 PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, "%s",
392 "Can't add good sig to list\n");
393 }
394 }
395 break;
396
397 /* ignore these */
398 case PGP_PARSER_PTAG:
399 case PGP_PTAG_CT_SIGNATURE_HEADER:
400 case PGP_PARSER_PACKET_END:
401 break;
402
403 case PGP_GET_PASSPHRASE:
404 if (key->getpassphrase) {
405 return key->getpassphrase(pkt, cbinfo);
406 }
407 break;
408
409 case PGP_PTAG_CT_TRUST:
410 /* 1 byte for level (depth), 1 byte for trust amount */
411 printf("trust dump\n");
412 printf("Got trust\n");
413 //hexdump(stdout, (const uint8_t *)content->trust.data, 10, " ");
414 //hexdump(stdout, (const uint8_t *)&content->ss_trust, 2, " ");
415 //printf("Trust level %d, amount %d\n", key->trust.level, key->trust.amount);
416 break;
417
418 default:
419 (void) fprintf(stderr, "unexpected tag=0x%x\n", pkt->tag);
420 return PGP_FINISHED;
421 }
422 return PGP_RELEASE_MEMORY;
423 }
424
425 pgp_cb_ret_t
validate_data_cb(const pgp_packet_t * pkt,pgp_cbdata_t * cbinfo)426 validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
427 {
428 const pgp_contents_t *content = &pkt->u;
429 const pgp_key_t *signer;
430 validate_data_cb_t *data;
431 pgp_pubkey_t *sigkey;
432 pgp_error_t **errors;
433 pgp_io_t *io;
434 unsigned from;
435 unsigned valid = 0;
436
437 io = cbinfo->io;
438 if (pgp_get_debug_level(__FILE__)) {
439 (void) fprintf(io->errs, "validate_data_cb: %s\n",
440 pgp_show_packet_tag(pkt->tag));
441 }
442 data = pgp_callback_arg(cbinfo);
443 errors = pgp_callback_errors(cbinfo);
444 switch (pkt->tag) {
445 case PGP_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
446 /*
447 * ignore - this gives us the "Armor Header" line "Hash:
448 * SHA1" or similar
449 */
450 break;
451
452 case PGP_PTAG_CT_LITDATA_HEADER:
453 /* ignore */
454 break;
455
456 case PGP_PTAG_CT_LITDATA_BODY:
457 data->data.litdata_body = content->litdata_body;
458 data->type = LITDATA;
459 pgp_memory_add(data->mem, data->data.litdata_body.data,
460 data->data.litdata_body.length);
461 return PGP_KEEP_MEMORY;
462
463 case PGP_PTAG_CT_SIGNED_CLEARTEXT_BODY:
464 data->data.cleartext_body = content->cleartext_body;
465 data->type = SIGNED_CLEARTEXT;
466 pgp_memory_add(data->mem, data->data.cleartext_body.data,
467 data->data.cleartext_body.length);
468 return PGP_KEEP_MEMORY;
469
470 case PGP_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
471 /* this gives us an pgp_hash_t struct */
472 break;
473
474 case PGP_PTAG_CT_SIGNATURE: /* V3 sigs */
475 case PGP_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */
476 if (pgp_get_debug_level(__FILE__)) {
477 hexdump(io->outs, "hashed data", content->sig.info.v4_hashed,
478 content->sig.info.v4_hashlen);
479 hexdump(io->outs, "signer id", content->sig.info.signer_id,
480 sizeof(content->sig.info.signer_id));
481 }
482 from = 0;
483 signer = pgp_getkeybyid(io, data->keyring,
484 content->sig.info.signer_id, &from, &sigkey);
485 if (!signer) {
486 PGP_ERROR_1(errors, PGP_E_V_UNKNOWN_SIGNER,
487 "%s", "Unknown Signer");
488 if (!add_sig_to_list(&content->sig.info,
489 &data->result->unknown_sigs,
490 &data->result->unknownc)) {
491 PGP_ERROR_1(errors, PGP_E_V_UNKNOWN_SIGNER,
492 "%s", "Can't add unknown sig to list");
493 }
494 break;
495 }
496 if (sigkey == &signer->enckey) {
497 (void) fprintf(io->errs,
498 "WARNING: signature made with encryption key\n");
499 }
500 if (content->sig.info.birthtime_set) {
501 data->result->birthtime = content->sig.info.birthtime;
502 }
503 if (content->sig.info.duration_set) {
504 data->result->duration = content->sig.info.duration;
505 }
506 switch (content->sig.info.type) {
507 case PGP_SIG_BINARY:
508 case PGP_SIG_TEXT:
509 if (pgp_mem_len(data->mem) == 0 &&
510 data->detachname) {
511 /* check we have seen some data */
512 /* if not, need to read from detached name */
513 (void) fprintf(io->errs,
514 "netpgp: assuming signed data in \"%s\"\n",
515 data->detachname);
516 data->mem = pgp_memory_new();
517 pgp_mem_readfile(data->mem, data->detachname);
518 }
519 if (pgp_get_debug_level(__FILE__)) {
520 hexdump(stderr, "sig dump", (const uint8_t *)(const void *)&content->sig,
521 sizeof(content->sig));
522 }
523 valid = check_binary_sig(pgp_mem_data(data->mem),
524 (const unsigned)pgp_mem_len(data->mem),
525 &content->sig,
526 pgp_get_pubkey(signer));
527 break;
528
529 default:
530 PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED,
531 "No Sig Verification type 0x%02x yet\n",
532 content->sig.info.type);
533 break;
534
535 }
536
537 if (valid) {
538 if (!add_sig_to_list(&content->sig.info,
539 &data->result->valid_sigs,
540 &data->result->validc)) {
541 PGP_ERROR_1(errors, PGP_E_V_BAD_SIGNATURE,
542 "%s", "Can't add good sig to list");
543 }
544 } else {
545 PGP_ERROR_1(errors, PGP_E_V_BAD_SIGNATURE,
546 "%s", "Bad Signature");
547 if (!add_sig_to_list(&content->sig.info,
548 &data->result->invalid_sigs,
549 &data->result->invalidc)) {
550 PGP_ERROR_1(errors, PGP_E_V_BAD_SIGNATURE, "%s",
551 "Can't add good sig to list");
552 }
553 }
554 break;
555
556 /* ignore these */
557 case PGP_PARSER_PTAG:
558 case PGP_PTAG_CT_SIGNATURE_HEADER:
559 case PGP_PTAG_CT_ARMOUR_HEADER:
560 case PGP_PTAG_CT_ARMOUR_TRAILER:
561 case PGP_PTAG_CT_1_PASS_SIG:
562 break;
563
564 case PGP_PARSER_PACKET_END:
565 break;
566
567 default:
568 PGP_ERROR_1(errors, PGP_E_V_NO_SIGNATURE, "%s", "No signature");
569 break;
570 }
571 return PGP_RELEASE_MEMORY;
572 }
573
574 static void
keydata_destroyer(pgp_reader_t * readinfo)575 keydata_destroyer(pgp_reader_t *readinfo)
576 {
577 free(pgp_reader_get_arg(readinfo));
578 }
579
580 void
pgp_keydata_reader_set(pgp_stream_t * stream,const pgp_key_t * key)581 pgp_keydata_reader_set(pgp_stream_t *stream, const pgp_key_t *key)
582 {
583 validate_reader_t *data;
584
585 if ((data = calloc(1, sizeof(*data))) == NULL) {
586 (void) fprintf(stderr, "pgp_keydata_reader_set: bad alloc\n");
587 } else {
588 data->key = key;
589 data->packet = 0;
590 data->offset = 0;
591 pgp_reader_set(stream, keydata_reader, keydata_destroyer, data);
592 }
593 }
594
595 static char *
fmtsecs(int64_t n,char * buf,size_t size)596 fmtsecs(int64_t n, char *buf, size_t size)
597 {
598 if (n > 365 * 24 * 60 * 60) {
599 n /= (365 * 24 * 60 * 60);
600 (void) snprintf(buf, size, "%" PRId64 " year%s", n, (n == 1) ? "" : "s");
601 return buf;
602 }
603 if (n > 30 * 24 * 60 * 60) {
604 n /= (30 * 24 * 60 * 60);
605 (void) snprintf(buf, size, "%" PRId64 " month%s", n, (n == 1) ? "" : "s");
606 return buf;
607 }
608 if (n > 24 * 60 * 60) {
609 n /= (24 * 60 * 60);
610 (void) snprintf(buf, size, "%" PRId64 " day%s", n, (n == 1) ? "" : "s");
611 return buf;
612 }
613 if (n > 60 * 60) {
614 n /= (60 * 60);
615 (void) snprintf(buf, size, "%" PRId64 " hour%s", n, (n == 1) ? "" : "s");
616 return buf;
617 }
618 if (n > 60) {
619 n /= 60;
620 (void) snprintf(buf, size, "%" PRId64 " minute%s", n, (n == 1) ? "" : "s");
621 return buf;
622 }
623 (void) snprintf(buf, size, "%" PRId64 " second%s", n, (n == 1) ? "" : "s");
624 return buf;
625 }
626
627 /**
628 * \ingroup HighLevel_Verify
629 * \brief Indicicates whether any errors were found
630 * \param result Validation result to check
631 * \return 0 if any invalid signatures or unknown signers
632 or no valid signatures; else 1
633 */
634 static unsigned
validate_result_status(FILE * errs,const char * f,pgp_validation_t * val)635 validate_result_status(FILE *errs, const char *f, pgp_validation_t *val)
636 {
637 time_t now;
638 time_t t;
639 char buf[128];
640
641 now = time(NULL);
642 if (now < val->birthtime) {
643 /* signature is not valid yet! */
644 if (f) {
645 (void) fprintf(errs, "\"%s\": ", f);
646 } else {
647 (void) fprintf(errs, "memory ");
648 }
649 (void) fprintf(errs,
650 "signature not valid until %.24s (%s)\n",
651 ctime(&val->birthtime),
652 fmtsecs((int64_t)(val->birthtime - now), buf, sizeof(buf)));
653 return 0;
654 }
655 if (val->duration != 0 && now > val->birthtime + val->duration) {
656 /* signature has expired */
657 t = val->duration + val->birthtime;
658 if (f) {
659 (void) fprintf(errs, "\"%s\": ", f);
660 } else {
661 (void) fprintf(errs, "memory ");
662 }
663 (void) fprintf(errs,
664 "signature not valid after %.24s (%s ago)\n",
665 ctime(&t),
666 fmtsecs((int64_t)(now - t), buf, sizeof(buf)));
667 return 0;
668 }
669 return val->validc && !val->invalidc && !val->unknownc;
670 }
671
672 /**
673 * \ingroup HighLevel_Verify
674 * \brief Validate all signatures on a single key against the given keyring
675 * \param result Where to put the result
676 * \param key Key to validate
677 * \param keyring Keyring to use for validation
678 * \param cb_get_passphrase Callback to use to get passphrase
679 * \return 1 if all signatures OK; else 0
680 * \note It is the caller's responsiblity to free result after use.
681 * \sa pgp_validate_result_free()
682 */
683 unsigned
pgp_validate_key_sigs(pgp_validation_t * result,const pgp_key_t * key,const pgp_keyring_t * keyring,pgp_cb_ret_t cb_get_passphrase (const pgp_packet_t *,pgp_cbdata_t *))684 pgp_validate_key_sigs(pgp_validation_t *result,
685 const pgp_key_t *key,
686 const pgp_keyring_t *keyring,
687 pgp_cb_ret_t cb_get_passphrase(const pgp_packet_t *,
688 pgp_cbdata_t *))
689 {
690 pgp_stream_t *stream;
691 validate_key_cb_t keysigs;
692 const int printerrors = 1;
693
694 (void) memset(&keysigs, 0x0, sizeof(keysigs));
695 keysigs.result = result;
696 keysigs.getpassphrase = cb_get_passphrase;
697
698 stream = pgp_new(sizeof(*stream));
699 /* pgp_parse_options(&opt,PGP_PTAG_CT_SIGNATURE,PGP_PARSE_PARSED); */
700
701 keysigs.keyring = keyring;
702
703 pgp_set_callback(stream, pgp_validate_key_cb, &keysigs);
704 stream->readinfo.accumulate = 1;
705 pgp_keydata_reader_set(stream, key);
706
707 /* Note: Coverity incorrectly reports an error that keysigs.reader */
708 /* is never used. */
709 keysigs.reader = stream->readinfo.arg;
710
711 pgp_parse(stream, !printerrors);
712
713 pgp_pubkey_free(&keysigs.pubkey);
714 if (keysigs.subkey.version) {
715 pgp_pubkey_free(&keysigs.subkey);
716 }
717 pgp_userid_free(&keysigs.userid);
718 pgp_data_free(&keysigs.userattr);
719
720 pgp_stream_delete(stream);
721
722 return (!result->invalidc && !result->unknownc && result->validc);
723 }
724
725 /**
726 \ingroup HighLevel_Verify
727 \param result Where to put the result
728 \param ring Keyring to use
729 \param cb_get_passphrase Callback to use to get passphrase
730 \note It is the caller's responsibility to free result after use.
731 \sa pgp_validate_result_free()
732 */
733 unsigned
pgp_validate_all_sigs(pgp_validation_t * result,const pgp_keyring_t * ring,pgp_cb_ret_t cb_get_passphrase (const pgp_packet_t *,pgp_cbdata_t *))734 pgp_validate_all_sigs(pgp_validation_t *result,
735 const pgp_keyring_t *ring,
736 pgp_cb_ret_t cb_get_passphrase(const pgp_packet_t *,
737 pgp_cbdata_t *))
738 {
739 unsigned n;
740
741 (void) memset(result, 0x0, sizeof(*result));
742 for (n = 0; n < ring->keyc; ++n) {
743 pgp_validate_key_sigs(result, &ring->keys[n], ring,
744 cb_get_passphrase);
745 }
746 return validate_result_status(stderr, "keyring", result);
747 }
748
749 /**
750 \ingroup HighLevel_Verify
751 \brief Frees validation result and associated memory
752 \param result Struct to be freed
753 \note Must be called after validation functions
754 */
755 void
pgp_validate_result_free(pgp_validation_t * result)756 pgp_validate_result_free(pgp_validation_t *result)
757 {
758 if (result != NULL) {
759 if (result->valid_sigs) {
760 free_sig_info(result->valid_sigs);
761 }
762 if (result->invalid_sigs) {
763 free_sig_info(result->invalid_sigs);
764 }
765 if (result->unknown_sigs) {
766 free_sig_info(result->unknown_sigs);
767 }
768 free(result);
769 /* result = NULL; - XXX unnecessary */
770 }
771 }
772
773 /**
774 \ingroup HighLevel_Verify
775 \brief Verifies the signatures in a signed file
776 \param result Where to put the result
777 \param filename Name of file to be validated
778 \param armoured Treat file as armoured, if set
779 \param keyring Keyring to use
780 \return 1 if signatures validate successfully;
781 0 if signatures fail or there are no signatures
782 \note After verification, result holds the details of all keys which
783 have passed, failed and not been recognised.
784 \note It is the caller's responsiblity to call
785 pgp_validate_result_free(result) after use.
786 */
787 unsigned
pgp_validate_file(pgp_io_t * io,pgp_validation_t * result,const char * infile,const char * outfile,const int user_says_armoured,const pgp_keyring_t * keyring)788 pgp_validate_file(pgp_io_t *io,
789 pgp_validation_t *result,
790 const char *infile,
791 const char *outfile,
792 const int user_says_armoured,
793 const pgp_keyring_t *keyring)
794 {
795 validate_data_cb_t validation;
796 pgp_stream_t *parse = NULL;
797 struct stat st;
798 const char *signame;
799 const int printerrors = 1;
800 unsigned ret;
801 char f[MAXPATHLEN];
802 char *dataname;
803 int realarmour;
804 int outfd = 0;
805 int infd;
806 int cc;
807
808 if (stat(infile, &st) < 0) {
809 (void) fprintf(io->errs,
810 "pgp_validate_file: can't open '%s'\n", infile);
811 return 0;
812 }
813 realarmour = user_says_armoured;
814 dataname = NULL;
815 signame = NULL;
816 cc = snprintf(f, sizeof(f), "%s", infile);
817 if (strcmp(&f[cc - 4], ".sig") == 0) {
818 /* we've been given a sigfile as infile */
819 f[cc - 4] = 0x0;
820 /* set dataname to name of file which was signed */
821 dataname = f;
822 signame = infile;
823 } else if (strcmp(&f[cc - 4], ".asc") == 0) {
824 /* we've been given an armored sigfile as infile */
825 f[cc - 4] = 0x0;
826 /* set dataname to name of file which was signed */
827 dataname = f;
828 signame = infile;
829 realarmour = 1;
830 } else {
831 signame = infile;
832 }
833 (void) memset(&validation, 0x0, sizeof(validation));
834 infd = pgp_setup_file_read(io, &parse, signame, &validation,
835 validate_data_cb, 1);
836 if (infd < 0) {
837 return 0;
838 }
839
840 if (dataname) {
841 validation.detachname = netpgp_strdup(dataname);
842 }
843
844 /* Set verification reader and handling options */
845 validation.result = result;
846 validation.keyring = keyring;
847 validation.mem = pgp_memory_new();
848 pgp_memory_init(validation.mem, 128);
849 /* Note: Coverity incorrectly reports an error that validation.reader */
850 /* is never used. */
851 validation.reader = parse->readinfo.arg;
852
853 if (realarmour) {
854 pgp_reader_push_dearmour(parse);
855 }
856
857 /* Do the verification */
858 pgp_parse(parse, !printerrors);
859
860 /* Tidy up */
861 if (realarmour) {
862 pgp_reader_pop_dearmour(parse);
863 }
864 pgp_teardown_file_read(parse, infd);
865
866 ret = validate_result_status(io->errs, infile, result);
867
868 /* this is triggered only for --cat output */
869 if (outfile) {
870 /* need to send validated output somewhere */
871 if (strcmp(outfile, "-") == 0) {
872 outfd = STDOUT_FILENO;
873 } else {
874 outfd = open(outfile, O_WRONLY | O_CREAT, 0666);
875 }
876 if (outfd < 0) {
877 /* even if the signature was good, we can't
878 * write the file, so send back a bad return
879 * code */
880 ret = 0;
881 } else if (validate_result_status(io->errs, infile, result)) {
882 unsigned len;
883 char *cp;
884 int i;
885
886 len = (unsigned)pgp_mem_len(validation.mem);
887 cp = pgp_mem_data(validation.mem);
888 for (i = 0 ; i < (int)len ; i += cc) {
889 cc = (int)write(outfd, &cp[i], (unsigned)(len - i));
890 if (cc < 0) {
891 (void) fprintf(io->errs,
892 "netpgp: short write\n");
893 ret = 0;
894 break;
895 }
896 }
897 if (strcmp(outfile, "-") != 0) {
898 (void) close(outfd);
899 }
900 }
901 }
902 pgp_memory_free(validation.mem);
903 return ret;
904 }
905
906 /**
907 \ingroup HighLevel_Verify
908 \brief Verifies the signatures in a pgp_memory_t struct
909 \param result Where to put the result
910 \param mem Memory to be validated
911 \param user_says_armoured Treat data as armoured, if set
912 \param keyring Keyring to use
913 \return 1 if signature validates successfully; 0 if not
914 \note After verification, result holds the details of all keys which
915 have passed, failed and not been recognised.
916 \note It is the caller's responsiblity to call
917 pgp_validate_result_free(result) after use.
918 */
919
920 unsigned
pgp_validate_mem(pgp_io_t * io,pgp_validation_t * result,pgp_memory_t * mem,pgp_memory_t ** cat,const int user_says_armoured,const pgp_keyring_t * keyring)921 pgp_validate_mem(pgp_io_t *io,
922 pgp_validation_t *result,
923 pgp_memory_t *mem,
924 pgp_memory_t **cat,
925 const int user_says_armoured,
926 const pgp_keyring_t *keyring)
927 {
928 validate_data_cb_t validation;
929 pgp_stream_t *stream = NULL;
930 const int printerrors = 1;
931 int realarmour;
932
933 pgp_setup_memory_read(io, &stream, mem, &validation, validate_data_cb, 1);
934 /* Set verification reader and handling options */
935 (void) memset(&validation, 0x0, sizeof(validation));
936 validation.result = result;
937 validation.keyring = keyring;
938 validation.mem = pgp_memory_new();
939 pgp_memory_init(validation.mem, 128);
940 /* Note: Coverity incorrectly reports an error that validation.reader */
941 /* is never used. */
942 validation.reader = stream->readinfo.arg;
943
944 if ((realarmour = user_says_armoured) != 0 ||
945 strncmp(pgp_mem_data(mem),
946 "-----BEGIN PGP MESSAGE-----", 27) == 0) {
947 realarmour = 1;
948 }
949 if (realarmour) {
950 pgp_reader_push_dearmour(stream);
951 }
952
953 /* Do the verification */
954 pgp_parse(stream, !printerrors);
955
956 /* Tidy up */
957 if (realarmour) {
958 pgp_reader_pop_dearmour(stream);
959 }
960 pgp_teardown_memory_read(stream, mem);
961
962 /* this is triggered only for --cat output */
963 if (cat) {
964 /* need to send validated output somewhere */
965 *cat = validation.mem;
966 } else {
967 pgp_memory_free(validation.mem);
968 }
969
970 return validate_result_status(io->errs, NULL, result);
971 }
972