2 * transsip - the telephony network
3 * By Daniel Borkmann <daniel@transsip.org>
4 * Copyright 2011 Daniel Borkmann.
5 * Subject to the GPL, version 2.
16 #include <sys/types.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 */
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,
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,
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')
120 if (x
>= 'a' && x
<= 'f')
121 return 10 + (x
- 'a');
122 if (x
>= 'A' && x
<= 'F')
123 return 10 + (x
- 'A');
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)
143 digit0
= hexdigit(x
[0]);
146 digit1
= hexdigit(x
[1]);
149 *y
++ = digit1
+ 16 * digit0
;
154 if (x
[0] != '\0' || seen_digits
!= 32 || seen_colons
!= 31)
159 int curve25519_alloc_or_maybe_die(struct curve25519_struct
*c
)
163 c
->enc_buf_size
= MAX_MSG
;
164 c
->dec_buf_size
= MAX_MSG
;
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();
173 void curve25519_free(void *vc
)
175 struct curve25519_struct
*c
= vc
;
178 memset(c
->enc_buf
, 0, c
->enc_buf_size
);
179 memset(c
->dec_buf
, 0, c
->dec_buf_size
);
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
)
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
)
197 memset(path
, 0, sizeof(path
));
198 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
199 fd
= open(path
, O_RDONLY
);
201 panic("Cannot open privkey file!\n");
202 ret
= read(fd
, secretkey_own
, sizeof(secretkey_own
));
203 if (ret
!= sizeof(secretkey_own
)) {
204 memset(secretkey_own
, 0, sizeof(secretkey_own
));
205 panic("Cannot read private key!\n");
208 crypto_scalarmult_curve25519_base(publickey_own
, secretkey_own
);
209 if (!crypto_verify_32(publickey_own
, pubkey_remote
)) {
210 memset(secretkey_own
, 0, sizeof(secretkey_own
));
211 memset(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 memset(p
->enonce
, 0, sizeof(p
->enonce
));
216 memset(p
->dnonce
, 0, sizeof(p
->dnonce
));
217 memset(secretkey_own
, 0, sizeof(secretkey_own
));
218 memset(publickey_own
, 0, sizeof(publickey_own
));
222 ssize_t
curve25519_encode(struct curve25519_struct
*c
, struct curve25519_proto
*p
,
223 unsigned char *plaintext
, size_t size
,
224 unsigned char **chipertext
)
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
);
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
,
240 spinlock_unlock(&c
->enc_lock
);
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
);
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
)
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
);
264 if (unlikely(size
< crypto_box_boxzerobytes
+ NONCE_LENGTH
)) {
265 spinlock_unlock(&c
->dec_lock
);
268 if (arrival_taia
== NULL
) {
269 taia_now(&__arrival_taia
);
270 arrival_taia
= &__arrival_taia
;
272 taia_unpack(chipertext
+ crypto_box_boxzerobytes
- NONCE_LENGTH
,
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");
280 memcpy(p
->dnonce
+ NONCE_OFFSET
,
281 chipertext
+ crypto_box_boxzerobytes
- NONCE_LENGTH
,
283 memset(c
->dec_buf
, 0, c
->dec_buf_size
);
284 ret
= crypto_box_open_afternm(c
->dec_buf
, chipertext
, size
,
287 spinlock_unlock(&c
->enc_lock
);
290 (*plaintext
) = c
->dec_buf
;
291 spinlock_unlock(&c
->dec_lock
);