Skip to content

Commit

Permalink
Merge branch 'netlist-modifier-wip' of https://github.com/emsec/hal i…
Browse files Browse the repository at this point in the history
…nto netlist-modifier-wip
  • Loading branch information
oleeng committed Jul 6, 2024
2 parents cb3d1aa + 9a8f102 commit f40e3a9
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ namespace hal
{
GuiExtensionNetlistModifier* m_gui_extension;

static bool replace_gate_in_netlist(Netlist* netlist, Gate* gate);
static std::string obfuscated_gate_name(int num_in, int num_out, int num_io=0);
bool modify_gatelibrary();
public:
std::string get_name() const override;
std::string get_version() const override;
Expand Down Expand Up @@ -42,4 +45,4 @@ namespace hal

void set_parameter(const std::vector<PluginParameter>& params) override;
};
} // namespace hal
} // namespace hal
138 changes: 128 additions & 10 deletions plugins/netlist_modifier/src/netlist_modifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "gui/gui_api/gui_api.h"
#include "hal_core/netlist/gate.h"
#include "hal_core/netlist/gate_library/gate_library_manager.h"
#include "hal_core/netlist/gate_library/gate_library_writer/gate_library_writer_manager.h"
#include "hal_core/netlist/module.h"
#include "hal_core/netlist/netlist_factory.h"
#include "hal_core/netlist/netlist_writer/netlist_writer_manager.h"
Expand All @@ -17,12 +18,19 @@
#include <fstream>

#include <JlCompress.h>
#include <rapidjson/filereadstream.h>
#include <rapidjson/filewritestream.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>

#define SECRET_PASSWORD "test12345"

namespace hal
{

const char* OBFUSCATED = "_obfuscated";
const char* GATE_LIB_TAG = "gate_library";

extern Netlist* gNetlist;

extern std::unique_ptr<BasePluginInterface> create_plugin_instance()
Expand Down Expand Up @@ -62,24 +70,33 @@ namespace hal
std::set<std::string> retval;
retval.insert("hal_gui");
retval.insert("verilog_writer");
retval.insert("hgl_writer");
return retval;
}

void NetlistModifierPlugin::initialize()
{
}

bool replace_gate_in_netlist(Netlist* netlist, Gate* gate)
std::string NetlistModifierPlugin::obfuscated_gate_name(int num_in, int num_out, int num_io)
{
std::string retval = "UNKNOWN_" + std::to_string(num_in) + "IN_" + std::to_string(num_out) + "OUT";
if (num_io)
retval += "_" + std::to_string(num_io) + "IO";
return retval;
}

bool NetlistModifierPlugin::replace_gate_in_netlist(Netlist* netlist, Gate* gate)
{
// get the number of input pins
int num_of_in = gate->get_fan_in_endpoints().size();
int num_of_out = gate->get_fan_out_endpoints().size();

GateType* new_gate_type = netlist->get_gate_library()->get_gate_type_by_name("UNKNOWN_" + std::to_string(num_of_in) + "IN_" + std::to_string(num_of_out) + "OUT");
GateType* new_gate_type = netlist->get_gate_library()->get_gate_type_by_name(obfuscated_gate_name(num_of_in,num_of_out));

if (!new_gate_type)
{
log_error("netlist_modifier", "No gatetype called 'UNKNOWN_" + std::to_string(num_of_in) + "IN_" + std::to_string(num_of_out) + "OUT' in gatelib");
log_error("netlist_modifier", "No gatetype called '{}' in gatelib", obfuscated_gate_name(num_of_in,num_of_out));
return false;
}

Expand All @@ -104,17 +121,17 @@ namespace hal
Gate* new_gate = netlist->create_gate(gate_id, new_gate_type, gate_name);

// add old connections
int counter = 1;
int counter = 0;
for (Net* net : in_nets)
{
net->add_destination(new_gate, "IN_" + std::to_string(counter));
net->add_destination(new_gate, "I" + std::to_string(counter));
counter++;
}

counter = 1;
counter = 0;
for (Net* net : out_nets)
{
net->add_source(new_gate, "OUT_" + std::to_string(counter));
net->add_source(new_gate, "O" + std::to_string(counter));
counter++;
}

Expand Down Expand Up @@ -207,11 +224,112 @@ max_probes=5)";
return true;
}

bool NetlistModifierPlugin::modify_gatelibrary()
{
ProjectManager* pm = ProjectManager::instance();

std::filesystem::path projFilePath(pm->get_project_directory());
if (projFilePath.empty() || !std::filesystem::exists(projFilePath))
{
log_warning("netlist_modifier", "Cannot access project directory '{}'.", projFilePath.string());
return false;
}
projFilePath.append(ProjectManager::s_project_file);

// get location of current gate library from project file
FILE* fp = fopen(projFilePath.string().c_str(), "rb");
if (fp == NULL)
{
log_warning("netlist_modifier", "Cannot open project file '{} for reading'.", projFilePath.string());
return false;
}

char buffer[65536];
rapidjson::FileReadStream frs(fp, buffer, sizeof(buffer));
rapidjson::Document doc;
doc.ParseStream<0, rapidjson::UTF8<>, rapidjson::FileReadStream>(frs);
fclose(fp);

std::filesystem::path modifiedGateLibraryPath;
if (doc.HasMember(GATE_LIB_TAG))
{
std::filesystem::path originalGateLibraryPath = doc[GATE_LIB_TAG].GetString();
if (originalGateLibraryPath.stem().string().find(OBFUSCATED) != std::string::npos)
{
// using already gate library with obfuscated gates
return true;
}
// generate new name for gate library with obfuscated gates
modifiedGateLibraryPath = pm->get_project_directory().get_filename(originalGateLibraryPath.stem().string() + OBFUSCATED + ".hgl");
}
else
{
log_warning("netlist_modifier", "Cannot find mandatory '{}' tag in project file '{}'.", GATE_LIB_TAG, projFilePath.string());
return false; // gate library entry missing in project file
}

// yes, we know what we are doing when casting away const ;-)
// Modifying attibutes of a GateType in HAL while netlist is loaded might produce unpredictable results,
// thus GateLibrary is declared const. However, we are only adding GateType's, this should be safe.
GateLibrary* gl = const_cast<GateLibrary*>(gNetlist->get_gate_library());

// map gate type categories by number of pins
std::unordered_map<u32,int> pinCountMap;
for (auto const& [key, gt] : gl->get_gate_types())
{
int count[5] = {0, 0, 0, 0, 0};
for (const GatePin* gp : gt->get_pins())
{
count[(int)gp->get_direction()]++;
}
u32 pinCount = (count[1] & 0x3FF) | ((count[2] & 0x3FF) << 10) | ((count[3] & 0x3FF) << 20);
++pinCountMap[pinCount];
}

// create dummy gate types with appropriate number of pins
for (auto const& [pc,count] : pinCountMap)
{
int inCount = pc & 0x3FF;
int outCount = (pc >> 10) & 0x3FF;
int ioCount = (pc >> 20) & 0x3FF;
GateType* gt = gl->create_gate_type(obfuscated_gate_name(inCount, outCount, ioCount));
for (int i=0; i<inCount; i++)
gt->create_pin("I" + std::to_string(i), PinDirection::input, PinType::none, true);
for (int i=0; i<outCount; i++)
gt->create_pin("O" + std::to_string(i), PinDirection::output, PinType::none, true);
for (int i=0; i<ioCount; i++)
gt->create_pin("IO" + std::to_string(i), PinDirection::inout, PinType::none, true);
}

if (!gate_library_writer_manager::write(gl, modifiedGateLibraryPath))
{
log_warning("netlist_modifier", "cannot write modified gate library to file'{}'.", modifiedGateLibraryPath.string());
return false;
}

// write modified project file
rapidjson::Value::MemberIterator gatelibMemberIterator = doc.FindMember(GATE_LIB_TAG);
gatelibMemberIterator->value.SetString(modifiedGateLibraryPath.filename().string().c_str(), doc.GetAllocator());

FILE* of = fopen(projFilePath.string().c_str(), "wb");
if (of == NULL)
{
log_warning("netlist_modifier", "cannot open project file '{}' for rewrite.", projFilePath.string());
return false;
}
rapidjson::FileWriteStream fws(of, buffer, sizeof(buffer));
rapidjson::Writer<rapidjson::FileWriteStream> writer(fws);
doc.Accept(writer);
fclose(of);

return true;
}

bool NetlistModifierPlugin::modify_in_place()
{
GuiApi* guiAPI = new GuiApi();
if (!modify_gatelibrary()) return false;

std::vector<Gate*> gates = guiAPI->getSelectedGates();
std::vector<Gate*> gates = GuiApi().getSelectedGates();

// save original netlist if it does not contain any UNKNOWN gates
bool contains_unknown = false;
Expand Down Expand Up @@ -297,4 +415,4 @@ max_probes=5)";
m_parent->save();
}
}
} // namespace hal
} // namespace hal

0 comments on commit f40e3a9

Please sign in to comment.