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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (show annotations) (download)
Tue Nov 6 23:41:58 2001 UTC (11 years, 7 months ago) by rabbi
File MIME type: text/plain
File size: 13841 byte(s)
First round of changes adding support for Mixmaster as a service under
Windows NT.
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 Create OpenPGP packets
9 $Id: pgpcreat.c,v 1.2 2001/11/06 23:41:58 rabbi Exp $ */
10
11
12 #include "mix3.h"
13 #ifdef USE_PGP
14 #include "pgp.h"
15 #include "crypto.h"
16 #include <assert.h>
17 #include <time.h>
18 #include <time.h>
19
20 int pgp_packet(BUFFER *in, int type)
21 {
22 int ctb;
23 BUFFER *out;
24
25 out = buf_new();
26 ctb = 128 + (type << 2);
27 if (in->length < 256 && type != PGP_PUBKEY && type != PGP_SECKEY &&
28 type != PGP_SIG && type != PGP_PUBSUBKEY && type != PGP_SECSUBKEY
29 #ifdef MIMIC
30 && type != PGP_ENCRYPTED
31 #endif
32 ) {
33 buf_setc(out, ctb);
34 buf_appendc(out, in->length);
35 }
36 #ifndef MIMIC
37 else if (in->length < 65536)
38 #else
39 else if ((type == PGP_PUBKEY || type == PGP_SECKEY || type == PGP_SIG
40 || type == PGP_SESKEY || type == PGP_PUBSUBKEY ||
41 type == PGP_SECSUBKEY) && in->length < 65536)
42 #endif
43 {
44 buf_appendc(out, ctb | 1);
45 buf_appendi(out, in->length);
46 } else {
47 buf_appendc(out, ctb | 2);
48 buf_appendl(out, in->length);
49 }
50 buf_cat(out, in);
51 buf_move(in, out);
52 buf_free(out);
53 return (0);
54 }
55
56 int pgp_subpacket(BUFFER *in, int type)
57 {
58 BUFFER *out;
59 int len;
60
61 out = buf_new();
62 len = in->length + 1;
63 if (len < 192)
64 buf_setc(out, len);
65 else {
66 buf_setc(out, 255);
67 buf_appendl(out, len);
68 }
69 buf_appendc(out, type);
70 buf_cat(out, in);
71 buf_move(in, out);
72 buf_free(out);
73 return (0);
74 }
75
76 int pgp_packet3(BUFFER *in, int type)
77 {
78 #ifdef MIMIC
79 int ctb;
80 BUFFER *out;
81
82 out = buf_new();
83 ctb = 128 + (type << 2);
84 buf_setc(out, ctb | 3);
85 buf_cat(out, in);
86 buf_move(in, out);
87 buf_free(out);
88 return (0);
89 #else
90 return pgp_packet(in, type);
91 #endif
92 }
93
94 #ifdef USE_IDEA
95 static int pgp_ideaencrypt(BUFFER *in, BUFFER *out, BUFFER *key)
96 {
97 byte iv[8];
98 int i, n = 0;
99 IDEA_KEY_SCHEDULE ks;
100
101 assert(key->length == 17);
102
103 for (i = 0; i < 8; i++)
104 iv[i] = 0;
105
106 idea_set_encrypt_key(key->data + 1, &ks);
107
108 rnd_bytes(out->data, 8);
109 out->data[8] = out->data[6], out->data[9] = out->data[7];
110 n = 0;
111 idea_cfb64_encrypt(out->data, out->data, 10, &ks, iv, &n, IDEA_ENCRYPT);
112 iv[6] = iv[0], iv[7] = iv[1];
113 memcpy(iv, out->data + 2, 6);
114 n = 0;
115 idea_cfb64_encrypt(in->data, out->data + 10, in->length, &ks, iv, &n,
116 IDEA_ENCRYPT);
117 return (0);
118 }
119 #endif
120
121 static int pgp_3desencrypt(BUFFER *in, BUFFER *out, BUFFER *key)
122 {
123 des_cblock iv;
124 int i, n = 0;
125 des_key_schedule ks1;
126 des_key_schedule ks2;
127 des_key_schedule ks3;
128
129 assert(key->length == 25);
130
131 for (i = 0; i < 8; i++)
132 iv[i] = 0;
133
134 des_set_key((const_des_cblock *) (key->data + 1), ks1);
135 des_set_key((const_des_cblock *) (key->data + 9), ks2);
136 des_set_key((const_des_cblock *) (key->data+ 17), ks3);
137
138 rnd_bytes(out->data, 8);
139 out->data[8] = out->data[6], out->data[9] = out->data[7];
140 n = 0;
141 des_ede3_cfb64_encrypt(out->data, out->data, 10, ks1, ks2, ks3, &iv, &n,
142 ENCRYPT);
143 iv[6] = iv[0], iv[7] = iv[1];
144 memcpy(iv, out->data + 2, 6);
145 n = 0;
146 des_ede3_cfb64_encrypt(in->data, out->data + 10, in->length, ks1, ks2, ks3,
147 &iv, &n, ENCRYPT);
148 return (0);
149 }
150
151 static int pgp_castencrypt(BUFFER *in, BUFFER *out, BUFFER *key)
152 {
153 byte iv[8];
154 int i, n = 0;
155 CAST_KEY ks;
156
157 assert(key->length == 17);
158
159 for (i = 0; i < 8; i++)
160 iv[i] = 0;
161
162 CAST_set_key(&ks, 16, key->data + 1);
163
164 rnd_bytes(out->data, 8);
165 out->data[8] = out->data[6], out->data[9] = out->data[7];
166 n = 0;
167 CAST_cfb64_encrypt(out->data, out->data, 10, &ks, iv, &n, CAST_ENCRYPT);
168 iv[6] = iv[0], iv[7] = iv[1];
169 memcpy(iv, out->data + 2, 6);
170 n = 0;
171 CAST_cfb64_encrypt(in->data, out->data + 10, in->length, &ks, iv, &n,
172 CAST_ENCRYPT);
173 return (0);
174 }
175
176 int pgp_symmetric(BUFFER *in, BUFFER *key)
177 {
178 BUFFER *out;
179
180 out = buf_new();
181 buf_prepare(out, in->length + 10);
182 switch (buf_getc(key)) {
183 #ifdef USE_IDEA
184 case PGP_K_IDEA:
185 pgp_ideaencrypt(in, out, key);
186 break;
187 #endif
188 case PGP_K_3DES:
189 pgp_3desencrypt(in, out, key);
190 break;
191 case PGP_K_CAST5:
192 pgp_castencrypt(in, out, key);
193 break;
194 default:
195 errlog(ERRORMSG, "Unknown symmetric algorithm.\n");
196 }
197 pgp_packet(out, PGP_ENCRYPTED);
198
199 buf_move(in, out);
200 buf_free(out);
201 return (0);
202 }
203
204 int pgp_literal(BUFFER *b, char *filename, int text)
205 {
206 BUFFER *out;
207 BUFFER *line;
208
209 if (filename == NULL)
210 filename = "stdin";
211
212 if (strlen(filename) > 255)
213 return (-1);
214
215 out = buf_new();
216 line = buf_new();
217
218 if (text)
219 buf_setc(out, 't');
220 else
221 buf_setc(out, 'b');
222 buf_appendc(out, strlen(filename));
223 buf_appends(out, filename);
224 buf_appendl(out, 0); /* timestamp */
225
226 if (b->length > 0) {
227 if (text)
228 while (buf_getline(b, line) != -1) {
229 buf_cat(out, line);
230 buf_appends(out, "\r\n");
231 } else
232 buf_cat(out, b);
233 }
234 pgp_packet(out, PGP_LITERAL);
235 buf_move(b, out);
236 buf_free(out);
237 buf_free(line);
238
239 return (0);
240 }
241
242 int pgp_compress(BUFFER *in)
243 {
244 int err;
245 BUFFER *out;
246
247 out = buf_new();
248 buf_setc(out, 1);
249 err = buf_zip(out, in, 13);
250 if (err == 0) {
251 pgp_packet3(out, PGP_COMPRESSED);
252 buf_move(in, out);
253 }
254 buf_free(out);
255 return (err);
256 }
257
258 int pgp_sessionkey(BUFFER *out, BUFFER *user, BUFFER *keyid, BUFFER *seskey,
259 char *pubring)
260 {
261 BUFFER *encrypt, *key, *id;
262 int algo, sym, err = -1;
263 int i, csum = 0;
264 int tempbuf = 0;
265
266 encrypt = buf_new();
267 key = buf_new();
268 id = buf_new();
269 if (keyid == NULL) {
270 keyid = buf_new();
271 tempbuf = 1;
272 }
273 sym = seskey->data[0];
274 if ((algo = pgpdb_getkey(PK_ENCRYPT, PGP_ANY, &sym, key, user, NULL, keyid,
275 pubring, NULL)) == -1)
276 goto end;
277
278 buf_setc(out, 3); /* type */
279 buf_cat(out, keyid);
280 buf_appendc(out, algo); /* algorithm */
281
282 buf_set(encrypt, seskey);
283
284 for (i = 1; i < encrypt->length; i++)
285 csum = (csum + encrypt->data[i]) % 65536;
286 buf_appendi(encrypt, csum);
287
288 switch (algo) {
289 #ifdef USE_RSA
290 case PGP_ES_RSA:
291 err = pgp_rsa(encrypt, key, PK_ENCRYPT);
292 mpi_put(out, encrypt);
293 break;
294 #endif
295 case PGP_E_ELG:
296 err = pgp_elgencrypt(encrypt, key);
297 buf_cat(out, encrypt);
298 break;
299 default:
300 errlog(NOTICE, "Unknown encryption algorithm.\n");
301 err = -1;
302 goto end;
303 }
304 if (err == -1) {
305 errlog(ERRORMSG, "Encryption failed!\n");
306 goto end;
307 }
308 pgp_packet(out, PGP_SESKEY);
309 end:
310 if (tempbuf)
311 buf_free(keyid);
312 buf_free(id);
313 buf_free(encrypt);
314 buf_free(key);
315 return (err);
316 }
317
318 void pgp_marker(BUFFER *out)
319 {
320 buf_clear(out);
321 buf_append(out, "PGP", 3);
322 pgp_packet(out, PGP_MARKER);
323 }
324
325 int pgp_symsessionkey(BUFFER *out, BUFFER *seskey, BUFFER *pass)
326 {
327 BUFFER *key;
328 int sym;
329 key = buf_new();
330
331 sym = seskey->data[0];
332 buf_setc(out, 4); /* version */
333 #ifdef MIMICPGP5
334 pgp_makesk(out, key, sym, 1, PGP_H_MD5, pass);
335 #else
336 pgp_makesk(out, key, sym, 3, PGP_H_SHA1, pass);
337 #endif
338 if (seskey->length > 1)
339 buf_cat(out, seskey);
340 else {
341 buf_setc(seskey, sym);
342 buf_cat(seskey, key);
343 }
344 pgp_packet(out, PGP_SYMSESKEY);
345 buf_free(key);
346 return (0);
347 }
348
349 int pgp_digest(int hashalgo, BUFFER *in, BUFFER *d)
350 {
351 switch (hashalgo) {
352 case PGP_H_MD5:
353 digest_md5(in, d);
354 return (0);
355 case PGP_H_SHA1:
356 digest_sha1(in, d);
357 return (0);
358 case PGP_H_RIPEMD:
359 digest_rmd160(in, d);
360 return (0);
361 default:
362 return (-1);
363 }
364 }
365
366 int asnprefix(BUFFER *b, int hashalgo)
367 {
368 switch (hashalgo) {
369 case PGP_H_MD5:
370 buf_append(b, MD5PREFIX, sizeof(MD5PREFIX) - 1);
371 return (0);
372 case PGP_H_SHA1:
373 buf_append(b, SHA1PREFIX, sizeof(SHA1PREFIX) - 1);
374 return (0);
375 default:
376 return (-1);
377 }
378 }
379
380 int pgp_expandsk(BUFFER *key, int skalgo, int hashalgo, BUFFER *data)
381 {
382 BUFFER *temp;
383 int keylen;
384 int err = 0;
385 temp = buf_new();
386
387 keylen = pgp_keylen(skalgo);
388 buf_clear(key);
389 while (key->length < keylen) {
390 if (pgp_digest(hashalgo, data, temp) == -1) {
391 err = -1;
392 goto end;
393 }
394 buf_cat(key, temp);
395
396 buf_setc(temp, 0);
397 buf_cat(temp, data);
398 buf_move(data, temp);
399 }
400
401 if (key->length > keylen) {
402 buf_set(temp, key);
403 buf_get(temp, key, keylen);
404 }
405 end:
406 buf_free(temp);
407 return(err);
408 }
409
410 int pgp_makesk(BUFFER *out, BUFFER *key, int sym, int type, int hash,
411 BUFFER *pass)
412 {
413 int err = 0;
414 BUFFER *salted;
415 salted = buf_new();
416
417 buf_appendc(out, sym);
418 buf_appendc(out, type);
419 buf_appendc(out, hash);
420 switch (type) {
421 case 0:
422 buf_set(salted, pass);
423 break;
424 case 1:
425 buf_appendrnd(salted, 8); /* salt */
426 buf_cat(out, salted);
427 buf_cat(salted, pass);
428 break;
429 case 3:
430 buf_appendrnd(salted, 8); /* salt */
431 buf_cat(out, salted);
432 buf_appendc(out, 96); /* encoded count value 65536 */
433 pgp_iteratedsk(salted, salted, pass, 96);
434 break;
435 default:
436 err = -1;
437 }
438 pgp_expandsk(key, sym, hash, salted);
439 buf_free(salted);
440 return (err);
441 }
442
443 /* PGP/MIME needs to know the hash algorithm */
444 int pgp_signhashalgo(BUFFER *algo, BUFFER *userid, char *secring, BUFFER *pass)
445 {
446 int pkalgo;
447
448 pkalgo = pgpdb_getkey(PK_SIGN, PGP_ANY, NULL, NULL, userid, NULL, NULL,
449 secring, pass);
450 if (pkalgo == PGP_S_DSA)
451 buf_sets(algo, "sha1");
452 if (pkalgo == PGP_ES_RSA)
453 buf_sets(algo, "md5");
454 return (pkalgo > 0 ? 0 : -1);
455 }
456
457 int pgp_sign(BUFFER *msg, BUFFER *msg2, BUFFER *sig, BUFFER *userid,
458 BUFFER *pass, int type, int self, long now, int remail,
459 BUFFER *keypacket, char *secring)
460 /* msg: data to be signed (buffer is modified)
461 msg2: additional data to be signed for certain sig types
462 sig: signature is placed here
463 userid: select signing key
464 pass: pass phrase for signing key
465 type: PGP signature type
466 self: is this a self-signature?
467 now: time of signature creation
468 remail: is this an anonymous message?
469 keypacket: signature key
470 secring: key ring with signature key */
471 {
472 BUFFER *key, *id, *d, *sub, *enc;
473 int algo, err = -1;
474 int version = 3, hashalgo;
475 int type1;
476
477 id = buf_new();
478 d = buf_new();
479 sub = buf_new();
480 enc = buf_new();
481 key = buf_new();
482
483 if (now == 0) {
484 now = time(NULL);
485 if (remail)
486 now -= rnd_number(4 * 24 * 60 * 60);
487 }
488 if (keypacket) {
489 buf_rewind(keypacket);
490 algo = pgp_getkey(PK_SIGN, PGP_ANY, NULL, keypacket, key, id, NULL, pass);
491 } else
492 algo = pgpdb_getkey(PK_SIGN, PGP_ANY, NULL, key, userid, NULL, id, secring,
493 pass);
494 if (algo <= -1) {
495 err = algo;
496 goto end;
497 }
498 if (algo == PGP_S_DSA)
499 version = 4;
500 if (version == 3)
501 hashalgo = PGP_H_MD5;
502 else
503 hashalgo = PGP_H_SHA1;
504
505 if (!self)
506 version = 3;
507
508 switch (type) {
509 case PGP_SIG_CERT:
510 type1 = pgp_getpacket(msg, d);
511 assert (type1 == PGP_PUBKEY);
512 buf_setc(msg, 0x99);
513 buf_appendi(msg, d->length);
514 buf_cat(msg, d);
515
516 pgp_getpacket(msg2, d);
517 switch (version) {
518 case 3:
519 buf_cat(msg, d);
520 break;
521 case 4:
522 buf_appendc(msg, 0xb4);
523 buf_appendl(msg, d->length);
524 buf_cat(msg, d);
525 break;
526 }
527 break;
528 case PGP_SIG_BINDSUBKEY:
529 type1 = pgp_getpacket(msg, d);
530 assert (type1 == PGP_PUBKEY);
531 buf_clear(msg);
532 buf_appendc(msg, 0x99);
533 buf_appendi(msg, d->length);
534 buf_cat(msg, d);
535
536 type1 = pgp_getpacket(msg2, d);
537 assert (type1 == PGP_PUBSUBKEY);
538 buf_appendc(msg, 0x99);
539 buf_appendi(msg, d->length);
540 buf_cat(msg, d);
541 break;
542 case PGP_SIG_BINARY:
543 break;
544 case PGP_SIG_CANONIC:
545 pgp_sigcanonic(msg);
546 break;
547 default:
548 NOT_IMPLEMENTED;
549 }
550 switch (version) {
551 case 3:
552 buf_set(d, msg);
553 buf_appendc(d, type);
554 buf_appendl(d, now);
555 pgp_digest(hashalgo, d, d);
556 if (algo == PGP_ES_RSA)
557 asnprefix(enc, hashalgo);
558 buf_cat(enc, d);
559 err = pgp_dosign(algo, enc, key);
560
561 buf_setc(sig, version);
562 buf_appendc(sig, 5);
563 buf_appendc(sig, type);
564 buf_appendl(sig, now);
565 buf_cat(sig, id);
566 buf_appendc(sig, algo);
567 buf_appendc(sig, hashalgo);
568 buf_append(sig, d->data, 2);
569 buf_cat(sig, enc);
570 break;
571
572 case 4:
573 buf_setc(sig, version);
574 buf_appendc(sig, type);
575 buf_appendc(sig, algo);
576 buf_appendc(sig, hashalgo);
577
578 buf_clear(d);
579 buf_appendl(d, now);
580 pgp_subpacket(d, PGP_SUB_CREATIME);
581 buf_cat(sub, d);
582
583 if (self) {
584 buf_setc(d, PGP_K_3DES);
585 pgp_subpacket(d, PGP_SUB_PSYMMETRIC);
586 buf_cat(sub, d);
587 }
588
589 buf_appendi(sig, sub->length); /* hashed subpacket length */
590 buf_cat(sig, sub);
591
592 /* compute message digest */
593 buf_set(d, msg);
594 buf_cat(d, sig);
595 buf_appendc(d, version);
596 buf_appendc(d, 0xff);
597 buf_appendl(d, sig->length);
598 pgp_digest(hashalgo, d, d);
599
600 pgp_subpacket(id, PGP_SUB_ISSUER);
601 buf_appendi(sig, id->length); /* unhashed subpacket length */
602 buf_cat(sig, id);
603
604 buf_append(sig, d->data, 2);
605
606 if (algo == PGP_ES_RSA)
607 asnprefix(enc, hashalgo);
608 buf_cat(enc, d);
609 err = pgp_dosign(algo, enc, key);
610 buf_cat(sig, enc);
611 break;
612 }
613 pgp_packet(sig, PGP_SIG);
614
615 end:
616 buf_free(key);
617 buf_free(id);
618 buf_free(d);
619 buf_free(sub);
620 buf_free(enc);
621 return (err);
622 }
623
624 int pgp_pubkeycert(BUFFER *userid, char *keyring, BUFFER *pass,
625 BUFFER *out, int remail)
626 {
627 BUFFER *key;
628 KEYRING *r;
629 int err = -1;
630
631 key = buf_new();
632 r = pgpdb_open(keyring, pass, 0);
633 if (r != NULL)
634 while (pgpdb_getnext(r, key, NULL, userid) != -1) {
635 if (pgp_makepubkey(key, NULL, out, pass, 0) != -1)
636 err = 0;
637 }
638 if (err == 0)
639 pgp_armor(out, remail);
640 else
641 buf_clear(out);
642 buf_free(key);
643 return (err);
644 }
645
646 #endif /* USE_PGP */

  ViewVC Help
Powered by ViewVC 1.1.5