/[pkg-mixmaster]/trunk/Mix/Src/pgp.c
ViewVC logotype

Contents of /trunk/Mix/Src/pgp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations) (download)
Wed Oct 31 08:19:51 2001 UTC (11 years, 7 months ago) by rabbi
File MIME type: text/plain
File size: 10450 byte(s)
Initial revision
1 /* Mixmaster version 3 -- (C) 1999 Anonymizer Inc.
2
3 Mixmaster may be redistributed and modified under certain conditions.
4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5 ANY KIND, either express or implied. See the file COPYRIGHT for
6 details.
7
8 OpenPGP messages
9 $Id: pgp.c,v 1.1 2001/10/31 08:19:53 rabbi Exp $ */
10
11
12 #include "mix3.h"
13 #ifdef USE_PGP
14 #include "pgp.h"
15 #include <ctype.h>
16
17 int pgp_decrypt(BUFFER *in, BUFFER *pass, BUFFER *sig, char *pubring,
18 char *secring)
19 {
20 BUFFER *key;
21 int err;
22
23 key = buf_new();
24 if (pass)
25 buf_set(key, pass);
26 if (!pgp_ispacket(in))
27 pgp_dearmor(in, in);
28 err = pgp_getmsg(in, key, sig, pubring, secring);
29 buf_free(key);
30 return (err);
31 }
32
33 static void appendaddr(BUFFER *to, BUFFER *addr)
34 {
35 if (bufifind(addr, "<")) {
36 for (addr->ptr = 0; addr->ptr < addr->length; addr->ptr++)
37 if (addr->data[addr->ptr] == '<') {
38 buf_rest(to, addr);
39 break;
40 }
41 } else {
42 buf_appendc(to, '<');
43 buf_cat(to, addr);
44 buf_appendc(to, '>');
45 }
46 buf_nl(to);
47 buf_clear(addr);
48 }
49
50 int pgp_mailenc(int mode, BUFFER *msg, char *sigid,
51 BUFFER *pass, char *pubring, char *secring)
52 {
53 BUFFER *hdr, *body, *line, *uid, *field, *content;
54 int err = -1;
55
56 hdr = buf_new();
57 body = buf_new();
58 line = buf_new();
59 uid = buf_new();
60 field = buf_new();
61 content = buf_new();
62
63 buf_appendc(uid, '<');
64 buf_appends(uid, sigid);
65 if (sigid[strlen(sigid) - 1] != '@')
66 buf_appendc(uid, '>');
67
68 while (buf_getline(msg, line) == 0)
69 buf_cat(hdr, line), buf_nl(hdr);
70
71 if ((mode & PGP_SIGN) && !(mode & PGP_ENCRYPT))
72 while (buf_getheader(hdr, field, content) == 0)
73 if (bufileft(field, "content-") || bufieq(field, "mime-version")) {
74 /* Is MIME message */
75 err = pgpmime_sign(msg, uid, pass, secring);
76 goto end;
77 }
78
79 buf_rest(body, msg);
80
81 if ((mode & PGP_SIGN) && !(mode & PGP_ENCRYPT)) {
82 err = pgp_signtxt(body, uid, pass, secring, mode & PGP_REMAIL);
83 }
84
85 if (mode & PGP_ENCRYPT) {
86 BUFFER *plainhdr, *encrhdr, *to, *addr;
87 int encapsulate = 0;
88
89 plainhdr = buf_new();
90 encrhdr = buf_new();
91 to = buf_new();
92 addr = buf_new();
93 while (buf_getheader(hdr, field, content) == 0) {
94 if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {
95 buf_appendheader(plainhdr, field, content);
96 rfc822_addr(content, addr);
97 while (buf_getline(addr, content) != -1)
98 appendaddr(to, content);
99 } else
100 buf_appendheader(encrhdr, field, content);
101 }
102 #if 1
103 /* encrypt the headers */
104 buf_appends(plainhdr, "Subject: PGP encrypted message\n");
105 if (encrhdr->length) {
106 buf_nl(encrhdr);
107 buf_cat(encrhdr, body);
108 buf_move(body, encrhdr);
109 encapsulate = 1;
110 }
111 #else
112 /* send headers as plain text */
113 buf_cat(plainhdr, encrhdr);
114 #endif
115 buf_move(hdr, plainhdr);
116
117 buf_clear(line);
118 if (encapsulate)
119 buf_sets(line, "Content-Type: message/rfc822\n");
120 else if (strlen(DEFLTENTITY))
121 buf_setf(line, "Content-Type: %s\n", DEFLTENTITY);
122 buf_nl(line);
123 buf_cat(line, body);
124 buf_move(body, line);
125
126 /* Use the user keyring if pubring == NULL */
127 err = pgp_encrypt(mode, body, to, uid, pass,
128 pubring ? pubring : PGPPUBRING, secring);
129 buf_free(plainhdr);
130 buf_free(encrhdr);
131 buf_free(to);
132 buf_free(addr);
133 }
134 if (err == 0) {
135 if (mode & PGP_ENCRYPT) {
136 #if 1
137 buf_sets(field, "+--");
138 #else
139 buf_setrnd(mboundary, 18);
140 encode(mboundary, 0);
141 #endif
142
143 buf_appendf(hdr,
144 "Content-Type: multipart/encrypted; boundary=\"%b\"; "
145 "protocol=\"application/pgp-encrypted\"\n\n"
146 "--%b\n"
147 "Content-Type: application/pgp-encrypted\n\n"
148 "Version: 1\n\n"
149 "--%b\n"
150 "Content-Type: application/octet-stream\n",
151 field, field, field);
152 buf_appendf(body, "\n--%b--\n", field);
153 }
154 buf_move(msg, hdr);
155 buf_nl(msg);
156 buf_cat(msg, body);
157 }
158 end:
159 buf_free(hdr);
160 buf_free(body);
161 buf_free(line);
162 buf_free(uid);
163 buf_free(field);
164 buf_free(content);
165 return (err);
166 }
167
168 static void pgp_setkey(BUFFER *key, int algo)
169 {
170 buf_setc(key, algo);
171 buf_appendrnd(key, pgp_keylen(algo));
172 }
173
174 int pgp_encrypt(int mode, BUFFER *in, BUFFER *to, BUFFER *sigid,
175 BUFFER *pass, char *pubring, char *secring)
176 {
177 BUFFER *dek, *out, *sig, *dest, *tmp;
178 int err = 0, sym = 0;
179 int text;
180
181 out = buf_new();
182 tmp = buf_new();
183 dek = buf_new();
184 sig = buf_new();
185 dest = buf_new();
186
187 text = mode & PGP_TEXT ? 1 : 0;
188
189 if (mode & (PGP_CONV3DES | PGP_CONVCAST))
190 mode |= PGP_NCONVENTIONAL;
191
192 if (mode & PGP_SIGN) {
193 err = pgp_sign(in, NULL, sig, sigid, pass, text, 0, 0,
194 mode & PGP_REMAIL ? 1 : 0, NULL, secring);
195 if (err < 0)
196 goto end;
197 if (mode & PGP_DETACHEDSIG) {
198 buf_move(in, sig);
199 if (!(mode & PGP_NOARMOR))
200 pgp_armor(in, 4);
201 goto end;
202 }
203 }
204 if (mode & PGP_ENCRYPT) {
205 err = buf_getline(to, dest);
206 if (err == -1)
207 goto end;
208 if (to->ptr == to->length) {
209 if ((err = pgpdb_getkey(PK_ENCRYPT, PGP_ANY, &sym, NULL, dest, NULL,
210 NULL, pubring, NULL)) < 0)
211 goto end;
212 pgp_setkey(dek, sym);
213 err = pgp_sessionkey(out, dest, NULL, dek, pubring);
214 #ifdef USE_IDEA
215 if (err < 0 && dek->data[0] == PGP_K_IDEA) {
216 pgp_setkey(dek, PGP_K_3DES);
217 err = pgp_sessionkey(out, dest, NULL, dek, pubring);
218 }
219 #endif
220 } else {
221 /* multiple recipients */
222 pgp_setkey(dek, PGP_K_3DES);
223 buf_rewind(to);
224 while (buf_getline(to, dest) != -1)
225 if (dest->length) {
226 err = pgp_sessionkey(tmp, dest, NULL, dek, pubring);
227 #ifdef USE_IDEA
228 if (err < 0 && dek->data[0] != PGP_K_IDEA) {
229 buf_rewind(to);
230 buf_clear(out);
231 pgp_setkey(dek, PGP_K_IDEA);
232 continue;
233 }
234 #endif
235 if (err < 0)
236 goto end;
237 buf_cat(out, tmp);
238 }
239 }
240 } else if (mode & PGP_NCONVENTIONAL) {
241 /* genereate DEK in pgp_symsessionkey */
242 buf_setc(dek, mode & PGP_CONVCAST ? PGP_K_CAST5 : PGP_K_3DES);
243 pgp_marker(out);
244 err = pgp_symsessionkey(tmp, dek, to);
245 buf_cat(out, tmp);
246 } else if (mode & PGP_CONVENTIONAL) {
247 digest_md5(to, tmp);
248 buf_setc(dek, PGP_K_IDEA);
249 buf_cat(dek, tmp);
250 }
251
252 pgp_literal(in, NULL, text);
253 if (sig->length) {
254 buf_cat(sig, in);
255 buf_move(in, sig);
256 }
257 pgp_compress(in);
258 if (mode & (PGP_ENCRYPT | PGP_CONVENTIONAL | PGP_NCONVENTIONAL))
259 pgp_symmetric(in, dek);
260 if (mode & (PGP_ENCRYPT | PGP_NCONVENTIONAL)) {
261 buf_cat(out, in);
262 buf_move(in, out);
263 }
264 if (!(mode & PGP_NOARMOR))
265 pgp_armor(in, (mode & PGP_REMAIL) ? 1 : 0);
266
267 end:
268 buf_free(out);
269 buf_free(tmp);
270 buf_free(dek);
271 buf_free(sig);
272 buf_free(dest);
273 return (err);
274 }
275
276 /* ASCII armor */
277
278 int pgp_dearmor(BUFFER *in, BUFFER *out)
279 {
280 BUFFER *line, *temp;
281 int err = 0;
282 int tempbuf = 0;
283
284 line = buf_new();
285 temp = buf_new();
286
287 if (in == out) {
288 out = buf_new();
289 tempbuf = 1;
290 }
291 do
292 if (buf_getline(in, line) == -1) {
293 err = -1;
294 goto end;
295 }
296 while (!bufleft(line, begin_pgp)) ;
297
298 while (buf_getheader(in, temp, line) == 0) ; /* scan for empty line */
299
300 err = decode(in, out);
301 err = buf_getline(in, line);
302 if (line->length == 5 && line->data[0] == '=') /* skip CRC */
303 err = buf_getline(in, line);
304 if (err == 0 && bufleft(line, end_pgp))
305 err = 0;
306 else
307 err = -1;
308
309 end:
310 buf_free(temp);
311 buf_free(line);
312
313 if (tempbuf) {
314 buf_move(in, out);
315 buf_free(out);
316 }
317 return (err);
318 }
319
320 #define POLY 0X1864CFB
321
322 int pgp_armor(BUFFER *in, int mode)
323 /* mode = 1: remailer message, 0: normal message, mode = 2: key 3=nym key
324 4=nym signature */
325 {
326 BUFFER *out;
327 unsigned long crc = 0xB704CE;
328 long p;
329 int i;
330
331 #if 0
332 /* CRC algorithm from RFC 2440 */
333 for (p = 0; p < in->length; p++) {
334 crc ^= in->data[p] << 16;
335 for (i = 0; i < 8; i++) {
336 crc <<= 1;
337 if (crc & 0x1000000)
338 crc ^= POLY;
339 }
340 }
341 #else
342 /* pre-computed CRC table -- much faster */
343 unsigned long table[256];
344 unsigned long t;
345 int q = 0;
346
347 table[0] = 0;
348 for (i = 0; i < 128; i++) {
349 t = table[i] << 1;
350 if (t & 0x1000000) {
351 table[q++] = t ^ POLY;
352 table[q++] = t;
353 } else {
354 table[q++] = t;
355 table[q++] = t ^ POLY;
356 }
357 }
358 for (p = 0; p < in->length; p++)
359 crc = crc << 8 ^ table[(in->data[p] ^ crc >> 16) & 255];
360 #endif
361 encode(in, 64);
362
363 out = buf_new();
364 if (mode == 2 || mode == 3)
365 buf_sets(out, begin_pgpkey);
366 else if (mode == 4)
367 buf_sets(out, begin_pgpsig);
368 else
369 buf_sets(out, begin_pgpmsg);
370 buf_nl(out);
371 #if 1
372 buf_appends(out, "Version: N/A\n");
373 #else
374 #ifdef MIMIC
375 if (mode == 1 || mode == 3 || mode == 4)
376 buf_appends(out, "Version: 2.6.3i\n");
377 else
378 #endif
379 {
380 buf_appends(out, "Version: Mixmaster ");
381 buf_appends(out, VERSION);
382 buf_appends(out, " (OpenPGP module)\n");
383 }
384 #endif
385 buf_nl(out);
386 buf_cat(out, in);
387 buf_reset(in);
388 buf_appendc(in, (crc >> 16) & 255);
389 buf_appendc(in, (crc >> 8) & 255);
390 buf_appendc(in, crc & 255);
391 encode(in, 0);
392 buf_appendc(out, '=');
393 buf_cat(out, in);
394 buf_nl(out);
395 if (mode == 2 || mode == 3)
396 buf_appends(out, end_pgpkey);
397 else if (mode == 4)
398 buf_appends(out, end_pgpsig);
399 else
400 buf_appends(out, end_pgpmsg);
401 buf_nl(out);
402
403 buf_move(in, out);
404 buf_free(out);
405 return (0);
406 }
407
408 int pgp_keygen(int algo, int bits, BUFFER *userid, BUFFER *pass, char *pubring,
409 char *secring, int remail)
410 {
411 switch (algo) {
412 #ifdef USE_RSA
413 case PGP_ES_RSA:
414 return (pgp_rsakeygen(bits, userid, pass, pubring, secring, remail));
415 #endif
416 case PGP_E_ELG:
417 return (pgp_dhkeygen(bits, userid, pass, pubring, secring, remail));
418 default:
419 return -1;
420 }
421 }
422
423 int pgp_signtxt(BUFFER *msg, BUFFER *uid, BUFFER *pass,
424 char *secring, int remail)
425 {
426 int err;
427 BUFFER *line, *sig, *out;
428
429 sig = buf_new();
430 out = buf_new();
431 line = buf_new();
432
433 buf_appends(out, begin_pgpsigned);
434 buf_nl(out);
435 buf_nl(out);
436 while (buf_getline(msg, line) != -1) {
437 if (line->data[0] == '-')
438 buf_appends(out, "- ");
439 buf_cat(out, line);
440 buf_nl(out);
441 }
442 buf_nl(out);
443
444 buf_rewind(msg);
445 err = pgp_encrypt(PGP_SIGN | PGP_DETACHEDSIG | PGP_TEXT |
446 (remail ? PGP_REMAIL : 0),
447 msg, NULL, uid, pass, NULL, secring);
448 if (err == -1)
449 goto end;
450 buf_cat(out, msg);
451 buf_move(msg, out);
452 end:
453 buf_free(sig);
454 buf_free(out);
455 return (err);
456 }
457
458 #endif /* USE_PGP */

  ViewVC Help
Powered by ViewVC 1.1.5