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