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., 51 Franklin Street, Fifth Floor, Boston,
20 /* This module peeks at a PGP signature and figures out the hash
30 #include "pgppacket.h"
47 { 3, "pgp-ripemd160" },
49 { 6, "pgp-tiger192" },
50 { 7, "pgp-haval-5-160" },
58 static const char *pgp_hash_to_micalg (short id)
62 for (i = 0; HashAlgorithms[i].id >= 0; i++)
63 if (HashAlgorithms[i].id == id)
64 return HashAlgorithms[i].name;
68 static void pgp_dearmor (FILE *in, FILE *out)
70 char line[HUGE_STRING];
77 memset (&state, 0, sizeof (STATE));
81 /* find the beginning of ASCII armor */
83 while ((r = fgets (line, sizeof (line), in)) != NULL)
85 if (!strncmp (line, "-----BEGIN", 10))
90 dprint (1, (debugfile, "pgp_dearmor: Can't find begin of ASCII armor.\n"));
94 /* skip the armor header */
96 while ((r = fgets (line, sizeof (line), in)) != NULL)
103 dprint (1, (debugfile, "pgp_dearmor: Armor header doesn't end.\n"));
107 /* actual data starts here */
110 /* find the checksum */
112 while ((r = fgets (line, sizeof (line), in)) != NULL)
114 if (*line == '=' || !strncmp (line, "-----END", 8))
119 dprint (1, (debugfile, "pgp_dearmor: Can't find end of ASCII armor.\n"));
123 if ((end = ftello (in) - strlen (line)) < start)
125 dprint (1, (debugfile, "pgp_dearmor: end < start???\n"));
129 if (fseeko (in, start, SEEK_SET) == -1)
131 dprint (1, (debugfile, "pgp_dearmor: Can't seekto start.\n"));
135 mutt_decode_base64 (&state, end - start, 0, (iconv_t) -1);
138 static short pgp_mic_from_packet (unsigned char *p, size_t len)
141 if ((p[0] & 0x3f) != PT_SIG)
143 dprint (1, (debugfile, "pgp_mic_from_packet: tag = %d, want %d.\n",
148 if (len >= 18 && p[1] == 3)
149 /* version 3 signature */
150 return (short) p[17];
151 else if (len >= 5 && p[1] == 4)
152 /* version 4 signature */
156 dprint (1, (debugfile, "pgp_mic_from_packet: Bad signature packet.\n"));
161 static short pgp_find_hash (const char *fname)
166 char tempfile[_POSIX_PATH_MAX];
173 mutt_mktemp (tempfile);
174 if ((out = safe_fopen (tempfile, "w+")) == NULL)
176 mutt_perror (tempfile);
181 if ((in = fopen (fname, "r")) == NULL)
187 pgp_dearmor (in, out);
190 if ((p = pgp_read_packet (out, &l)) != NULL)
192 rv = pgp_mic_from_packet (p, l);
196 dprint (1, (debugfile, "pgp_find_hash: No packet.\n"));
203 pgp_release_packet ();
207 const char *pgp_micalg (const char *fname)
209 return pgp_hash_to_micalg (pgp_find_hash (fname));