1 #ifndef BLOCK_TX_UTILS_H
2 #define BLOCK_TX_UTILS_H
3 
4 #include <event2/buffer.h>
5 #include <event2/util.h>
6 #include <openssl/evp.h>
7 
8 /* Common structures and contants shared by the client and server. */
9 
10 /* We use AES 256 */
11 #define ENC_KEY_SIZE 32
12 #define ENC_BLOCK_SIZE 16
13 
14 #define BLOCK_PROTOCOL_VERSION 2
15 
16 enum {
17     STATUS_OK = 0,
18     STATUS_VERSION_MISMATCH,
19     STATUS_BAD_REQUEST,
20     STATUS_ACCESS_DENIED,
21     STATUS_INTERNAL_SERVER_ERROR,
22     STATUS_NOT_FOUND,
23 };
24 
25 struct _HandshakeRequest {
26     gint32 version;
27     gint32 key_len;
28     char enc_session_key[0];
29 } __attribute__((__packed__));
30 
31 typedef struct _HandshakeRequest HandshakeRequest;
32 
33 struct _HandshakeResponse {
34     gint32 status;
35     gint32 version;
36 } __attribute__((__packed__));
37 
38 typedef struct _HandshakeResponse HandshakeResponse;
39 
40 struct _AuthResponse {
41     gint32 status;
42 } __attribute__((__packed__));
43 
44 typedef struct _AuthResponse AuthResponse;
45 
46 enum {
47     REQUEST_COMMAND_GET = 0,
48     REQUEST_COMMAND_PUT,
49 };
50 
51 struct _RequestHeader {
52     gint32 command;
53     char block_id[40];
54 } __attribute__((__packed__));
55 
56 typedef struct _RequestHeader RequestHeader;
57 
58 struct _ResponseHeader {
59     gint32 status;
60 } __attribute__((__packed__));
61 
62 typedef struct _ResponseHeader ResponseHeader;
63 
64 /* Utility functions for encryption. */
65 
66 void
67 blocktx_generate_encrypt_key (unsigned char *session_key, int sk_len,
68                               unsigned char *key, unsigned char *iv);
69 
70 int
71 blocktx_encrypt_init (EVP_CIPHER_CTX **ctx,
72                       const unsigned char *key,
73                       const unsigned char *iv);
74 
75 int
76 blocktx_decrypt_init (EVP_CIPHER_CTX **ctx,
77                       const unsigned char *key,
78                       const unsigned char *iv);
79 
80 /*
81  * Encrypted data is sent in "frames".
82  * Format of a frame:
83  *
84  * length of data in the frame after encryption + encrypted data.
85  *
86  * Each frame can contain three types of contents:
87  * 1. Auth request or response;
88  * 2. Block request or response header;
89  * 3. Block content.
90  */
91 
92 int
93 send_encrypted_data_frame_begin (evutil_socket_t data_fd,
94                                  int frame_len);
95 
96 int
97 send_encrypted_data (EVP_CIPHER_CTX *ctx,
98                      evutil_socket_t data_fd,
99                      const void *buf, int len);
100 
101 int
102 send_encrypted_data_frame_end (EVP_CIPHER_CTX *ctx,
103                                evutil_socket_t data_fd);
104 
105 typedef int (*FrameContentCB) (char *, int, void *);
106 
107 typedef int (*FrameFragmentCB) (char *, int, int, void *);
108 
109 typedef struct _FrameParser {
110     int enc_frame_len;
111 
112     unsigned char key[ENC_KEY_SIZE];
113     unsigned char iv[ENC_BLOCK_SIZE];
114     gboolean enc_init;
115     EVP_CIPHER_CTX *ctx;
116 
117     unsigned char key_v2[ENC_KEY_SIZE];
118     unsigned char iv_v2[ENC_BLOCK_SIZE];
119 
120     int version;
121 
122     /* Used when parsing fragments */
123     int remain;
124 
125     FrameContentCB content_cb;
126     FrameFragmentCB fragment_cb;
127     void *cbarg;
128 } FrameParser;
129 
130 /* Handle entire frame all at once.
131  * parser->content_cb() will be called after the entire frame is read.
132  */
133 int
134 handle_one_frame (struct evbuffer *buf, FrameParser *parser);
135 
136 /* Handle a frame fragment by fragment.
137  * parser->fragment_cb() will be called when any amount data is read.
138  */
139 int
140 handle_frame_fragments (struct evbuffer *buf, FrameParser *parser);
141 
142 #endif
143