torc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
EdifObfuscator.cpp
Go to the documentation of this file.
1 // Torc - Copyright 2011-2013 University of Southern California. All Rights Reserved.
2 // $HeadURL$
3 // $Id$
4 
5 // This program is free software: you can redistribute it and/or modify it under the terms of the
6 // GNU General Public License as published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11 // the GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License along with this program. If
14 // not, see <http://www.gnu.org/licenses/>.
15 
16 /// \file
17 /// \brief Source for the EDIF obfuscator.
18 
19 #include "torc/Generic.hpp"
20 #include "torc/Common.hpp"
21 #include "torc/externals/md5/md5.h"
22 #include <iostream>
23 #include <fstream>
24 #include <sstream>
25 #include <iomanip>
26 #include <boost/filesystem.hpp>
27 #include <boost/regex.hpp>
28 #include <boost/cstdint.hpp>
29 #include <boost/lexical_cast.hpp>
30 
31 using namespace torc::generic;
32 
33 boost::uint32_t mIdentifierCount = 0;
34 
35 // function prototypes
36 std::string md5(const char* inMessage);
37 std::string obfuscate(const std::string& inIdentifier);
38 void obfuscate(RootSharedPtr rootPtr, std::fstream& log);
39 
40 // calculate and return the MD5 hash on the given message
41 std::string md5(const char* inMessage) {
42  // prepare for hashing
43  md5_state_t md5_state;
44  md5_byte_t digest[16];
45  md5_init(&md5_state);
46  // hash the input
47  md5_append(&md5_state, (md5_byte_t*) inMessage, strlen(inMessage));
48  md5_finish(&md5_state, digest);
49  // return the hash as a hex string
50  std::ostringstream md5oss;
51  md5oss << 'i';
52  for(boost::uint16_t i = 0; i < sizeof(digest); i++) md5oss << std::hex << std::setw(2)
53  << std::setfill('0') << (boost::uint16_t) (digest[i] & 0xff) << std::dec;
54  return md5oss.str();
55 }
56 
57 // obfuscate the given identifier and return it
58 std::string obfuscate(const std::string& inIdentifier) {
59  // we don't actually need to hash the original string; we'll just hash a unique identifier
60  // count instead
61  std::string message = boost::lexical_cast<std::string>(mIdentifierCount++);
62  // hash the message
63  std::string hash = md5(message.c_str());
64  // return the result
65  return hash;
66 }
67 
68 void obfuscate(RootSharedPtr rootPtr, std::fstream& log) {
69 
70  // reset the md5 hashing scheme
71  mIdentifierCount = 0;
72 
73  // track libraries and cells that should be protected from obfuscation
74  typedef std::map<std::string, bool> StringToBoolMap;
75  StringToBoolMap protectedCells;
76  StringToBoolMap protectedLibraries;
77 
78  // enumerate the root designs
79  typedef std::vector<DesignSharedPtr> DesignSharedPtrVector;
80  DesignSharedPtrVector designs;
81  rootPtr->getDesigns(designs);
82  DesignSharedPtrVector::iterator dp = designs.begin();
83  DesignSharedPtrVector::iterator de = designs.end();
84  while(dp < de) {
85 
86  // look up the design name and specifics
87  DesignSharedPtr& designPtr = *dp++;
88  std::string designName = designPtr->getName();
89  std::string cellRefName = designPtr->getCellRefName();
90  std::string libraryRefName = designPtr->getLibraryRefName();
91  std::cout << " Protecting design \"" << designName << "\" (cell \"" << cellRefName
92  << "\", library \"" << libraryRefName << "\")" << std::endl;
93  protectedCells[libraryRefName + ":" + cellRefName] = true;
94  protectedLibraries[libraryRefName] = true;
95 
96  }
97 
98  // define libraries that must not be obfuscated
99  boost::regex regexVendorLibraries("^(VhdlGenLib|virtex|virtexr|unilib)$",
100  boost::regex_constants::icase);
101 
102  // iterate over the root libraries
103  typedef std::vector<LibrarySharedPtr> LibrarySharedPtrVector;
104  LibrarySharedPtrVector libraries;
105  rootPtr->getLibraries(libraries);
106  LibrarySharedPtrVector::iterator lp = libraries.begin();
107  LibrarySharedPtrVector::iterator le = libraries.end();
108  while(lp < le) {
109 
110  // look up the library name
111  LibrarySharedPtr& libraryPtr = *lp++;
112  std::string libraryName = libraryPtr->getName();
113  //std::cout << " found library \"" << libraryName << "\"" << std::endl;
114 
115  // leave vendor libraries alone
116  if(boost::regex_search(libraryName, regexVendorLibraries)) continue;
117 
118  // identify and protect any black boxes in the library
119  typedef std::vector<CellSharedPtr> CellSharedPtrVector;
120  CellSharedPtrVector cells;
121  libraryPtr->getCells(cells);
122  CellSharedPtrVector::iterator cp = cells.begin();
123  CellSharedPtrVector::iterator ce = cells.end();
124  while(cp < ce) {
125  // look up the cell name
126  CellSharedPtr& cellPtr = *cp++;
127  std::string cellName = cellPtr->getName();
128  // iterate over the cell modules
129  typedef std::vector<ViewSharedPtr> ViewSharedPtrVector;
130  ViewSharedPtrVector views;
131  cellPtr->getViews(views);
132  ViewSharedPtrVector::iterator vp = views.begin();
133  ViewSharedPtrVector::iterator ve = views.end();
134  while(vp < ve) {
135  // look up the view name
136  ViewSharedPtr& viewPtr = *vp++;
137  std::string viewName = viewPtr->getName();
138  if(viewName == "syn_black_box") {
139  protectedLibraries[libraryName] = true;
140  protectedCells[libraryName + ":" + cellName] = true;
141  }
142  }
143  }
144 
145  // obfuscate the name
146  bool libraryIsProtected = protectedLibraries.count(libraryName) > 0;
147  if(!libraryIsProtected) {
148  std::string obfuscatedLibraryName
149  = libraryIsProtected ? libraryName : obfuscate(libraryName);
150  libraryPtr->setName(obfuscatedLibraryName);
151  libraryPtr->setOriginalName("");
152  log << "library " << libraryName << "=> " << obfuscatedLibraryName << std::endl;
153  }
154 
155  // iterate over the library cells
156  //typedef std::vector<CellSharedPtr> CellSharedPtrVector;
157  //CellSharedPtrVector cells;
158  //libraryPtr->getCells(cells);
159  //CellSharedPtrVector::iterator cp = cells.begin();
160  //CellSharedPtrVector::iterator ce = cells.end();
161  cp = cells.begin();
162  ce = cells.end();
163  while(cp < ce) {
164 
165  // look up the cell name
166  CellSharedPtr& cellPtr = *cp++;
167  std::string cellName = cellPtr->getName();
168  //std::cout << " found cell \"" << cellName << "\"" << std::endl;
169 
170  // obfuscate the name
171  bool cellIsProtected = protectedCells.count(libraryName + ":" + cellName) > 0;
172  if(cellIsProtected == false) {
173  std::string obfuscatedCellName = obfuscate(cellName);
174  cellPtr->setName(obfuscatedCellName);
175  cellPtr->setOriginalName("");
176  log << "cell " << cellName << " => " << obfuscatedCellName << std::endl;
177  } else {
178  log << "cell " << cellName << " => " << cellName << std::endl;
179  }
180 
181  // iterate over the cell modules
182  typedef std::vector<ViewSharedPtr> ViewSharedPtrVector;
183  ViewSharedPtrVector views;
184  cellPtr->getViews(views);
185  ViewSharedPtrVector::iterator vp = views.begin();
186  ViewSharedPtrVector::iterator ve = views.end();
187  while(vp < ve) {
188 
189  // look up the view name
190  ViewSharedPtr& viewPtr = *vp++;
191  std::string viewName = viewPtr->getName();
192  //std::cout << " found view \"" << viewName << "\"" << std::endl;
193 
194  // obfuscate the name
195  if(cellIsProtected == false) {
196  std::string obfuscatedViewName = obfuscate(viewName);
197  viewPtr->setName(obfuscatedViewName);
198  viewPtr->setOriginalName("");
199  log << " view " << viewName << " => " << obfuscatedViewName << std::endl;
200  } else {
201  log << " view " << viewName << " => " << viewName << std::endl;
202  }
203 
204  // iterate over all the ports
205  typedef std::vector<PortSharedPtr> PortSharedPtrVector;
206  PortSharedPtrVector ports;
207  viewPtr->getPorts(ports);
208  PortSharedPtrVector::iterator pp = ports.begin();
209  PortSharedPtrVector::iterator pe = ports.end();
210  while(pp < pe) {
211 
212  // look up the port name
213  PortSharedPtr& portPtr = *pp++;
214  std::string portName = portPtr->getName();
215  //std::cout << " found port \"" << portName << "\"" << std::endl;
216 
217  // obfuscate the name
218  if(cellIsProtected == false) {
219  std::string obfuscatedPortName = obfuscate(portName);
220  portPtr->setName(obfuscatedPortName);
221  std::string originalName = portPtr->getOriginalName();
222  // protect bus nets
223  boost::smatch what;
224  boost::regex re(".*([\\(\\[].+[\\)\\]])");
225  if(boost::regex_match(originalName, what, re, boost::match_default)) {
226  std::string newName = obfuscatedPortName
227  + std::string(what[1].first, what[1].second);
228  //std::cout << "replacing \"" << originalName << "\" with \""
229  // << newName << "\"" << std::endl;
230  originalName = newName;
231  }
232  portPtr->setOriginalName(originalName);
233  log << " port " << portName << " => " << obfuscatedPortName
234  << std::endl;
235  } else {
236  log << " port " << portName << " => " << portName << std::endl;
237  }
238 
239  }
240 
241  // iterate over all the instances
242  typedef std::vector<InstanceSharedPtr> InstanceSharedPtrVector;
243  InstanceSharedPtrVector instances;
244  viewPtr->getInstances(instances);
245  InstanceSharedPtrVector::iterator ip = instances.begin();
246  InstanceSharedPtrVector::iterator ie = instances.end();
247  while(ip < ie) {
248 
249  // look up the instance name
250  InstanceSharedPtr& instancePtr = *ip++;
251  std::string instanceName = instancePtr->getName();
252  //std::cout << " found instance \"" << instanceName << "\""
253  // << std::endl;
254 
255  // obfuscate the name
256  std::string obfuscatedInstanceName = obfuscate(instanceName);
257  instancePtr->setName(obfuscatedInstanceName);
258  instancePtr->setOriginalName("");
259  log << " instance " << instanceName << " => " << obfuscatedInstanceName
260  << std::endl;
261 
262  }
263 
264  // iterate over all the nets
265  typedef std::vector<NetSharedPtr> NetSharedPtrVector;
266  NetSharedPtrVector nets;
267  viewPtr->getNets(nets);
268  NetSharedPtrVector::iterator np = nets.begin();
269  NetSharedPtrVector::iterator ne = nets.end();
270  while(np < ne) {
271 
272  // look up the net name
273  NetSharedPtr& netPtr = *np++;
274  std::string netName = netPtr->getName();
275  //std::cout << " found net \"" << netName << "\"" << std::endl;
276 
277  // obfuscate the name
278  std::string obfuscatedNetName = obfuscate(netName);
279  netPtr->setName(obfuscatedNetName);
280  netPtr->setOriginalName("");
281  log << " net " << netName << " => " << obfuscatedNetName << std::endl;
282 
283  // iterate over all the ports
284  typedef std::vector<PortSharedPtr> PortSharedPtrVector;
285  PortSharedPtrVector ports;
286  netPtr->getConnectedPorts(ports, false);
287  PortSharedPtrVector::iterator pp = ports.begin();
288  PortSharedPtrVector::iterator pe = ports.end();
289  while(pp < pe) {
290  // look up the port name
291  PortSharedPtr& portPtr = *pp++;
292  std::string portName = portPtr->getName();
293  std::string parentPortName;
294  CompositionType compositionType = portPtr->getCompositionType();
295  switch(compositionType) {
297  parentPortName = portPtr->getName();
298  if(parentPortName == portName) break;
299  portPtr->setName(parentPortName);
300  //std::cout << " NOTE: changing port name from \""
301  // << portName << "\" to \"" << parentPortName << "\""
302  // << std::endl;
303  break;
305  const PortSharedPtr& vectorPtr = portPtr->getParentCollection();
306  parentPortName = vectorPtr->getName();
307  if(parentPortName == portName) break;
308  vectorPtr->setName(parentPortName);
309  //std::cout << " NOTE: changing port name from \""
310  // << portName << "\" to \"" << parentPortName << "\""
311  // << std::endl;
312  } break;
313  default:
314  std::cerr << "ERROR: Unsupported composition type "
315  << compositionType << " in " << __FILE__ << " line "
316  << __LINE__ << std::endl;
317  break;
318  }
319 
320  }
321 
322  /* this should no longer be necessary with the updated EDIF portref handling
323  // iterate over all the portRefs
324  typedef std::vector<PortReferenceSharedPtr> PortReferenceSharedPtrVector;
325  PortReferenceSharedPtrVector portRefs;
326  netPtr->getConnectedPortRefs(portRefs, false);
327  PortReferenceSharedPtrVector::iterator prp = portRefs.begin();
328  PortReferenceSharedPtrVector::iterator pre = portRefs.end();
329  while(prp < pre) {
330  // look up the portRef name
331  PortReferenceSharedPtr& portRefPtr = *prp++;
332  std::string portRefName = portRefPtr->getName();
333  std::string masterPortName;
334  CompositionType compositionType = portRefPtr->getCompositionType();
335  switch(compositionType) {
336  case eCompositionTypeScalar:
337  masterPortName = portRefPtr->getMaster()->getName();
338  if(masterPortName == portRefName) break;
339  //portRefPtr->setName(masterPortName);
340  //std::cout << " NOTE: changing portRef name from \""
341  // << portRefName << "\" to \"" << masterPortName << "\""
342  // << std::endl;
343  break;
344  case eCompositionTypeVectorBit: {
345  const PortReferenceSharedPtr& vectorRefPtr
346  = portRefPtr->getParentCollection();
347  masterPortName = vectorRefPtr->getMaster()->getName();
348  if(masterPortName == portRefName) break;
349  //vectorRefPtr->setName(masterPortName);
350  //std::cout << " NOTE: changing portRef name from \""
351  // << portRefName << "\" to \"" << masterPortName << "\""
352  // << std::endl;
353  } break;
354  default:
355  std::cerr << "ERROR: Unsupported composition type "
356  << compositionType << " in " << __FILE__ << " line "
357  << __LINE__ << std::endl;
358  break;
359  }
360  }
361  */
362 
363  }
364  }
365 
366  }
367 
368  }
369 }
370 
371 int main(int argc, char** argv) {
372 
373  // iterate through each EDIF file specified
374  for(int i = 1; i < argc; i++) {
375  // build the file names
376  boost::filesystem::path sourcePath = argv[i];
377  boost::filesystem::path targetPath = sourcePath;
378  targetPath = targetPath.replace_extension().string()
379  + ".mod" + boost::filesystem::extension(sourcePath);
380  boost::filesystem::path logPath = sourcePath;
381  logPath = logPath.replace_extension().string() + ".obfuscation_log";
382  // obfuscate the file
383  try {
384  // read the source file
385  std::cout << "Reading source: " << sourcePath.string() << " ... ";
386  std::cout.flush();
387  boost::shared_ptr<ObjectFactory> factoryPtr(new ObjectFactory());
388  boost::shared_ptr<Root> rootPtr;
389  factoryPtr->create(rootPtr);
390  boost::shared_ptr<Linker> linkerPtr(new Linker(rootPtr));
391  ParserOptions options;
392  EdifParser parser;
393  try {
394  parser.parse(sourcePath.string(), rootPtr, linkerPtr, factoryPtr, options);
395  std::cout << "done." << std::endl;
396  } catch(Error& e) {
397  std::cerr << std::endl;
399  << std::endl;
400  const std::vector<Error::StackFrameInfo> &stack = e.getStackTrace();
401  for(std::vector<Error::StackFrameInfo>::const_iterator it = stack.begin();
402  it != stack.end(); it++) {
403  std::cerr << " " << (*it).getFunction() << "() [" << (*it).getFile() << ":"
404  << (*it).getLine() << "]" << std::endl;
405  }
406  }
407  // open the log file
408  std::fstream logStream(logPath.string().c_str(), std::ios_base::out);
409  // obfuscate the design
410  obfuscate(rootPtr, logStream);
411  // write the target file
412  std::cout << "Writing target: " << targetPath.string() << " ... ";
413  std::cout.flush();
414  std::fstream targetStream(targetPath.string().c_str(), std::ios_base::out);
415  Decompiler decompiler(rootPtr, targetStream);
416  decompiler();
417  std::cout << "done." << std::endl;
418  }
419  // report failure
420  catch(...) {
421  std::cerr << "ERROR: Failed to obfuscate " << sourcePath.string() << std::endl;
422  }
423  }
424 
425  return 0;
426 }
void log(const char *fmt,...)
Definition: Log.cpp:89
boost::shared_ptr< Instance > InstanceSharedPtr
Bison stack class.
static MessageTable * instance()
Main torc::generic namespace header.
std::vector< InstanceSharedPtr > InstanceSharedPtrVector
Vector of Instance shared pointers.
The Top level parser for parsing EDIF files.
Definition: EdifParser.hpp:41
std::vector< DesignSharedPtr > DesignSharedPtrVector
Vector of Design shared pointers.
std::string string
boost::shared_ptr< Design > DesignSharedPtr
CompositionType
Defines possible Composition types.
The Error object thrown by different methods of EdifOM.
Definition: Error.hpp:41
const std::vector< StackFrameInfo > & getStackTrace() const
Definition: Error.hpp:175
boost::shared_ptr< Net > NetSharedPtr
boost::shared_ptr< Library > LibrarySharedPtr
std::string obfuscate(const std::string &inIdentifier)
boost::uint32_t mIdentifierCount
Represents a repository of unresolved usage references.
Definition: Linker.hpp:51
std::vector< NetSharedPtr > NetSharedPtrVector
Vector of Net shared pointers.
boost::filesystem::path path
const MessageId getErrorMessageId() const
Definition: Error.hpp:195
boost::shared_ptr< View > ViewSharedPtr
boost::shared_ptr< Cell > CellSharedPtr
boost::shared_ptr< Port > PortSharedPtr
Main torc::common namespace header.
std::string md5(const char *inMessage)
std::string getMessage(MessageId inId) const
std::vector< PortSharedPtr > PortSharedPtrVector
Vector of Port shared pointers.
int main(int argc, char **argv)
boost::shared_ptr< Root > RootSharedPtr
void parse(const std::string &inFileName, const RootSharedPtr &outRoot, const LinkerSharedPtr &outLinker, const ObjectFactorySharedPtr &inFactory, const ParserOptions &inOptions)
Definition: EdifParser.cpp:40