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
26 #include "pgppacket.h"
44 { 3, "pgp-ripemd160" },
46 { 6, "pgp-tiger192" },
47 { 7, "pgp-haval-5-160" },
54 static const char *pgp_hash_to_micalg (short id)
58 for (i = 0; HashAlgorithms[i].id >= 0; i++)
59 if (HashAlgorithms[i].id == id)
60 return HashAlgorithms[i].name;
64 static void pgp_dearmor (FILE *in, FILE *out)
66 char line[HUGE_STRING];
73 memset (&state, 0, sizeof (STATE));
77 /* find the beginning of ASCII armor */
79 while ((r = fgets (line, sizeof (line), in)) != NULL)
81 if (!strncmp (line, "-----BEGIN", 10))
86 dprint (1, (debugfile, "pgp_dearmor: Can't find begin of ASCII armor.\n"));
90 /* skip the armor header */
92 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)
110 if (*line == '=' || !strncmp (line, "-----END", 8))
115 dprint (1, (debugfile, "pgp_dearmor: Can't find end of ASCII armor.\n"));
119 if ((end = ftell (in) - strlen (line)) < start)
121 dprint (1, (debugfile, "pgp_dearmor: end < start???\n"));
125 if (fseek (in, start, SEEK_SET) == -1)
127 dprint (1, (debugfile, "pgp_dearmor: Can't seekto start.\n"));
131 mutt_decode_base64 (&state, end - start, 0, (iconv_t) -1);
134 static short pgp_mic_from_packet (unsigned char *p, size_t len)
137 if ((p[0] & 0x3f) != PT_SIG)
139 dprint (1, (debugfile, "pgp_mic_from_packet: tag = %d, want %d.\n",
144 if (len >= 18 && p[1] == 3)
145 /* version 3 signature */
146 return (short) p[17];
147 else if (len >= 5 && p[1] == 4)
148 /* version 4 signature */
152 dprint (1, (debugfile, "pgp_mic_from_packet: Bad signature packet.\n"));
157 static short pgp_find_hash (const char *fname)
162 char tempfile[_POSIX_PATH_MAX];
169 mutt_mktemp (tempfile);
170 if ((out = safe_fopen (tempfile, "w+")) == NULL)
172 mutt_perror (tempfile);
177 if ((in = fopen (fname, "r")) == NULL)
183 pgp_dearmor (in, out);
186 if ((p = pgp_read_packet (out, &l)) != NULL)
188 rv = pgp_mic_from_packet (p, l);
192 dprint (1, (debugfile, "pgp_find_hash: No packet.\n"));
199 pgp_release_packet ();
203 const char *pgp_micalg (const char *fname)
205 return pgp_hash_to_micalg (pgp_find_hash (fname));