0
|
1 /* Copyright 2010 Ivo Smits <Ivo@UCIS.nl>. All rights reserved. |
|
2 Redistribution and use in source and binary forms, with or without modification, are |
|
3 permitted provided that the following conditions are met: |
|
4 |
|
5 1. Redistributions of source code must retain the above copyright notice, this list of |
|
6 conditions and the following disclaimer. |
|
7 |
|
8 2. Redistributions in binary form must reproduce the above copyright notice, this list |
|
9 of conditions and the following disclaimer in the documentation and/or other materials |
|
10 provided with the distribution. |
|
11 |
|
12 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
|
13 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
|
14 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR |
|
15 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
16 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
17 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
|
18 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
19 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
|
20 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
21 |
|
22 The views and conclusions contained in the software and documentation are those of the |
|
23 authors and should not be interpreted as representing official policies, either expressed |
|
24 or implied, of Ivo Smits.*/ |
|
25 |
|
26 #include "common.c" |
|
27 #include "crypto_box.h" |
|
28 #include <sys/types.h> |
|
29 #include <sys/time.h> |
|
30 |
|
31 #define uint64 unsigned long long //typedef unsigned long long uint64; |
|
32 |
|
33 struct tai { |
|
34 uint64 x; |
|
35 }; |
|
36 struct taia { |
|
37 struct tai sec; |
|
38 unsigned long nano; /* 0...999999999 */ |
|
39 unsigned long atto; /* 0...999999999 */ |
|
40 }; |
|
41 |
|
42 struct qt_proto_data_nacltai { |
|
43 unsigned char cenonce[crypto_box_NONCEBYTES], cdnonce[crypto_box_NONCEBYTES]; |
|
44 unsigned char cbefore[crypto_box_BEFORENMBYTES]; |
|
45 struct taia cdtaip, cdtaic; |
|
46 }; |
|
47 |
|
48 #define noncelength sizeof(struct taia) |
|
49 #define nonceoffset (crypto_box_NONCEBYTES - noncelength) |
|
50 /*static unsigned char cbefore[crypto_box_BEFORENMBYTES]; |
|
51 static unsigned char buffer1[MAX_PACKET_LEN+crypto_box_ZEROBYTES], buffer2[MAX_PACKET_LEN+crypto_box_ZEROBYTES]; |
|
52 static const unsigned char* buffer1offset = buffer1 + crypto_box_ZEROBYTES; |
|
53 static const unsigned char* buffer2offset = buffer2 + crypto_box_BOXZEROBYTES - noncelength;*/ |
|
54 static const int overhead = crypto_box_BOXZEROBYTES + noncelength; |
|
55 |
|
56 void tai_pack(char *s, struct tai *t) { |
|
57 uint64 x; |
|
58 x = t->x; |
|
59 s[7] = x & 255; x >>= 8; |
|
60 s[6] = x & 255; x >>= 8; |
|
61 s[5] = x & 255; x >>= 8; |
|
62 s[4] = x & 255; x >>= 8; |
|
63 s[3] = x & 255; x >>= 8; |
|
64 s[2] = x & 255; x >>= 8; |
|
65 s[1] = x & 255; x >>= 8; |
|
66 s[0] = x; |
|
67 } |
|
68 void tai_unpack(char *s, struct tai *t) { |
|
69 uint64 x; |
|
70 x = (unsigned char) s[0]; |
|
71 x <<= 8; x += (unsigned char) s[1]; |
|
72 x <<= 8; x += (unsigned char) s[2]; |
|
73 x <<= 8; x += (unsigned char) s[3]; |
|
74 x <<= 8; x += (unsigned char) s[4]; |
|
75 x <<= 8; x += (unsigned char) s[5]; |
|
76 x <<= 8; x += (unsigned char) s[6]; |
|
77 x <<= 8; x += (unsigned char) s[7]; |
|
78 t->x = x; |
|
79 } |
|
80 void taia_pack(char *s, struct taia *t) { |
|
81 unsigned long x; |
|
82 tai_pack(s,&t->sec); |
|
83 s += 8; |
|
84 x = t->atto; |
|
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; |
|
89 x = t->nano; |
|
90 s[3] = x & 255; x >>= 8; |
|
91 s[2] = x & 255; x >>= 8; |
|
92 s[1] = x & 255; x >>= 8; |
|
93 s[0] = x; |
|
94 } |
|
95 void taia_unpack(char *s, struct taia *t) { |
|
96 unsigned long x; |
|
97 tai_unpack(s,&t->sec); |
|
98 s += 8; |
|
99 x = (unsigned char) s[4]; |
|
100 x <<= 8; x += (unsigned char) s[5]; |
|
101 x <<= 8; x += (unsigned char) s[6]; |
|
102 x <<= 8; x += (unsigned char) s[7]; |
|
103 t->atto = x; |
|
104 x = (unsigned char) s[0]; |
|
105 x <<= 8; x += (unsigned char) s[1]; |
|
106 x <<= 8; x += (unsigned char) s[2]; |
|
107 x <<= 8; x += (unsigned char) s[3]; |
|
108 t->nano = x; |
|
109 } |
|
110 |
|
111 void taia_now(struct taia *t) { |
|
112 struct timeval now; |
|
113 gettimeofday(&now,(struct timezone *) 0); |
|
114 t->sec.x = 4611686018427387914ULL + (uint64) now.tv_sec; |
|
115 t->nano = 1000 * now.tv_usec + 500; |
|
116 t->atto = 0; |
|
117 } |
|
118 |
|
119 extern crypto_scalarmult_curve25519_base(unsigned char *pk, unsigned char *sk); |
|
120 |
|
121 static int encode(struct qtsession* sess, char* raw, char* enc, int len) { |
|
122 struct qt_proto_data_nacltai* d = (struct qt_proto_data_nacltai*)sess->protocol_data; |
|
123 memset(raw, 0, crypto_box_ZEROBYTES); |
|
124 taia_now(&d->cdtaic); |
|
125 taia_pack(d->cenonce + nonceoffset, &(d->cdtaic)); |
|
126 if (crypto_box_afternm(enc, raw, len + crypto_box_ZEROBYTES, d->cenonce, d->cbefore)) return errorexit("Crypto failed"); |
|
127 memcpy((void*)(enc + crypto_box_BOXZEROBYTES - noncelength), d->cenonce + nonceoffset, noncelength); |
|
128 len += overhead; |
|
129 return len; |
|
130 } |
|
131 |
|
132 static int decode(struct qtsession* sess, char* enc, char* raw, int len) { |
|
133 struct qt_proto_data_nacltai* d = (struct qt_proto_data_nacltai*)sess->protocol_data; |
|
134 int i; |
|
135 if (len < overhead) { |
|
136 fprintf(stderr, "Short packet received: %d\n", len); |
|
137 return 0; |
|
138 } |
|
139 len -= overhead; |
|
140 taia_unpack((char*)(enc + crypto_box_BOXZEROBYTES - noncelength), &(d->cdtaic)); |
|
141 if (d->cdtaic.sec.x <= d->cdtaip.sec.x || d->cdtaic.nano <= d->cdtaip.nano || d->cdtaic.atto <= d->cdtaip.atto) { |
|
142 fprintf(stderr, "Timestamp going back, ignoring packet\n"); |
|
143 return 0; |
|
144 } |
|
145 memcpy(d->cdnonce + nonceoffset, enc + crypto_box_BOXZEROBYTES - noncelength, noncelength); |
|
146 memset(enc, 0, crypto_box_BOXZEROBYTES); |
|
147 if (i = crypto_box_open_afternm(raw, enc, len + crypto_box_ZEROBYTES, d->cdnonce, d->cbefore)) { |
|
148 fprintf(stderr, "Decryption failed len=%d result=%d\n", len, i); |
|
149 return 0; |
|
150 } |
|
151 d->cdtaip = d->cdtaic; |
|
152 return len; |
|
153 } |
|
154 |
|
155 static int init(struct qtsession* sess) { |
|
156 struct qt_proto_data_nacltai* d = (struct qt_proto_data_nacltai*)sess->protocol_data; |
|
157 char* envval; |
|
158 printf("Initializing cryptography...\n"); |
|
159 unsigned char cownpublickey[crypto_box_PUBLICKEYBYTES], cpublickey[crypto_box_PUBLICKEYBYTES], csecretkey[crypto_box_SECRETKEYBYTES]; |
|
160 if (!(envval = getconf("PUBLIC_KEY"))) return errorexit("Missing PUBLIC_KEY"); |
|
161 if (strlen(envval) != 2*crypto_box_PUBLICKEYBYTES) return errorexit("PUBLIC_KEY length"); |
|
162 hex2bin(cpublickey, envval, crypto_box_PUBLICKEYBYTES); |
|
163 if (!(envval = getconf("PRIVATE_KEY"))) return errorexit("Missing PRIVATE_KEY"); |
|
164 if (strlen(envval) != 2*crypto_box_PUBLICKEYBYTES) return errorexit("PRIVATE_KEY length"); |
|
165 hex2bin(csecretkey, envval, crypto_box_SECRETKEYBYTES); |
|
166 crypto_box_beforenm(d->cbefore, cpublickey, csecretkey); |
|
167 |
|
168 memset(d->cenonce, 0, crypto_box_NONCEBYTES); |
|
169 memset(d->cdnonce, 0, crypto_box_NONCEBYTES); |
|
170 |
|
171 crypto_scalarmult(cownpublickey, csecretkey); |
|
172 |
|
173 if (envval = getenv("TIME_WINDOW")) { |
|
174 taia_now(&d->cdtaip); |
|
175 d->cdtaip.sec.x -= atol(envval); |
|
176 } else { |
|
177 printf("Warning: TIME_WINDOW not set, risking an initial replay attack\n"); |
|
178 } |
|
179 if (envval = getenv("ROLE")) { |
|
180 d->cenonce[nonceoffset-1] = atoi(envval) ? 1 : 0; |
|
181 } else { |
|
182 d->cenonce[nonceoffset-1] = memcmp(cpublickey, cownpublickey, crypto_box_PUBLICKEYBYTES) ? 1 : 0; |
|
183 } |
|
184 d->cdnonce[nonceoffset-1] = d->cenonce[nonceoffset-1] ? 0 : 1; |
|
185 } |
|
186 |
|
187 #ifdef COMBINED_BINARY |
|
188 int tunmain_nacltai() { |
|
189 #else |
|
190 int tunmain() { |
|
191 #endif |
|
192 struct qtproto p = { |
|
193 1, |
|
194 MAX_PACKET_LEN + crypto_box_ZEROBYTES, |
|
195 MAX_PACKET_LEN + crypto_box_ZEROBYTES, |
|
196 crypto_box_ZEROBYTES, |
|
197 crypto_box_BOXZEROBYTES - noncelength, |
|
198 encode, |
|
199 decode, |
|
200 init, |
|
201 sizeof(struct qt_proto_data_nacltai), |
|
202 }; |
|
203 return qtrun(&p); |
|
204 } |
|
205 |
|
206 #ifndef COMBINED_BINARY |
|
207 int main() { |
|
208 print_header(); |
|
209 return tunmain(); |
|
210 } |
|
211 #endif |