1 #include "common.h"
2 #define DEBUG_FLAG SEAFILE_DEBUG_TRANSFER
3 #include "log.h"
4 
5 #include "utils.h"
6 #include "block-tx-utils.h"
7 
8 /* Utility functions for block transfer protocol. */
9 
10 /* Encryption related functions. */
11 
12 void
blocktx_generate_encrypt_key(unsigned char * session_key,int sk_len,unsigned char * key,unsigned char * iv)13 blocktx_generate_encrypt_key (unsigned char *session_key, int sk_len,
14                               unsigned char *key, unsigned char *iv)
15 {
16     EVP_BytesToKey (EVP_aes_256_cbc(), /* cipher mode */
17                     EVP_sha1(),        /* message digest */
18                     NULL,              /* salt */
19                     session_key,
20                     sk_len,
21                     3,   /* iteration times */
22                     key, /* the derived key */
23                     iv); /* IV, initial vector */
24 }
25 
26 int
blocktx_encrypt_init(EVP_CIPHER_CTX ** ctx,const unsigned char * key,const unsigned char * iv)27 blocktx_encrypt_init (EVP_CIPHER_CTX **ctx,
28                       const unsigned char *key,
29                       const unsigned char *iv)
30 {
31     int ret;
32 
33     /* Prepare CTX for encryption. */
34     *ctx = EVP_CIPHER_CTX_new ();
35 
36     ret = EVP_EncryptInit_ex (*ctx,
37                               EVP_aes_256_cbc(), /* cipher mode */
38                               NULL, /* engine, NULL for default */
39                               key,  /* derived key */
40                               iv);  /* initial vector */
41     if (ret == 0)
42         return -1;
43 
44     return 0;
45 }
46 
47 int
blocktx_decrypt_init(EVP_CIPHER_CTX ** ctx,const unsigned char * key,const unsigned char * iv)48 blocktx_decrypt_init (EVP_CIPHER_CTX **ctx,
49                       const unsigned char *key,
50                       const unsigned char *iv)
51 {
52     int ret;
53 
54     /* Prepare CTX for decryption. */
55     *ctx = EVP_CIPHER_CTX_new();
56 
57     ret = EVP_DecryptInit_ex (*ctx,
58                               EVP_aes_256_cbc(), /* cipher mode */
59                               NULL, /* engine, NULL for default */
60                               key,  /* derived key */
61                               iv);  /* initial vector */
62     if (ret == 0)
63         return -1;
64 
65     return 0;
66 }
67 
68 /* Sending frame */
69 
70 int
send_encrypted_data_frame_begin(evutil_socket_t data_fd,int frame_len)71 send_encrypted_data_frame_begin (evutil_socket_t data_fd,
72                                  int frame_len)
73 {
74     /* Compute data size after encryption.
75      * Block size is 16 bytes and AES always add one padding block.
76      */
77     int enc_frame_len;
78 
79     enc_frame_len = ((frame_len >> 4) + 1) << 4;
80     enc_frame_len = htonl (enc_frame_len);
81 
82     if (sendn (data_fd, &enc_frame_len, sizeof(int)) < 0) {
83         seaf_warning ("Failed to send frame length: %s.\n",
84                       evutil_socket_error_to_string(evutil_socket_geterror(data_fd)));
85         return -1;
86     }
87 
88     return 0;
89 }
90 
91 int
send_encrypted_data(EVP_CIPHER_CTX * ctx,evutil_socket_t data_fd,const void * buf,int len)92 send_encrypted_data (EVP_CIPHER_CTX *ctx,
93                      evutil_socket_t data_fd,
94                      const void *buf, int len)
95 {
96     char out_buf[len + ENC_BLOCK_SIZE];
97     int out_len;
98 
99     if (EVP_EncryptUpdate (ctx,
100                            (unsigned char *)out_buf, &out_len,
101                            (unsigned char *)buf, len) == 0) {
102         seaf_warning ("Failed to encrypt data.\n");
103         return -1;
104     }
105 
106     if (sendn (data_fd, out_buf, out_len) < 0) {
107         seaf_warning ("Failed to write data: %s.\n",
108                       evutil_socket_error_to_string(evutil_socket_geterror(data_fd)));
109         return -1;
110     }
111 
112     return 0;
113 }
114 
115 int
send_encrypted_data_frame_end(EVP_CIPHER_CTX * ctx,evutil_socket_t data_fd)116 send_encrypted_data_frame_end (EVP_CIPHER_CTX *ctx,
117                                evutil_socket_t data_fd)
118 {
119     char out_buf[ENC_BLOCK_SIZE];
120     int out_len;
121 
122     if (EVP_EncryptFinal_ex (ctx, (unsigned char *)out_buf, &out_len) == 0) {
123         seaf_warning ("Failed to encrypt data.\n");
124         return -1;
125     }
126     if (sendn (data_fd, out_buf, out_len) < 0) {
127         seaf_warning ("Failed to write data: %s.\n",
128                       evutil_socket_error_to_string(evutil_socket_geterror(data_fd)));
129         return -1;
130     }
131 
132     return 0;
133 }
134 
135 /* Receiving frame */
136 
137 static int
handle_frame_content(struct evbuffer * buf,FrameParser * parser)138 handle_frame_content (struct evbuffer *buf, FrameParser *parser)
139 {
140     char *frame;
141     EVP_CIPHER_CTX *ctx;
142     char *out;
143     int outlen, outlen2;
144     int ret = 0;
145 
146     struct evbuffer *input = buf;
147 
148     if (evbuffer_get_length (input) < parser->enc_frame_len)
149         return 0;
150 
151     if (parser->version == 1)
152         blocktx_decrypt_init (&ctx, parser->key, parser->iv);
153     else if (parser->version == 2)
154         blocktx_decrypt_init (&ctx, parser->key_v2, parser->iv_v2);
155 
156     frame = g_malloc (parser->enc_frame_len);
157     out = g_malloc (parser->enc_frame_len + ENC_BLOCK_SIZE);
158 
159     evbuffer_remove (input, frame, parser->enc_frame_len);
160 
161     if (EVP_DecryptUpdate (ctx,
162                            (unsigned char *)out, &outlen,
163                            (unsigned char *)frame,
164                            parser->enc_frame_len) == 0) {
165         seaf_warning ("Failed to decrypt frame content.\n");
166         ret = -1;
167         goto out;
168     }
169 
170     if (EVP_DecryptFinal_ex (ctx, (unsigned char *)(out + outlen), &outlen2) == 0)
171     {
172         seaf_warning ("Failed to decrypt frame content.\n");
173         ret = -1;
174         goto out;
175     }
176 
177     ret = parser->content_cb (out, outlen + outlen2, parser->cbarg);
178 
179 out:
180     g_free (frame);
181     g_free (out);
182     parser->enc_frame_len = 0;
183     EVP_CIPHER_CTX_free (ctx);
184     return ret;
185 }
186 
187 int
handle_one_frame(struct evbuffer * buf,FrameParser * parser)188 handle_one_frame (struct evbuffer *buf, FrameParser *parser)
189 {
190     struct evbuffer *input = buf;
191 
192     if (!parser->enc_frame_len) {
193         /* Read the length of the encrypted frame first. */
194         if (evbuffer_get_length (input) < sizeof(int))
195             return 0;
196 
197         int frame_len;
198         evbuffer_remove (input, &frame_len, sizeof(int));
199         parser->enc_frame_len = ntohl (frame_len);
200 
201         if (evbuffer_get_length (input) > 0)
202             return handle_frame_content (buf, parser);
203 
204         return 0;
205     } else {
206         return handle_frame_content (buf, parser);
207     }
208 }
209 
210 static int
handle_frame_fragment_content(struct evbuffer * buf,FrameParser * parser)211 handle_frame_fragment_content (struct evbuffer *buf, FrameParser *parser)
212 {
213     char *fragment = NULL, *out = NULL;
214     int fragment_len, outlen;
215     int ret = 0;
216 
217     struct evbuffer *input = buf;
218 
219     fragment_len = evbuffer_get_length (input);
220     fragment = g_malloc (fragment_len);
221     evbuffer_remove (input, fragment, fragment_len);
222 
223     out = g_malloc (fragment_len + ENC_BLOCK_SIZE);
224 
225     if (EVP_DecryptUpdate (parser->ctx,
226                            (unsigned char *)out, &outlen,
227                            (unsigned char *)fragment, fragment_len) == 0) {
228         seaf_warning ("Failed to decrypt frame fragment.\n");
229         ret = -1;
230         goto out;
231     }
232 
233     ret = parser->fragment_cb (out, outlen, 0, parser->cbarg);
234     if (ret < 0)
235         goto out;
236 
237     parser->remain -= fragment_len;
238 
239     if (parser->remain <= 0) {
240         if (EVP_DecryptFinal_ex (parser->ctx,
241                                  (unsigned char *)out,
242                                  &outlen) == 0) {
243             seaf_warning ("Failed to decrypt frame fragment.\n");
244             ret = -1;
245             goto out;
246         }
247 
248         ret = parser->fragment_cb (out, outlen, 1, parser->cbarg);
249         if (ret < 0)
250             goto out;
251 
252         EVP_CIPHER_CTX_free (parser->ctx);
253         parser->enc_init = FALSE;
254         parser->enc_frame_len = 0;
255     }
256 
257 out:
258     g_free (fragment);
259     g_free (out);
260     if (ret < 0) {
261         EVP_CIPHER_CTX_free (parser->ctx);
262         parser->enc_init = FALSE;
263         parser->enc_frame_len = 0;
264     }
265     return ret;
266 }
267 
268 int
handle_frame_fragments(struct evbuffer * buf,FrameParser * parser)269 handle_frame_fragments (struct evbuffer *buf, FrameParser *parser)
270 {
271     struct evbuffer *input = buf;
272 
273     if (!parser->enc_frame_len) {
274         /* Read the length of the encrypted frame first. */
275         if (evbuffer_get_length (input) < sizeof(int))
276             return 0;
277 
278         int frame_len;
279         evbuffer_remove (input, &frame_len, sizeof(int));
280         parser->enc_frame_len = ntohl (frame_len);
281         parser->remain = parser->enc_frame_len;
282 
283         if (parser->version == 1)
284             blocktx_decrypt_init (&parser->ctx, parser->key, parser->iv);
285         else if (parser->version == 2)
286             blocktx_decrypt_init (&parser->ctx, parser->key_v2, parser->iv_v2);
287         parser->enc_init = TRUE;
288 
289         if (evbuffer_get_length (input) > 0)
290             return handle_frame_fragment_content (buf, parser);
291 
292         return 0;
293     } else {
294         return handle_frame_fragment_content (buf, parser);
295     }
296 }
297