LCOV - code coverage report
Current view: top level - plugins/ioam/lib-pot - pot_util.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 21 201 10.4 %
Date: 2023-10-26 01:39:38 Functions: 11 29 37.9 %

          Line data    Source code
       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             : 
      23             : pot_main_t pot_main;
      24             : 
      25             : static void pot_profile_cleanup(pot_profile *profile);
      26             : 
      27         575 : static void pot_main_profiles_reset (void)
      28             : {
      29         575 :     pot_main_t *sm = &pot_main;
      30         575 :     int i = 0;
      31             : 
      32        1725 :     for (i = 0; i < MAX_POT_PROFILES; i++)
      33             :     {
      34        1150 :       pot_profile_cleanup(&(sm->profile_list[i]));
      35             :     }
      36         575 :     sm->active_profile_id = 0;
      37         575 :     if (sm->profile_list_name)
      38           0 :         vec_free(sm->profile_list_name);
      39         575 :     sm->profile_list_name = NULL;
      40         575 : }
      41             : 
      42         575 : int pot_util_init (void)
      43             : {
      44         575 :     pot_main_profiles_reset();
      45             :     
      46         575 :     return(0);
      47             : }
      48             : 
      49           0 : static void pot_profile_init(pot_profile * new, u8 id)
      50             : {
      51           0 :     if (new)
      52             :     {
      53           0 :         clib_memset(new, 0, sizeof(pot_profile));
      54           0 :         new->id = id;
      55             :     }
      56           0 : }
      57             : 
      58           0 : pot_profile *pot_profile_find(u8 id)
      59             : {
      60           0 :     pot_main_t *sm = &pot_main;
      61             : 
      62           0 :     if (id < MAX_POT_PROFILES)
      63             :     {
      64           0 :         return (&(sm->profile_list[id]));
      65             :     }
      66           0 :     return (NULL);
      67             : }
      68           0 : static int pot_profile_name_equal (u8 *name0, u8 *name1)
      69             : {
      70             :     int len0, len1;
      71             : 
      72           0 :     len0 = vec_len (name0);
      73           0 :     len1 = vec_len (name1);
      74           0 :     if (len0 != len1)
      75           0 :         return(0);
      76           0 :     return (0==strncmp ((char *) name0, (char *)name1, len0));
      77             : }
      78             : 
      79           0 : int pot_profile_list_is_enabled (u8 *name)
      80             : {
      81           0 :     pot_main_t *sm = &pot_main;
      82           0 :     return (pot_profile_name_equal(sm->profile_list_name, name));
      83             : }
      84             : 
      85           0 : void pot_profile_list_init(u8 * profile_list_name)
      86             : {
      87           0 :     pot_main_t *sm = &pot_main;
      88           0 :     int i = 0;
      89             : 
      90             :     /* If it is the same profile list skip reset */
      91           0 :     if (pot_profile_name_equal(sm->profile_list_name, profile_list_name))
      92             :     {
      93           0 :       return;
      94             :     }
      95             : 
      96           0 :     pot_main_profiles_reset();
      97           0 :     if (vec_len(profile_list_name))
      98           0 :       sm->profile_list_name = (u8 *)vec_dup(profile_list_name);
      99             :     else
     100           0 :       sm->profile_list_name = 0;
     101           0 :     sm->active_profile_id = 0;
     102             :     
     103           0 :     for (i = 0; i < MAX_POT_PROFILES; i++)
     104             :     {
     105           0 :       pot_profile_init(&(sm->profile_list[i]), i);
     106             :     }
     107             : }
     108             : 
     109        1150 : static void pot_profile_cleanup(pot_profile * profile)
     110             : {
     111        1150 :     u16 id = profile->id;
     112             : 
     113        1150 :     clib_memset(profile, 0, sizeof(pot_profile));
     114        1150 :     profile->id = id;           /* Restore id alone */
     115        1150 : }
     116             : 
     117           0 : int pot_profile_create(pot_profile * profile, u64 prime,
     118             :     u64 poly2, u64 lpc, u64 secret_share)
     119             : {
     120           0 :     if (profile && !profile->in_use)
     121             :     {
     122           0 :         pot_profile_cleanup(profile);
     123           0 :         profile->prime = prime;
     124           0 :         profile->primeinv = 1.0 / prime;
     125           0 :         profile->lpc = lpc;
     126           0 :         profile->poly_pre_eval = poly2;
     127           0 :         profile->secret_share = secret_share;
     128           0 :         profile->total_pkts_using_this_profile = 0;
     129           0 :         profile->valid = 1;
     130           0 :         return(0);
     131             :     }
     132             :     
     133           0 :     return(-1);
     134             : }
     135             : 
     136           0 : int pot_set_validator(pot_profile * profile, u64 key)
     137             : {
     138           0 :     if (profile && !profile->in_use)
     139             :     {
     140           0 :         profile->validator = 1;
     141           0 :         profile->secret_key = key;
     142           0 :         return(0);
     143             :     }
     144           0 :     return(-1);
     145             : }
     146             : 
     147           0 : always_inline u64 pot_update_cumulative_inline(u64 cumulative, u64 random,
     148             :     u64 secret_share, u64 prime, u64 lpc, u64 pre_split, double prime_inv)
     149             : {
     150           0 :     u64 share_random = 0;
     151           0 :     u64 cumulative_new = 0;
     152             : 
     153             :     /* 
     154             :      * calculate split share for random
     155             :      */
     156           0 :     share_random = add64_mod(pre_split, random, prime, prime_inv);
     157             : 
     158             :     /* 
     159             :      * lpc * (share_secret + share_random)
     160             :      */
     161           0 :     share_random = add64_mod(share_random, secret_share, prime, prime_inv);
     162           0 :     share_random = mul64_mod(share_random, lpc, prime, prime_inv);
     163             : 
     164           0 :     cumulative_new = add64_mod(cumulative, share_random, prime, prime_inv);
     165             : 
     166           0 :     return (cumulative_new);
     167             : }
     168             : 
     169           0 : u64 pot_update_cumulative(pot_profile * profile, u64 cumulative, u64 random)
     170             : {
     171           0 :     if (profile && profile->valid != 0)
     172             :     {
     173           0 :         return (pot_update_cumulative_inline(cumulative, random, profile->secret_share,
     174             :                 profile->prime, profile->lpc, profile->poly_pre_eval,
     175             :                 profile->primeinv));
     176             :     }
     177           0 :     return (0);
     178             : }
     179             : 
     180           0 : always_inline u8 pot_validate_inline(u64 secret, u64 prime, double prime_inv,
     181             :     u64 cumulative, u64 random)
     182             : {
     183           0 :     if (cumulative == (random + secret))
     184             :     {
     185           0 :         return (1);
     186             :     }
     187           0 :     else if (cumulative == add64_mod(random, secret, prime, prime_inv))
     188             :     {
     189           0 :         return (1);
     190             :     }
     191           0 :     return (0);
     192             : }
     193             : 
     194             : /* 
     195             :  * return True if the cumulative matches secret from a profile
     196             :  */
     197           0 : u8 pot_validate(pot_profile * profile, u64 cumulative, u64 random)
     198             : {
     199           0 :     if (profile && profile->validator)
     200             :     {
     201           0 :         return (pot_validate_inline(profile->secret_key, profile->prime,
     202             :                 profile->primeinv, cumulative, random));
     203             :     }
     204           0 :     return (0);
     205             : }
     206             : 
     207             : /* 
     208             :  * Utility function to get random number per pack
     209             :  */
     210           0 : u64 pot_generate_random(pot_profile * profile)
     211             : {
     212           0 :     u64 random = 0;
     213             :     int32_t second_half;
     214             :     static u32 seed = 0;
     215             : 
     216           0 :     if (PREDICT_FALSE(!seed))
     217           0 :         seed = random_default_seed();
     218             : 
     219             :     /* 
     220             :      * Upper 4 bytes seconds
     221             :      */
     222           0 :     random = (u64) time(NULL);
     223             : 
     224           0 :     random &= 0xffffffff;
     225           0 :     random = random << 32;
     226             :     /* 
     227             :      * Lower 4 bytes random number
     228             :      */
     229           0 :     second_half = random_u32(&seed);
     230             : 
     231           0 :     random |= second_half;
     232             : 
     233           0 :     if (PREDICT_TRUE(profile != NULL))
     234             :     {
     235           0 :         random &= profile->bit_mask;
     236             :     }
     237           0 :     return (random);
     238             : }
     239             : 
     240           0 : int pot_profile_set_bit_mask(pot_profile * profile, u16 bits)
     241             : {
     242             :     int sizeInBits;
     243             : 
     244           0 :     if (profile && !profile->in_use)
     245             :     {
     246           0 :         sizeInBits = sizeof(profile->bit_mask) * 8;
     247           0 :         profile->bit_mask =
     248           0 :             (bits >=
     249           0 :             sizeInBits ? (u64) - 1 : (u64) ((u64) 1 << (u64) bits) - 1);
     250           0 :         return(0);
     251             :     }
     252           0 :     return(-1);
     253             : }
     254             : 
     255           0 : clib_error_t *clear_pot_profile_command_fn(vlib_main_t * vm,
     256             :     unformat_input_t * input, vlib_cli_command_t * cmd)
     257             : {
     258             : 
     259           0 :     pot_main_profiles_reset();
     260             :     
     261           0 :     return 0;
     262             : }
     263             : 
     264           0 : void clear_pot_profiles()
     265             : {
     266           0 :     clear_pot_profile_command_fn(0, 0, 0);
     267           0 : }
     268             : 
     269      186217 : 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             : 
     276           0 : static clib_error_t *set_pot_profile_command_fn(vlib_main_t * vm,
     277             :     unformat_input_t * input, vlib_cli_command_t * cmd)
     278             : {
     279             :     u64 prime;
     280             :     u64 secret_share;
     281             :     u64 secret_key;
     282           0 :     u8 validator = 0;
     283           0 :     u32 profile_id = ~0;
     284             :     u32 bits;
     285           0 :     u64 lpc = 0, poly2 = 0;
     286           0 :     pot_profile *profile = NULL;
     287           0 :     u8 *profile_list_name = NULL;
     288             :     
     289           0 :     bits = MAX_BITS;
     290             : 
     291           0 :     while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
     292             :     {
     293           0 :         if (unformat(input, "name %s",
     294             :                      &profile_list_name));
     295           0 :         else if (unformat(input, "id %d", &profile_id))
     296             :             ;
     297           0 :         else if (unformat(input, "validate-key 0x%Lx", &secret_key))
     298           0 :             validator = 1;
     299           0 :         else if (unformat(input, "prime-number 0x%Lx", &prime))
     300             :             ;
     301           0 :         else if (unformat(input, "secret_share 0x%Lx", &secret_share))
     302             :             ;
     303           0 :         else if (unformat(input, "polynomial2 0x%Lx", &poly2))
     304             :             ;
     305           0 :         else if (unformat(input, "lpc 0x%Lx", &lpc))
     306             :             ;
     307           0 :         else if (unformat(input, "bits-in-random %d", &bits))
     308             :         {
     309           0 :             if (bits > MAX_BITS)
     310           0 :                 bits = MAX_BITS;
     311             :         }
     312             :         else
     313           0 :           break;
     314             :     }
     315           0 :     if (profile_list_name == 0)
     316             :     {
     317           0 :         return clib_error_return(0, "Name cannot be null");
     318             :     }   
     319           0 :     pot_profile_list_init(profile_list_name);
     320           0 :     profile = pot_profile_find(profile_id);
     321             : 
     322           0 :     if (profile)
     323             :     {
     324           0 :         pot_profile_create(profile, prime, poly2, lpc, secret_share);
     325           0 :         if (validator)
     326           0 :             pot_set_validator(profile, secret_key);
     327           0 :         pot_profile_set_bit_mask(profile, bits);
     328             :     }
     329           0 :     vec_free(profile_list_name);
     330           0 :     return 0;
     331             : }
     332             : 
     333      186217 : 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             : 
     342           0 : static clib_error_t *set_pot_profile_activate_command_fn(vlib_main_t * vm,
     343             :     unformat_input_t * input, vlib_cli_command_t * cmd)
     344             : {
     345           0 :     pot_main_t *sm = &pot_main;
     346           0 :     u8 *profile_list_name = NULL;
     347           0 :     u32 id = 0;
     348           0 :     clib_error_t *result = NULL;
     349             :     
     350           0 :     while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
     351             :     {
     352           0 :         if (unformat(input, "name %s",
     353             :                      &profile_list_name));
     354           0 :         else if (unformat(input, "id %d", &id))
     355             :             ;
     356             :         else
     357           0 :             return clib_error_return(0, "unknown input `%U'",
     358             :                 format_unformat_error, input);
     359             :     }
     360           0 :     if (profile_list_name == 0)
     361             :     {
     362           0 :         return clib_error_return(0, "Name cannot be null");
     363             :     }
     364             : 
     365           0 :     if (!pot_profile_list_is_enabled(profile_list_name)) {
     366           0 :         result = clib_error_return(0, "%s list is not enabled, profile in use %s",
     367             :                                  profile_list_name, sm->profile_list_name);
     368           0 :     } else if (0 != pot_profile_set_active((u8)id)) {
     369           0 :         result = clib_error_return(0, "Profile %d not defined in %s",
     370             :                                  id, sm->profile_list_name);
     371             :     }
     372           0 :     vec_free(profile_list_name);
     373           0 :     return result;
     374             : }
     375             : 
     376      186217 : 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]",
     380             : .function = set_pot_profile_activate_command_fn,
     381             : };
     382             : 
     383           0 : static clib_error_t *show_pot_profile_command_fn(vlib_main_t * vm,
     384             :     unformat_input_t * input, vlib_cli_command_t * cmd)
     385             : {
     386           0 :     pot_main_t *sm = &pot_main;
     387           0 :     pot_profile *p = NULL;
     388             :     u16 i;
     389           0 :     u8 *s = 0;
     390             : 
     391           0 :     if (vec_len(sm->profile_list_name) == 0)
     392             :     {
     393           0 :         s = format(s, "POT Profiles not configured\n");
     394           0 :         vlib_cli_output(vm, "%v", s);
     395           0 :         return 0;
     396             :     }
     397           0 :     s = format(s, "Profile list in use  : %s\n",sm->profile_list_name);
     398           0 :     for (i = 0; i < MAX_POT_PROFILES; i++)
     399             :     {
     400           0 :         p = pot_profile_find(i);
     401           0 :         if (p->valid == 0)
     402           0 :             continue;
     403           0 :         s = format(s, "POT Profile at index: %d\n", i);
     404           0 :         s = format(s, "                 Id : %d\n", p->id);
     405           0 :         s = format(s, "          Validator : %s (%d)\n",
     406           0 :             (p->validator) ? "True" : "False", p->validator);
     407           0 :         if (p->validator == 1)
     408           0 :             s = format(s, "         Secret key : 0x%Lx (%Ld)\n",
     409             :                 p->secret_key, p->secret_key);
     410           0 :         s = format(s, "       Secret share : 0x%Lx (%Ld)\n",
     411             :             p->secret_share, p->secret_share);
     412           0 :         s = format(s, "       Prime number : 0x%Lx (%Ld)\n",
     413             :             p->prime, p->prime);
     414           0 :         s = format(s, "2nd polynomial(eval) : 0x%Lx (%Ld)\n",
     415             :             p->poly_pre_eval, p->poly_pre_eval);
     416           0 :         s = format(s, "                 LPC : 0x%Lx (%Ld)\n", p->lpc, p->lpc);
     417             : 
     418           0 :         s = format(s, "           Bit mask : 0x%Lx (%Ld)\n",
     419             :             p->bit_mask, p->bit_mask);
     420             :     }
     421             : 
     422           0 :     p = pot_profile_find(sm->active_profile_id);
     423             : 
     424           0 :     if (p && p->valid && p->in_use) {
     425           0 :         s = format(s, "\nProfile index in use: %d\n", sm->active_profile_id);
     426           0 :         s = format(s, "Pkts passed : 0x%Lx (%Ld)\n",
     427             :                    p->total_pkts_using_this_profile,
     428             :                    p->total_pkts_using_this_profile);
     429           0 :         if (pot_is_decap(p))
     430           0 :             s = format(s, "  This is Decap node.  \n");
     431             :     } else {
     432           0 :         s = format(s, "\nProfile index in use: None\n");
     433             :     }
     434           0 :     vlib_cli_output(vm, "%v", s);
     435           0 :     vec_free(s);
     436             : 
     437           0 :     return 0;
     438             : }
     439             : 
     440      186217 : 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             : };

Generated by: LCOV version 1.14