summaryrefslogtreecommitdiffstats
path: root/src/sbefw/core/securityAlgo.C
blob: 1cdc819820b294a2e21dce7a4f66516f219c95f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/sbefw/core/securityAlgo.C $                               */
/*                                                                        */
/* OpenPOWER sbe Project                                                  */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2019                             */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include "securityAlgo.H"
#include <stddef.h>
#ifndef __PPE__
    #include <string.h>
static bool isSecurityListInitDone = false;
#endif

// Helper function to figure out the number of shifts required for the mask
constexpr uint32_t get_shift_len(uint32_t mask, uint8_t shifts = 0)
{
    return ((mask>>shifts) & 0x01) ? (shifts) : (get_shift_len(mask, ++shifts));
}

template <typename Func>
map_t binary_search(
                    const uint32_t search_key,
                    range_t x_range,
                    Func get_element)
{
    map_t ret = {false, 0}; // found=false

    while((x_range.start <= x_range.end) &&
          (ret.key == false))
    {
        int32_t midpoint = (x_range.start + x_range.end) / 2;
        uint32_t ele = get_element(midpoint);
        if(search_key == ele)
        {
            ret.key = true;
            ret.value = midpoint;
        }
        else if(search_key < ele)
        {
            x_range.end = midpoint - 1;
        }
        else
        {
            x_range.start = midpoint + 1;
        }
    }
    return ret;
}

//----------------------------------------------------------------------------
//  @brief Public function used for init all white, black and grey list table
//  data, WhiteList/ BalckList Tables [T1, T2 and T3] and GreyList [T1]
//----------------------------------------------------------------------------
bool _is_present( const _t1_table_t &table1,
                           const _t2_table_t &table2,
                           const _t3_table_t &table3,
                           const uint32_t i_addr)
{
    for(size_t i = 0; i < table1.size; i++)
    {
        uint32_t search_key = (i_addr & table1.mask) >> get_shift_len(table1.mask);
        if((table1.table[i].key_start <= search_key) &&
           (table1.table[i].key_end >= search_key))
        {
            search_key = (i_addr & table2.mask) >> get_shift_len(table2.mask);
            range_t search_range = {};
            search_range.start = i ? table1.table[i-1].value : 0;
            search_range.end = table1.table[i].value - 1;
            map_t search_result =
                binary_search(
                        search_key,
                        search_range,
                        [&table2](int32_t midpoint) -> uint32_t {
                            return table2.table[midpoint].key;
                        });
            if(search_result.key == true)
            {
                // Found the key
                search_range.start = (search_result.value ?
                                table2.table[search_result.value-1].value : 0);
                search_range.end =
                                table2.table[search_result.value].value - 1;
                search_key = (i_addr & table3.mask) >>
                                               get_shift_len(table3.mask);
                search_result = binary_search(
                                            search_key,
                                            search_range,
                                            [&table3](int32_t midpoint) -> uint32_t {
                                                return table3.table[midpoint].value;
                                            });
                if(search_result.key == true)
                {
                    // Found the number
                    return true;
                }
            }
        }
    }
    return false;
}

//----------------------------------------------------------------------------
//  @brief Look up tables to find if the given address with mask is present
//  on GreyList Table [T1]
//----------------------------------------------------------------------------
bool _is_present(const _gl_t1_table_t &table1,
                 const uint32_t i_addr,
                 const uint64_t i_mask)
{
    bool ret = false;
    for(size_t i = 0; i < table1.size; i++)
    {
        // Not using mask in table for search
        if((table1.table[i].key ==  i_addr) &&
           (( i_mask & (~table1.table[i].value)) == 0 ))
        {
            ret = true;
            break;
        }
    }
    return ret;
}

//----------------------------------------------------------------------------
//  @brief Public function used for address verification for a given type of
//  access.
//----------------------------------------------------------------------------
bool isAccessAllowed(const uint32_t i_addr, uint64_t i_mask,
                     secAccessType i_type)
{
    bool ret = true;
#ifndef __PPE__
    if(!isSecurityListInitDone)
    {
        ret = false; // Table Init was not yet done
    }
    else if(i_type == WRITE_ACCESS)
    {
        ret = _is_present( secListTableSupport.wl_t1,
                           secListTableSupport.wl_t2,
                           secListTableSupport.wl_t3,
                           i_addr );
        if( (ret == false ) && (i_mask != 0xffffffffffffffffull ))
        {
            ret = _is_present( secListTableSupport.gl_t1,
                               i_addr, i_mask );
        }
    }
    else if(i_type == READ_ACCESS)
    {
        ret = !_is_present( secListTableSupport.bl_t1,
                            secListTableSupport.bl_t2,
                            secListTableSupport.bl_t3,
                            i_addr );
    }
#endif
    return ret;
}

//----------------------------------------------------------------------------
//  @brief Public function used for init all white, black and grey list table
//  data, WhiteList/ BalckList Tables [T1, T2 and T3] and GreyList [T1]
//----------------------------------------------------------------------------
bool securityAccessTablesInit(const void * i_buf )
{
    bool ret = false;
#ifndef __PPE__
    do
    {
        uint8_t * l_buf = reinterpret_cast<uint8_t*>(const_cast<void*>(i_buf));
        if(isSecurityListInitDone)
        {
            break; // Table Init was already done
        }
        // Read header
        sec_header_dump_t* l_table_sizes =
                      reinterpret_cast<sec_header_dump_t*>(l_buf);
        // Read and Update whitelist tables1
        size_t l_size = SEC_LIST_TABLE_HDR_SIZE;
        secListTableSupport.wl_t1.size = l_table_sizes->wl_t1_count;
        secListTableSupport.wl_t1.mask = WHITELIST_TABLE1_MASK;

        secListTableSupport.wl_t1.table = (_t1_t*) malloc((sizeof(_t1_t))*(l_table_sizes->wl_t1_count));
        memcpy( secListTableSupport.wl_t1.table, l_buf+SEC_LIST_TABLE_HDR_SIZE, (sizeof(_t1_t))*((l_table_sizes->wl_t1_count)) );

        // Read and Update whitelist tables2
        l_size += (sizeof (_t1_t))*(l_table_sizes->wl_t1_count) ;
        secListTableSupport.wl_t2.size = l_table_sizes->wl_t2_count;
        secListTableSupport.wl_t2.mask = WHITELIST_TABLE2_MASK;
        secListTableSupport.wl_t2.table = (_t2_t*)malloc((sizeof(_t2_t))*(l_table_sizes->wl_t2_count));
        memcpy( secListTableSupport.wl_t2.table, l_buf+l_size, (sizeof(_t2_t))*(l_table_sizes->wl_t2_count) );

        // Read and Update whitelist tables3
        l_size += (sizeof (_t2_t))*(l_table_sizes->wl_t2_count) ;
        secListTableSupport.wl_t3.size = l_table_sizes->wl_t3_count;
        secListTableSupport.wl_t3.mask = WHITELIST_TABLE3_MASK;
        secListTableSupport.wl_t3.table = (_t3_t*)malloc((sizeof(_t3_t))*(l_table_sizes->wl_t3_count));
        memcpy( secListTableSupport.wl_t3.table, l_buf+l_size, (sizeof(_t3_t))*(l_table_sizes->wl_t3_count) );

        // Read and Update blacklist tables1
        l_size += (sizeof (_t3_t))*(l_table_sizes->wl_t3_count) ;
        secListTableSupport.bl_t1.size = l_table_sizes->bl_t1_count;
        secListTableSupport.bl_t1.mask = BLACKLIST_TABLE1_MASK;
        secListTableSupport.bl_t1.table = (_t1_t*)malloc((sizeof(_t1_t))*(l_table_sizes->bl_t1_count));
        memcpy( secListTableSupport.bl_t1.table, l_buf+l_size,(sizeof(_t1_t))*(l_table_sizes->bl_t1_count) );

        // Read and Update blacklist tables2
        l_size += (sizeof (_t1_t))*(l_table_sizes->bl_t1_count) ;
        secListTableSupport.bl_t2.size = l_table_sizes->bl_t2_count;
        secListTableSupport.bl_t2.mask = BLACKLIST_TABLE2_MASK;
        secListTableSupport.bl_t2.table = (_t2_t*)malloc((sizeof(_t2_t))*(l_table_sizes->bl_t2_count));
        memcpy( secListTableSupport.bl_t2.table, l_buf+l_size,(sizeof(_t2_t))*(l_table_sizes->bl_t2_count) );

        // Read and Update blacklist tables3
        l_size += (sizeof (_t2_t))*(l_table_sizes->bl_t2_count) ;
        secListTableSupport.bl_t3.size = l_table_sizes->bl_t3_count;
        secListTableSupport.bl_t3.mask = BLACKLIST_TABLE3_MASK;
        secListTableSupport.bl_t3.table = (_t3_t*)malloc((sizeof(_t3_t))*(l_table_sizes->bl_t3_count));
        memcpy( secListTableSupport.bl_t3.table, l_buf+l_size,(sizeof(_t3_t))*(l_table_sizes->bl_t3_count) );

        // Read and Update greylist tables1
        l_size += (sizeof (_t3_t))*(l_table_sizes->bl_t3_count) ;
        secListTableSupport.gl_t1.size = l_table_sizes->gl_t1_count;
        secListTableSupport.gl_t1.mask = GREYLIST_TABLE1_MASK;
        secListTableSupport.gl_t1.table = (_gl_t1_t*)malloc((sizeof(_gl_t1_t))*(l_table_sizes->gl_t1_count));
        memcpy( secListTableSupport.gl_t1.table, l_buf+l_size,(sizeof(_gl_t1_t))*(l_table_sizes->gl_t1_count));

        isSecurityListInitDone = true;
        ret = true;
    }
    while(0);
#endif
    return ret;
}
OpenPOWER on IntegriCloud