source: tools/traceanon/Anon.cc @ 823d8e1

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformance
Last change on this file since 823d8e1 was cb075c5, checked in by Shane Alcock <salcock@…>, 5 years ago

Fix bug where traceanon would not build with newer versions
of libssl (>= 1.1.0).

  • Property mode set to 100644
File size: 8.5 KB
Line 
1/*
2 *
3 * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand.
4 * All rights reserved.
5 *
6 * This file is part of libtrace.
7 *
8 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/
10 *
11 * libtrace is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * libtrace is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 *
25 */
26
27
28#include "config.h"
29#include <stdlib.h>
30#include <string.h>
31#include <stdio.h>
32#include <assert.h>
33#include <arpa/inet.h>
34#include "Anon.h"
35
36
37static uint32_t masks[33] = {
38                0x00000000, 0x80000000, 0xC0000000, 0xe0000000, 0xf0000000,
39                0xf8000000, 0xfC000000, 0xfe000000, 0xff000000, 0xff800000,
40                0xffC00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffC0000,
41                0xfffe0000, 0xffff0000, 0xffff8000, 0xffffC000, 0xffffe000,
42                0xfffff000, 0xfffff800, 0xfffffC00, 0xfffffe00, 0xffffff00,
43                0xffffff80, 0xffffffC0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
44                0xfffffffC, 0xfffffffe, 0xffffffff,
45};
46
47
48Anonymiser::Anonymiser () {
49    /* empty constructor */
50}
51
52PrefixSub::PrefixSub(const char *ipv4_key, const char *ipv6_key) : Anonymiser() {
53    this->ipv4_mask = 0;
54    this->ipv4_prefix = 0;
55
56    memset(this->ipv6_mask, 0, 16);
57    memset(this->ipv6_prefix, 0, 16);
58
59    if (ipv4_key != NULL) {
60        int a,b,c,d;
61        int bits;
62
63        if (sscanf(ipv4_key, "%i.%i.%i.%i/%i", &a, &b, &c, &d, &bits) != 5) {
64            fprintf(stderr, "Invalid IPv4 prefix: %s\n", ipv4_key);
65
66        } else {
67            this->ipv4_prefix = (a<<24) + (b<<16) + (c<<8) + d;
68            if (bits < 0 || bits > 32) {
69                fprintf(stderr, "Invalid IPv4 prefix: %s\n", ipv4_key);
70            } else {
71                this->ipv4_mask = masks[bits];
72            }
73        }
74    }
75
76    /* TODO IPv6 */
77
78
79}
80
81PrefixSub::~PrefixSub() {
82
83}
84
85uint32_t PrefixSub::anonIPv4(uint32_t orig) {
86
87    return (this->ipv4_prefix & this->ipv4_mask) | (orig & ~this->ipv4_mask);
88
89}
90
91void PrefixSub::anonIPv6(uint8_t *orig, uint8_t *result) {
92
93    /* TODO */
94    memcpy(result, orig, 16);
95
96}
97
98#ifdef HAVE_LIBCRYPTO
99#include <openssl/evp.h>
100
101CryptoAnon::CryptoAnon(uint8_t *key, uint8_t len, uint8_t cachebits) :
102        Anonymiser() {
103
104    assert(len >= 32);
105    memcpy(this->key, key, 16);
106    memcpy(this->padding, key + 16, 16);
107
108    this->cipher = EVP_aes_128_ecb();
109    this->ctx = EVP_CIPHER_CTX_new();
110    EVP_CIPHER_CTX_init(this->ctx);
111
112    EVP_EncryptInit_ex(this->ctx, this->cipher, NULL, this->key, NULL);
113
114    this->cachebits = cachebits;
115
116    this->ipv4_cache = new IPv4AnonCache();
117    this->ipv6_cache = new IPv6AnonCache();
118    this->recent_ipv4_cache[0][0] = 0;
119    this->recent_ipv4_cache[0][1] = 0;
120    this->recent_ipv4_cache[1][0] = 0;
121    this->recent_ipv4_cache[0][1] = 0;
122
123}
124
125
126CryptoAnon::~CryptoAnon() {
127    delete(this->ipv4_cache);
128    EVP_CIPHER_CTX_cleanup(this->ctx);
129    EVP_CIPHER_CTX_free(this->ctx);
130}
131
132static inline uint32_t generateFirstPad(uint8_t *pad) {
133    uint32_t fp = 0;
134
135    fp = (((uint32_t)pad[0]) << 24) + (((uint32_t)pad[1]) << 16) +
136            (((uint32_t)pad[2]) << 8) + (uint32_t)pad[3];
137    return fp;
138
139}
140
141uint32_t CryptoAnon::anonIPv4(uint32_t orig) {
142    uint32_t cacheprefix =
143            (orig >> (32 - this->cachebits)) << (32 - this->cachebits);
144    uint32_t result = 0;
145
146    if (this->recent_ipv4_cache[0][0] == orig)
147        return this->recent_ipv4_cache[0][1];
148    else if (this->recent_ipv4_cache[1][0] == orig) {
149        uint32_t tmp = this->recent_ipv4_cache[1][1];
150        this->recent_ipv4_cache[1][0] = this->recent_ipv4_cache[0][0];
151        this->recent_ipv4_cache[1][1] = this->recent_ipv4_cache[0][1];
152        this->recent_ipv4_cache[0][0] = orig;
153        this->recent_ipv4_cache[0][1] = tmp;
154        return tmp;
155
156    }
157
158    result = this->lookupv4Cache(cacheprefix);
159    result = this->encrypt32Bits(orig, this->cachebits, 32, result);
160
161    this->recent_ipv4_cache[1][0] = this->recent_ipv4_cache[0][0];
162    this->recent_ipv4_cache[1][1] = this->recent_ipv4_cache[0][1];
163    this->recent_ipv4_cache[0][0] = orig;
164    this->recent_ipv4_cache[0][1] = result ^ orig;
165
166    return this->recent_ipv4_cache[0][1];
167}
168
169static uint64_t swap64(uint64_t num) {
170    uint32_t swapa, swapb;
171    uint64_t res;
172
173    swapa = (num & 0xffffffff);
174    swapb = (num >> 32);
175    swapa = ntohl(swapa);
176    swapb = ntohl(swapb);
177    res =(uint64_t)swapa << 32 | (swapb);
178    return res;
179}
180
181void CryptoAnon::anonIPv6(uint8_t *orig, uint8_t *result) {
182
183    uint64_t prefix, anonprefixmap;
184    uint64_t suffix, anonsuffixmap;
185
186    memcpy(&prefix, orig, 8);
187    memcpy(&suffix, orig + 8, 8);
188
189    prefix = swap64(prefix);
190    suffix = swap64(suffix);
191
192    anonprefixmap = this->lookupv6Cache(prefix);
193    anonsuffixmap = this->lookupv6Cache(suffix);
194
195    prefix = (swap64(anonprefixmap ^ prefix));
196    suffix = (swap64(anonsuffixmap ^ suffix));
197
198    memcpy(result, &prefix, sizeof(uint64_t));
199    memcpy(result + sizeof(uint64_t), &suffix, sizeof(uint64_t));
200
201}
202
203uint32_t CryptoAnon::lookupv4Cache(uint32_t prefix) {
204
205    IPv4AnonCache::iterator it = this->ipv4_cache->find(prefix);
206
207    if (it == this->ipv4_cache->end()) {
208        uint32_t prefmask = this->encrypt32Bits(prefix, 0, this->cachebits, 0);
209        (*this->ipv4_cache)[prefix] = prefmask;
210        return prefmask;
211    }
212    return it->second;
213
214}
215
216uint64_t CryptoAnon::lookupv6Cache(uint64_t prefix) {
217    IPv6AnonCache::iterator it = this->ipv6_cache->find(prefix);
218
219    if (it == this->ipv6_cache->end()) {
220        uint64_t prefmask = this->encrypt64Bits(prefix);
221        (*this->ipv6_cache)[prefix] = prefmask;
222        return prefmask;
223    }
224    return it->second;
225}
226
227uint32_t CryptoAnon::encrypt32Bits(uint32_t orig, uint8_t start, uint8_t stop, 
228        uint32_t res) {
229    uint8_t rin_output[32];
230    uint8_t rin_input[16];
231    uint32_t first4pad;
232    int outl = 32;
233
234    memcpy(rin_input, this->padding, 16);
235    first4pad = generateFirstPad(this->padding);
236
237    for (int pos = start; pos < stop; pos ++) {
238        uint32_t input;
239
240        /* The MS bits are taken from the original address. The remaining
241         * bits are taken from padding. first4pad is used to help ensure we
242         * use the right bits from padding when pos < 32.
243         */
244        if (pos == 0) {
245            input = first4pad;
246        } else {
247            input = ((orig >> (32 - pos)) << (32 - pos)) |
248                    ((first4pad << pos) >> pos);
249        }
250
251        rin_input[0] = (uint8_t) (input >> 24);
252        rin_input[1] = (uint8_t) ((input << 8) >> 24);
253        rin_input[2] = (uint8_t) ((input << 16) >> 24);
254        rin_input[3] = (uint8_t) ((input << 24) >> 24);
255
256        /* Encryption: we're using AES as a pseudorandom function. For each
257         * bit in the original address, we use the first bit of the resulting
258         * encrypted output as part of an XOR mask */
259        EVP_EncryptUpdate(this->ctx, (unsigned char *)rin_output, &outl, 
260                (unsigned char *)rin_input, 16);
261
262        /* Put the first bit of the output into the right slot of our mask */
263        res |= (((uint32_t)rin_output[0]) >> 7) << (31 - pos);
264
265    }
266    return res;
267
268}
269
270uint64_t CryptoAnon::encrypt64Bits(uint64_t orig) {
271
272    /* See encrypt32Bits for more explanation of how this works */
273    uint8_t rin_output[32];
274    uint8_t rin_input[16];
275    uint64_t first8pad;
276    int outl = 32;
277    uint64_t result = 0;
278
279    memcpy(rin_input, this->padding, 16);
280    memcpy(&first8pad, this->padding, 8);
281
282    for (int pos = 0; pos < 64; pos ++) {
283        uint64_t input;
284
285        if (pos == 0) {
286            input = first8pad;
287        } else {
288            input = ((orig >> (64 - pos)) << (64 - pos)) |
289                    ((first8pad << pos) >> pos);
290        }
291
292        memcpy(rin_input, &input, 8);
293
294        EVP_EncryptUpdate(this->ctx, (unsigned char *)rin_output, &outl,
295                (unsigned char *)rin_input, 16);
296
297        result |= ((((uint64_t)rin_output[0]) >> 7) << (63 - pos));
298    }
299
300    return result;
301}
302
303#endif
304
305// vim: set sw=4 tabstop=4 softtabstop=4 expandtab :
Note: See TracBrowser for help on using the repository browser.