xutils: break out promisc mode functions
[netsniff-ng.git] / curve.c
blob243e8334b367981b4b141fa9dbe0cbdf03eabd59
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2011 - 2013 Daniel Borkmann.
4 * Subject to the GPL, version 2.
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdint.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <syslog.h>
13 #include <limits.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #include <sys/time.h>
17 #include <sys/stat.h>
19 #include "built_in.h"
20 #include "xmalloc.h"
21 #include "curve.h"
22 #include "xutils.h"
23 #include "ioops.h"
24 #include "rnd.h"
25 #include "die.h"
26 #include "str.h"
27 #include "curvetun.h"
28 #include "locking.h"
29 #include "crypto_verify_32.h"
30 #include "crypto_box_curve25519xsalsa20poly1305.h"
31 #include "crypto_scalarmult_curve25519.h"
33 #define crypto_box_beforenm crypto_box_curve25519xsalsa20poly1305_beforenm
34 #define crypto_box_afternm crypto_box_curve25519xsalsa20poly1305_afternm
35 #define crypto_box_open_afternm crypto_box_curve25519xsalsa20poly1305_open_afternm
37 #define NONCE_LENGTH (sizeof(struct taia))
38 #define NONCE_OFFSET (crypto_box_curve25519xsalsa20poly1305_NONCEBYTES - NONCE_LENGTH)
40 void curve25519_selftest(void)
42 int i;
43 unsigned char alicesk[32] = {
44 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d,
45 0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45,
46 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a,
47 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a
49 unsigned char bobpk[32] = {
50 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4,
51 0xd3, 0x5b, 0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37,
52 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, 0x67, 0x4d,
53 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f
55 unsigned char nonce[24] = {
56 0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73,
57 0xcd, 0x62, 0xbd, 0xa8, 0x75, 0xfc, 0x73, 0xd6,
58 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37
60 unsigned char m[163] = {
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 0xbe, 0x07, 0x5f, 0xc5, 0x3c, 0x81, 0xf2, 0xd5,
66 0xcf, 0x14, 0x13, 0x16, 0xeb, 0xeb, 0x0c, 0x7b,
67 0x52, 0x28, 0xc5, 0x2a, 0x4c, 0x62, 0xcb, 0xd4,
68 0x4b, 0x66, 0x84, 0x9b, 0x64, 0x24, 0x4f, 0xfc,
69 0xe5, 0xec, 0xba, 0xaf, 0x33, 0xbd, 0x75, 0x1a,
70 0x1a, 0xc7, 0x28, 0xd4, 0x5e, 0x6c, 0x61, 0x29,
71 0x6c, 0xdc, 0x3c, 0x01, 0x23, 0x35, 0x61, 0xf4,
72 0x1d, 0xb6, 0x6c, 0xce, 0x31, 0x4a, 0xdb, 0x31,
73 0x0e, 0x3b, 0xe8, 0x25, 0x0c, 0x46, 0xf0, 0x6d,
74 0xce, 0xea, 0x3a, 0x7f, 0xa1, 0x34, 0x80, 0x57,
75 0xe2, 0xf6, 0x55, 0x6a, 0xd6, 0xb1, 0x31, 0x8a,
76 0x02, 0x4a, 0x83, 0x8f, 0x21, 0xaf, 0x1f, 0xde,
77 0x04, 0x89, 0x77, 0xeb, 0x48, 0xf5, 0x9f, 0xfd,
78 0x49, 0x24, 0xca, 0x1c, 0x60, 0x90, 0x2e, 0x52,
79 0xf0, 0xa0, 0x89, 0xbc, 0x76, 0x89, 0x70, 0x40,
80 0xe0, 0x82, 0xf9, 0x37, 0x76, 0x38, 0x48, 0x64,
81 0x5e, 0x07, 0x05
83 unsigned char c[163];
84 unsigned char result[147] = {
85 0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5,
86 0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9,
87 0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73,
88 0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce,
89 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4,
90 0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a,
91 0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b,
92 0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72,
93 0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2,
94 0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38,
95 0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a,
96 0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae,
97 0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea,
98 0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda,
99 0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde,
100 0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3,
101 0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6,
102 0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74,
103 0xe3, 0x55, 0xa5
106 bug_on(NONCE_LENGTH != 16);
108 crypto_box_curve25519xsalsa20poly1305(c, m, 163, nonce, bobpk, alicesk);
110 for (i = 16; i < 163; ++i) {
111 if (c[i] != result[i - 16])
112 panic("Crypto selftest failed! :-(\n");
116 int curve25519_pubkey_hexparse_32(unsigned char *bin, size_t blen,
117 const char *ascii, size_t alen)
119 int ret = sscanf(ascii,
120 "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:"
121 "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:"
122 "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:"
123 "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
124 &bin[0], &bin[1], &bin[2], &bin[3], &bin[4],
125 &bin[5], &bin[6], &bin[7], &bin[8], &bin[9],
126 &bin[10], &bin[11], &bin[12], &bin[13], &bin[14],
127 &bin[15], &bin[16], &bin[17], &bin[18], &bin[19],
128 &bin[20], &bin[21], &bin[22], &bin[23], &bin[24],
129 &bin[25], &bin[26], &bin[27], &bin[28], &bin[29],
130 &bin[30], &bin[31]);
131 return ret == 32;
134 void curve25519_alloc_or_maybe_die(struct curve25519_struct *curve)
136 curve->enc_buf_size = curve->dec_buf_size = TUNBUFF_SIZ;
138 curve->enc_buf = xmalloc_aligned(curve->enc_buf_size, 16);
139 curve->dec_buf = xmalloc_aligned(curve->dec_buf_size, 16);
141 spinlock_init(&curve->enc_lock);
142 spinlock_init(&curve->dec_lock);
145 void curve25519_free(void *curvep)
147 struct curve25519_struct *curve = curvep;
149 memset(curve->enc_buf, 0, curve->enc_buf_size);
150 memset(curve->dec_buf, 0, curve->dec_buf_size);
152 xfree(curve->enc_buf);
153 xfree(curve->dec_buf);
155 spinlock_destroy(&curve->enc_lock);
156 spinlock_destroy(&curve->dec_lock);
159 int curve25519_proto_init(struct curve25519_proto *proto, unsigned char *pubkey_remote,
160 size_t len, char *home, int server)
162 int fd;
163 ssize_t ret;
164 char path[PATH_MAX];
165 unsigned char secretkey_own[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES];
166 unsigned char publickey_own[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES];
168 fmemset(secretkey_own, 0, sizeof(secretkey_own));
169 fmemset(publickey_own, 0, sizeof(publickey_own));
171 if (!pubkey_remote || len != sizeof(publickey_own))
172 return -EINVAL;
174 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
175 fd = open_or_die(path, O_RDONLY);
177 ret = read(fd, secretkey_own, sizeof(secretkey_own));
178 if (ret != sizeof(secretkey_own)) {
179 xmemset(secretkey_own, 0, sizeof(secretkey_own));
180 panic("Cannot read private key!\n");
183 close(fd);
185 crypto_scalarmult_curve25519_base(publickey_own, secretkey_own);
187 if (!crypto_verify_32(publickey_own, pubkey_remote)) {
188 xmemset(secretkey_own, 0, sizeof(secretkey_own));
189 xmemset(publickey_own, 0, sizeof(publickey_own));
190 panic("PANIC: remote end has same public key as you have!!!\n");
193 crypto_box_beforenm(proto->key, pubkey_remote, secretkey_own);
195 xmemset(proto->enonce, 0, sizeof(proto->enonce));
196 xmemset(proto->dnonce, 0, sizeof(proto->dnonce));
198 xmemset(secretkey_own, 0, sizeof(secretkey_own));
199 xmemset(publickey_own, 0, sizeof(publickey_own));
201 return 0;
204 ssize_t curve25519_encode(struct curve25519_struct *curve, struct curve25519_proto *proto,
205 unsigned char *plaintext, size_t size, unsigned char **chipertext)
207 int ret, i;
208 ssize_t done = size;
209 struct taia packet_taia;
211 spinlock_lock(&curve->enc_lock);
213 if (unlikely(size > curve->enc_buf_size)) {
214 done = -ENOMEM;
215 goto out;
218 taia_now(&packet_taia);
219 taia_pack(proto->enonce + NONCE_OFFSET, &packet_taia);
221 memset(curve->enc_buf, 0, curve->enc_buf_size);
222 ret = crypto_box_afternm(curve->enc_buf, plaintext, size, proto->enonce, proto->key);
223 if (unlikely(ret)) {
224 done = -EIO;
225 goto out;
228 fmemcpy(curve->enc_buf + crypto_box_boxzerobytes - NONCE_LENGTH,
229 proto->enonce + NONCE_OFFSET, NONCE_LENGTH);
231 for (i = 0; i < crypto_box_boxzerobytes - NONCE_LENGTH; ++i)
232 curve->enc_buf[i] = (uint8_t) secrand();
234 (*chipertext) = curve->enc_buf;
235 out:
236 spinlock_unlock(&curve->enc_lock);
237 return done;
240 ssize_t curve25519_decode(struct curve25519_struct *curve, struct curve25519_proto *proto,
241 unsigned char *chipertext, size_t size, unsigned char **plaintext,
242 struct taia *arrival_taia)
244 int ret;
245 ssize_t done = size;
246 struct taia packet_taia, arrival_taia2;
248 spinlock_lock(&curve->dec_lock);
250 if (unlikely(size > curve->dec_buf_size)) {
251 done = -ENOMEM;
252 goto out;
254 if (unlikely(size < crypto_box_boxzerobytes + NONCE_LENGTH)) {
255 done = 0;
256 goto out;
258 if (arrival_taia == NULL) {
259 taia_now(&arrival_taia2);
260 arrival_taia = &arrival_taia2;
263 taia_unpack(chipertext + crypto_box_boxzerobytes - NONCE_LENGTH, &packet_taia);
264 if (is_good_taia(arrival_taia, &packet_taia) == 0) {
265 syslog(LOG_ERR, "Bad packet time! Dropping connection!\n");
266 done = 0;
267 goto out;
270 memcpy(proto->dnonce + NONCE_OFFSET, chipertext + crypto_box_boxzerobytes - NONCE_LENGTH, NONCE_LENGTH);
271 memset(curve->dec_buf, 0, curve->dec_buf_size);
273 ret = crypto_box_open_afternm(curve->dec_buf, chipertext, size, proto->dnonce, proto->key);
274 if (unlikely(ret)) {
275 done = -EIO;
276 goto out;
279 (*plaintext) = curve->dec_buf;
280 out:
281 spinlock_unlock(&curve->dec_lock);
282 return done;