2 * Copyright (C) 2001 Thomas Roessler <roessler@does-not-exist.org>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public
15 * License along with this program; if not, write to the Free
16 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 /* This module peeks at a PGP signature and figures out the hash
30 #include "pgppacket.h"
42 } HashAlgorithms[] = {
46 3, "pgp-ripemd160"}, {
49 7, "pgp-haval-5-160"}, {
56 static const char *pgp_hash_to_micalg (short id)
60 for (i = 0; HashAlgorithms[i].id >= 0; i++)
61 if (HashAlgorithms[i].id == id)
62 return HashAlgorithms[i].name;
66 static void pgp_dearmor (FILE * in, FILE * out)
68 char line[HUGE_STRING];
75 memset (&state, 0, sizeof (STATE));
79 /* find the beginning of ASCII armor */
81 while ((r = fgets (line, sizeof (line), in)) != NULL) {
82 if (!strncmp (line, "-----BEGIN", 10))
87 (debugfile, "pgp_dearmor: Can't find begin of ASCII armor.\n"));
91 /* skip the armor header */
93 while ((r = fgets (line, sizeof (line), in)) != NULL) {
99 dprint (1, (debugfile, "pgp_dearmor: Armor header doesn't end.\n"));
103 /* actual data starts here */
106 /* find the checksum */
108 while ((r = fgets (line, sizeof (line), in)) != NULL) {
109 if (*line == '=' || !strncmp (line, "-----END", 8))
113 dprint (1, (debugfile, "pgp_dearmor: Can't find end of ASCII armor.\n"));
117 if ((end = ftell (in) - strlen (line)) < start) {
118 dprint (1, (debugfile, "pgp_dearmor: end < start???\n"));
122 if (fseek (in, start, SEEK_SET) == -1) {
123 dprint (1, (debugfile, "pgp_dearmor: Can't seekto start.\n"));
127 mutt_decode_base64 (&state, end - start, 0, (iconv_t) - 1);
130 static short pgp_mic_from_packet (unsigned char *p, size_t len)
133 if ((p[0] & 0x3f) != PT_SIG) {
134 dprint (1, (debugfile, "pgp_mic_from_packet: tag = %d, want %d.\n",
135 p[0] & 0x3f, PT_SIG));
139 if (len >= 18 && p[1] == 3)
140 /* version 3 signature */
141 return (short) p[17];
142 else if (len >= 5 && p[1] == 4)
143 /* version 4 signature */
146 dprint (1, (debugfile, "pgp_mic_from_packet: Bad signature packet.\n"));
151 static short pgp_find_hash (const char *fname)
156 char tempfile[_POSIX_PATH_MAX];
163 mutt_mktemp (tempfile);
164 if ((out = safe_fopen (tempfile, "w+")) == NULL) {
165 mutt_perror (tempfile);
170 if ((in = fopen (fname, "r")) == NULL) {
175 pgp_dearmor (in, out);
178 if ((p = pgp_read_packet (out, &l)) != NULL) {
179 rv = pgp_mic_from_packet (p, l);
182 dprint (1, (debugfile, "pgp_find_hash: No packet.\n"));
189 pgp_release_packet ();
193 const char *pgp_micalg (const char *fname)
195 return pgp_hash_to_micalg (pgp_find_hash (fname));