Adding even more stuff from the CABAL branch.
[tinc] / src / encr.c
1 /*
2     encr.c -- everything that deals with encryption
3     Copyright (C) 1998,1999,2000 Ivo Timmermans <itimmermans@bigfoot.com>
4                             2000 Guus Sliepen <guus@sliepen.warande.net>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20     $Id: encr.c,v 1.13 2000/10/18 20:12:08 zarq Exp $
21 */
22
23 #include "config.h"
24
25 #include <sys/types.h>
26
27 #include <ctype.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <syslog.h>
32 #include <sys/socket.h>
33 #include <sys/time.h>
34
35 #ifdef HAVE_GMP_H
36 # include <gmp.h>
37 #else
38 # ifdef HAVE_GMP2_GMP_H
39 #  include <gmp2/gmp.h>
40 # endif
41 #endif
42
43 #include <utils.h>
44 #include <xalloc.h>
45
46 #include <cipher.h>
47
48 #include "conf.h"
49 #include "encr.h"
50 #include "net.h"
51 #include "protocol.h"
52
53 #include "system.h"
54
55 #define ENCR_GENERATOR "0xd"
56 #define ENCR_PRIME "0x7fffffffffffffffffffffffffffffff" /* Mersenne :) */
57
58 char text_key[1000];
59 char *my_public_key_base36;
60 int key_inited = 0, encryption_keylen;
61 mpz_t my_private_key, my_public_key, generator, shared_prime;
62 int my_key_expiry = (time_t)(-1);
63
64 char* mypassphrase;
65 int mypassphraselen;
66
67 int char_hex_to_bin(int c)
68 {
69   if(isdigit(c))
70     return c - '0';
71   else
72     return tolower(c) - 'a' + 10;
73 }
74
75 int str_hex_to_bin(unsigned char *bin, unsigned char *hex)
76 {
77   int i = 0, j = 0, l = strlen(hex);
78 cp
79   if(l&1)
80     {
81       i = j = 1;
82       bin[0] = char_hex_to_bin(hex[0]);
83     }
84   for(; i < l; i+=2, j++)
85     bin[j] = (char_hex_to_bin(hex[i]) << 4) + char_hex_to_bin(hex[i+1]);
86 cp
87   return j&1?j+1:j;
88 }
89
90 int read_passphrase(char *which, char **out)
91 {
92   FILE *f;
93   config_t const *cfg;
94   char *filename;
95   int size;
96   extern char *confbase;
97   char *pp;
98 cp
99   if((cfg = get_config_val(passphrasesdir)) == NULL)
100     {
101       asprintf(&filename, "%spassphrases/%s", confbase, which);
102     }
103   else
104     {
105       asprintf(&filename, "%s/%s", (char*)cfg->data.ptr, which);
106     }
107
108   if((f = fopen(filename, "rb")) == NULL)
109     {
110       if(debug_lvl > 1)
111         syslog(LOG_ERR, _("Could not open %s: %m"), filename);
112       return -1;
113     }
114
115   fscanf(f, "%d ", &size);
116   if(size < 1 || size > (1<<15))
117     {
118       syslog(LOG_ERR, _("Illegal passphrase in %s; size would be %d"), filename, size);
119       return -1;
120     }
121
122   /* Hmz... hackish... strange +1 and +2 stuff... I really like more comments on those alignment thingies! */
123
124   pp = xmalloc(size/4 + 1);     /* Allocate enough for fgets */
125   fgets(pp, size/4 + 1, f);     /* Read passhrase and reserve one byte for end-of-string */
126   fclose(f);
127
128   *out = xmalloc(size/8 + 2);   /* Allocate enough bytes, +1 for rounding if bits%8 != 0, +1 for 2-byte alignment */
129 cp
130   return str_hex_to_bin(*out, pp);
131 }
132
133 int read_my_passphrase(void)
134 {
135 cp
136   if((mypassphraselen = read_passphrase("local", &mypassphrase)) < 0)
137     return -1;
138 cp
139   return 0;
140 }
141
142 int generate_private_key(void)
143 {
144   FILE *f;
145   int i;
146   char *s;
147   config_t const *cfg;
148 cp
149   if((cfg = get_config_val(keyexpire)) == NULL)
150     my_key_expiry = (time_t)(time(NULL) + 3600);
151   else
152     my_key_expiry = (time_t)(time(NULL) + cfg->data.val);
153
154   if(debug_lvl > 1)
155     syslog(LOG_NOTICE, _("Generating %d bits keys"), PRIVATE_KEY_BITS);
156
157   if((f = fopen("/dev/urandom", "r")) == NULL)
158     {
159       syslog(LOG_ERR, _("Opening /dev/urandom failed: %m"));
160       return -1;
161     }
162
163   s = xmalloc((2 * PRIVATE_KEY_LENGTH) + 1);
164
165   for(i = 0; i < PRIVATE_KEY_LENGTH; i++)
166     sprintf(&s[i << 1], "%02x", fgetc(f));
167
168   s[2 * PRIVATE_KEY_LENGTH] = '\0';
169
170   mpz_set_str(my_private_key, s, 16);
171 cp
172   return 0;
173 }
174
175 void calculate_public_key(void)
176 {
177 cp
178   mpz_powm(my_public_key, generator, my_private_key, shared_prime);
179   my_public_key_base36 = mpz_get_str(NULL, 36, my_public_key);
180 cp
181 }
182
183 unsigned char static_key[] = { 0x9c, 0xbf, 0x36, 0xa9, 0xce, 0x20, 0x1b, 0x8b, 0x67, 0x56, 0x21, 0x5d, 0x27, 0x1b, 0xd8, 0x7a };
184
185 int security_init(void)
186 {
187 cp
188   mpz_init(my_private_key);
189   mpz_init(my_public_key);
190   mpz_init_set_str(shared_prime, ENCR_PRIME, 0);
191   mpz_init_set_str(generator, ENCR_GENERATOR, 0);
192
193   if(read_my_passphrase() < 0)
194     return -1;
195   if(generate_private_key() < 0)
196     return -1;
197
198   if(cipher_init(CIPHER_BLOWFISH) < 0)
199     return -1;
200
201   calculate_public_key();
202 cp
203   return 0;
204 }
205
206 void set_shared_key(char *almost_key)
207 {
208   char *tmp;
209   int len;
210   mpz_t ak, our_shared_key;
211 cp
212   mpz_init_set_str(ak, almost_key, 36);
213   mpz_init(our_shared_key);
214   mpz_powm(our_shared_key, ak, my_private_key, shared_prime);
215
216   tmp = mpz_get_str(NULL, 16, our_shared_key);
217   len = str_hex_to_bin(text_key, tmp);
218
219   cipher_set_key(&encryption_key, len, text_key);
220   key_inited = 1;
221   encryption_keylen = len;
222
223   if(debug_lvl > 2)
224     syslog(LOG_INFO, _("Encryption key set to %s"), tmp);
225
226   free(tmp);
227   mpz_clear(ak);
228   mpz_clear(our_shared_key);
229 cp
230 }
231
232
233 void encrypt_passphrase(passphrase_t *pp)
234 {
235   char key[1000];
236   char tmp[1000];
237   unsigned char phrase[1000];
238   int keylen;
239   int i;
240   BF_KEY bf_key;
241   
242 cp  
243   mpz_get_str(tmp, 16, my_public_key);
244   keylen = str_hex_to_bin(key, tmp);
245
246   cipher_set_key(&bf_key, keylen, key);
247
248   low_crypt_key(mypassphrase, phrase, &bf_key, mypassphraselen, BF_ENCRYPT);
249   pp->len = ((mypassphraselen - 1) | 7) + 1;
250   pp->phrase = xmalloc((pp->len << 1) + 1);
251   
252   for(i = 0; i < pp->len; i++)
253     snprintf(&(pp->phrase)[i << 1], 3, "%02x", (int)phrase[i]);
254
255   pp->phrase[(pp->len << 1) + 1] = '\0';
256
257   if(key_inited)
258     cipher_set_key(&encryption_key, encryption_keylen, text_key);
259 cp
260 }
261
262 int verify_passphrase(conn_list_t *cl, unsigned char *his_pubkey)
263 {
264   char key[1000];
265   char *tmp;
266   unsigned char phrase[1000];
267   int keylen, pplen;
268   mpz_t pk;
269   unsigned char *out;
270   BF_KEY bf_key;
271   char *which;
272   char *meuk;
273 cp
274   mpz_init_set_str(pk, his_pubkey, 36);
275   tmp = mpz_get_str(NULL, 16, pk);
276   keylen = str_hex_to_bin(key, tmp);
277   out = xmalloc((cl->pp->len >> 1) + 3);
278   pplen = str_hex_to_bin(phrase, cl->pp->phrase);
279
280   cipher_set_key(&bf_key, keylen, key);
281   low_crypt_key(phrase, out, &bf_key, pplen, BF_DECRYPT);
282   if(key_inited)
283     cipher_set_key(&encryption_key, encryption_keylen, text_key);
284
285   asprintf(&which, IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
286   if((pplen = read_passphrase(which, &meuk)) < 0)
287     return -1;
288
289   if(memcmp(meuk, out, pplen))
290     return -1;
291 cp
292   return 0;
293 }
294
295 char *make_shared_key(char *pk)
296 {
297   mpz_t tmp, res;
298   char *r;
299 cp
300   mpz_init_set_str(tmp, pk, 36);
301   mpz_init(res);
302   mpz_powm(res, tmp, my_private_key, shared_prime);
303
304   r = mpz_get_str(NULL, 36, res);
305
306   mpz_clear(res);
307   mpz_clear(tmp);
308 cp
309   return r;
310 }
311
312 /*
313   free a key after overwriting it
314 */
315 void free_key(enc_key_t *k)
316 {
317 cp
318   if(!k)
319     return;
320   if(k->key)
321     {
322       memset(k->key, (char)(-1), k->length);
323       free(k->key);
324     }
325   free(k);
326 cp
327 }
328
329 void recalculate_encryption_keys(void)
330 {
331   conn_list_t *p;
332   char *ek;
333 cp
334   for(p = conn_list; p != NULL; p = p->next)
335     {
336       if(!p->public_key || !p->public_key->key)
337         /* We haven't received a key from this host (yet). */
338         continue;
339       ek = make_shared_key(p->public_key->key);
340       free_key(p->datakey);
341       p->datakey = xmalloc(sizeof(*p->datakey));
342       p->datakey->length = strlen(ek);
343       p->datakey->expiry = p->public_key->expiry;
344       p->datakey->key = xmalloc(strlen(ek) + 1);
345       strcpy(p->datakey->key, ek);
346     }
347 cp
348 }
349
350 void regenerate_keys(void)
351 {
352 cp
353   generate_private_key();
354   calculate_public_key();
355   send_key_changed_all();
356   recalculate_encryption_keys();
357 cp
358 }