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