blob: 195ac424252cd18c61526d6ee3d49ab92efcc4be [file] [log] [blame]
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
import re
from typing import Dict, List
from .lib import check_keys, check_str, check_list
CM_ASSETS = [
'KEY',
'ADDR',
'DATA_REG',
'CTRL_FLOW',
'CTRL',
'CONFIG',
'LFSR',
'CTR',
'FSM',
'MEM',
'CLK',
'RST',
'BUS',
'INTERSIG',
'MUX',
'CONSTANTS',
'STATE',
'TOKEN',
'LOGIC'
]
CM_TYPES = [
'MUBI',
'SPARSE',
'DIFF',
'REDUN',
'SHADOW',
'SCRAMBLE',
'INTEGRITY',
'CONSISTENCY',
'DIGEST',
'LC_GATED',
'BKGN_CHK',
'GLITCH_DETECT',
'SW_UNREADABLE',
'SCA',
'MASKING',
'LOCAL_ESC',
'GLOBAL_ESC'
]
class CounterMeasure:
"""Object holding details for one countermeasure within an IP block."""
def __init__(self, instance: str, asset: str, cm_type: str, desc: str):
self.instance = instance
self.asset = asset
self.cm_type = cm_type
self.desc = desc
@staticmethod
def from_raw(what: str, raw: object) -> 'CounterMeasure':
"""
Create a CounterMeasure object from a dict.
The 'raw' dict must have the keys 'name' and 'desc', where 'name' has
to follow the canonical countermeasure naming convention.
"""
rd = check_keys(raw, what, ['name', 'desc'], [])
name = check_str(rd['name'], f'name field of {what}')
desc = check_str(rd['desc'], f'desc field of {what}')
try:
# the format is [CM_INST_NAME].<CM_ASSET>.<CM_TYPE>
# i.e., the countermeasure instance name is optional.
fields = name.split('.')
if len(fields) == 3:
instance, asset, cm_type = fields
else:
asset, cm_type = fields
instance = ""
except ValueError:
raise ValueError(
f'Invalid format: {name} ({what}).')
if not re.fullmatch(r'^([a-zA-Z0-9_]*)', instance):
raise ValueError(
f'Invalid instance name: {instance} ({what}).')
if asset not in CM_ASSETS:
raise ValueError(
f'Invalid asset: {asset} ({what}).')
if cm_type not in CM_TYPES:
raise ValueError(
f'Invalid type: {cm_type} ({what}).')
return CounterMeasure(instance, asset, cm_type, desc)
@staticmethod
def from_raw_list(what: str,
raw: object) -> List['CounterMeasure']:
"""
Create a list of CounterMeasure objects from a list of dicts.
The dicts in 'raw' must have the keys 'name' and 'desc', where 'name'
has to follow the canonical countermeasure naming convention.
"""
ret = []
for idx, entry in enumerate(check_list(raw, what)):
entry_what = f'entry {idx} of {what}'
cm = CounterMeasure.from_raw(entry_what, entry)
ret.append(cm)
return ret
def _asdict(self) -> Dict[str, object]:
"""Returns a dict with 'name' and 'desc' fields"""
return {
'name': str(self),
'desc': self.desc
}
def __str__(self) -> str:
namestr = self.asset + '.' + self.cm_type
return self.instance + '.' + namestr if self.instance else namestr