| @@ -23,26 +23,27 @@ | | | @@ -23,26 +23,27 @@ |
23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ | | 24 | */ |
25 | #include "config.h" | | 25 | #include "config.h" |
26 | | | 26 | |
27 | #include <sys/types.h> | | 27 | #include <sys/types.h> |
28 | #include <sys/stat.h> | | 28 | #include <sys/stat.h> |
29 | #include <sys/param.h> | | 29 | #include <sys/param.h> |
30 | #include <sys/mman.h> | | 30 | #include <sys/mman.h> |
31 | | | 31 | |
32 | #include <arpa/inet.h> | | 32 | #include <arpa/inet.h> |
33 | | | 33 | |
34 | #include <inttypes.h> | | 34 | #include <inttypes.h> |
35 | #include <limits.h> | | 35 | #include <limits.h> |
| | | 36 | #include <stdbool.h> |
36 | #include <stdarg.h> | | 37 | #include <stdarg.h> |
37 | #include <stdio.h> | | 38 | #include <stdio.h> |
38 | #include <stdlib.h> | | 39 | #include <stdlib.h> |
39 | #include <string.h> | | 40 | #include <string.h> |
40 | #include <time.h> | | 41 | #include <time.h> |
41 | #include <unistd.h> | | 42 | #include <unistd.h> |
42 | | | 43 | |
43 | #include "bzlib.h" | | 44 | #include "bzlib.h" |
44 | #include "zlib.h" | | 45 | #include "zlib.h" |
45 | | | 46 | |
46 | #include "array.h" | | 47 | #include "array.h" |
47 | #include "b64.h" | | 48 | #include "b64.h" |
48 | #include "bn.h" | | 49 | #include "bn.h" |
| @@ -157,26 +158,91 @@ | | | @@ -157,26 +158,91 @@ |
157 | | | 158 | |
158 | #define SIGTYPE_KEY_REVOCATION 0x20 /* Key revocation signature */ | | 159 | #define SIGTYPE_KEY_REVOCATION 0x20 /* Key revocation signature */ |
159 | #define SIGTYPE_SUBKEY_REVOCATION 0x28 /* Subkey revocation signature */ | | 160 | #define SIGTYPE_SUBKEY_REVOCATION 0x28 /* Subkey revocation signature */ |
160 | #define SIGTYPE_CERT_REVOCATION 0x30 /* Certification revocation signature */ | | 161 | #define SIGTYPE_CERT_REVOCATION 0x30 /* Certification revocation signature */ |
161 | | | 162 | |
162 | #define SIGTYPE_TIMESTAMP_SIG 0x40 /* Timestamp signature */ | | 163 | #define SIGTYPE_TIMESTAMP_SIG 0x40 /* Timestamp signature */ |
163 | #define SIGTYPE_3RDPARTY 0x50 /* Third-Party Confirmation signature */ | | 164 | #define SIGTYPE_3RDPARTY 0x50 /* Third-Party Confirmation signature */ |
164 | | | 165 | |
165 | /* Forward declarations */ | | 166 | /* Forward declarations */ |
166 | static int read_all_packets(pgpv_t */*pgp*/, pgpv_mem_t */*mem*/, const char */*op*/); | | 167 | static int read_all_packets(pgpv_t */*pgp*/, pgpv_mem_t */*mem*/, const char */*op*/); |
167 | static int read_binary_file(pgpv_t */*pgp*/, const char */*op*/, const char */*fmt*/, ...) __printflike(3, 4); | | 168 | static int read_binary_file(pgpv_t */*pgp*/, const char */*op*/, const char */*fmt*/, ...) __printflike(3, 4); |
168 | static int read_binary_memory(pgpv_t */*pgp*/, const char */*op*/, const void */*memory*/, size_t /*size*/); | | 169 | static int read_binary_memory(pgpv_t */*pgp*/, const char */*op*/, const void */*memory*/, size_t /*size*/); |
169 | | | 170 | |
| | | 171 | /* output buffer structure */ |
| | | 172 | typedef struct obuf_t { |
| | | 173 | size_t alloc; /* amount of memory allocated */ |
| | | 174 | size_t c; /* # of chars used so far */ |
| | | 175 | uint8_t *v; /* array of bytes */ |
| | | 176 | uint32_t endian; /* byte order of output stream */ |
| | | 177 | } obuf_t; |
| | | 178 | |
| | | 179 | /* grow the buffer, if needed */ |
| | | 180 | static bool |
| | | 181 | growbuf(obuf_t *obuf, size_t cc) |
| | | 182 | { |
| | | 183 | size_t newalloc; |
| | | 184 | uint8_t *newv; |
| | | 185 | |
| | | 186 | if (obuf->c + cc > obuf->alloc) { |
| | | 187 | newalloc = howmany(obuf->alloc + cc, 128) * 128; |
| | | 188 | newv = realloc(obuf->v, newalloc); |
| | | 189 | if (newv == NULL) { |
| | | 190 | return false; |
| | | 191 | } |
| | | 192 | obuf->v = newv; |
| | | 193 | obuf->alloc = newalloc; |
| | | 194 | } |
| | | 195 | return true; |
| | | 196 | } |
| | | 197 | |
| | | 198 | /* add a fixed-length area of memory */ |
| | | 199 | static bool |
| | | 200 | obuf_add_mem(obuf_t *obuf, const char *s, size_t len) |
| | | 201 | { |
| | | 202 | if (obuf && s && len > 0) { |
| | | 203 | if (!growbuf(obuf, len)) { |
| | | 204 | return false; |
| | | 205 | } |
| | | 206 | memcpy(&obuf->v[obuf->c], s, len); |
| | | 207 | obuf->c += len; |
| | | 208 | return true; |
| | | 209 | } |
| | | 210 | return false; |
| | | 211 | } |
| | | 212 | |
| | | 213 | /* varargs-based printf to string */ |
| | | 214 | static bool |
| | | 215 | obuf_printf(obuf_t *obuf, const char *fmt, ...) |
| | | 216 | { |
| | | 217 | va_list args; |
| | | 218 | char *cp; |
| | | 219 | bool ret; |
| | | 220 | int cc; |
| | | 221 | |
| | | 222 | if (obuf && fmt) { |
| | | 223 | ret = true; |
| | | 224 | va_start(args, fmt); |
| | | 225 | cc = vasprintf(&cp, fmt, args); |
| | | 226 | va_end(args); |
| | | 227 | if (cc > 0) { |
| | | 228 | ret = obuf_add_mem(obuf, cp, (size_t)cc); |
| | | 229 | free(cp); |
| | | 230 | } |
| | | 231 | return ret; |
| | | 232 | } |
| | | 233 | return false; |
| | | 234 | } |
| | | 235 | |
170 | /* read a file into the pgpv_mem_t struct */ | | 236 | /* read a file into the pgpv_mem_t struct */ |
171 | static int | | 237 | static int |
172 | read_file(pgpv_t *pgp, const char *f) | | 238 | read_file(pgpv_t *pgp, const char *f) |
173 | { | | 239 | { |
174 | struct stat st; | | 240 | struct stat st; |
175 | pgpv_mem_t *mem; | | 241 | pgpv_mem_t *mem; |
176 | | | 242 | |
177 | ARRAY_EXPAND(pgp->areas); | | 243 | ARRAY_EXPAND(pgp->areas); |
178 | ARRAY_COUNT(pgp->areas) += 1; | | 244 | ARRAY_COUNT(pgp->areas) += 1; |
179 | mem = &ARRAY_LAST(pgp->areas); | | 245 | mem = &ARRAY_LAST(pgp->areas); |
180 | memset(mem, 0x0, sizeof(*mem)); | | 246 | memset(mem, 0x0, sizeof(*mem)); |
181 | if ((mem->fp = fopen(f, "r")) == NULL) { | | 247 | if ((mem->fp = fopen(f, "r")) == NULL) { |
182 | fprintf(stderr, "can't read '%s'", f); | | 248 | fprintf(stderr, "can't read '%s'", f); |
| @@ -405,35 +471,36 @@ fmt_32(uint8_t *p, uint32_t a) | | | @@ -405,35 +471,36 @@ fmt_32(uint8_t *p, uint32_t a) |
405 | } | | 471 | } |
406 | | | 472 | |
407 | /* copy the 16bit integer in memory in network order */ | | 473 | /* copy the 16bit integer in memory in network order */ |
408 | static unsigned | | 474 | static unsigned |
409 | fmt_16(uint8_t *p, uint16_t a) | | 475 | fmt_16(uint8_t *p, uint16_t a) |
410 | { | | 476 | { |
411 | a = pgp_hton16(a); | | 477 | a = pgp_hton16(a); |
412 | memcpy(p, &a, sizeof(a)); | | 478 | memcpy(p, &a, sizeof(a)); |
413 | return sizeof(a); | | 479 | return sizeof(a); |
414 | } | | 480 | } |
415 | | | 481 | |
416 | /* format a binary string in memory */ | | 482 | /* format a binary string in memory */ |
417 | static size_t | | 483 | static size_t |
418 | fmt_binary(char *s, size_t size, const uint8_t *bin, unsigned len) | | 484 | fmt_binary(obuf_t *obuf, const uint8_t *bin, unsigned len) |
419 | { | | 485 | { |
420 | unsigned i; | | 486 | unsigned i; |
421 | size_t cc; | | | |
422 | | | 487 | |
423 | for (cc = 0, i = 0 ; i < len && cc < size ; i++) { | | 488 | for (i = 0 ; i < len ; i++) { |
424 | cc += snprintf(&s[cc], size - cc, "%02x", bin[i]); | | 489 | if (!obuf_printf(obuf, "%02hhx", bin[i])) { |
| | | 490 | return false; |
| | | 491 | } |
425 | } | | 492 | } |
426 | return cc; | | 493 | return true; |
427 | } | | 494 | } |
428 | | | 495 | |
429 | /* format an mpi into memory */ | | 496 | /* format an mpi into memory */ |
430 | static unsigned | | 497 | static unsigned |
431 | fmt_binary_mpi(pgpv_bignum_t *mpi, uint8_t *p, size_t size) | | 498 | fmt_binary_mpi(pgpv_bignum_t *mpi, uint8_t *p, size_t size) |
432 | { | | 499 | { |
433 | unsigned bytes; | | 500 | unsigned bytes; |
434 | PGPV_BIGNUM *bn; | | 501 | PGPV_BIGNUM *bn; |
435 | | | 502 | |
436 | bytes = BITS_TO_BYTES(mpi->bits); | | 503 | bytes = BITS_TO_BYTES(mpi->bits); |
437 | if ((size_t)bytes + 2 + 1 > size) { | | 504 | if ((size_t)bytes + 2 + 1 > size) { |
438 | fprintf(stderr, "truncated mpi"); | | 505 | fprintf(stderr, "truncated mpi"); |
439 | return 0; | | 506 | return 0; |
| @@ -542,39 +609,41 @@ pgpv_calc_fingerprint(pgpv_fingerprint_t | | | @@ -542,39 +609,41 @@ pgpv_calc_fingerprint(pgpv_fingerprint_t |
542 | if (pubkey->bn[RSA_N].bn) { | | 609 | if (pubkey->bn[RSA_N].bn) { |
543 | if ((cc = fmt_binary_mpi(&pubkey->bn[RSA_N], buf, sizeof(buf))) >= PGPV_KEYID_LEN) { | | 610 | if ((cc = fmt_binary_mpi(&pubkey->bn[RSA_N], buf, sizeof(buf))) >= PGPV_KEYID_LEN) { |
544 | memcpy(fingerprint->v, &buf[cc - PGPV_KEYID_LEN], PGPV_KEYID_LEN); | | 611 | memcpy(fingerprint->v, &buf[cc - PGPV_KEYID_LEN], PGPV_KEYID_LEN); |
545 | fingerprint->len = PGPV_KEYID_LEN; | | 612 | fingerprint->len = PGPV_KEYID_LEN; |
546 | return 1; | | 613 | return 1; |
547 | } | | 614 | } |
548 | } | | 615 | } |
549 | /* exhausted all avenues, really */ | | 616 | /* exhausted all avenues, really */ |
550 | memset(fingerprint->v, 0xff, fingerprint->len = PGPV_KEYID_LEN); | | 617 | memset(fingerprint->v, 0xff, fingerprint->len = PGPV_KEYID_LEN); |
551 | return 1; | | 618 | return 1; |
552 | } | | 619 | } |
553 | | | 620 | |
554 | /* format a fingerprint into memory */ | | 621 | /* format a fingerprint into memory */ |
555 | static size_t | | 622 | static bool |
556 | fmt_fingerprint(char *s, size_t size, pgpv_fingerprint_t *fingerprint, const char *name) | | 623 | fmt_fingerprint(obuf_t *obuf, pgpv_fingerprint_t *fingerprint, const char *name) |
557 | { | | 624 | { |
558 | unsigned i; | | 625 | unsigned i; |
559 | size_t cc; | | | |
560 | | | 626 | |
561 | cc = snprintf(s, size, "%s ", name); | | 627 | if (!obuf_printf(obuf, "%s ", name)) { |
| | | 628 | return false; |
| | | 629 | } |
562 | for (i = 0 ; i < fingerprint->len ; i++) { | | 630 | for (i = 0 ; i < fingerprint->len ; i++) { |
563 | cc += snprintf(&s[cc], size - cc, "%02hhx%s", | | 631 | if (!obuf_printf(obuf, "%02hhx%s", |
564 | fingerprint->v[i], (i % 2 == 1) ? " " : ""); | | 632 | fingerprint->v[i], (i % 2 == 1) ? " " : "")) { |
| | | 633 | return false; |
| | | 634 | } |
565 | } | | 635 | } |
566 | cc += snprintf(&s[cc], size - cc, "\n"); | | 636 | return obuf_printf(obuf, "\n"); |
567 | return cc; | | | |
568 | } | | 637 | } |
569 | | | 638 | |
570 | /* calculate keyid from a pubkey */ | | 639 | /* calculate keyid from a pubkey */ |
571 | static int | | 640 | static int |
572 | calc_keyid(pgpv_pubkey_t *key, const char *hashtype) | | 641 | calc_keyid(pgpv_pubkey_t *key, const char *hashtype) |
573 | { | | 642 | { |
574 | pgpv_calc_fingerprint(&key->fingerprint, key, hashtype); | | 643 | pgpv_calc_fingerprint(&key->fingerprint, key, hashtype); |
575 | memcpy(key->keyid, &key->fingerprint.v[key->fingerprint.len - PGPV_KEYID_LEN], PGPV_KEYID_LEN); | | 644 | memcpy(key->keyid, &key->fingerprint.v[key->fingerprint.len - PGPV_KEYID_LEN], PGPV_KEYID_LEN); |
576 | return 1; | | 645 | return 1; |
577 | } | | 646 | } |
578 | | | 647 | |
579 | /* convert a hex string to a 64bit key id (in big endian byte order */ | | 648 | /* convert a hex string to a 64bit key id (in big endian byte order */ |
580 | static void | | 649 | static void |
| @@ -649,50 +718,52 @@ get_32(uint8_t *p) | | | @@ -649,50 +718,52 @@ get_32(uint8_t *p) |
649 | uint32_t u32; | | 718 | uint32_t u32; |
650 | | | 719 | |
651 | memcpy(&u32, p, sizeof(u32)); | | 720 | memcpy(&u32, p, sizeof(u32)); |
652 | return pgp_ntoh32(u32); | | 721 | return pgp_ntoh32(u32); |
653 | } | | 722 | } |
654 | | | 723 | |
655 | #define HOURSECS (int64_t)(60 * 60) | | 724 | #define HOURSECS (int64_t)(60 * 60) |
656 | #define DAYSECS (int64_t)(24 * 60 * 60) | | 725 | #define DAYSECS (int64_t)(24 * 60 * 60) |
657 | #define MONSECS (int64_t)(30 * DAYSECS) | | 726 | #define MONSECS (int64_t)(30 * DAYSECS) |
658 | #define YEARSECS (int64_t)(365 * DAYSECS) | | 727 | #define YEARSECS (int64_t)(365 * DAYSECS) |
659 | | | 728 | |
660 | /* format (human readable) time into memory */ | | 729 | /* format (human readable) time into memory */ |
661 | static size_t | | 730 | static size_t |
662 | fmt_time(char *s, size_t size, const char *header, int64_t n, const char *trailer, int relative) | | 731 | fmt_time(obuf_t *obuf, const char *header, int64_t n, const char *trailer, int relative) |
663 | { | | 732 | { |
664 | struct tm tm; | | 733 | struct tm tm; |
665 | time_t elapsed; | | 734 | time_t elapsed; |
666 | time_t now; | | 735 | time_t now; |
667 | time_t t; | | 736 | time_t t; |
668 | size_t cc; | | | |
669 | | | 737 | |
670 | t = (time_t)n; | | 738 | t = (time_t)n; |
671 | now = time(NULL); | | 739 | now = time(NULL); |
672 | elapsed = now - t; | | 740 | elapsed = now - t; |
673 | gmtime_r(&t, &tm); | | 741 | gmtime_r(&t, &tm); |
674 | cc = snprintf(s, size, "%s%04d-%02d-%02d", header, | | 742 | if (!obuf_printf(obuf, "%s%04d-%02d-%02d", header, |
675 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | | 743 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday)) { |
| | | 744 | return false; |
| | | 745 | } |
676 | if (relative) { | | 746 | if (relative) { |
677 | cc += snprintf(&s[cc], size - cc, " (%lldy %lldm %lldd %lldh %s)", | | 747 | if (!obuf_printf(obuf, " (%lldy %lldm %lldd %lldh %s)", |
678 | llabs((long long)elapsed / YEARSECS), | | 748 | llabs((long long)elapsed / YEARSECS), |
679 | llabs(((long long)elapsed % YEARSECS) / MONSECS), | | 749 | llabs(((long long)elapsed % YEARSECS) / MONSECS), |
680 | llabs(((long long)elapsed % MONSECS) / DAYSECS), | | 750 | llabs(((long long)elapsed % MONSECS) / DAYSECS), |
681 | llabs(((long long)elapsed % DAYSECS) / HOURSECS), | | 751 | llabs(((long long)elapsed % DAYSECS) / HOURSECS), |
682 | (now > t) ? "ago" : "ahead"); | | 752 | (now > t) ? "ago" : "ahead")) { |
| | | 753 | return false; |
| | | 754 | } |
683 | } | | 755 | } |
684 | cc += snprintf(&s[cc], size - cc, "%s", trailer); | | 756 | return obuf_printf(obuf, "%s", trailer); |
685 | return cc; | | | |
686 | } | | 757 | } |
687 | | | 758 | |
688 | /* dump key mpis to stdout */ | | 759 | /* dump key mpis to stdout */ |
689 | static void | | 760 | static void |
690 | print_key_mpis(pgpv_bignum_t *v, uint8_t keyalg) | | 761 | print_key_mpis(pgpv_bignum_t *v, uint8_t keyalg) |
691 | { | | 762 | { |
692 | char s[8192]; | | 763 | char s[8192]; |
693 | | | 764 | |
694 | switch(keyalg) { | | 765 | switch(keyalg) { |
695 | case PUBKEY_RSA_ENCRYPT_OR_SIGN: | | 766 | case PUBKEY_RSA_ENCRYPT_OR_SIGN: |
696 | case PUBKEY_RSA_ENCRYPT: | | 767 | case PUBKEY_RSA_ENCRYPT: |
697 | case PUBKEY_RSA_SIGN: | | 768 | case PUBKEY_RSA_SIGN: |
698 | fmt_mpi(s, sizeof(s), &v[RSA_N], "rsa.n", 1); | | 769 | fmt_mpi(s, sizeof(s), &v[RSA_N], "rsa.n", 1); |
| @@ -1421,102 +1492,120 @@ numkeybits(const pgpv_pubkey_t *pubkey) | | | @@ -1421,102 +1492,120 @@ numkeybits(const pgpv_pubkey_t *pubkey) |
1421 | case PUBKEY_DSA: | | 1492 | case PUBKEY_DSA: |
1422 | case PUBKEY_ECDSA: | | 1493 | case PUBKEY_ECDSA: |
1423 | return pubkey->bn[DSA_P].bits; | | 1494 | return pubkey->bn[DSA_P].bits; |
1424 | //return BITS_TO_BYTES(pubkey->bn[DSA_Q].bits) * 64; | | 1495 | //return BITS_TO_BYTES(pubkey->bn[DSA_Q].bits) * 64; |
1425 | case PUBKEY_ELGAMAL_ENCRYPT: | | 1496 | case PUBKEY_ELGAMAL_ENCRYPT: |
1426 | case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN: | | 1497 | case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN: |
1427 | return pubkey->bn[ELGAMAL_P].bits; | | 1498 | return pubkey->bn[ELGAMAL_P].bits; |
1428 | default: | | 1499 | default: |
1429 | return 0; | | 1500 | return 0; |
1430 | } | | 1501 | } |
1431 | } | | 1502 | } |
1432 | | | 1503 | |
1433 | /* print a public key */ | | 1504 | /* print a public key */ |
1434 | static size_t | | 1505 | static bool |
1435 | fmt_pubkey(char *s, size_t size, pgpv_pubkey_t *pubkey, const char *leader) | | 1506 | fmt_pubkey(obuf_t *obuf, pgpv_pubkey_t *pubkey, const char *leader) |
1436 | { | | 1507 | { |
1437 | size_t cc; | | 1508 | if (!obuf_printf(obuf, "%s %u/%s ", leader, numkeybits(pubkey), fmtkeyalg(pubkey->keyalg))) { |
1438 | | | 1509 | return false; |
1439 | cc = snprintf(s, size, "%s %u/%s ", leader, numkeybits(pubkey), fmtkeyalg(pubkey->keyalg)); | | 1510 | } |
1440 | cc += fmt_binary(&s[cc], size - cc, pubkey->keyid, PGPV_KEYID_LEN); | | 1511 | if (!fmt_binary(obuf, pubkey->keyid, PGPV_KEYID_LEN)) { |
1441 | cc += fmt_time(&s[cc], size - cc, " ", pubkey->birth, "", 0); | | 1512 | return false; |
| | | 1513 | } |
| | | 1514 | if (!fmt_time(obuf, " ", pubkey->birth, "", 0)) { |
| | | 1515 | return false; |
| | | 1516 | } |
1442 | if (pubkey->expiry) { | | 1517 | if (pubkey->expiry) { |
1443 | cc += fmt_time(&s[cc], size - cc, " [Expiry ", pubkey->birth + pubkey->expiry, "]", 0); | | 1518 | if (!fmt_time(obuf, " [Expiry ", pubkey->birth + pubkey->expiry, "]", 0)) { |
| | | 1519 | return false; |
| | | 1520 | } |
1444 | } | | 1521 | } |
1445 | cc += snprintf(&s[cc], size - cc, "\n"); | | 1522 | if (!obuf_printf(obuf, "\n")) { |
1446 | cc += fmt_fingerprint(&s[cc], size - cc, &pubkey->fingerprint, "fingerprint "); | | 1523 | return false; |
1447 | return cc; | | 1524 | } |
| | | 1525 | return fmt_fingerprint(obuf, &pubkey->fingerprint, "fingerprint "); |
1448 | } | | 1526 | } |
1449 | | | 1527 | |
1450 | /* we add 1 to revocation value to denote compromised */ | | 1528 | /* we add 1 to revocation value to denote compromised */ |
1451 | #define COMPROMISED (0x02 + 1) | | 1529 | #define COMPROMISED (0x02 + 1) |
1452 | | | 1530 | |
1453 | /* format a userid - used to order the userids when formatting */ | | 1531 | /* format a userid - used to order the userids when formatting */ |
1454 | static size_t | | 1532 | static bool |
1455 | fmt_userid(char *s, size_t size, pgpv_primarykey_t *primary, uint8_t u) | | 1533 | fmt_userid(obuf_t *obuf, pgpv_primarykey_t *primary, uint8_t u) |
1456 | { | | 1534 | { |
1457 | pgpv_signed_userid_t *userid; | | 1535 | pgpv_signed_userid_t *userid; |
1458 | | | 1536 | |
1459 | userid = &ARRAY_ELEMENT(primary->signed_userids, u); | | 1537 | userid = &ARRAY_ELEMENT(primary->signed_userids, u); |
1460 | return snprintf(s, size, "uid %.*s%s\n", | | 1538 | return obuf_printf(obuf, "uid %.*s%s\n", |
1461 | (int)userid->userid.size, userid->userid.data, | | 1539 | (int)userid->userid.size, userid->userid.data, |
1462 | (userid->revoked == COMPROMISED) ? " [COMPROMISED AND REVOKED]" : | | 1540 | (userid->revoked == COMPROMISED) ? " [COMPROMISED AND REVOKED]" : |
1463 | (userid->revoked) ? " [REVOKED]" : ""); | | 1541 | (userid->revoked) ? " [REVOKED]" : ""); |
1464 | } | | 1542 | } |
1465 | | | 1543 | |
1466 | /* format a trust sig - used to order the userids when formatting */ | | 1544 | /* format a trust sig - used to order the userids when formatting */ |
1467 | static size_t | | 1545 | static bool |
1468 | fmt_trust(char *s, size_t size, pgpv_signed_userid_t *userid, uint32_t u) | | 1546 | fmt_trust(obuf_t *obuf, pgpv_signed_userid_t *userid, uint32_t u) |
1469 | { | | 1547 | { |
1470 | pgpv_signature_t *sig; | | 1548 | pgpv_signature_t *sig; |
1471 | size_t cc; | | | |
1472 | | | 1549 | |
1473 | sig = &ARRAY_ELEMENT(userid->sigs, u); | | 1550 | sig = &ARRAY_ELEMENT(userid->sigs, u); |
1474 | cc = snprintf(s, size, "trust "); | | 1551 | if (!obuf_printf(obuf, "trust ")) { |
1475 | cc += fmt_binary(&s[cc], size - cc, sig->signer, 8); | | 1552 | return false; |
1476 | return cc + snprintf(&s[cc], size - cc, "\n"); | | 1553 | } |
| | | 1554 | if (!fmt_binary(obuf, sig->signer, 8)) { |
| | | 1555 | return false; |
| | | 1556 | } |
| | | 1557 | return obuf_printf(obuf, "\n"); |
1477 | } | | 1558 | } |
1478 | | | 1559 | |
1479 | /* print a primary key, per RFC 4880 */ | | 1560 | /* print a primary key, per RFC 4880 */ |
1480 | static size_t | | 1561 | static bool |
1481 | fmt_primary(char *s, size_t size, pgpv_primarykey_t *primary, unsigned subkey, const char *modifiers) | | 1562 | fmt_primary(obuf_t *obuf, pgpv_primarykey_t *primary, unsigned subkey, const char *modifiers) |
1482 | { | | 1563 | { |
1483 | pgpv_signed_userid_t *userid; | | 1564 | pgpv_signed_userid_t *userid; |
1484 | pgpv_pubkey_t *pubkey; | | 1565 | pgpv_pubkey_t *pubkey; |
1485 | unsigned i; | | 1566 | unsigned i; |
1486 | unsigned j; | | 1567 | unsigned j; |
1487 | size_t cc; | | | |
1488 | | | 1568 | |
1489 | pubkey = (subkey == 0) ? &primary->primary : &ARRAY_ELEMENT(primary->signed_subkeys, subkey - 1).subkey; | | 1569 | pubkey = (subkey == 0) ? &primary->primary : &ARRAY_ELEMENT(primary->signed_subkeys, subkey - 1).subkey; |
1490 | cc = fmt_pubkey(s, size, pubkey, "signature "); | | 1570 | if (!fmt_pubkey(obuf, pubkey, "signature ")) { |
1491 | cc += fmt_userid(&s[cc], size - cc, primary, primary->primary_userid); | | 1571 | return false; |
| | | 1572 | } |
| | | 1573 | if (!fmt_userid(obuf, primary, primary->primary_userid)) { |
| | | 1574 | return false; |
| | | 1575 | } |
1492 | for (i = 0 ; i < ARRAY_COUNT(primary->signed_userids) ; i++) { | | 1576 | for (i = 0 ; i < ARRAY_COUNT(primary->signed_userids) ; i++) { |
1493 | if (i != primary->primary_userid) { | | 1577 | if (i != primary->primary_userid) { |
1494 | cc += fmt_userid(&s[cc], size - cc, primary, i); | | 1578 | if (!fmt_userid(obuf, primary, i)) { |
| | | 1579 | return false; |
| | | 1580 | } |
1495 | if (strcasecmp(modifiers, "trust") == 0) { | | 1581 | if (strcasecmp(modifiers, "trust") == 0) { |
1496 | userid = &ARRAY_ELEMENT(primary->signed_userids, i); | | 1582 | userid = &ARRAY_ELEMENT(primary->signed_userids, i); |
1497 | for (j = 0 ; j < ARRAY_COUNT(userid->sigs) ; j++) { | | 1583 | for (j = 0 ; j < ARRAY_COUNT(userid->sigs) ; j++) { |
1498 | cc += fmt_trust(&s[cc], size - cc, userid, j); | | 1584 | if (!fmt_trust(obuf, userid, j)) { |
| | | 1585 | return false; |
| | | 1586 | } |
1499 | } | | 1587 | } |
1500 | } | | 1588 | } |
1501 | } | | 1589 | } |
1502 | } | | 1590 | } |
1503 | if (strcasecmp(modifiers, "subkeys") == 0) { | | 1591 | if (strcasecmp(modifiers, "subkeys") == 0) { |
1504 | for (i = 0 ; i < ARRAY_COUNT(primary->signed_subkeys) ; i++) { | | 1592 | for (i = 0 ; i < ARRAY_COUNT(primary->signed_subkeys) ; i++) { |
1505 | cc += fmt_pubkey(&s[cc], size - cc, &ARRAY_ELEMENT(primary->signed_subkeys, i).subkey, "encryption"); | | 1593 | if (!fmt_pubkey(obuf, &ARRAY_ELEMENT(primary->signed_subkeys, i).subkey, "encryption")) { |
| | | 1594 | return false; |
| | | 1595 | } |
1506 | } | | 1596 | } |
1507 | } | | 1597 | } |
1508 | cc += snprintf(&s[cc], size - cc, "\n"); | | 1598 | return obuf_printf(obuf, "\n"); |
1509 | return cc; | | | |
1510 | } | | 1599 | } |
1511 | | | 1600 | |
1512 | | | 1601 | |
1513 | /* check the padding on the signature */ | | 1602 | /* check the padding on the signature */ |
1514 | static int | | 1603 | static int |
1515 | rsa_padding_check_none(uint8_t *to, int tlen, const uint8_t *from, int flen, int num) | | 1604 | rsa_padding_check_none(uint8_t *to, int tlen, const uint8_t *from, int flen, int num) |
1516 | { | | 1605 | { |
1517 | USE_ARG(num); | | 1606 | USE_ARG(num); |
1518 | if (flen > tlen) { | | 1607 | if (flen > tlen) { |
1519 | printf("from length larger than to length\n"); | | 1608 | printf("from length larger than to length\n"); |
1520 | return -1; | | 1609 | return -1; |
1521 | } | | 1610 | } |
1522 | (void) memset(to, 0x0, (size_t)(tlen - flen)); | | 1611 | (void) memset(to, 0x0, (size_t)(tlen - flen)); |
| @@ -2521,45 +2610,43 @@ pgpv_close(pgpv_t *pgp) | | | @@ -2521,45 +2610,43 @@ pgpv_close(pgpv_t *pgp) |
2521 | } | | 2610 | } |
2522 | } | | 2611 | } |
2523 | return 1; | | 2612 | return 1; |
2524 | } | | 2613 | } |
2525 | | | 2614 | |
2526 | #define NO_SUBKEYS 0 | | 2615 | #define NO_SUBKEYS 0 |
2527 | | | 2616 | |
2528 | /* return the formatted entry for the primary key desired */ | | 2617 | /* return the formatted entry for the primary key desired */ |
2529 | size_t | | 2618 | size_t |
2530 | pgpv_get_entry(pgpv_t *pgp, unsigned ent, char **s, const char *modifiers) | | 2619 | pgpv_get_entry(pgpv_t *pgp, unsigned ent, char **s, const char *modifiers) |
2531 | { | | 2620 | { |
2532 | unsigned subkey; | | 2621 | unsigned subkey; |
2533 | unsigned prim; | | 2622 | unsigned prim; |
2534 | size_t cc; | | 2623 | obuf_t obuf; |
2535 | | | 2624 | |
2536 | prim = ((ent >> 8) & 0xffffff); | | 2625 | prim = ((ent >> 8) & 0xffffff); |
2537 | subkey = (ent & 0xff); | | 2626 | subkey = (ent & 0xff); |
2538 | if (s == NULL || pgp == NULL || prim >= ARRAY_COUNT(pgp->primaries)) { | | 2627 | if (s == NULL || pgp == NULL || prim >= ARRAY_COUNT(pgp->primaries)) { |
2539 | return 0; | | 2628 | return 0; |
2540 | } | | 2629 | } |
2541 | *s = NULL; | | 2630 | *s = NULL; |
2542 | cc = ARRAY_ELEMENT(pgp->primaries, prim).fmtsize; | | | |
2543 | if (modifiers == NULL || (strcasecmp(modifiers, "trust") != 0 && strcasecmp(modifiers, "subkeys") != 0)) { | | 2631 | if (modifiers == NULL || (strcasecmp(modifiers, "trust") != 0 && strcasecmp(modifiers, "subkeys") != 0)) { |
2544 | modifiers = "no-subkeys"; | | 2632 | modifiers = "no-subkeys"; |
2545 | } | | 2633 | } |
2546 | if (strcasecmp(modifiers, "trust") == 0) { | | 2634 | memset(&obuf, 0x0, sizeof(obuf)); |
2547 | cc *= 2048; | | 2635 | if (!fmt_primary(&obuf, &ARRAY_ELEMENT(pgp->primaries, prim), subkey, modifiers)) { |
2548 | } | | | |
2549 | if ((*s = calloc(1, cc)) == NULL) { | | | |
2550 | return 0; | | 2636 | return 0; |
2551 | } | | 2637 | } |
2552 | return fmt_primary(*s, cc, &ARRAY_ELEMENT(pgp->primaries, prim), subkey, modifiers); | | 2638 | *s = (char *)obuf.v; |
| | | 2639 | return obuf.c; |
2553 | } | | 2640 | } |
2554 | | | 2641 | |
2555 | /* fixup key id, with birth, keyalg and hashalg value from signature */ | | 2642 | /* fixup key id, with birth, keyalg and hashalg value from signature */ |
2556 | static int | | 2643 | static int |
2557 | fixup_ssh_keyid(pgpv_t *pgp, pgpv_signature_t *signature, const char *hashtype) | | 2644 | fixup_ssh_keyid(pgpv_t *pgp, pgpv_signature_t *signature, const char *hashtype) |
2558 | { | | 2645 | { |
2559 | pgpv_pubkey_t *pubkey; | | 2646 | pgpv_pubkey_t *pubkey; |
2560 | unsigned i; | | 2647 | unsigned i; |
2561 | | | 2648 | |
2562 | for (i = 0 ; i < ARRAY_COUNT(pgp->primaries) ; i++) { | | 2649 | for (i = 0 ; i < ARRAY_COUNT(pgp->primaries) ; i++) { |
2563 | pubkey = &ARRAY_ELEMENT(pgp->primaries, i).primary; | | 2650 | pubkey = &ARRAY_ELEMENT(pgp->primaries, i).primary; |
2564 | pubkey->keyalg = signature->keyalg; | | 2651 | pubkey->keyalg = signature->keyalg; |
2565 | calc_keyid(pubkey, hashtype); | | 2652 | calc_keyid(pubkey, hashtype); |
| @@ -2668,83 +2755,100 @@ pgpv_get_cursor_element(pgpv_cursor_t *c | | | @@ -2668,83 +2755,100 @@ pgpv_get_cursor_element(pgpv_cursor_t *c |
2668 | } | | 2755 | } |
2669 | return -1; | | 2756 | return -1; |
2670 | } | | 2757 | } |
2671 | | | 2758 | |
2672 | /* verify the signed packets we have */ | | 2759 | /* verify the signed packets we have */ |
2673 | size_t | | 2760 | size_t |
2674 | pgpv_verify(pgpv_cursor_t *cursor, pgpv_t *pgp, const void *p, ssize_t size) | | 2761 | pgpv_verify(pgpv_cursor_t *cursor, pgpv_t *pgp, const void *p, ssize_t size) |
2675 | { | | 2762 | { |
2676 | pgpv_signature_t *signature; | | 2763 | pgpv_signature_t *signature; |
2677 | pgpv_onepass_t *onepass; | | 2764 | pgpv_onepass_t *onepass; |
2678 | pgpv_litdata_t *litdata; | | 2765 | pgpv_litdata_t *litdata; |
2679 | unsigned sub; | | 2766 | unsigned sub; |
2680 | size_t pkt; | | 2767 | size_t pkt; |
2681 | char strkeyid[PGPV_STR_KEYID_LEN]; | | 2768 | obuf_t obuf; |
2682 | int j; | | 2769 | int j; |
2683 | | | 2770 | |
2684 | if (cursor == NULL || pgp == NULL || p == NULL) { | | 2771 | if (cursor == NULL || pgp == NULL || p == NULL) { |
2685 | return 0; | | 2772 | return 0; |
2686 | } | | 2773 | } |
2687 | if (!setup_data(cursor, pgp, p, size)) { | | 2774 | if (!setup_data(cursor, pgp, p, size)) { |
2688 | snprintf(cursor->why, sizeof(cursor->why), "No input data"); | | 2775 | snprintf(cursor->why, sizeof(cursor->why), "No input data"); |
2689 | return 0; | | 2776 | return 0; |
2690 | } | | 2777 | } |
2691 | if (ARRAY_COUNT(cursor->pgp->pkts) == ARRAY_LAST(cursor->pgp->datastarts) + 1) { | | 2778 | if (ARRAY_COUNT(cursor->pgp->pkts) == ARRAY_LAST(cursor->pgp->datastarts) + 1) { |
2692 | /* got detached signature here */ | | 2779 | /* got detached signature here */ |
2693 | if (!fixup_detached(cursor, p)) { | | 2780 | if (!fixup_detached(cursor, p)) { |
2694 | snprintf(cursor->why, sizeof(cursor->why), "Can't read signed file '%s'", (const char *)p); | | 2781 | snprintf(cursor->why, sizeof(cursor->why), "Can't read signed file '%s'", (const char *)p); |
2695 | return 0; | | 2782 | return 0; |
2696 | } | | 2783 | } |
2697 | } | | 2784 | } |
2698 | if ((pkt = find_onepass(cursor, ARRAY_LAST(cursor->pgp->datastarts))) == 0) { | | 2785 | if ((pkt = find_onepass(cursor, ARRAY_LAST(cursor->pgp->datastarts))) == 0) { |
2699 | snprintf(cursor->why, sizeof(cursor->why), "No signature found"); | | 2786 | snprintf(cursor->why, sizeof(cursor->why), "No signature found"); |
2700 | return 0; | | 2787 | return 0; |
2701 | } | | 2788 | } |
2702 | pkt -= 1; | | 2789 | pkt -= 1; |
2703 | onepass = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt).u.onepass; | | 2790 | onepass = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt).u.onepass; |
2704 | litdata = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt + 1).u.litdata; | | 2791 | litdata = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt + 1).u.litdata; |
2705 | signature = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt + 2).u.sigpkt.sig; | | 2792 | signature = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt + 2).u.sigpkt.sig; |
2706 | /* sanity check values in signature and onepass agree */ | | 2793 | /* sanity check values in signature and onepass agree */ |
2707 | if (signature->birth == 0) { | | 2794 | if (signature->birth == 0) { |
2708 | fmt_time(cursor->why, sizeof(cursor->why), "Signature creation time [", | | 2795 | if (!fmt_time(&obuf, "Signature creation time [", |
2709 | signature->birth, "] out of range", 0); | | 2796 | signature->birth, "] out of range", 0)) { |
| | | 2797 | } |
| | | 2798 | snprintf(cursor->why, sizeof(cursor->why), "%.*s", (int)obuf.c, (char *)obuf.v); |
2710 | return 0; | | 2799 | return 0; |
2711 | } | | 2800 | } |
| | | 2801 | memset(&obuf, 0x0, sizeof(obuf)); |
2712 | if (memcmp(onepass->keyid, signature->signer, PGPV_KEYID_LEN) != 0) { | | 2802 | if (memcmp(onepass->keyid, signature->signer, PGPV_KEYID_LEN) != 0) { |
2713 | fmt_binary(strkeyid, sizeof(strkeyid), onepass->keyid, (unsigned)sizeof(onepass->keyid)); | | 2803 | if (!fmt_binary(&obuf, onepass->keyid, (unsigned)sizeof(onepass->keyid))) { |
2714 | snprintf(cursor->why, sizeof(cursor->why), "Signature key id %s does not match onepass keyid", | | 2804 | snprintf(cursor->why, sizeof(cursor->why), "Memory allocation failure"); |
2715 | strkeyid); | | 2805 | return 0; |
| | | 2806 | } |
| | | 2807 | snprintf(cursor->why, sizeof(cursor->why), |
| | | 2808 | "Signature key id %.*s does not match onepass keyid", |
| | | 2809 | (int)obuf.c, (char *)obuf.v); |
2716 | return 0; | | 2810 | return 0; |
2717 | } | | 2811 | } |
2718 | if (onepass->hashalg != signature->hashalg) { | | 2812 | if (onepass->hashalg != signature->hashalg) { |
2719 | snprintf(cursor->why, sizeof(cursor->why), "Signature hashalg %u does not match onepass hashalg %u", | | 2813 | snprintf(cursor->why, sizeof(cursor->why), |
| | | 2814 | "Signature hashalg %u does not match onepass hashalg %u", |
2720 | signature->hashalg, onepass->hashalg); | | 2815 | signature->hashalg, onepass->hashalg); |
2721 | return 0; | | 2816 | return 0; |
2722 | } | | 2817 | } |
2723 | if (onepass->keyalg != signature->keyalg) { | | 2818 | if (onepass->keyalg != signature->keyalg) { |
2724 | snprintf(cursor->why, sizeof(cursor->why), "Signature keyalg %u does not match onepass keyalg %u", | | 2819 | snprintf(cursor->why, sizeof(cursor->why), |
| | | 2820 | "Signature keyalg %u does not match onepass keyalg %u", |
2725 | signature->keyalg, onepass->keyalg); | | 2821 | signature->keyalg, onepass->keyalg); |
2726 | return 0; | | 2822 | return 0; |
2727 | } | | 2823 | } |
2728 | if (cursor->pgp->ssh) { | | 2824 | if (cursor->pgp->ssh) { |
2729 | fixup_ssh_keyid(cursor->pgp, signature, "sha1"); | | 2825 | fixup_ssh_keyid(cursor->pgp, signature, "sha1"); |
2730 | } | | 2826 | } |
2731 | sub = 0; | | 2827 | sub = 0; |
2732 | if ((j = find_keyid(cursor->pgp, NULL, onepass->keyid, &sub)) < 0) { | | 2828 | if ((j = find_keyid(cursor->pgp, NULL, onepass->keyid, &sub)) < 0) { |
2733 | fmt_binary(strkeyid, sizeof(strkeyid), onepass->keyid, (unsigned)sizeof(onepass->keyid)); | | 2829 | if (!fmt_binary(&obuf, onepass->keyid, (unsigned)sizeof(onepass->keyid))) { |
2734 | snprintf(cursor->why, sizeof(cursor->why), "Signature key id %s not found ", strkeyid); | | 2830 | snprintf(cursor->why, sizeof(cursor->why), "Memory allocation failure"); |
| | | 2831 | return 0; |
| | | 2832 | } |
| | | 2833 | snprintf(cursor->why, sizeof(cursor->why), |
| | | 2834 | "Signature key id %.*s not found ", |
| | | 2835 | (int)obuf.c, (char *)obuf.v); |
2735 | return 0; | | 2836 | return 0; |
2736 | } | | 2837 | } |
2737 | if (!match_sig_id(cursor, signature, litdata, (unsigned)j, sub)) { | | 2838 | if (!match_sig_id(cursor, signature, litdata, (unsigned)j, sub)) { |
| | | 2839 | snprintf(cursor->why, sizeof(cursor->why), |
| | | 2840 | "Signature does not match %.*s", |
| | | 2841 | (int)obuf.c, (char *)obuf.v); |
2738 | return 0; | | 2842 | return 0; |
2739 | } | | 2843 | } |
2740 | ARRAY_APPEND(cursor->datacookies, pkt); | | 2844 | ARRAY_APPEND(cursor->datacookies, pkt); |
2741 | j = ((j & 0xffffff) << 8) | (sub & 0xff); | | 2845 | j = ((j & 0xffffff) << 8) | (sub & 0xff); |
2742 | ARRAY_APPEND(cursor->found, j); | | 2846 | ARRAY_APPEND(cursor->found, j); |
2743 | return pkt + 1; | | 2847 | return pkt + 1; |
2744 | } | | 2848 | } |
2745 | | | 2849 | |
2746 | /* set up the pubkey keyring */ | | 2850 | /* set up the pubkey keyring */ |
2747 | int | | 2851 | int |
2748 | pgpv_read_pubring(pgpv_t *pgp, const void *keyring, ssize_t size) | | 2852 | pgpv_read_pubring(pgpv_t *pgp, const void *keyring, ssize_t size) |
2749 | { | | 2853 | { |
2750 | if (pgp == NULL) { | | 2854 | if (pgp == NULL) { |