* Import keyanalyze into signing-party. Thanks to Matthew Wilcox for the
[pgp-tools.git] / keyanalyze / pgpring / pgppacket.c
1 /*
2 * Copyright (C) 2001 Thomas Roessler <roessler@does-not-exist.org>
3 *
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.
8 *
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.
13 *
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,
17 * MA 02111, USA.
18 */
19
20 #include "config.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <time.h>
26
27 #include "sha1.h"
28 #include "lib.h"
29 #include "pgplib.h"
30 #include "pgppacket.h"
31
32 #define CHUNKSIZE 1024
33
34 static unsigned char *pbuf = NULL;
35 static size_t plen = 0;
36
37 static int read_material (size_t material, size_t * used, FILE * fp)
38 {
39 if (*used + material >= plen)
40 {
41 unsigned char *p;
42 size_t nplen;
43
44 nplen = *used + material + CHUNKSIZE;
45
46 if (!(p = realloc (pbuf, nplen))) /* __MEM_CHECKED__ */
47 {
48 perror ("realloc");
49 return -1;
50 }
51 plen = nplen;
52 pbuf = p;
53 }
54
55 if (fread (pbuf + *used, 1, material, fp) < material)
56 {
57 perror ("fread");
58 return -1;
59 }
60
61 *used += material;
62 return 0;
63 }
64
65 unsigned char *pgp_read_packet (FILE * fp, size_t * len)
66 {
67 size_t used = 0;
68 long startpos;
69 unsigned char ctb;
70 unsigned char b;
71 size_t material;
72
73 startpos = ftell (fp);
74
75 if (!plen)
76 {
77 plen = CHUNKSIZE;
78 pbuf = safe_malloc (plen);
79 }
80
81 if (fread (&ctb, 1, 1, fp) < 1)
82 {
83 if (!feof (fp))
84 perror ("fread");
85 goto bail;
86 }
87
88 if (!(ctb & 0x80))
89 {
90 goto bail;
91 }
92
93 if (ctb & 0x40) /* handle PGP 5.0 packets. */
94 {
95 int partial = 0;
96 pbuf[0] = ctb;
97 used++;
98
99 do
100 {
101 if (fread (&b, 1, 1, fp) < 1)
102 {
103 perror ("fread");
104 goto bail;
105 }
106
107 if (b < 192)
108 {
109 material = b;
110 partial = 0;
111 /* material -= 1; */
112 }
113 else if (192 <= b && b <= 223)
114 {
115 material = (b - 192) * 256;
116 if (fread (&b, 1, 1, fp) < 1)
117 {
118 perror ("fread");
119 goto bail;
120 }
121 material += b + 192;
122 partial = 0;
123 /* material -= 2; */
124 }
125 else if (b < 255)
126 {
127 material = 1 << (b & 0x1f);
128 partial = 1;
129 /* material -= 1; */
130 }
131 else
132 /* b == 255 */
133 {
134 unsigned char buf[4];
135 if (fread (buf, 4, 1, fp) < 1)
136 {
137 perror ("fread");
138 goto bail;
139 }
140 /*assert( sizeof(material) >= 4 ); */
141 material = buf[0] << 24;
142 material |= buf[1] << 16;
143 material |= buf[2] << 8;
144 material |= buf[3];
145 partial = 0;
146 /* material -= 5; */
147 }
148
149 if (read_material (material, &used, fp) == -1)
150 goto bail;
151
152 }
153 while (partial);
154 }
155 else
156 /* Old-Style PGP */
157 {
158 int bytes = 0;
159 pbuf[0] = 0x80 | ((ctb >> 2) & 0x0f);
160 used++;
161
162 switch (ctb & 0x03)
163 {
164 case 0:
165 {
166 if (fread (&b, 1, 1, fp) < 1)
167 {
168 perror ("fread");
169 goto bail;
170 }
171
172 material = b;
173 break;
174 }
175
176 case 1:
177 bytes = 2;
178
179 case 2:
180 {
181 int i;
182
183 if (!bytes)
184 bytes = 4;
185
186 material = 0;
187
188 for (i = 0; i < bytes; i++)
189 {
190 if (fread (&b, 1, 1, fp) < 1)
191 {
192 perror ("fread");
193 goto bail;
194 }
195
196 material = (material << 8) + b;
197 }
198 break;
199 }
200
201 default:
202 goto bail;
203 }
204
205 if (read_material (material, &used, fp) == -1)
206 goto bail;
207 }
208
209 if (len)
210 *len = used;
211
212 return pbuf;
213
214 bail:
215
216 fseek (fp, startpos, SEEK_SET);
217 return NULL;
218 }
219
220 void pgp_release_packet (void)
221 {
222 plen = 0;
223 safe_free (&pbuf);
224 }
225