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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations) (download)
Wed Oct 31 08:19:51 2001 UTC (11 years, 6 months ago) by rabbi
File MIME type: text/plain
File size: 11381 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 Encrypt message for Mixmaster chain
9 $Id: chain2.c,v 1.1 2001/10/31 08:19:53 rabbi Exp $ */
10
11
12 #include "mix3.h"
13 #include <string.h>
14 #include <stdlib.h>
15 #include <time.h>
16 #include <ctype.h>
17 #include <assert.h>
18
19 #ifdef USE_RSA
20
21 #define N(X) (isdigit(X) ? (X)-'0' : 0)
22
23 int mix2_rlist(REMAILER remailer[])
24 {
25 FILE *list;
26 int n, i, listed = 0;
27
28 char line[LINELEN], name[LINELEN], addr[LINELEN], keyid[LINELEN],
29 version[LINELEN], flags[LINELEN];
30
31 list = mix_openfile(TYPE2LIST, "r");
32 if (list == NULL) {
33 list = mix_openfile(PUBRING, "r");
34 if (list == NULL)
35 return (-1);
36 }
37 for (n = 1; fgets(line, sizeof(line), list) != NULL && n < MAXREM;)
38 if (strleft(line, begin_key)) {
39 while (fgets(line, sizeof(line), list) != NULL &&
40 !strleft(line, end_key)) ;
41 } else if (strlen(line) > 36 && line[0] != '#') {
42 flags[0] = '\0';
43 if (sscanf(line, "%127s %127s %127s %127s %127s", name,
44 addr, keyid, version, flags) < 4)
45 continue;
46 strncpy(remailer[n].name, name, sizeof(remailer[n].name));
47 remailer[n].name[sizeof(remailer[n].name) - 1] = '\0';
48 strncpy(remailer[n].addr, addr, sizeof(remailer[n].addr));
49 remailer[n].addr[sizeof(remailer[n].addr) - 1] = '\0';
50 remailer[n].flags.mix = 1;
51 remailer[n].flags.cpunk = 0;
52 remailer[n].flags.nym = 0;
53 remailer[n].flags.newnym = 0;
54 id_decode(keyid, remailer[n].keyid);
55 remailer[n].version = N(version[0]);
56 remailer[n].flags.compress = strfind(flags, "C");
57 remailer[n].flags.post = strfind(flags, "N");
58 remailer[n].flags.middle = strfind(flags, "M");
59 remailer[n].info[0].reliability = 0;
60 remailer[n].info[0].latency = 0;
61 remailer[n].info[0].history[0] = '\0';
62 n++;
63 }
64 fclose(list);
65 list = mix_openfile(TYPE2REL, "r");
66 if (list != NULL) {
67 while (fgets(line, sizeof(line), list) != NULL &&
68 !strleft(line, "--------------------------------------------")) ;
69 while (fgets(line, sizeof(line), list) != NULL &&
70 !strleft(line, "</PRE>"))
71 if (strlen(line) >= 44 && strlen(line) <= 46)
72 for (i = 1; i < n; i++)
73 if (strleft(line, remailer[i].name) &&
74 line[strlen(remailer[i].name)] == ' ') {
75 strncpy(remailer[i].info[0].history, line + 15, 12);
76 remailer[i].info[0].history[12] = '\0';
77 remailer[i].info[0].reliability = 10000 * N(line[37])
78 + 1000 * N(line[38]) + 100 * N(line[39])
79 + 10 * N(line[41]) + N(line[42]);
80 remailer[i].info[0].latency = 36000 * N(line[28])
81 + 3600 * N(line[29]) + 600 * N(line[31])
82 + 60 * N(line[32]) + 10 * N(line[34])
83 + N(line[35]);
84 listed++;
85 }
86 fclose(list);
87 }
88 if (listed < 4) /* we have no valid reliability info */
89 for (i = 1; i < n; i++)
90 remailer[i].info[0].reliability = 10000;
91 return (n);
92 }
93
94 static int send_packet(int numcopies, BUFFER *packet, int chain[],
95 int chainlen, int packetnum, int numpackets,
96 BUFFER *mid, REMAILER remailer[], int maxrem,
97 BUFFER *feedback)
98 {
99 BUFFER *pid, *out, *header, *other, *encrypted, *key, *body;
100 BUFFER *iv, *ivarray, *temp;
101 BUFFER *pubkey;
102 char addr[LINELEN];
103 int thischain[20];
104 int hop;
105 int c, i;
106 int timestamp = 0;
107 int israndom = 0;
108 int err = 1;
109
110 body = buf_new();
111 pid = buf_new();
112 out = buf_new();
113 header = buf_new();
114 other = buf_new();
115 key = buf_new();
116 encrypted = buf_new();
117 iv = buf_new();
118 ivarray = buf_new();
119 temp = buf_new();
120
121 buf_setrnd(pid, 16);
122
123 for (c = 0; c < numcopies; c++) {
124 buf_set(body, packet);
125
126 for (hop = 0; hop < chainlen; hop++)
127 thischain[hop] = chain[hop];
128
129 israndom = chain_rand(remailer, maxrem, thischain, chainlen, 0);
130 if (israndom == -1) {
131 err = -1;
132 clienterr(feedback, "No reliable remailers!");
133 }
134 if ((numcopies > 1 || numpackets > 1) && !israndom && (chainlen != 1)) {
135 clienterr(feedback,
136 "Multi-packet message without random remailers!");
137 err = -1;
138 goto end;
139 }
140 for (hop = 0; hop < chainlen; hop++) {
141 switch (remailer[thischain[hop]].version) {
142 case 2:
143 case 3: /* not implemented yet; fall back to version 2 */
144 /* create header chart to be encrypted with the session key */
145 if (numcopies > 1 && hop == 0)
146 buf_set(encrypted, pid); /* same ID only at final hop */
147 else
148 buf_setrnd(encrypted, 16);
149 buf_setrnd(key, 24); /* key for encrypting the body */
150 buf_cat(encrypted, key);
151 buf_setrnd(iv, 8); /* IV for encrypting the body */
152
153 if (hop > 0) {
154 /* IVs for header chart encryption */
155 buf_setrnd(ivarray, 18 * 8);
156 buf_cat(ivarray, iv); /* 19th IV equals the body IV */
157
158 buf_appendc(encrypted, 0);
159 buf_cat(encrypted, ivarray);
160 memset(addr, 0, 80);
161 strcpy(addr, remailer[thischain[hop - 1]].addr);
162 buf_append(encrypted, addr, 80);
163 } else {
164 if (numpackets == 1)
165 buf_appendc(encrypted, 1);
166 else {
167 buf_appendc(encrypted, 2);
168 buf_appendc(encrypted, (byte) packetnum);
169 buf_appendc(encrypted, (byte) numpackets);
170 }
171 buf_cat(encrypted, mid);
172 buf_cat(encrypted, iv); /* body encryption IV */
173 }
174
175 /* timestamp */
176 buf_appends(encrypted, "0000");
177 buf_appendc(encrypted, '\0'); /* timestamp magic */
178 timestamp = time(NULL) / SECONDSPERDAY - rnd_number(4);
179 buf_appendi_lo(encrypted, timestamp);
180
181 /* message digest for this header */
182 digest_md5(encrypted, temp);
183 buf_cat(encrypted, temp);
184 buf_pad(encrypted, 328);
185
186 /* encrypt message body */
187 buf_crypt(body, key, iv, ENCRYPT);
188
189 if (hop > 0) {
190 /* encrypt the other header charts */
191 buf_clear(other);
192 for (i = 0; i < 19; i++) {
193 buf_clear(iv);
194 buf_clear(temp);
195 buf_append(iv, ivarray->data + 8 * i, 8);
196 buf_append(temp, header->data + 512 * i, 512);
197 buf_crypt(temp, key, iv, ENCRYPT);
198 buf_cat(other, temp);
199 }
200 } else
201 buf_setrnd(other, 19 * 512); /* fill with random data */
202
203 /* create session key and IV to encrypt the header ... */
204 buf_setrnd(key, 24);
205 buf_setrnd(iv, 8);
206 buf_crypt(encrypted, key, iv, ENCRYPT);
207 pubkey = buf_new();
208 err = db_getpubkey(remailer[thischain[hop]].keyid, pubkey);
209 if (err == -1)
210 goto end;
211 err = pk_encrypt(key, pubkey); /* ... and encrypt the
212 session key */
213 buf_free(pubkey);
214 if (err == -1 || key->length != 128) {
215 clienterr(feedback, "Encryption failed!");
216 err = -1;
217 goto end;
218 }
219 /* now build the new header */
220 buf_clear(header);
221 buf_append(header, remailer[thischain[hop]].keyid, 16);
222 buf_appendc(header, 128);
223 buf_cat(header, key);
224 buf_cat(header, iv);
225 buf_cat(header, encrypted);
226 buf_pad(header, 512);
227 buf_cat(header, other);
228 break;
229 default:
230 err = -1;
231 goto end;
232 }
233 }
234
235 /* build the message */
236 buf_sets(out, remailer[thischain[chainlen - 1]].addr);
237 buf_nl(out);
238 buf_cat(out, header);
239 buf_cat(out, body);
240 assert(header->length == 10240 && body->length == 10240);
241 mix_pool(out, INTERMEDIATE, -1);
242
243 if (feedback) {
244 for (hop = chainlen - 1; hop >= 0; hop--) {
245 buf_appends(feedback, remailer[thischain[hop]].name);
246 if (hop > 0)
247 buf_appendc(feedback, ',');
248 }
249 buf_nl(feedback);
250 }
251 }
252 end:
253 buf_free(pid);
254 buf_free(body);
255 buf_free(out);
256 buf_free(header);
257 buf_free(temp);
258 buf_free(other);
259 buf_free(key);
260 buf_free(encrypted);
261 buf_free(iv);
262 buf_free(ivarray);
263 return (err);
264 }
265
266 int mix2_encrypt(int type, BUFFER *message, char *chainstr, int numcopies,
267 BUFFER *feedback)
268 {
269 /* returns 0 on success, -1 on error. feedback contains the selected
270 remailer chain or an error message */
271
272 REMAILER remailer[MAXREM];
273 int maxrem;
274 BUFFER *line, *field, *content, *header, *msgdest, *msgheader, *body,
275 *temp, *mid;
276 byte numdest = 0, numhdr = 0;
277 char hdrline[LINELEN];
278 BUFFER *packet;
279 int chain[20];
280 int chainlen;
281 int i;
282 int err = 0;
283
284 mix_init(NULL);
285 packet = buf_new();
286 line = buf_new();
287 field = buf_new();
288 content = buf_new();
289 msgheader = buf_new();
290 msgdest = buf_new();
291 body = buf_new();
292 temp = buf_new();
293 mid = buf_new();
294 header = buf_new();
295 if (feedback)
296 buf_reset(feedback);
297
298 if (numcopies == 0)
299 numcopies = NUMCOPIES;
300 if (numcopies > 10)
301 numcopies = 10;
302
303 maxrem = mix2_rlist(remailer);
304 if (maxrem < 1) {
305 clienterr(feedback, "No remailer list!");
306 err = -1;
307 goto end;
308 }
309 chainlen = chain_select(chain, chainstr, maxrem, remailer, 0, line);
310 if (chainlen < 1) {
311 if (line->length)
312 clienterr(feedback, line->data);
313 else
314 clienterr(feedback, "Invalid remailer chain!");
315 err = -1;
316 goto end;
317 }
318 if (chain[0] == 0)
319 chain[0] = chain_randfinal(type, remailer, maxrem, 0);
320
321 if (chain[0] == -1) {
322 clienterr(feedback, "No reliable remailers!");
323 err = -1;
324 goto end;
325 }
326 switch (remailer[chain[0]].version) {
327 case 2:
328 if (type == MSG_NULL) {
329 memset(hdrline, 0, 80);
330 strcpy(hdrline, "null:");
331 buf_append(msgdest, hdrline, 80);
332 numdest++;
333 } else
334 while (buf_getheader(message, field, content) == 0) {
335 if (bufieq(field, "to")) {
336 memset(hdrline, 0, 80);
337 strncpy(hdrline, content->data, 80);
338 buf_append(msgdest, hdrline, 80);
339 numdest++;
340 } else if (type == MSG_POST && bufieq(field, "newsgroups")) {
341 memset(hdrline, 0, 80);
342 strcpy(hdrline, "post: ");
343 strcatn(hdrline, content->data, 80);
344 buf_append(msgdest, hdrline, 80);
345 numdest++;
346 } else {
347 buf_clear(header);
348 buf_appendheader(header, field, content);
349 hdr_encode(header, 80);
350 while (buf_getline(header, line) == 0) {
351 /* paste in encoded header entry */
352 memset(hdrline, 0, 80);
353 strncpy(hdrline, line->data, 80);
354 buf_append(msgheader, hdrline, 80);
355 numhdr++;
356 }
357 }
358 }
359 buf_appendc(body, numdest);
360 buf_cat(body, msgdest);
361 buf_appendc(body, numhdr);
362 buf_cat(body, msgheader);
363
364 if (type != MSG_NULL) {
365 buf_rest(temp, message);
366 if (temp->length > 10236 && remailer[chain[0]].flags.compress)
367 buf_compress(temp);
368 buf_cat(body, temp);
369 buf_reset(temp);
370 }
371 buf_setrnd(mid, 16); /* message ID */
372 for (i = 0; i <= body->length / 10236; i++) {
373 long length;
374
375 length = body->length - i * 10236;
376 if (length > 10236)
377 length = 10236;
378 buf_clear(packet);
379 buf_appendl_lo(packet, length);
380 buf_append(packet, body->data + i * 10236, length);
381 buf_pad(packet, 10240);
382 if (send_packet(numcopies, packet, chain, chainlen,
383 i + 1, body->length / 10236 + 1,
384 mid, remailer, maxrem, feedback) == -1)
385 err = -1;
386 }
387 break;
388 case 3:
389 NOT_IMPLEMENTED;
390 break;
391 default:
392 clienterr(feedback, "Unknown remailer version!");
393 err = -1;
394 }
395
396 end:
397 buf_free(packet);
398 buf_free(line);
399 buf_free(field);
400 buf_free(content);
401 buf_free(header);
402 buf_free(msgheader);
403 buf_free(msgdest);
404 buf_free(body);
405 buf_free(temp);
406 buf_free(mid);
407 return (err);
408 }
409
410 #else
411
412 int mix2_rlist(REMAILER remailer[])
413 {
414 return (0);
415 }
416
417 int mix2_encrypt(int type, BUFFER *message, char *chainstr, int numcopies,
418 BUFFER *feedback)
419 {
420 return (-1);
421 }
422 #endif

  ViewVC Help
Powered by ViewVC 1.1.5