2 * transsip - the telephony network
3 * By Daniel Borkmann <daniel@transsip.org>
4 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
5 * Swiss federal institute of technology (ETH Zurich)
6 * Subject to the GPL, version 2.
8 * This is transsip, a minimalistic, high-speed ECDH peer-to-peer telephony
9 * network. It supports IPv4 and IPv6. As an appropriate key management,
10 * public-key cryptography based on elliptic curves are being used and
11 * packets are encrypted by a symmetric stream cipher (Salsa20) and
12 * authenticated by a MAC (Poly1305), where keys have previously been
13 * computed with the ECDH key agreement protocol (Curve25519). Cryptography
14 * is based on Daniel J. Bernsteins Networking and Cryptography library (NaCl).
15 * Our motivation: Privacy is necessary for an open society in the electronic
16 * age. Privacy is not secrecy. A private matter is something one doesn't
17 * want the whole world to know, but a secret matter is something one doesn't
18 * want anybody to know. Privacy is the power to selectively reveal oneself
19 * to the world. [...] We must defend our own privacy if we expect to have any.
21 * Let folly be our cloak, a veil before the eyes of the Enemy! For he is
22 * very wise, and weighs all things to a nicety in the scales of his malice.
23 * But the only measure that he knows is desire, desire for power; and so he
24 * judges all hearts. Into his heart the thought will not enter that any will
25 * refuse it, that having the Ring we may seek to destroy it. If we seek this,
26 * we shall put him out of reckoning.
28 * -- The Lord of the Rings, Gandalf, Chapter 'The Council of Elrond'.
38 #include <sys/types.h>
39 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
45 #include <celt/celt.h>
46 #include <sys/ptrace.h>
47 #include <speex/speex_jitter.h>
48 #include <speex/speex_echo.h>
58 #include "crypto_verify_32.h"
59 #include "crypto_box_curve25519xsalsa20poly1305.h"
60 #include "crypto_scalarmult_curve25519.h"
61 #include "crypto_auth_hmacsha512256.h"
63 noinline
void *memset(void *__s
, int __c
, size_t __n
);
64 extern void enter_shell_loop(void);
65 int show_key_export(char *home
);
67 static pthread_t ptid
;
69 static char *port
= "30111";
70 static char *stun_server
= "stunserver.org";
71 static char *alsadev
= "plughw:0,0";
73 extern sig_atomic_t quit
;
74 sig_atomic_t did_stun
= 0;
75 static sig_atomic_t incoming_call
= 0;
77 static struct pollfd
*pfds
= NULL
;
78 static struct alsa_dev
*dev
= NULL
;
79 static CELTEncoder
*encoder
= NULL
;
80 static CELTDecoder
*decoder
= NULL
;
81 static JitterBuffer
*jitter
= NULL
;
82 static SpeexEchoState
*echostate
= NULL
;
84 static void check_file_or_die(char *home
, char *file
, int maybeempty
)
88 memset(path
, 0, sizeof(path
));
89 slprintf(path
, sizeof(path
), "%s/%s", home
, file
);
91 panic("No such file %s! Type --keygen to generate initial config!\n",
93 if (!S_ISREG(st
.st_mode
))
94 panic("%s is not a regular file!\n", path
);
95 if ((st
.st_mode
& ~S_IFREG
) != (S_IRUSR
| S_IWUSR
))
96 panic("You have set too many permissions on %s (%o)!\n",
98 if (maybeempty
== 0 && st
.st_size
== 0)
99 panic("%s is empty!\n", path
);
102 static void check_config_exists_or_die(char *home
)
105 panic("No home dir specified!\n");
106 check_file_or_die(home
, FILE_CONTACTS
, 1);
107 check_file_or_die(home
, FILE_SETTINGS
, 0);
108 check_file_or_die(home
, FILE_PRIVKEY
, 0);
109 check_file_or_die(home
, FILE_PUBKEY
, 0);
110 check_file_or_die(home
, FILE_USERNAME
, 0);
113 static char *fetch_home_dir(void)
115 char *home
= getenv("HOME");
117 panic("No HOME defined!\n");
121 static void write_username(char *home
)
124 char path
[PATH_MAX
], *eof
;
126 memset(path
, 0, sizeof(path
));
127 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAME
);
128 printf("Username: [%s] ", getenv("USER"));
130 memset(user
, 0, sizeof(user
));
131 eof
= fgets(user
, sizeof(user
), stdin
);
132 user
[sizeof(user
) - 1] = 0;
133 user
[strlen(user
) - 1] = 0; /* omit last \n */
134 if (strlen(user
) == 0)
135 strlcpy(user
, getenv("USER"), sizeof(user
));
136 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
138 panic("Cannot open your username file!\n");
139 ret
= write(fd
, user
, strlen(user
));
140 if (ret
!= strlen(user
))
141 panic("Could not write username!\n");
143 info("Username written to %s!\n", path
);
146 static void create_transsipdir(char *home
)
150 memset(path
, 0, sizeof(path
));
151 slprintf(path
, sizeof(path
), "%s/%s", home
, ".transsip/");
153 ret
= mkdir(path
, S_IRWXU
);
154 if (ret
< 0 && errno
!= EEXIST
)
155 panic("Cannot create transsip dir!\n");
156 info("transsip directory %s created!\n", path
);
157 /* We also create empty files for contacts and settings! */
158 memset(path
, 0, sizeof(path
));
159 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_CONTACTS
);
160 fd
= open(path
, O_WRONLY
| O_CREAT
, S_IRUSR
| S_IWUSR
);
162 panic("Cannot open contacts file!\n");
164 info("Empty contacts file written to %s!\n", path
);
165 memset(path
, 0, sizeof(path
));
166 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_SETTINGS
);
167 fd
= open(path
, O_WRONLY
| O_CREAT
, S_IRUSR
| S_IWUSR
);
169 panic("Cannot open settings file!\n");
171 info("Empty settings file written to %s!\n", path
);
174 static void create_keypair(char *home
)
178 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
] = { 0 };
179 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
] = { 0 };
181 const char * errstr
= NULL
;
183 info("Reading from %s (this may take a while) ...\n", ENTROPY_SOURCE
);
184 fd
= open_or_die(ENTROPY_SOURCE
, O_RDONLY
);
185 ret
= read_exact(fd
, secretkey
, sizeof(secretkey
), 0);
186 if (ret
!= sizeof(secretkey
)) {
188 errstr
= "Cannot read from "ENTROPY_SOURCE
"!\n";
192 crypto_scalarmult_curve25519_base(publickey
, secretkey
);
193 memset(path
, 0, sizeof(path
));
194 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
195 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
198 errstr
= "Cannot open pubkey file!\n";
201 ret
= write(fd
, publickey
, sizeof(publickey
));
202 if (ret
!= sizeof(publickey
)) {
204 errstr
= "Cannot write public key!\n";
208 info("Public key written to %s!\n", path
);
209 memset(path
, 0, sizeof(path
));
210 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
211 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
214 errstr
= "Cannot open privkey file!\n";
217 ret
= write(fd
, secretkey
, sizeof(secretkey
));
218 if (ret
!= sizeof(secretkey
)) {
220 errstr
= "Cannot write private key!\n";
225 memset(publickey
, 0, sizeof(publickey
));
226 memset(secretkey
, 0, sizeof(secretkey
));
228 panic("%s: %s", errstr
, strerror(errno
));
230 info("Private key written to %s!\n", path
);
233 static void check_config_keypair_or_die(char *home
)
238 const char * errstr
= NULL
;
239 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
240 unsigned char publicres
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
241 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
];
243 memset(path
, 0, sizeof(path
));
244 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
245 fd
= open(path
, O_RDONLY
);
248 errstr
= "Cannot open privkey file!\n";
251 ret
= read(fd
, secretkey
, sizeof(secretkey
));
252 if (ret
!= sizeof(secretkey
)) {
254 errstr
= "Cannot read private key!\n";
258 memset(path
, 0, sizeof(path
));
259 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
260 fd
= open(path
, O_RDONLY
);
263 errstr
= "Cannot open pubkey file!\n";
266 ret
= read(fd
, publickey
, sizeof(publickey
));
267 if (ret
!= sizeof(publickey
)) {
269 errstr
= "Cannot read public key!\n";
272 crypto_scalarmult_curve25519_base(publicres
, secretkey
);
273 err
= crypto_verify_32(publicres
, publickey
);
276 errstr
= "WARNING: your keypair is corrupted!!! You need to "
277 "generate new keys!!!\n";
282 memset(publickey
, 0, sizeof(publickey
));
283 memset(publicres
, 0, sizeof(publicres
));
284 memset(secretkey
, 0, sizeof(secretkey
));
286 panic("%s: %s\n", errstr
, strerror(errno
));
289 static int keygen(char *home
)
291 create_transsipdir(home
);
292 write_username(home
);
293 create_keypair(home
);
294 check_config_keypair_or_die(home
);
295 printf("\nNow edit your .transsip/settings file before starting i.e.:\n");
296 printf(" port <your-transsip-port>\n");
297 printf(" stun stunserver.org\n");
298 printf(" alsa plughw:0,0\n");
299 printf("To add contacts, add a new line into .transsip/contacts with:\n");
300 printf(" <user> <pubkey>\n");
304 static void do_call_duplex(void)
307 int ret
, recv_started
= 0;
310 while (likely(!quit
)) {
311 ret
= poll(pfds
, nfds
+ 1, -1);
313 panic("Poll returned with %d!\n", ret
);
315 /* Received packets */
316 if (pfds
[nfds
].revents
& POLLIN
) {
317 n
= recv(sd
, msg
, MAX_MSG
, 0);
318 int recv_timestamp
= ((int*) msg
)[0];
320 JitterBufferPacket packet
;
321 packet
.data
= msg
+ 4;
323 packet
.timestamp
= recv_timestamp
;
324 packet
.span
= FRAME_SIZE
;
327 jitter_buffer_put(jitter
, &packet
);
331 /* Ready to play a frame (playback) */
332 if (alsa_play_ready(dev
, pfds
, nfds
)) {
333 short pcm
[FRAME_SIZE
* CHANNELS
];
335 JitterBufferPacket packet
;
336 /* Get audio from the jitter buffer */
338 packet
.len
= MAX_MSG
;
339 jitter_buffer_tick(jitter
);
340 jitter_buffer_get(jitter
, &packet
, FRAME_SIZE
,
344 celt_decode(dec_state
, (const unsigned char *)
345 packet
.data
, packet
.len
, pcm
);
347 for (i
= 0; i
< FRAME_SIZE
* CHANNELS
; ++i
)
351 /* Playback the audio and reset the echo canceller
352 if we got an underrun */
354 if (alsa_write(dev
, pcm
, FRAME_SIZE
))
355 speex_echo_state_reset(echo_state
);
356 /* Put frame into playback buffer */
357 speex_echo_playback(echo_state
, pcm
);
360 /* Audio available from the soundcard (capture) */
361 if (alsa_cap_ready(dev
, pfds
, nfds
)) {
362 short pcm
[FRAME_SIZE
* CHANNELS
],
363 pcm2
[FRAME_SIZE
* CHANNELS
];
364 char outpacket
[MAX_MSG
];
366 alsa_read(dev
, pcm
, FRAME_SIZE
);
368 /* Perform echo cancellation */
369 speex_echo_capture(echo_state
, pcm
, pcm2
);
370 for (i
= 0; i
< FRAME_SIZE
* CHANNELS
; ++i
)
373 celt_encode(enc_state
, pcm
, NULL
, (unsigned char *)
374 (outpacket
+ 4), PACKETSIZE
);
376 /* Pseudo header: four null bytes and a 32-bit
378 ((int*)outpacket
)[0] = send_timestamp
;
379 send_timestamp
+= FRAME_SIZE
;
381 rc
= sendto(sd
, outpacket
, PACKETSIZE
+ 4, 0,
382 (struct sockaddr
*) &remote_addr
,
383 sizeof(remote_addr
));
385 panic("cannot send to socket");
391 void call_out(char *host
, char *port
)
394 /* wait for accept */
397 printf("Trying to call %s:%s ...\n", host
, port
);
401 void call_in(int take
)
403 /* lookup addrbook */
408 if (incoming_call
== 0) {
409 printf("No incoming call right now!\n");
413 printf("Trying to take incoming call ...\n");
417 static void *thread(void *null
)
419 int sock
= -1, ret
, mtu
, nfds
, tmp
;
420 struct addrinfo hints
, *ahead
, *ai
;
423 while (did_stun
== 0)
425 memset(&hints
, 0, sizeof(hints
));
426 hints
.ai_family
= PF_UNSPEC
;
427 hints
.ai_socktype
= SOCK_DGRAM
;
428 hints
.ai_protocol
= IPPROTO_UDP
;
429 hints
.ai_flags
= AI_PASSIVE
;
430 ret
= getaddrinfo(NULL
, port
, &hints
, &ahead
);
432 panic("Cannot get address info!\n");
433 for (ai
= ahead
; ai
!= NULL
&& sock
< 0; ai
= ai
->ai_next
) {
434 sock
= socket(ai
->ai_family
, ai
->ai_socktype
, ai
->ai_protocol
);
437 if (ai
->ai_family
== AF_INET6
) {
440 ret
= setsockopt(sock
, IPPROTO_IPV6
, IPV6_V6ONLY
,
451 #endif /* IPV6_V6ONLY */
453 mtu
= IP_PMTUDISC_DONT
;
454 setsockopt(sock
, SOL_IP
, IP_MTU_DISCOVER
, &mtu
, sizeof(mtu
));
455 ret
= bind(sock
, ai
->ai_addr
, ai
->ai_addrlen
);
464 panic("Cannot open socket!\n");
465 dev
= alsa_open(alsadev
, SAMPLING_RATE
, CHANNELS
, FRAME_SIZE
);
467 panic("Cannot open ALSA device %s!\n", alsadev
);
468 mode
= celt_mode_create(SAMPLING_RATE
, FRAME_SIZE
, NULL
);
469 encoder
= celt_encoder_create(mode
, CHANNELS
, NULL
);
470 decoder
= celt_decoder_create(mode
, CHANNELS
, NULL
);
471 nfds
= alsa_nfds(dev
);
472 pfds
= xmalloc(sizeof(*pfds
) * (nfds
+ 1));
473 alsa_getfds(dev
, pfds
, nfds
);
474 pfds
[nfds
].fd
= sock
;
475 pfds
[nfds
].events
= POLLIN
;
476 jitter
= jitter_buffer_init(FRAME_SIZE
);
478 jitter_buffer_ctl(jitter
, JITTER_BUFFER_SET_MARGIN
, &tmp
);
479 echostate
= speex_echo_state_init(FRAME_SIZE
, 10 * FRAME_SIZE
);
481 speex_echo_ctl(echostate
, SPEEX_ECHO_SET_SAMPLING_RATE
, &tmp
);
482 while (likely(!quit
)) {
483 ret
= poll(&pfds
[nfds
], 1, -1);
485 panic("Poll returned with %d!\n", ret
);
486 if (pfds
[nfds
].revents
& POLLIN
) {
487 /* Check for Auth pkt, if yes, set current caller and notifiy cli */
488 /* cli user must call take, that triggers call_in() */
498 static void start_server(void)
500 int ret
= pthread_create(&ptid
, NULL
, thread
, NULL
);
502 panic("Cannot create server thread!\n");
505 static void stop_server(void)
507 /* pthread_join(ptid, NULL);*/
510 static void help(void)
512 printf("\ntranssip %s, peer-to-peer elliptic-curve-crypto-based "
513 "telephony network\n", VERSION_STRING
);
514 printf("http://www.transsip.org\n\n");
515 printf("Usage: transsip [options]\n");
516 printf("Options:\n");
517 printf(" -k|--keygen Generate public/private keypair\n");
518 printf(" -v|--version Show version\n");
519 printf(" -h|--help Guess what?!\n\n");
521 printf(" There is no default port specified, so that you are forced\n");
522 printf(" to select your own!\n");
524 printf("Secret ingredient: 7647-14-5\n");
526 printf("Please report bugs to <bugs@transsip.org>\n");
527 printf("Copyright (C) 2011 Daniel Borkmann <daniel@transsip.org>,\n");
528 printf("License: GNU GPL version 2\n");
529 printf("This is free software: you are free to change and redistribute it.\n");
530 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
534 static void version(void)
536 printf("\ntranssip %s, peer-to-peer elliptic-curve-crypto-based "
537 "telephony network\n", VERSION_STRING
);
538 printf("Build: %s\n", BUILD_STRING
);
539 printf("http://www.transsip.org\n\n");
540 printf("Please report bugs to <bugs@transsip.org>\n");
541 printf("Copyright (C) 2011 Daniel Borkmann <daniel@transsip.org>,\n");
542 printf("License: GNU GPL version 2\n");
543 printf("This is free software: you are free to change and redistribute it.\n");
544 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
548 int main(int argc
, char **argv
)
550 char *home
= fetch_home_dir();
551 if (getuid() != geteuid())
553 if (getenv("LD_PRELOAD"))
554 panic("transsip cannot be preloaded!\n");
555 if (ptrace(PTRACE_TRACEME
, 0, 1, 0) < 0)
556 panic("transsip cannot be ptraced!\n");
557 curve25519_selftest();
558 if (argc
== 2 && (!strncmp("-k", argv
[1], strlen("-k")) ||
559 !strncmp("--keygen", argv
[1], strlen("--keygen")))) {
561 show_key_export(home
);
564 if (argc
== 2 && (!strncmp("-v", argv
[1], strlen("-v")) ||
565 !strncmp("--version", argv
[1], strlen("--version"))))
567 if (argc
== 2 && (!strncmp("-h", argv
[1], strlen("-h")) ||
568 !strncmp("--help", argv
[1], strlen("--help"))))
570 check_config_exists_or_die(home
);
571 check_config_keypair_or_die(home
);
583 char *get_stun_server(void)
588 int show_key_export(char *home
)
592 char path
[PATH_MAX
], tmp
[64];
593 check_config_keypair_or_die(home
);
594 printf("Your public peer information:\n ");
596 memset(path
, 0, sizeof(path
));
597 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAME
);
598 fd
= open_or_die(path
, O_RDONLY
);
599 while ((ret
= read(fd
, tmp
, sizeof(tmp
))) > 0) {
600 ret
= write(STDOUT_FILENO
, tmp
, ret
);
604 memset(path
, 0, sizeof(path
));
605 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
606 fd
= open_or_die(path
, O_RDONLY
);
607 ret
= read(fd
, tmp
, sizeof(tmp
));
608 if (ret
!= crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
)
609 panic("Cannot read public key!\n");
610 for (i
= 0; i
< ret
; ++i
)
612 printf("%02x\n\n", (unsigned char) tmp
[i
]);
614 printf("%02x:", (unsigned char) tmp
[i
]);