html: some further minor tweaks on the index page
[netsniff-ng.git] / src / curve.c
bloba100d1fe1cbded9e73997f706d185f0eaa87c370
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2011 Daniel Borkmann.
5 * Subject to the GPL, version 2.
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <syslog.h>
14 #include <limits.h>
15 #include <string.h>
16 #include <sys/types.h>
17 #include <sys/time.h>
18 #include <sys/stat.h>
20 #include "compiler.h"
21 #include "xmalloc.h"
22 #include "curve.h"
23 #include "xstring.h"
24 #include "die.h"
25 #include "mtrand.h"
26 #include "curvetun.h"
27 #include "locking.h"
28 #include "crypto_verify_32.h"
29 #include "crypto_box_curve25519xsalsa20poly1305.h"
30 #include "crypto_scalarmult_curve25519.h"
32 /* Some parts derived from public domain code from curveprotect project */
34 #define crypto_box_beforenm crypto_box_curve25519xsalsa20poly1305_beforenm
35 #define crypto_box_afternm crypto_box_curve25519xsalsa20poly1305_afternm
36 #define crypto_box_open_afternm crypto_box_curve25519xsalsa20poly1305_open_afternm
38 #define NONCE_LENGTH 16 /* size of taia */
39 #define NONCE_OFFSET (crypto_box_curve25519xsalsa20poly1305_NONCEBYTES - NONCE_LENGTH)
41 void curve25519_selftest(void)
43 /* Test from the NaCl library */
44 int i;
45 unsigned char alicesk[32] = {
46 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d,
47 0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45,
48 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a,
49 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a
51 unsigned char bobpk[32] = {
52 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4,
53 0xd3, 0x5b, 0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37,
54 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, 0x67, 0x4d,
55 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f
57 unsigned char nonce[24] = {
58 0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73,
59 0xcd, 0x62, 0xbd, 0xa8, 0x75, 0xfc, 0x73, 0xd6,
60 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37
62 /* API requires first 32 bytes to be 0 */
63 unsigned char m[163] = {
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0xbe, 0x07, 0x5f, 0xc5, 0x3c, 0x81, 0xf2, 0xd5,
69 0xcf, 0x14, 0x13, 0x16, 0xeb, 0xeb, 0x0c, 0x7b,
70 0x52, 0x28, 0xc5, 0x2a, 0x4c, 0x62, 0xcb, 0xd4,
71 0x4b, 0x66, 0x84, 0x9b, 0x64, 0x24, 0x4f, 0xfc,
72 0xe5, 0xec, 0xba, 0xaf, 0x33, 0xbd, 0x75, 0x1a,
73 0x1a, 0xc7, 0x28, 0xd4, 0x5e, 0x6c, 0x61, 0x29,
74 0x6c, 0xdc, 0x3c, 0x01, 0x23, 0x35, 0x61, 0xf4,
75 0x1d, 0xb6, 0x6c, 0xce, 0x31, 0x4a, 0xdb, 0x31,
76 0x0e, 0x3b, 0xe8, 0x25, 0x0c, 0x46, 0xf0, 0x6d,
77 0xce, 0xea, 0x3a, 0x7f, 0xa1, 0x34, 0x80, 0x57,
78 0xe2, 0xf6, 0x55, 0x6a, 0xd6, 0xb1, 0x31, 0x8a,
79 0x02, 0x4a, 0x83, 0x8f, 0x21, 0xaf, 0x1f, 0xde,
80 0x04, 0x89, 0x77, 0xeb, 0x48, 0xf5, 0x9f, 0xfd,
81 0x49, 0x24, 0xca, 0x1c, 0x60, 0x90, 0x2e, 0x52,
82 0xf0, 0xa0, 0x89, 0xbc, 0x76, 0x89, 0x70, 0x40,
83 0xe0, 0x82, 0xf9, 0x37, 0x76, 0x38, 0x48, 0x64,
84 0x5e, 0x07, 0x05
86 unsigned char c[163];
87 unsigned char result[147] = {
88 0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5,
89 0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9,
90 0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73,
91 0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce,
92 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4,
93 0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a,
94 0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b,
95 0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72,
96 0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2,
97 0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38,
98 0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a,
99 0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae,
100 0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea,
101 0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda,
102 0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde,
103 0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3,
104 0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6,
105 0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74,
106 0xe3, 0x55, 0xa5
108 crypto_box_curve25519xsalsa20poly1305(c, m, 163, nonce, bobpk, alicesk);
109 for (i = 16; i < 163; ++i) {
110 if (c[i] != result[i - 16])
111 panic("PANIC: crypto selftest failed at pos %d "
112 "(%u != %u)! :-(\n", i, c[i], result[i]);
116 static int hexdigit(char x)
118 if (x >= '0' && x <= '9')
119 return x - '0';
120 if (x >= 'a' && x <= 'f')
121 return 10 + (x - 'a');
122 if (x >= 'A' && x <= 'F')
123 return 10 + (x - 'A');
124 return -1;
127 int curve25519_pubkey_hexparse_32(unsigned char *y, size_t ylen,
128 const char *x, size_t len)
130 int seen_digits = 0, seen_colons = 0;
131 if (!x || !y || ylen != 32)
132 return 0;
133 while (len > 0) {
134 int digit0, digit1;
135 if (x[0] == '\0')
136 break;
137 if (x[0] == ':') {
138 seen_colons++;
139 --len;
140 x++;
141 continue;
143 digit0 = hexdigit(x[0]);
144 if (digit0 == -1)
145 return 0;
146 digit1 = hexdigit(x[1]);
147 if (digit1 == -1)
148 return 0;
149 *y++ = digit1 + 16 * digit0;
150 seen_digits++;
151 --len;
152 x += 2;
154 if (x[0] != '\0' || seen_digits != 32 || seen_colons != 31)
155 return 0;
156 return 1;
159 int curve25519_alloc_or_maybe_die(struct curve25519_struct *c)
161 if (!c)
162 return -EINVAL;
163 c->enc_buf_size = TUNBUFF_SIZ;
164 c->dec_buf_size = TUNBUFF_SIZ;
165 c->enc_buf = xmalloc_aligned(c->enc_buf_size, 16);
166 c->dec_buf = xmalloc_aligned(c->dec_buf_size, 16);
167 spinlock_init(&c->enc_lock);
168 spinlock_init(&c->dec_lock);
169 mt_init_by_seed_rand_array();
170 return 0;
173 void curve25519_free(void *vc)
175 struct curve25519_struct *c = vc;
176 if (!c)
177 return;
178 memset(c->enc_buf, 0, c->enc_buf_size);
179 memset(c->dec_buf, 0, c->dec_buf_size);
180 xfree(c->enc_buf);
181 xfree(c->dec_buf);
182 spinlock_destroy(&c->enc_lock);
183 spinlock_destroy(&c->dec_lock);
186 int curve25519_proto_init(struct curve25519_proto *p, unsigned char *pubkey_remote,
187 size_t len, char *home, int server)
189 int fd;
190 ssize_t ret;
191 char path[PATH_MAX];
192 unsigned char secretkey_own[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES] = { 0 };
193 unsigned char publickey_own[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES] = { 0 };
194 if (!pubkey_remote ||
195 len != crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES)
196 return -EINVAL;
197 memset(path, 0, sizeof(path));
198 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
199 fd = open(path, O_RDONLY);
200 if (fd < 0)
201 panic("Cannot open privkey file!\n");
202 ret = read(fd, secretkey_own, sizeof(secretkey_own));
203 if (ret != sizeof(secretkey_own)) {
204 xmemset(secretkey_own, 0, sizeof(secretkey_own));
205 panic("Cannot read private key!\n");
207 close(fd);
208 crypto_scalarmult_curve25519_base(publickey_own, secretkey_own);
209 if (!crypto_verify_32(publickey_own, pubkey_remote)) {
210 xmemset(secretkey_own, 0, sizeof(secretkey_own));
211 xmemset(publickey_own, 0, sizeof(publickey_own));
212 panic("PANIC: remote end has same public key as you have!!!\n");
214 crypto_box_beforenm(p->key, pubkey_remote, secretkey_own);
215 xmemset(p->enonce, 0, sizeof(p->enonce));
216 xmemset(p->dnonce, 0, sizeof(p->dnonce));
217 xmemset(secretkey_own, 0, sizeof(secretkey_own));
218 xmemset(publickey_own, 0, sizeof(publickey_own));
219 return 0;
222 ssize_t curve25519_encode(struct curve25519_struct *c, struct curve25519_proto *p,
223 unsigned char *plaintext, size_t size,
224 unsigned char **chipertext)
226 int ret, i;
227 ssize_t done = size;
228 struct taia packet_taia;
229 spinlock_lock(&c->enc_lock);
230 if (unlikely(size > c->enc_buf_size)) {
231 spinlock_unlock(&c->enc_lock);
232 return -ENOMEM;
234 taia_now(&packet_taia);
235 taia_pack(p->enonce + NONCE_OFFSET, &packet_taia);
236 memset(c->enc_buf, 0, c->enc_buf_size);
237 ret = crypto_box_afternm(c->enc_buf, plaintext, size,
238 p->enonce, p->key);
239 if (unlikely(ret)) {
240 spinlock_unlock(&c->enc_lock);
241 return -EIO;
243 memcpy(c->enc_buf + crypto_box_boxzerobytes - NONCE_LENGTH,
244 p->enonce + NONCE_OFFSET, NONCE_LENGTH);
245 for (i = 0; i < crypto_box_boxzerobytes - NONCE_LENGTH; ++i)
246 c->enc_buf[i] = (uint8_t) mt_rand_int32();
247 (*chipertext) = c->enc_buf;
248 spinlock_unlock(&c->enc_lock);
249 return done;
252 ssize_t curve25519_decode(struct curve25519_struct *c, struct curve25519_proto *p,
253 unsigned char *chipertext, size_t size,
254 unsigned char **plaintext, struct taia *arrival_taia)
256 int ret;
257 ssize_t done = size;
258 struct taia packet_taia, __arrival_taia;
259 spinlock_lock(&c->dec_lock);
260 if (unlikely(size > c->dec_buf_size)) {
261 spinlock_unlock(&c->dec_lock);
262 return -ENOMEM;
264 if (unlikely(size < crypto_box_boxzerobytes + NONCE_LENGTH)) {
265 spinlock_unlock(&c->dec_lock);
266 return 0;
268 if (arrival_taia == NULL) {
269 taia_now(&__arrival_taia);
270 arrival_taia = &__arrival_taia;
272 taia_unpack(chipertext + crypto_box_boxzerobytes - NONCE_LENGTH,
273 &packet_taia);
274 if (is_good_taia(arrival_taia, &packet_taia) == 0) {
275 /* Ignoring packet */
276 spinlock_unlock(&c->dec_lock);
277 syslog(LOG_ERR, "Bad packet time! Dropping connection!\n");
278 return 0;
280 memcpy(p->dnonce + NONCE_OFFSET,
281 chipertext + crypto_box_boxzerobytes - NONCE_LENGTH,
282 NONCE_LENGTH);
283 memset(c->dec_buf, 0, c->dec_buf_size);
284 ret = crypto_box_open_afternm(c->dec_buf, chipertext, size,
285 p->dnonce, p->key);
286 if (unlikely(ret)) {
287 spinlock_unlock(&c->enc_lock);
288 return -EIO;
290 (*plaintext) = c->dec_buf;
291 spinlock_unlock(&c->dec_lock);
292 return done;