comparison src/proto.nacltai.c @ 44:55f379f0a650

Fixed/improved handling of timestamp in nonce in nacltai protocol
author Ivo Smits <Ivo@UCIS.nl>
date Fri, 17 May 2013 16:09:49 +0200
parents 4adbd9b67fe2
children 3115f8af98bb
comparison
equal deleted inserted replaced
43:4adbd9b67fe2 44:55f379f0a650
27 #include "crypto_box_curve25519xsalsa20poly1305.h" 27 #include "crypto_box_curve25519xsalsa20poly1305.h"
28 #include "crypto_scalarmult_curve25519.h" 28 #include "crypto_scalarmult_curve25519.h"
29 #include <sys/types.h> 29 #include <sys/types.h>
30 #include <sys/time.h> 30 #include <sys/time.h>
31 31
32 #define uint64 unsigned long long //typedef unsigned long long uint64;
33
34 struct tai {
35 uint64 x;
36 };
37 struct taia {
38 struct tai sec;
39 unsigned long nano; /* 0...999999999 */
40 unsigned long atto; /* 0...999999999 */
41 };
42
43 struct qt_proto_data_nacltai { 32 struct qt_proto_data_nacltai {
44 unsigned char cenonce[crypto_box_curve25519xsalsa20poly1305_NONCEBYTES], cdnonce[crypto_box_curve25519xsalsa20poly1305_NONCEBYTES]; 33 unsigned char cenonce[crypto_box_curve25519xsalsa20poly1305_NONCEBYTES], cdnonce[crypto_box_curve25519xsalsa20poly1305_NONCEBYTES];
45 unsigned char cbefore[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES]; 34 unsigned char cbefore[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES];
46 struct taia cdtaip, cdtaie; 35 unsigned char cdtaipp[16];
47 }; 36 };
48 37
49 #define noncelength 16 38 #define noncelength 16
50 #define nonceoffset (crypto_box_curve25519xsalsa20poly1305_NONCEBYTES - noncelength) 39 #define nonceoffset (crypto_box_curve25519xsalsa20poly1305_NONCEBYTES - noncelength)
51 /*static unsigned char cbefore[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES];
52 static unsigned char buffer1[MAX_PACKET_LEN+crypto_box_curve25519xsalsa20poly1305_ZEROBYTES], buffer2[MAX_PACKET_LEN+crypto_box_curve25519xsalsa20poly1305_ZEROBYTES];
53 static const unsigned char* buffer1offset = buffer1 + crypto_box_curve25519xsalsa20poly1305_ZEROBYTES;
54 static const unsigned char* buffer2offset = buffer2 + crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES - noncelength;*/
55 static const int overhead = crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES + noncelength; 40 static const int overhead = crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES + noncelength;
56 41
57 void tai_pack(char *s, struct tai *t) { 42 static void taia_now_packed(unsigned char* b, int secoffset) {
58 uint64 x; 43 struct timeval now;
59 x = t->x; 44 gettimeofday(&now, NULL);
60 s[7] = x & 255; x >>= 8; 45 u_int64_t sec = 4611686018427387914ULL + (u_int64_t)now.tv_sec + secoffset;
61 s[6] = x & 255; x >>= 8; 46 b[0] = (sec >> 56) & 0xff;
62 s[5] = x & 255; x >>= 8; 47 b[1] = (sec >> 48) & 0xff;
63 s[4] = x & 255; x >>= 8; 48 b[2] = (sec >> 40) & 0xff;
64 s[3] = x & 255; x >>= 8; 49 b[3] = (sec >> 32) & 0xff;
65 s[2] = x & 255; x >>= 8; 50 b[4] = (sec >> 24) & 0xff;
66 s[1] = x & 255; x >>= 8; 51 b[5] = (sec >> 16) & 0xff;
67 s[0] = x; 52 b[6] = (sec >> 8) & 0xff;
68 } 53 b[7] = (sec >> 0) & 0xff;
69 void tai_unpack(char *s, struct tai *t) { 54 u_int32_t nano = 1000 * now.tv_usec + 500;
70 uint64 x; 55 b[8] = (nano >> 24) & 0xff;
71 x = (unsigned char) s[0]; 56 b[9] = (nano >> 16) & 0xff;
72 x <<= 8; x += (unsigned char) s[1]; 57 b[10] = (nano >> 8) & 0xff;
73 x <<= 8; x += (unsigned char) s[2]; 58 b[11] = (nano >> 0) & 0xff;
74 x <<= 8; x += (unsigned char) s[3]; 59 ++b[15] == 0 && ++b[14] == 0 && ++b[13] == 0 && ++b[12] == 0;
75 x <<= 8; x += (unsigned char) s[4];
76 x <<= 8; x += (unsigned char) s[5];
77 x <<= 8; x += (unsigned char) s[6];
78 x <<= 8; x += (unsigned char) s[7];
79 t->x = x;
80 }
81 void taia_pack(char *s, struct taia *t) {
82 unsigned long x;
83 tai_pack(s,&t->sec);
84 s += 8;
85 x = t->atto;
86 s[7] = x & 255; x >>= 8;
87 s[6] = x & 255; x >>= 8;
88 s[5] = x & 255; x >>= 8;
89 s[4] = x;
90 x = t->nano;
91 s[3] = x & 255; x >>= 8;
92 s[2] = x & 255; x >>= 8;
93 s[1] = x & 255; x >>= 8;
94 s[0] = x;
95 }
96 void taia_unpack(char *s, struct taia *t) {
97 unsigned long x;
98 tai_unpack(s,&t->sec);
99 s += 8;
100 x = (unsigned char) s[4];
101 x <<= 8; x += (unsigned char) s[5];
102 x <<= 8; x += (unsigned char) s[6];
103 x <<= 8; x += (unsigned char) s[7];
104 t->atto = x;
105 x = (unsigned char) s[0];
106 x <<= 8; x += (unsigned char) s[1];
107 x <<= 8; x += (unsigned char) s[2];
108 x <<= 8; x += (unsigned char) s[3];
109 t->nano = x;
110 } 60 }
111 61
112 void taia_now(struct taia *t) { 62 //Packet format: <16 bytes taia packed timestamp><16 bytes checksum><n bytes encrypted data>
113 struct timeval now;
114 gettimeofday(&now,(struct timezone *) 0);
115 t->sec.x = 4611686018427387914ULL + (uint64) now.tv_sec;
116 t->nano = 1000 * now.tv_usec + 500;
117 t->atto++;
118 }
119 63
120 static int encode(struct qtsession* sess, char* raw, char* enc, int len) { 64 static int encode(struct qtsession* sess, char* raw, char* enc, int len) {
121 if (debug) fprintf(stderr, "Encoding packet of %d bytes from %p to %p\n", len, raw, enc); 65 if (debug) fprintf(stderr, "Encoding packet of %d bytes from %p to %p\n", len, raw, enc);
122 struct qt_proto_data_nacltai* d = (struct qt_proto_data_nacltai*)sess->protocol_data; 66 struct qt_proto_data_nacltai* d = (struct qt_proto_data_nacltai*)sess->protocol_data;
123 memset(raw, 0, crypto_box_curve25519xsalsa20poly1305_ZEROBYTES); 67 memset(raw, 0, crypto_box_curve25519xsalsa20poly1305_ZEROBYTES);
124 taia_now(&d->cdtaie); 68 taia_now_packed(d->cenonce + nonceoffset, 0);
125 taia_pack(d->cenonce + nonceoffset, &(d->cdtaie));
126 if (crypto_box_curve25519xsalsa20poly1305_afternm(enc, raw, len + crypto_box_curve25519xsalsa20poly1305_ZEROBYTES, d->cenonce, d->cbefore)) return errorexit("Encryption failed"); 69 if (crypto_box_curve25519xsalsa20poly1305_afternm(enc, raw, len + crypto_box_curve25519xsalsa20poly1305_ZEROBYTES, d->cenonce, d->cbefore)) return errorexit("Encryption failed");
127 memcpy((void*)(enc + crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES - noncelength), d->cenonce + nonceoffset, noncelength); 70 memcpy((void*)(enc + crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES - noncelength), d->cenonce + nonceoffset, noncelength);
128 len += overhead; 71 len += overhead;
129 if (debug) fprintf(stderr, "Encoded packet of %d bytes from %p to %p\n", len, raw, enc); 72 if (debug) fprintf(stderr, "Encoded packet of %d bytes from %p to %p\n", len, raw, enc);
130 return len; 73 return len;
131 } 74 }
132 75
133 static int decode(struct qtsession* sess, char* enc, char* raw, int len) { 76 static int decode(struct qtsession* sess, char* enc, char* raw, int len) {
134 if (debug) fprintf(stderr, "Decoding packet of %d bytes from %p to %p\n", len, enc, raw); 77 if (debug) fprintf(stderr, "Decoding packet of %d bytes from %p to %p\n", len, enc, raw);
135 struct qt_proto_data_nacltai* d = (struct qt_proto_data_nacltai*)sess->protocol_data; 78 struct qt_proto_data_nacltai* d = (struct qt_proto_data_nacltai*)sess->protocol_data;
136 struct taia cdtaic;
137 int i; 79 int i;
138 if (len < overhead) { 80 if (len < overhead) {
139 fprintf(stderr, "Short packet received: %d\n", len); 81 fprintf(stderr, "Short packet received: %d\n", len);
140 return -1; 82 return -1;
141 } 83 }
142 len -= overhead; 84 len -= overhead;
143 taia_unpack((char*)(enc + crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES - noncelength), &cdtaic); 85 if (memcmp(enc, d->cdtaipp, 16) <= 0) {
144 if (cdtaic.sec.x <= d->cdtaip.sec.x && cdtaic.nano <= d->cdtaip.nano && cdtaic.atto <= d->cdtaip.atto) {
145 fprintf(stderr, "Timestamp going back, ignoring packet\n"); 86 fprintf(stderr, "Timestamp going back, ignoring packet\n");
146 return -1; 87 return -1;
147 } 88 }
148 memcpy(d->cdnonce + nonceoffset, enc + crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES - noncelength, noncelength); 89 memcpy(d->cdnonce + nonceoffset, enc, noncelength);
149 memset(enc, 0, crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES); 90 memset(enc, 0, crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES);
150 if (i = crypto_box_curve25519xsalsa20poly1305_open_afternm(raw, enc, len + crypto_box_curve25519xsalsa20poly1305_ZEROBYTES, d->cdnonce, d->cbefore)) { 91 if (i = crypto_box_curve25519xsalsa20poly1305_open_afternm(raw, enc, len + crypto_box_curve25519xsalsa20poly1305_ZEROBYTES, d->cdnonce, d->cbefore)) {
151 fprintf(stderr, "Decryption failed len=%d result=%d\n", len, i); 92 fprintf(stderr, "Decryption failed len=%d result=%d\n", len, i);
152 return -1; 93 return -1;
153 } 94 }
154 d->cdtaip = cdtaic; 95 memcpy(d->cdtaipp, d->cdnonce + nonceoffset, 16);
155 if (debug) fprintf(stderr, "Decoded packet of %d bytes from %p to %p\n", len, enc, raw); 96 if (debug) fprintf(stderr, "Decoded packet of %d bytes from %p to %p\n", len, enc, raw);
156 return len; 97 return len;
157 } 98 }
158 99
159 static int init(struct qtsession* sess) { 100 static int init(struct qtsession* sess) {
185 } 126 }
186 crypto_box_curve25519xsalsa20poly1305_beforenm(d->cbefore, cpublickey, csecretkey); 127 crypto_box_curve25519xsalsa20poly1305_beforenm(d->cbefore, cpublickey, csecretkey);
187 128
188 memset(d->cenonce, 0, crypto_box_curve25519xsalsa20poly1305_NONCEBYTES); 129 memset(d->cenonce, 0, crypto_box_curve25519xsalsa20poly1305_NONCEBYTES);
189 memset(d->cdnonce, 0, crypto_box_curve25519xsalsa20poly1305_NONCEBYTES); 130 memset(d->cdnonce, 0, crypto_box_curve25519xsalsa20poly1305_NONCEBYTES);
131 memset(d->cdtaipp, 0, 16);
190 132
191 crypto_scalarmult_curve25519_base(cownpublickey, csecretkey); 133 crypto_scalarmult_curve25519_base(cownpublickey, csecretkey);
192 134
193 if (envval = getconf("TIME_WINDOW")) { 135 if (envval = getconf("TIME_WINDOW")) {
194 taia_now(&d->cdtaip); 136 taia_now_packed(d->cdtaipp, -atol(envval));
195 d->cdtaip.sec.x -= atol(envval);
196 } else { 137 } else {
197 fprintf(stderr, "Warning: TIME_WINDOW not set, risking an initial replay attack\n"); 138 fprintf(stderr, "Warning: TIME_WINDOW not set, risking an initial replay attack\n");
198 } 139 }
199 int role = memcmp(cownpublickey, cpublickey, crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES); 140 int role = memcmp(cownpublickey, cpublickey, crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES);
200 if (envval = getconf("ROLE")) role = atoi(envval) ? 1 : -1; 141 if (envval = getconf("ROLE")) role = atoi(envval) ? 1 : -1;