1 /**
2 * (C) 2007-20 - ntop.org and contributors
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not see see <http://www.gnu.org/licenses/>
16 *
17 */
18
19 #include "n2n.h"
20
21 #define N2N_TWOFISH_NUM_SA 32 /* space for SAa */
22
23 #define N2N_TWOFISH_TRANSFORM_VERSION 1 /* version of the transform encoding */
24
25 typedef struct transop_tf {
26 TWOFISH* enc_tf; /* tx state */
27 TWOFISH* dec_tf; /* rx state */
28 } transop_tf_t;
29
transop_deinit_twofish(n2n_trans_op_t * arg)30 static int transop_deinit_twofish( n2n_trans_op_t * arg ) {
31 transop_tf_t *priv = (transop_tf_t *)arg->priv;
32
33 if(priv) {
34 TwoFishDestroy(priv->enc_tf); /* deallocate TWOFISH */
35 TwoFishDestroy(priv->dec_tf); /* deallocate TWOFISH */
36 free(priv);
37 }
38
39 return 0;
40 }
41
42 #define TRANSOP_TF_VER_SIZE 1 /* Support minor variants in encoding in one module. */
43 #define TRANSOP_TF_NONCE_SIZE 4
44 #define TRANSOP_TF_SA_SIZE 4
45
46 /** The twofish packet format consists of:
47 *
48 * - a 8-bit twofish encoding version in clear text
49 * - a 32-bit SA number in clear text
50 * - ciphertext encrypted from a 32-bit nonce followed by the payload.
51 *
52 * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD]
53 * |<------ encrypted ------>|
54 */
transop_encode_twofish(n2n_trans_op_t * arg,uint8_t * outbuf,size_t out_len,const uint8_t * inbuf,size_t in_len,const uint8_t * peer_mac)55 static int transop_encode_twofish( n2n_trans_op_t * arg,
56 uint8_t * outbuf,
57 size_t out_len,
58 const uint8_t * inbuf,
59 size_t in_len,
60 const uint8_t * peer_mac)
61 {
62 int len=-1;
63 transop_tf_t * priv = (transop_tf_t *)arg->priv;
64 uint8_t assembly[N2N_PKT_BUF_SIZE];
65 uint32_t * pnonce;
66
67 if ( (in_len + TRANSOP_TF_NONCE_SIZE) <= N2N_PKT_BUF_SIZE )
68 {
69 if ( (in_len + TRANSOP_TF_NONCE_SIZE + TRANSOP_TF_SA_SIZE + TRANSOP_TF_VER_SIZE) <= out_len )
70 {
71 size_t idx=0;
72 uint32_t sa_id=0; // Not used
73
74 traceEvent(TRACE_DEBUG, "encode_twofish %lu", in_len);
75
76 /* Encode the twofish format version. */
77 encode_uint8( outbuf, &idx, N2N_TWOFISH_TRANSFORM_VERSION );
78
79 /* Encode the security association (SA) number */
80 encode_uint32( outbuf, &idx, sa_id );
81
82 /* The assembly buffer is a source for encrypting data. The nonce is
83 * written in first followed by the packet payload. The whole
84 * contents of assembly are encrypted. */
85 pnonce = (uint32_t *)assembly;
86 *pnonce = n2n_rand();
87 memcpy( assembly + TRANSOP_TF_NONCE_SIZE, inbuf, in_len );
88
89 /* Encrypt the assembly contents and write the ciphertext after the SA. */
90 len = TwoFishEncryptRaw( assembly, /* source */
91 outbuf + TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE,
92 in_len + TRANSOP_TF_NONCE_SIZE, /* enc size */
93 priv->enc_tf);
94 if ( len > 0 )
95 {
96 len += TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE; /* size of data carried in UDP. */
97 }
98 else
99 {
100 traceEvent( TRACE_ERROR, "encode_twofish encryption failed." );
101 }
102
103 }
104 else
105 {
106 traceEvent( TRACE_ERROR, "encode_twofish outbuf too small." );
107 }
108 }
109 else
110 {
111 traceEvent( TRACE_ERROR, "encode_twofish inbuf too big to encrypt." );
112 }
113
114 return len;
115 }
116
117 /** The twofish packet format consists of:
118 *
119 * - a 8-bit twofish encoding version in clear text
120 * - a 32-bit SA number in clear text
121 * - ciphertext encrypted from a 32-bit nonce followed by the payload.
122 *
123 * [V|SSSS|nnnnDDDDDDDDDDDDDDDDDDDDD]
124 * |<------ encrypted ------>|
125 */
transop_decode_twofish(n2n_trans_op_t * arg,uint8_t * outbuf,size_t out_len,const uint8_t * inbuf,size_t in_len,const uint8_t * peer_mac)126 static int transop_decode_twofish( n2n_trans_op_t * arg,
127 uint8_t * outbuf,
128 size_t out_len,
129 const uint8_t * inbuf,
130 size_t in_len,
131 const uint8_t * peer_mac)
132 {
133 int len=0;
134 transop_tf_t * priv = (transop_tf_t *)arg->priv;
135 uint8_t assembly[N2N_PKT_BUF_SIZE];
136
137 if ( ( (in_len - (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE)) <= N2N_PKT_BUF_SIZE ) /* Cipher text fits in assembly */
138 && (in_len >= (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE + TRANSOP_TF_NONCE_SIZE) ) /* Has at least version, SA and nonce */
139 ) {
140 size_t rem=in_len;
141 size_t idx=0;
142 uint8_t tf_enc_ver=0;
143 uint32_t sa_rx=0; // Not used
144
145 /* Get the encoding version to make sure it is supported */
146 decode_uint8( &tf_enc_ver, inbuf, &rem, &idx );
147
148 if ( N2N_TWOFISH_TRANSFORM_VERSION == tf_enc_ver ) {
149 /* Get the SA number and make sure we are decrypting with the right one. */
150 decode_uint32( &sa_rx, inbuf, &rem, &idx );
151
152 traceEvent(TRACE_DEBUG, "decode_twofish %lu", in_len);
153
154 len = TwoFishDecryptRaw( (void *)(inbuf + TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE),
155 assembly, /* destination */
156 (in_len - (TRANSOP_TF_VER_SIZE + TRANSOP_TF_SA_SIZE)),
157 priv->dec_tf);
158
159 if(len > 0) {
160 /* Step over 4-byte random nonce value */
161 len -= TRANSOP_TF_NONCE_SIZE; /* size of ethernet packet */
162
163 memcpy( outbuf,
164 assembly + TRANSOP_TF_NONCE_SIZE,
165 len );
166 } else
167 traceEvent(TRACE_ERROR, "decode_twofish decryption failed");
168 } else
169 traceEvent( TRACE_ERROR, "decode_twofish unsupported twofish version %u.", tf_enc_ver );
170 } else
171 traceEvent( TRACE_ERROR, "decode_twofish inbuf wrong size (%ul) to decrypt.", in_len );
172
173 return len;
174 }
175
transop_tick_twofish(n2n_trans_op_t * arg,time_t now)176 static void transop_tick_twofish( n2n_trans_op_t * arg, time_t now ) {}
177
178 /* Twofish initialization function */
n2n_transop_twofish_init(const n2n_edge_conf_t * conf,n2n_trans_op_t * ttt)179 int n2n_transop_twofish_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) {
180 transop_tf_t *priv;
181 const u_char *encrypt_key = (const u_char *)conf->encrypt_key;
182 size_t encrypt_key_len = strlen(conf->encrypt_key);
183
184 memset(ttt, 0, sizeof(*ttt));
185 ttt->transform_id = N2N_TRANSFORM_ID_TWOFISH;
186
187 ttt->tick = transop_tick_twofish;
188 ttt->deinit = transop_deinit_twofish;
189 ttt->fwd = transop_encode_twofish;
190 ttt->rev = transop_decode_twofish;
191
192 priv = (transop_tf_t*) calloc(1, sizeof(transop_tf_t));
193 if(!priv) {
194 traceEvent(TRACE_ERROR, "cannot allocate transop_tf_t memory");
195 return(-1);
196 }
197 ttt->priv = priv;
198
199 /* This is a preshared key setup. Both Tx and Rx are using the same security association. */
200 priv->enc_tf = TwoFishInit(encrypt_key, encrypt_key_len);
201 priv->dec_tf = TwoFishInit(encrypt_key, encrypt_key_len);
202
203 if((!priv->enc_tf) || (!priv->dec_tf)) {
204 if(priv->enc_tf) TwoFishDestroy(priv->enc_tf);
205 if(priv->dec_tf) TwoFishDestroy(priv->dec_tf);
206 free(priv);
207 traceEvent(TRACE_ERROR, "TwoFishInit failed");
208 return(-2);
209 }
210
211 return(0);
212 }
213