1 /*
2 version 20130522
3 Jan Mojzis
4 Public domain.
5 */
6
7 #include "nanoseconds.h"
8 #include "randombytes.h"
9 #include "uint32_pack.h"
10 #include "uint32_unpack.h"
11 #include "crypto_uint64.h"
12 #include "byte.h"
13 #include "purge.h"
14 #include "dns.h"
15
16 #define NSS 1 /* nonce separation space, 1 - 3 bytes */
17
18 static unsigned char noncekey[16] = {0};
19 static crypto_uint64 noncecounter = 0;
20 static unsigned char noncemask[NSS];
21 static unsigned char noncedata[NSS];
22
dns_nonce_purge(void)23 void dns_nonce_purge(void) {
24 purge(noncekey, sizeof noncekey);
25 }
26
dns_nonce_init(const char * ns,const unsigned char * nk)27 int dns_nonce_init(const char *ns, const unsigned char *nk) {
28
29 long long i;
30
31 noncecounter = nanoseconds();
32
33 for (i = 0; i < NSS; ++i) noncemask[i] = 0xff;
34 for (i = 0; i < NSS; ++i) noncedata[i] = 0x00;
35
36 if (!ns) ns = "";
37 i = 0;
38 while (i < 8 * NSS) {
39 if (ns[i] != '0' && ns[i] != '1') break;
40 noncemask[i/8] = noncemask[i/8] * 2;
41 noncedata[i/8] = noncedata[i/8] * 2 + ns[i] - '0';
42 ++i;
43 }
44
45 if (ns[i] == '0' || ns[i] == '1') return 0;
46
47 while (i < 8 * NSS) {
48 noncemask[i/8] = noncemask[i/8] * 2 + 1;
49 noncedata[i/8] = noncedata[i/8] * 2;
50 ++i;
51 }
52
53 if (nk) byte_copy(noncekey, sizeof noncekey, nk);
54 else randombytes(noncekey, sizeof noncekey);
55 return 1;
56 }
57
dns_nonce_encrypt(unsigned char * out,crypto_uint64 in,const unsigned char * k)58 static void dns_nonce_encrypt(unsigned char *out, crypto_uint64 in, const unsigned char *k) {
59
60 long long i;
61
62 crypto_uint32 v0, v1, k0, k1, k2, k3;
63 crypto_uint32 sum = 0;
64 crypto_uint32 delta = 0x9e3779b9;
65
66 v0 = in; in >>= 32;
67 v1 = in;
68 k0 = uint32_unpack(k + 0);
69 k1 = uint32_unpack(k + 4);
70 k2 = uint32_unpack(k + 8);
71 k3 = uint32_unpack(k + 12);
72
73 for (i = 0; i < 32; i++) {
74 sum += delta;
75 v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
76 v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
77 }
78 uint32_pack(out + 0, v0);
79 uint32_pack(out + 4, v1);
80 }
81
82 /*
83 n is 12-byte nonce with the following structure:
84 n[0...NSS-1]: random or nonce-separation bits
85 n[NSS...4]: random
86 n[4...11]: TEA encrypted counter
87 */
88
dns_nonce(unsigned char * n)89 void dns_nonce(unsigned char *n) {
90
91 long long x;
92
93 if (!noncecounter) dns_nonce_init(0, 0);
94
95 x = nanoseconds();
96 if (x > noncecounter) noncecounter = x;
97
98 randombytes(n, 4);
99 for(x = 0; x < NSS; ++x) {
100 n[x] &= noncemask[x];
101 n[x] += noncedata[x];
102 }
103
104 dns_nonce_encrypt((n + 4), ++noncecounter, noncekey);
105 }
106