2 * transsip - the telephony network
3 * By Daniel Borkmann <daniel@transsip.org>
4 * Copyright 2011 Daniel Borkmann.
5 * Subject to the GPL, version 2.
17 #include "crypto_box_curve25519xsalsa20poly1305.h"
19 /* Some parts derived from public domain code from curveprotect project */
27 uint32_t nano
; /* 0...999999999 */
28 uint32_t atto
; /* 0...999999999 */
31 /* Delay tolerance for packets! */
32 static struct taia tolerance_taia
= {
38 #define crypto_box_zerobytes crypto_box_curve25519xsalsa20poly1305_ZEROBYTES
39 #define crypto_box_boxzerobytes crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES
41 #define crypto_box_noncebytes crypto_box_curve25519xsalsa20poly1305_NONCEBYTES
42 #define crypto_box_beforenmbytes crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES
45 struct curve25519_proto
{
46 unsigned char enonce
[crypto_box_noncebytes
] __aligned_16
;
47 unsigned char dnonce
[crypto_box_noncebytes
] __aligned_16
;
48 unsigned char key
[crypto_box_noncebytes
] __aligned_16
;
52 struct curve25519_struct
{
55 unsigned char *enc_buf
;
56 struct spinlock enc_lock
;
59 unsigned char *dec_buf
;
60 struct spinlock dec_lock
;
63 extern void curve25519_selftest(void);
64 extern int curve25519_pubkey_hexparse_32(unsigned char *y
, size_t ylen
,
65 const char *x
, size_t len
);
66 extern int curve25519_alloc_or_maybe_die(struct curve25519_struct
*c
);
67 extern void curve25519_free(void *vc
);
68 extern int curve25519_proto_init(struct curve25519_proto
*p
,
69 unsigned char *pubkey_remote
, size_t len
,
70 char *home
, int server
);
71 extern ssize_t
curve25519_encode(struct curve25519_struct
*c
,
72 struct curve25519_proto
*p
,
73 unsigned char *plaintext
, size_t size
,
74 unsigned char **chipertext
);
75 extern ssize_t
curve25519_decode(struct curve25519_struct
*c
,
76 struct curve25519_proto
*p
,
77 unsigned char *chipertext
, size_t size
,
78 unsigned char **plaintext
,
79 struct taia
*arrival_taia
);
81 static inline void tai_pack(unsigned char *s
, struct tai
*t
)
85 s
[7] = x
& 255; x
>>= 8;
86 s
[6] = x
& 255; x
>>= 8;
87 s
[5] = x
& 255; x
>>= 8;
88 s
[4] = x
& 255; x
>>= 8;
89 s
[3] = x
& 255; x
>>= 8;
90 s
[2] = x
& 255; x
>>= 8;
91 s
[1] = x
& 255; x
>>= 8;
95 static inline void tai_unpack(unsigned char *s
, struct tai
*t
)
98 x
= (unsigned char) s
[0];
99 x
<<= 8; x
+= (unsigned char) s
[1];
100 x
<<= 8; x
+= (unsigned char) s
[2];
101 x
<<= 8; x
+= (unsigned char) s
[3];
102 x
<<= 8; x
+= (unsigned char) s
[4];
103 x
<<= 8; x
+= (unsigned char) s
[5];
104 x
<<= 8; x
+= (unsigned char) s
[6];
105 x
<<= 8; x
+= (unsigned char) s
[7];
109 static inline void taia_pack(unsigned char *s
, struct taia
*t
)
112 tai_pack(s
, &t
->sec
);
115 s
[7] = x
& 255; x
>>= 8;
116 s
[6] = x
& 255; x
>>= 8;
117 s
[5] = x
& 255; x
>>= 8;
120 s
[3] = x
& 255; x
>>= 8;
121 s
[2] = x
& 255; x
>>= 8;
122 s
[1] = x
& 255; x
>>= 8;
126 static inline void taia_unpack(unsigned char *s
, struct taia
*t
)
129 tai_unpack(s
, &t
->sec
);
131 x
= (unsigned char) s
[4];
132 x
<<= 8; x
+= (unsigned char) s
[5];
133 x
<<= 8; x
+= (unsigned char) s
[6];
134 x
<<= 8; x
+= (unsigned char) s
[7];
136 x
= (unsigned char) s
[0];
137 x
<<= 8; x
+= (unsigned char) s
[1];
138 x
<<= 8; x
+= (unsigned char) s
[2];
139 x
<<= 8; x
+= (unsigned char) s
[3];
143 #define tai_unix(t, u) ((void) ((t)->x = 4611686018427387914ULL + (uint64_t) (u)))
145 static inline void taia_now(struct taia
*t
)
148 gettimeofday(&now
, NULL
);
149 tai_unix(&t
->sec
, now
.tv_sec
);
150 t
->nano
= 1000 * now
.tv_usec
+ 500;
151 t
->atto
= mt_rand_int32();
154 /* XXX: breaks tai encapsulation */
157 static inline void taia_sub(struct taia
*res
,
158 const struct taia
*u
,
159 const struct taia
*v
)
161 unsigned long unano
= u
->nano
;
162 unsigned long uatto
= u
->atto
;
163 res
->sec
.x
= u
->sec
.x
- v
->sec
.x
;
164 res
->nano
= unano
- v
->nano
;
165 res
->atto
= uatto
- v
->atto
;
166 if (res
->atto
> uatto
) {
167 res
->atto
+= 1000000000UL;
170 if (res
->nano
> unano
) {
171 res
->nano
+= 1000000000UL;
176 /* XXX: breaks tai encapsulation */
179 static inline void taia_add(struct taia
*res
,
180 const struct taia
*u
,
181 const struct taia
*v
)
183 res
->sec
.x
= u
->sec
.x
+ v
->sec
.x
;
184 res
->nano
= u
->nano
+ v
->nano
;
185 res
->atto
= u
->atto
+ v
->atto
;
186 if (res
->atto
> 999999999UL) {
187 res
->atto
-= 1000000000UL;
190 if (res
->nano
> 999999999UL) {
191 res
->nano
-= 1000000000UL;
196 /* 1 if t is less than u, 0 otherwise */
197 static inline int taia_less(const struct taia
*t
, const struct taia
*u
)
199 if (t
->sec
.x
< u
->sec
.x
)
201 if (t
->sec
.x
> u
->sec
.x
)
203 if (t
->nano
< u
->nano
)
205 if (t
->nano
> u
->nano
)
207 return t
->atto
< u
->atto
;
210 static inline int is_good_taia(struct taia
*arrival_taia
,
211 struct taia
*packet_taia
)
215 if (taia_less(arrival_taia
, packet_taia
)) {
216 taia_sub(&sub_res
, packet_taia
, arrival_taia
);
217 if (taia_less(&sub_res
, &tolerance_taia
))
222 taia_sub(&sub_res
, arrival_taia
, packet_taia
);
223 if (taia_less(&sub_res
, &tolerance_taia
))