FD.io VPP  v20.05.1-6-gf53edbc3b
Vector Packet Processing
pot_util.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <vnet/vnet.h>
16 #include <stdint.h>
17 #include <time.h>
18 #include <string.h>
19 #include <vppinfra/mem.h>
20 #include "math64.h"
21 #include "pot_util.h"
22 
24 
25 static void pot_profile_cleanup(pot_profile *profile);
26 
27 static void pot_main_profiles_reset (void)
28 {
29  pot_main_t *sm = &pot_main;
30  int i = 0;
31 
32  for (i = 0; i < MAX_POT_PROFILES; i++)
33  {
35  }
36  sm->active_profile_id = 0;
37  if (sm->profile_list_name)
39  sm->profile_list_name = NULL;
40 }
41 
42 int pot_util_init (void)
43 {
45 
46  return(0);
47 }
48 
49 static void pot_profile_init(pot_profile * new, u8 id)
50 {
51  if (new)
52  {
53  clib_memset(new, 0, sizeof(pot_profile));
54  new->id = id;
55  }
56 }
57 
59 {
60  pot_main_t *sm = &pot_main;
61 
62  if (id < MAX_POT_PROFILES)
63  {
64  return (&(sm->profile_list[id]));
65  }
66  return (NULL);
67 }
68 static int pot_profile_name_equal (u8 *name0, u8 *name1)
69 {
70  int len0, len1;
71 
72  len0 = vec_len (name0);
73  len1 = vec_len (name1);
74  if (len0 != len1)
75  return(0);
76  return (0==strncmp ((char *) name0, (char *)name1, len0));
77 }
78 
80 {
81  pot_main_t *sm = &pot_main;
82  return (pot_profile_name_equal(sm->profile_list_name, name));
83 }
84 
85 void pot_profile_list_init(u8 * profile_list_name)
86 {
87  pot_main_t *sm = &pot_main;
88  int i = 0;
89 
90  /* If it is the same profile list skip reset */
91  if (pot_profile_name_equal(sm->profile_list_name, profile_list_name))
92  {
93  return;
94  }
95 
97  if (vec_len(profile_list_name))
98  sm->profile_list_name = (u8 *)vec_dup(profile_list_name);
99  else
100  sm->profile_list_name = 0;
101  sm->active_profile_id = 0;
102 
103  for (i = 0; i < MAX_POT_PROFILES; i++)
104  {
105  pot_profile_init(&(sm->profile_list[i]), i);
106  }
107 }
108 
109 static void pot_profile_cleanup(pot_profile * profile)
110 {
111  u16 id = profile->id;
112 
113  clib_memset(profile, 0, sizeof(pot_profile));
114  profile->id = id; /* Restore id alone */
115 }
116 
117 int pot_profile_create(pot_profile * profile, u64 prime,
118  u64 poly2, u64 lpc, u64 secret_share)
119 {
120  if (profile && !profile->in_use)
121  {
122  pot_profile_cleanup(profile);
123  profile->prime = prime;
124  profile->primeinv = 1.0 / prime;
125  profile->lpc = lpc;
126  profile->poly_pre_eval = poly2;
127  profile->secret_share = secret_share;
128  profile->total_pkts_using_this_profile = 0;
129  profile->valid = 1;
130  return(0);
131  }
132 
133  return(-1);
134 }
135 
137 {
138  if (profile && !profile->in_use)
139  {
140  profile->validator = 1;
141  profile->secret_key = key;
142  return(0);
143  }
144  return(-1);
145 }
146 
148  u64 secret_share, u64 prime, u64 lpc, u64 pre_split, double prime_inv)
149 {
150  u64 share_random = 0;
151  u64 cumulative_new = 0;
152 
153  /*
154  * calculate split share for random
155  */
156  share_random = add64_mod(pre_split, random, prime, prime_inv);
157 
158  /*
159  * lpc * (share_secret + share_random)
160  */
161  share_random = add64_mod(share_random, secret_share, prime, prime_inv);
162  share_random = mul64_mod(share_random, lpc, prime, prime_inv);
163 
164  cumulative_new = add64_mod(cumulative, share_random, prime, prime_inv);
165 
166  return (cumulative_new);
167 }
168 
169 u64 pot_update_cumulative(pot_profile * profile, u64 cumulative, u64 random)
170 {
171  if (profile && profile->valid != 0)
172  {
173  return (pot_update_cumulative_inline(cumulative, random, profile->secret_share,
174  profile->prime, profile->lpc, profile->poly_pre_eval,
175  profile->primeinv));
176  }
177  return (0);
178 }
179 
180 always_inline u8 pot_validate_inline(u64 secret, u64 prime, double prime_inv,
181  u64 cumulative, u64 random)
182 {
183  if (cumulative == (random + secret))
184  {
185  return (1);
186  }
187  else if (cumulative == add64_mod(random, secret, prime, prime_inv))
188  {
189  return (1);
190  }
191  return (0);
192 }
193 
194 /*
195  * return True if the cumulative matches secret from a profile
196  */
197 u8 pot_validate(pot_profile * profile, u64 cumulative, u64 random)
198 {
199  if (profile && profile->validator)
200  {
201  return (pot_validate_inline(profile->secret_key, profile->prime,
202  profile->primeinv, cumulative, random));
203  }
204  return (0);
205 }
206 
207 /*
208  * Utility function to get random number per pack
209  */
211 {
212  u64 random = 0;
213  int32_t second_half;
214  static u32 seed = 0;
215 
216  if (PREDICT_FALSE(!seed))
217  seed = random_default_seed();
218 
219  /*
220  * Upper 4 bytes seconds
221  */
222  random = (u64) time(NULL);
223 
224  random &= 0xffffffff;
225  random = random << 32;
226  /*
227  * Lower 4 bytes random number
228  */
229  second_half = random_u32(&seed);
230 
231  random |= second_half;
232 
233  if (PREDICT_TRUE(profile != NULL))
234  {
235  random &= profile->bit_mask;
236  }
237  return (random);
238 }
239 
241 {
242  int sizeInBits;
243 
244  if (profile && !profile->in_use)
245  {
246  sizeInBits = sizeof(profile->bit_mask) * 8;
247  profile->bit_mask =
248  (bits >=
249  sizeInBits ? (u64) - 1 : (u64) ((u64) 1 << (u64) bits) - 1);
250  return(0);
251  }
252  return(-1);
253 }
254 
256  unformat_input_t * input, vlib_cli_command_t * cmd)
257 {
258 
260 
261  return 0;
262 }
263 
265 {
267 }
268 
269 VLIB_CLI_COMMAND(clear_pot_profile_command) =
270 {
271 .path = "clear pot profile",
272 .short_help = "clear pot profile [<index>|all]",
273 .function = clear_pot_profile_command_fn,
274 };
275 
277  unformat_input_t * input, vlib_cli_command_t * cmd)
278 {
279  u64 prime;
280  u64 secret_share;
281  u64 secret_key;
282  u8 validator = 0;
283  u32 profile_id = ~0;
284  u32 bits;
285  u64 lpc = 0, poly2 = 0;
286  pot_profile *profile = NULL;
287  u8 *profile_list_name = NULL;
288 
289  bits = MAX_BITS;
290 
292  {
293  if (unformat(input, "name %s",
294  &profile_list_name));
295  else if (unformat(input, "id %d", &profile_id))
296  ;
297  else if (unformat(input, "validate-key 0x%Lx", &secret_key))
298  validator = 1;
299  else if (unformat(input, "prime-number 0x%Lx", &prime))
300  ;
301  else if (unformat(input, "secret_share 0x%Lx", &secret_share))
302  ;
303  else if (unformat(input, "polynomial2 0x%Lx", &poly2))
304  ;
305  else if (unformat(input, "lpc 0x%Lx", &lpc))
306  ;
307  else if (unformat(input, "bits-in-random %d", &bits))
308  {
309  if (bits > MAX_BITS)
310  bits = MAX_BITS;
311  }
312  else
313  break;
314  }
315  if (profile_list_name == 0)
316  {
317  return clib_error_return(0, "Name cannot be null");
318  }
319  pot_profile_list_init(profile_list_name);
320  profile = pot_profile_find(profile_id);
321 
322  if (profile)
323  {
324  pot_profile_create(profile, prime, poly2, lpc, secret_share);
325  if (validator)
326  pot_set_validator(profile, secret_key);
327  pot_profile_set_bit_mask(profile, bits);
328  }
329  vec_free(profile_list_name);
330  return 0;
331 }
332 
333 VLIB_CLI_COMMAND(set_pot_profile_command) =
334 {
335 .path = "set pot profile",
336 .short_help = "set pot profile name <string> id [0-1] [validator-key 0xu64] \
337  prime-number 0xu64 secret_share 0xu64 lpc 0xu64 \
338  polynomial2 0xu64 bits-in-random [0-64] ",
339 .function = set_pot_profile_command_fn,
340 };
341 
343  unformat_input_t * input, vlib_cli_command_t * cmd)
344 {
345  pot_main_t *sm = &pot_main;
346  u8 *profile_list_name = NULL;
347  u32 id = 0;
348  clib_error_t *result = NULL;
349 
351  {
352  if (unformat(input, "name %s",
353  &profile_list_name));
354  else if (unformat(input, "id %d", &id))
355  ;
356  else
357  return clib_error_return(0, "unknown input `%U'",
358  format_unformat_error, input);
359  }
360  if (profile_list_name == 0)
361  {
362  return clib_error_return(0, "Name cannot be null");
363  }
364 
365  if (!pot_profile_list_is_enabled(profile_list_name)) {
366  result = clib_error_return(0, "%s list is not enabled, profile in use %s",
367  profile_list_name, sm->profile_list_name);
368  } else if (0 != pot_profile_set_active((u8)id)) {
369  result = clib_error_return(0, "Profile %d not defined in %s",
370  id, sm->profile_list_name);
371  }
372  vec_free(profile_list_name);
373  return result;
374 }
375 
376 VLIB_CLI_COMMAND(set_pot_profile_activate_command) =
377 {
378 .path = "set pot profile-active",
379 .short_help = "set pot profile-active name <string> id [0-1]",
381 };
382 
384  unformat_input_t * input, vlib_cli_command_t * cmd)
385 {
386  pot_main_t *sm = &pot_main;
387  pot_profile *p = NULL;
388  u16 i;
389  u8 *s = 0;
390 
391  if (vec_len(sm->profile_list_name) == 0)
392  {
393  s = format(s, "POT Profiles not configured\n");
394  vlib_cli_output(vm, "%v", s);
395  return 0;
396  }
397  s = format(s, "Profile list in use : %s\n",sm->profile_list_name);
398  for (i = 0; i < MAX_POT_PROFILES; i++)
399  {
400  p = pot_profile_find(i);
401  if (p->valid == 0)
402  continue;
403  s = format(s, "POT Profile at index: %d\n", i);
404  s = format(s, " Id : %d\n", p->id);
405  s = format(s, " Validator : %s (%d)\n",
406  (p->validator) ? "True" : "False", p->validator);
407  if (p->validator == 1)
408  s = format(s, " Secret key : 0x%Lx (%Ld)\n",
409  p->secret_key, p->secret_key);
410  s = format(s, " Secret share : 0x%Lx (%Ld)\n",
411  p->secret_share, p->secret_share);
412  s = format(s, " Prime number : 0x%Lx (%Ld)\n",
413  p->prime, p->prime);
414  s = format(s, "2nd polynomial(eval) : 0x%Lx (%Ld)\n",
416  s = format(s, " LPC : 0x%Lx (%Ld)\n", p->lpc, p->lpc);
417 
418  s = format(s, " Bit mask : 0x%Lx (%Ld)\n",
419  p->bit_mask, p->bit_mask);
420  }
421 
423 
424  if (p && p->valid && p->in_use) {
425  s = format(s, "\nProfile index in use: %d\n", sm->active_profile_id);
426  s = format(s, "Pkts passed : 0x%Lx (%Ld)\n",
429  if (pot_is_decap(p))
430  s = format(s, " This is Decap node. \n");
431  } else {
432  s = format(s, "\nProfile index in use: None\n");
433  }
434  vlib_cli_output(vm, "%v", s);
435  vec_free(s);
436 
437  return 0;
438 }
439 
440 VLIB_CLI_COMMAND(show_pot_profile_command) =
441 {
442 .path = "show pot profile",
443 .short_help = "show pot profile",
444 .function = show_pot_profile_command_fn,
445 };
pot_main_t pot_main
Definition: pot_util.c:23
void clear_pot_profiles()
Definition: pot_util.c:264
static uword random_default_seed(void)
Default random seed (unix/linux user-mode)
Definition: random.h:91
pot_profile * pot_profile_find(u8 id)
Definition: pot_util.c:58
int pot_profile_create(pot_profile *profile, u64 prime, u64 poly2, u64 lpc, u64 secret_share)
Definition: pot_util.c:117
Optimized string handling code, including c11-compliant "safe C library" variants.
#define PREDICT_TRUE(x)
Definition: clib.h:119
unsigned long u64
Definition: types.h:89
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static clib_error_t * set_pot_profile_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: pot_util.c:276
static u64 mul64_mod(u64 a, u64 b, u64 p, double pi)
Definition: math64.h:151
static u64 add64_mod(u64 a, u64 b, u64 p, double pi)
Definition: math64.h:140
static void pot_main_profiles_reset(void)
Definition: pot_util.c:27
static clib_error_t * show_pot_profile_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: pot_util.c:383
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static u8 pot_validate_inline(u64 secret, u64 prime, double prime_inv, u64 cumulative, u64 random)
Definition: pot_util.c:180
u64 secret_share
Definition: pot_util.h:62
static int pot_profile_name_equal(u8 *name0, u8 *name1)
Definition: pot_util.c:68
#define MAX_BITS
Definition: pot_util.h:121
unsigned char u8
Definition: types.h:56
u8 id[64]
Definition: dhcp.api:160
static int pot_profile_set_active(u8 id)
Definition: pot_util.h:148
#define MAX_POT_PROFILES
Definition: pot_util.h:28
static clib_error_t * set_pot_profile_activate_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: pot_util.c:342
#define clib_error_return(e, args...)
Definition: error.h:99
double primeinv
Definition: pot_util.h:68
unsigned int u32
Definition: types.h:88
u64 poly_pre_eval
Definition: pot_util.h:65
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
static void pot_profile_cleanup(pot_profile *profile)
Definition: pot_util.c:109
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:427
u8 active_profile_id
Definition: pot_util.h:77
#define PREDICT_FALSE(x)
Definition: clib.h:118
#define always_inline
Definition: ipsec.h:28
u8 pot_validate(pot_profile *profile, u64 cumulative, u64 random)
Definition: pot_util.c:197
vlib_main_t * vm
Definition: in2out_ed.c:1599
static u64 pot_update_cumulative_inline(u64 cumulative, u64 random, u64 secret_share, u64 prime, u64 lpc, u64 pre_split, double prime_inv)
Definition: pot_util.c:147
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u64 total_pkts_using_this_profile
Definition: pot_util.h:69
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
u64 pot_generate_random(pot_profile *profile)
Definition: pot_util.c:210
Usage:
Definition: pot_util.h:54
string name[64]
Definition: ip.api:44
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
pot_profile profile_list[MAX_POT_PROFILES]
Definition: pot_util.h:75
u64 secret_key
Definition: pot_util.h:61
u8 * profile_list_name
Definition: pot_util.h:74
int pot_set_validator(pot_profile *profile, u64 key)
Definition: pot_util.c:136
int pot_util_init(void)
Definition: pot_util.c:42
typedef key
Definition: ipsec_types.api:85
static void pot_profile_init(pot_profile *new, u8 id)
Definition: pot_util.c:49
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
clib_error_t * clear_pot_profile_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: pot_util.c:255
u64 pot_update_cumulative(pot_profile *profile, u64 cumulative, u64 random)
Definition: pot_util.c:169
u8 validator
Definition: pot_util.h:60
void pot_profile_list_init(u8 *profile_list_name)
Definition: pot_util.c:85
int pot_profile_list_is_enabled(u8 *name)
Definition: pot_util.c:79
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static u8 pot_is_decap(pot_profile *p)
Definition: pot_util.h:143
u64 bit_mask
Definition: pot_util.h:66
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
int pot_profile_set_bit_mask(pot_profile *profile, u16 bits)
Definition: pot_util.c:240