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

Contents of /branches/mixmaster_2_9_STABLE/Mix/Src/pgp.c

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native
svn:keywords Id

  ViewVC Help
Powered by ViewVC 1.1.5