7e98416e54e77329949915a98397bc1d17efeea3
[debian/uanytun.git] / src / key_derivation.c
1 /*
2  *  uAnytun
3  *
4  *  uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
5  *  featured implementation uAnytun has no support for multiple connections
6  *  or synchronisation. It is a small single threaded implementation intended
7  *  to act as a client on small platforms.
8  *  The secure anycast tunneling protocol (satp) defines a protocol used
9  *  for communication between any combination of unicast and anycast
10  *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
11  *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
12  *  ethernet, ip, arp ...). satp directly includes cryptography and
13  *  message authentication based on the methodes used by SRTP.  It is
14  *  intended to deliver a generic, scaleable and secure solution for
15  *  tunneling and relaying of packets of any protocol.
16  *  
17  *
18  *  Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
19  *
20  *  This file is part of uAnytun.
21  *
22  *  uAnytun is free software: you can redistribute it and/or modify
23  *  it under the terms of the GNU General Public License as published by
24  *  the Free Software Foundation, either version 3 of the License, or
25  *  any later version.
26  *
27  *  uAnytun is distributed in the hope that it will be useful,
28  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
29  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  *  GNU General Public License for more details.
31  *
32  *  You should have received a copy of the GNU General Public License
33  *  along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
34  */
35
36 #include "datatypes.h"
37
38 #include "key_derivation.h"
39
40 #ifdef USE_SSL_CRYPTO
41 #include <openssl/sha.h>
42 #endif
43
44 #include "log.h"
45
46 #include <stdlib.h>
47 #include <string.h>
48
49 int key_derivation_init(key_derivation_t* kd, const char* type, role_t role, const char* passphrase, u_int8_t* key, u_int32_t key_len, u_int8_t* salt, u_int32_t salt_len)
50 {
51   if(!kd) 
52     return -1;
53
54   kd->role_ = role;
55   kd->key_length_ = 0;
56
57   kd->type_ = kd_unknown;
58   if(!strcmp(type, "null"))
59     kd->type_ = kd_null;
60   else if(!strncmp(type, "aes-ctr", 7)) {
61     kd->type_ = kd_aes_ctr;
62     if(type[7] == 0) {
63       kd->key_length_ = KD_AESCTR_DEFAULT_KEY_LENGTH;
64     }
65     else if(type[7] != '-') 
66       return -1;
67     else {
68       const char* tmp = &type[8];
69       kd->key_length_ = atoi(tmp);
70     }
71   }
72   else {
73     log_printf(ERROR, "unknown key derivation type");
74     return -1;
75   }
76
77   switch(role) {
78   case ROLE_LEFT: log_printf(NOTICE, "key derivation role: left"); break;
79   case ROLE_RIGHT: log_printf(NOTICE, "key derivation role: right"); break;
80   default: log_printf(NOTICE, "key derivation role: unknown"); break;
81   }
82   kd->params_ = NULL;
83
84   if(!key) {
85     kd->master_key_.buf_ = NULL;
86     kd->master_key_.length_ = 0;
87   }
88   else {
89     kd->master_key_.buf_ = malloc(key_len);
90     if(!kd->master_key_.buf_)
91       return -2;
92     memcpy(kd->master_key_.buf_, key, key_len);
93     kd->master_key_.length_ = key_len;
94   }
95
96   if(!salt) {
97     kd->master_salt_.buf_ = NULL;
98     kd->master_salt_.length_ = 0;
99   }
100   else {
101     kd->master_salt_.buf_ = malloc(salt_len);
102     if(!kd->master_salt_.buf_) {
103       if(kd->master_key_.buf_)
104         free(kd->master_key_.buf_);
105       return -2;
106     }
107     memcpy(kd->master_salt_.buf_, salt, salt_len);
108     kd->master_salt_.length_ = salt_len;
109   }
110
111   int ret = 0;
112   if(kd->type_ == kd_aes_ctr)
113     ret = key_derivation_aesctr_init(kd, passphrase);
114
115   if(ret)
116     key_derivation_close(kd);
117
118   return ret;
119 }
120
121 #ifndef NO_PASSPHRASE
122 int key_derivation_generate_master_key(key_derivation_t* kd, const char* passphrase, u_int16_t key_length)
123 {
124   if(!kd || !passphrase)
125     return -1;
126
127   if(kd->master_key_.buf_) {
128     log_printf(WARNING, "master key and passphrase provided, ignoring passphrase");
129     return 0;
130   }    
131   log_printf(NOTICE, "using passphrase to generate master key");
132
133   if(!key_length || (key_length % 8)) {
134     log_printf(ERROR, "bad master key length");
135     return -1;
136   }
137
138 #ifndef USE_SSL_CRYPTO
139   if(key_length > (gcry_md_get_algo_dlen(GCRY_MD_SHA256) * 8)) {
140 #else
141   if(key_length > (SHA256_DIGEST_LENGTH * 8)) {
142 #endif
143     log_printf(ERROR, "master key too long for passphrase algorithm");
144     return -1;
145   }
146
147   buffer_t digest;
148 #ifndef USE_SSL_CRYPTO
149   digest.length_ = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
150 #else
151   digest.length_ = SHA256_DIGEST_LENGTH;
152 #endif
153   digest.buf_ = malloc(digest.length_);
154   if(!digest.buf_)
155     return -2;
156
157
158 #ifndef USE_SSL_CRYPTO
159   gcry_md_hash_buffer(GCRY_MD_SHA256, digest.buf_, passphrase, strlen(passphrase));
160 #else
161   SHA256(passphrase, strlen(passphrase), digest.buf_);
162 #endif
163
164   kd->master_key_.length_ = key_length/8;
165   kd->master_key_.buf_ = malloc(kd->master_key_.length_);
166   if(!kd->master_key_.buf_) {
167     kd->master_key_.length_ = 0;
168     free(digest.buf_);
169     return -2;
170   }
171
172   memcpy(kd->master_key_.buf_, &digest.buf_[digest.length_ - kd->master_key_.length_], kd->master_key_.length_);
173   free(digest.buf_);
174
175   return 0;
176 }
177
178 int key_derivation_generate_master_salt(key_derivation_t* kd, const char* passphrase, u_int16_t salt_length)
179 {
180   if(!kd || !passphrase)
181     return -1;
182
183   if(kd->master_salt_.buf_) {
184     log_printf(WARNING, "master salt and passphrase provided, ignoring passphrase");
185     return 0;
186   }    
187   log_printf(NOTICE, "using passphrase to generate master salt");
188
189   if(!salt_length || (salt_length % 8)) {
190     log_printf(ERROR, "bad master salt length");
191     return -1;
192   }
193
194 #ifndef USE_SSL_CRYPTO
195   if(salt_length > (gcry_md_get_algo_dlen(GCRY_MD_SHA1) * 8)) {
196 #else
197   if(salt_length > (SHA_DIGEST_LENGTH * 8)) {
198 #endif
199     log_printf(ERROR, "master salt too long for passphrase algorithm");
200     return -1;
201   }
202
203   buffer_t digest;
204 #ifndef USE_SSL_CRYPTO
205   digest.length_ = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
206 #else
207   digest.length_ = SHA_DIGEST_LENGTH;
208 #endif
209   digest.buf_ = malloc(digest.length_);
210   if(!digest.buf_)
211     return -2;
212
213 #ifndef USE_SSL_CRYPTO
214   gcry_md_hash_buffer(GCRY_MD_SHA1, digest.buf_, passphrase, strlen(passphrase));
215 #else
216   SHA1(passphrase, strlen(passphrase), digest.buf_);
217 #endif
218
219   kd->master_salt_.length_ = salt_length/8;
220   kd->master_salt_.buf_ = malloc(kd->master_salt_.length_);
221   if(!kd->master_salt_.buf_) {
222     kd->master_salt_.length_ = 0;
223     free(digest.buf_);
224     return -2;
225   }
226
227   memcpy(kd->master_salt_.buf_, &digest.buf_[digest.length_ - kd->master_salt_.length_], kd->master_salt_.length_);
228   free(digest.buf_);
229
230   return 0;
231 }
232 #endif
233
234 void key_derivation_close(key_derivation_t* kd)
235 {
236   if(!kd)
237     return;
238
239   if(kd->type_ == kd_aes_ctr)
240     key_derivation_aesctr_close(kd);
241
242   if(kd->master_key_.buf_)
243     free(kd->master_key_.buf_);
244   if(kd->master_salt_.buf_)
245     free(kd->master_salt_.buf_);
246 }
247
248 int key_derivation_generate(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, u_int8_t* key, u_int32_t len)
249 {
250   if(!kd || !key) 
251     return -1;
252
253   if(label >= LABEL_NIL) {
254     log_printf(ERROR, "unknown label 0x%02X", label);
255     return -1;
256   }
257
258   int ret = 0;
259   if(kd->type_ == kd_null)
260     ret = key_derivation_null_generate(key, len);
261   else if(kd->type_ == kd_aes_ctr)
262     ret = key_derivation_aesctr_generate(kd, dir, label, seq_nr, key, len);
263   else {
264     log_printf(ERROR, "unknown key derivation type");
265     return -1;
266   }
267   return ret;
268 }
269
270 satp_prf_label_t convert_label(role_t role, key_derivation_dir_t dir, satp_prf_label_t label)
271 {
272   switch(label) {
273   case LABEL_ENC: {
274     if(dir == kd_outbound) {
275       if(role == ROLE_LEFT) return LABEL_LEFT_ENC;
276       if(role == ROLE_RIGHT) return LABEL_RIGHT_ENC;
277     }
278     else {
279       if(role == ROLE_LEFT) return LABEL_RIGHT_ENC;
280       if(role == ROLE_RIGHT) return LABEL_LEFT_ENC;
281     }
282     break;
283   }
284   case LABEL_SALT: {
285     if(dir == kd_outbound) {
286       if(role == ROLE_LEFT) return LABEL_LEFT_SALT;
287       if(role == ROLE_RIGHT) return LABEL_RIGHT_SALT;
288     }
289     else {
290       if(role == ROLE_LEFT) return LABEL_RIGHT_SALT;
291       if(role == ROLE_RIGHT) return LABEL_LEFT_SALT;
292     }
293     break;
294   }
295   case LABEL_AUTH: {
296     if(dir == kd_outbound) {
297       if(role == ROLE_LEFT) return LABEL_LEFT_AUTH;
298       if(role == ROLE_RIGHT) return LABEL_RIGHT_AUTH;
299     }
300     else {
301       if(role == ROLE_LEFT) return LABEL_RIGHT_AUTH;
302       if(role == ROLE_RIGHT) return LABEL_LEFT_AUTH;
303     }
304     break;
305   }
306   }
307
308   return label;
309 }
310
311 /* ---------------- NULL Key Derivation ---------------- */
312
313 int key_derivation_null_generate(u_int8_t* key, u_int32_t len)
314 {
315   memset(key, 0, len);
316   return 1;
317 }
318
319 /* ---------------- AES-Ctr Key Derivation ---------------- */
320
321 int key_derivation_aesctr_init(key_derivation_t* kd, const char* passphrase)
322 {
323   if(!kd)
324     return -1;
325
326   if(kd->params_)
327     free(kd->params_);
328   kd->params_ = malloc(sizeof(key_derivation_aesctr_param_t));
329   if(!kd->params_)
330     return -2;
331
332   key_derivation_aesctr_param_t* params = kd->params_;
333 #ifndef USE_SSL_CRYPTO
334   params->handle_ = 0;
335 #endif
336
337 #ifndef NO_PASSPHRASE
338   if(passphrase) {
339     int ret = key_derivation_generate_master_key(kd, passphrase, kd->key_length_);
340     if(ret)
341       return ret;
342     ret = key_derivation_generate_master_salt(kd, passphrase, KD_AESCTR_SALT_LENGTH*8);
343     if(ret)
344       return ret;
345   }
346 #endif
347
348 #ifndef USE_SSL_CRYPTO
349   int algo;
350   switch(kd->key_length_) {
351   case 128: algo = GCRY_CIPHER_AES128; break;
352   case 192: algo = GCRY_CIPHER_AES192; break;
353   case 256: algo = GCRY_CIPHER_AES256; break;
354   default: {
355     log_printf(ERROR, "key derivation key length of %d Bits is not supported", kd->key_length_);
356     return -1;
357   }
358   }
359
360   gcry_error_t err = gcry_cipher_open(&params->handle_, algo, GCRY_CIPHER_MODE_CTR, 0);
361   if(err) {
362     log_printf(ERROR, "failed to open key derivation cipher: %s", gcry_strerror(err));
363     return -1;
364   } 
365
366   err = gcry_cipher_setkey(params->handle_, kd->master_key_.buf_, kd->master_key_.length_);
367   if(err) {
368     log_printf(ERROR, "failed to set key derivation key: %s", gcry_strerror(err));
369     return -1;
370   }
371 #else
372   int ret = AES_set_encrypt_key(kd->master_key_.buf_, kd->master_key_.length_*8, &params->aes_key_);
373   if(ret) {
374     log_printf(ERROR, "failed to set key derivation ssl aes-key (code: %d)", ret);
375     return -1;
376   }
377 #endif
378
379   return 0;
380 }
381
382 void key_derivation_aesctr_close(key_derivation_t* kd)
383 {
384   if(!kd)
385     return;
386
387   if(kd->params_) {
388     key_derivation_aesctr_param_t* params = kd->params_;
389
390 #ifndef USE_SSL_CRYPTO
391     if(params->handle_)
392       gcry_cipher_close(params->handle_);
393 #endif
394
395     free(kd->params_);
396   }
397 }
398
399 int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr)
400 {
401   if(!kd || !kd->params_)
402     return -1;
403
404   key_derivation_aesctr_param_t* params = kd->params_;
405
406   if(kd->master_salt_.length_ != KD_AESCTR_SALT_LENGTH) {
407     log_printf(ERROR, "master salt has wrong length");
408     return -1;
409   }
410   memcpy(params->ctr_.salt_.buf_, kd->master_salt_.buf_, KD_AESCTR_SALT_LENGTH);
411   params->ctr_.salt_.zero_ = 0;
412   params->ctr_.params_.label_ ^= SATP_PRF_LABEL_T_HTON(convert_label(kd->role_, dir, label));
413   params->ctr_.params_.seq_ ^= SEQ_NR_T_HTON(seq_nr);
414
415   return 0;
416 }
417
418 int key_derivation_aesctr_generate(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, u_int8_t* key, u_int32_t len)
419 {
420   if(!kd || !kd->params_ || !kd->master_key_.buf_ || !kd->master_salt_.buf_) {
421     log_printf(ERROR, "key derivation not initialized or no key or salt set");
422     return -1;
423   }
424
425   key_derivation_aesctr_param_t* params = kd->params_;
426
427   if(key_derivation_aesctr_calc_ctr(kd, dir, label, seq_nr)) {
428     log_printf(ERROR, "failed to calculate key derivation CTR");
429     return -1;
430   }
431
432 #ifndef USE_SSL_CRYPTO
433   gcry_error_t err = gcry_cipher_reset(params->handle_);
434   if(err) {
435     log_printf(ERROR, "failed to reset key derivation cipher: %s", gcry_strerror(err));
436     return -1;
437   }
438
439   err = gcry_cipher_setctr(params->handle_, params->ctr_.buf_, KD_AESCTR_CTR_LENGTH);
440   if(err) {
441     log_printf(ERROR, "failed to set key derivation CTR: %s", gcry_strerror(err));
442     return -1;
443   }
444
445   memset(key, 0, len);
446   err = gcry_cipher_encrypt(params->handle_, key, len, NULL, 0);
447   if(err) {
448     log_printf(ERROR, "failed to generate key derivation bitstream: %s", gcry_strerror(err));
449     return -1;
450   }
451 #else
452   if(KD_AESCTR_CTR_LENGTH != AES_BLOCK_SIZE) {
453     log_printf(ERROR, "failed to set key derivation CTR: size don't fits");
454     return -1;
455   }
456   u_int32_t num = 0;
457   memset(params->ecount_buf_, 0, AES_BLOCK_SIZE);
458   memset(key, 0, len);
459   AES_ctr128_encrypt(key, key, len, &params->aes_key_, params->ctr_.buf_, params->ecount_buf_, &num);
460 #endif
461   
462   return 0;
463 }