netsniff-ng: Add cooked cmdline option.
[netsniff-ng.git] / curve.c
blob319991b6e842cbc5ef421dcebafd1ada991daebe
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 <pwd.h>
16 #include <sys/types.h>
17 #include <sys/time.h>
18 #include <sys/stat.h>
20 #include "built_in.h"
21 #include "xmalloc.h"
22 #include "curve.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.h"
30 #include "config.h"
32 static void curve25519_init(struct curve25519_struct *curve)
34 curve->enc_size = curve->dec_size = TUNBUFF_SIZ;
36 curve->enc = xmalloc_aligned(curve->enc_size, 16);
37 curve->dec = xmalloc_aligned(curve->dec_size, 16);
39 spinlock_init(&curve->enc_lock);
40 spinlock_init(&curve->dec_lock);
43 static void curve25519_destroy(struct curve25519_struct *curve)
45 spinlock_destroy(&curve->enc_lock);
46 spinlock_destroy(&curve->dec_lock);
48 xzfree(curve->enc, curve->enc_size);
49 xzfree(curve->dec, curve->dec_size);
52 struct curve25519_struct *curve25519_tfm_alloc(void)
54 struct curve25519_struct *tfm;
56 tfm = xzmalloc_aligned(sizeof(*tfm), 16);
57 curve25519_init(tfm);
59 return tfm;
62 void curve25519_tfm_free(struct curve25519_struct *tfm)
64 curve25519_destroy(tfm);
65 xzfree(tfm, sizeof(*tfm));
68 void curve25519_tfm_free_void(void *tfm)
70 curve25519_tfm_free(tfm);
73 void curve25519_proto_init(struct curve25519_proto *proto,
74 unsigned char *pubkey_remote, size_t len)
76 int result;
77 char file[128];
78 struct passwd *pw = getpwuid(getuid());
79 unsigned char secretkey_own[crypto_box_sec_key_size];
80 unsigned char publickey_own[crypto_box_pub_key_size];
82 fmemset(secretkey_own, 0, sizeof(secretkey_own));
83 fmemset(publickey_own, 0, sizeof(publickey_own));
85 if (unlikely(!pubkey_remote || len != sizeof(publickey_own)))
86 panic("Invalid argument on curve25519_proto_init!\n");
88 slprintf(file, sizeof(file), "%s/%s", pw->pw_dir, FILE_PRIVKEY);
89 read_blob_or_die(file, secretkey_own, sizeof(secretkey_own));
91 crypto_scalarmult_curve25519_base(publickey_own, secretkey_own);
92 result = crypto_verify_32(publickey_own, pubkey_remote);
94 if (result == 0)
95 panic("Remote end has same public key as you have!\n");
97 crypto_box_beforenm(proto->key, pubkey_remote, secretkey_own);
99 fmemset(proto->enonce, 0, sizeof(proto->enonce));
100 fmemset(proto->dnonce, 0, sizeof(proto->dnonce));
102 xmemset(secretkey_own, 0, sizeof(secretkey_own));
103 xmemset(publickey_own, 0, sizeof(publickey_own));
106 ssize_t curve25519_encode(struct curve25519_struct *curve,
107 struct curve25519_proto *proto,
108 unsigned char *plaintext, size_t size,
109 unsigned char **ciphertext)
111 int ret, i;
112 ssize_t done = size;
113 struct taia packet_taia;
115 spinlock_lock(&curve->enc_lock);
116 if (unlikely(size > curve->enc_size)) {
117 done = -ENOMEM;
118 goto out;
121 taia_now(&packet_taia);
122 taia_pack(NONCE_EDN_OFFSET(proto->enonce), &packet_taia);
124 fmemset(curve->enc, 0, curve->enc_size);
125 ret = crypto_box_afternm(curve->enc, plaintext, size,
126 proto->enonce, proto->key);
127 if (unlikely(ret)) {
128 done = -EIO;
129 goto out;
132 fmemcpy(NONCE_PKT_OFFSET(curve->enc),
133 NONCE_EDN_OFFSET(proto->enonce), NONCE_LENGTH);
134 for (i = 0; i < NONCE_RND_LENGTH; ++i)
135 curve->enc[i] = (uint8_t) secrand();
137 (*ciphertext) = curve->enc;
138 out:
139 spinlock_unlock(&curve->enc_lock);
140 return done;
143 ssize_t curve25519_decode(struct curve25519_struct *curve,
144 struct curve25519_proto *proto,
145 unsigned char *ciphertext, size_t size,
146 unsigned char **plaintext,
147 struct taia *arrival_taia)
149 int ret;
150 ssize_t done = size;
151 struct taia packet_taia, tmp_taia;
153 spinlock_lock(&curve->dec_lock);
154 if (unlikely(size > curve->dec_size || size < NONCE_ALL_LENGTH)) {
155 done = size < NONCE_ALL_LENGTH ? 0 : -ENOMEM;
156 goto out;
159 if (arrival_taia == NULL) {
160 taia_now(&tmp_taia);
161 arrival_taia = &tmp_taia;
164 taia_unpack(NONCE_PKT_OFFSET(ciphertext), &packet_taia);
165 if (taia_looks_good(arrival_taia, &packet_taia) == 0) {
166 done = 0;
167 goto out;
170 fmemcpy(NONCE_EDN_OFFSET(proto->dnonce),
171 NONCE_PKT_OFFSET(ciphertext), NONCE_LENGTH);
172 fmemset(curve->dec, 0, curve->dec_size);
174 ret = crypto_box_open_afternm(curve->dec, ciphertext, size,
175 proto->dnonce, proto->key);
176 if (unlikely(ret)) {
177 done = -EIO;
178 goto out;
181 (*plaintext) = curve->dec;
182 out:
183 spinlock_unlock(&curve->dec_lock);
184 return done;
187 int curve25519_pubkey_hexparse_32(unsigned char *bin, size_t blen,
188 const char *ascii, size_t alen)
190 int ret = sscanf(ascii,
191 "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:"
192 "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:"
193 "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:"
194 "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
195 &bin[0], &bin[1], &bin[2], &bin[3], &bin[4],
196 &bin[5], &bin[6], &bin[7], &bin[8], &bin[9],
197 &bin[10], &bin[11], &bin[12], &bin[13], &bin[14],
198 &bin[15], &bin[16], &bin[17], &bin[18], &bin[19],
199 &bin[20], &bin[21], &bin[22], &bin[23], &bin[24],
200 &bin[25], &bin[26], &bin[27], &bin[28], &bin[29],
201 &bin[30], &bin[31]);
202 return ret == 32;