cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
cryptlibConverter.py
Go to the documentation of this file.
1 import sys
2 import os
3 import stat
4 import re
5 
6 
7 #Helper Functions
8 #==========================================================================
9 
10 def parseEnumContents(enumContents, nameSpace, debugString):
11  enumPattern = re.compile(r"(CRYPT_[\w_]*)\s*(=.*?)?(\Z|,|(?=/))", re.DOTALL) # %1 [= %2][,]
12  commentPattern = re.compile(r"\s*/\*(.*)\*/") # /* %1 */
13  counter = 0 #Keep track of the implicit enum value
14  enumTuples = [] #Build a list of (key, val, comment) tuples, one for each enum value
15 
16  #Find the next "enum value"
17  enumMatch = enumPattern.search(enumContents)
18  while enumMatch:
19 
20  #Extract the key and RHS value
21  rawKey, rawVal = enumMatch.groups()[:-1]
22 
23  key = rawKey.rstrip()
24  if not key.startswith("CRYPT_"):
25  raise "enum'd value doesn't start with CRYPT_ "+key
26  key = key.replace("CRYPT_", "")
27 
28  #Evaluate the RHS (if it exists) to get the value
29  if rawVal:
30  rhs = rawVal[1:].strip().replace("CRYPT_", "")
31  val = eval(rhs, nameSpace)
32  #Otherwise the value is the implicit counter
33  else:
34  val = counter
35 
36  #Extract the comment
37  commentMatch = commentPattern.match(enumContents, enumMatch.end())
38  if commentMatch:
39  rawComment = commentMatch.group(1)
40  comment = rawComment.strip()
41  else:
42  comment = ""
43 
44  #Collect all the parsed values into a tuple
45  enumTuple = (key, str(val), comment)
46 
47  #if comment:
48  # print debugString+ ":" + " Parsed Element %s = %s /* %s */" % enumTuple
49  #else:
50  # print debugString+ ":" + " Parsed Element %s = %s" % enumTuple[:-1]
51  #raw_input()
52 
53  nameSpace[key] = val #Add new enum value into namespace
54  counter = val + 1 #Increment implicit enum value
55 
56  #Accumulate the parsed (key, val, comment) tuples
57  enumTuples.append(enumTuple)
58 
59  #Get next enum value
60  enumMatch = enumPattern.search(enumContents, enumMatch.end())
61 
62  return enumTuples
63 
64 #Parses a string of function parameters into a list of ParamStruct
66  def __init__(self):
67  self.type = ""
68  self.isPtr = 0
69  self.isOut = 0
70  self.category = ""
71  self.name = ""
72  self.rawIndex = 0 # The index of this param in the initial, raw cryptlib header
73  def __str__(self):
74  return str( (self.type, self.isPtr, self.category, self.name, self.rawIndex) )
75 
76 def parseFunctionParams(functionParams):
77  paramStructs = []
78  functionParams = functionParams.replace("\n", "") #Make one big line
79  functionParamsList = [e.strip() for e in functionParams.split(",")] #Break into a list of params
80  index = 0
81  for e in functionParamsList:
82  pieces = e.split(" ") #Separate each param into component pieces, ie ["C_IN", "CRYPT_ALGO_TYPE", "cryptAlgo"]
83  p = ParamStruct()
84  if len(pieces)==1 and pieces[0]=="void":
85  continue
86  elif len(pieces)==3:
87  if pieces[0] == "C_OUT":
88  p.isOut = 1
89  if pieces[0] == "C_OUT_OPT":
90  p.isOut = 1
91  if pieces[1] == "C_STR":
92  p.type = "char"
93  p.name = pieces[2]
94  p.isPtr = 1
95  else:
96  p.type = pieces[1]
97  p.name = pieces[2]
98  p.isPtr = 0
99  elif len(pieces)==4: #Ie ["C_OUT", "CRYPT_CONTEXT", "C_PTR", "cryptContext"]
100  if pieces[0] == "C_OUT":
101  p.isOut = 1
102  if pieces[0] == "C_OUT_OPT":
103  p.isOut = 1
104  p.type = pieces[1]
105  if pieces[2] == "C_PTR":
106  p.isPtr = 1
107  else:
108  raise "Expecting C_PTR in parseFunctionParams"
109  p.name = pieces[3]
110  else:
111  raise "parsing error in parseFunctionParams"
112  if p.type in enumTypes:
113  p.category = "enumType"
114  elif p.type in intTypes:
115  p.category = "intType"
116  elif p.type in structTypes:
117  p.category = "structType"
118  elif p.type in rawTypes:
119  p.category = "rawType"
120  else:
121  raise "unknown type error is parseFunctionParams"
122  p.rawIndex = index
123  index += 1
124  paramStructs.append(p)
125  #for p in paramStructs:
126  # print p.__dict__
127  #raw_input()
128  return paramStructs
129 
130 #Takes a string containing a JNI function parameters prototype list, and a list of ParamStructs
131 #And injects names into the string and returns it
132 def expandFunctionPrototype(functionPrototype, newParamStructs):
133  functionPrototype = functionPrototype.replace("\n", "") #Make one big line
134  paramPrototypesList = [e.strip() for e in functionPrototype.split(",")] #Break into a list of params
135  paramNamesList = ["env", "cryptClass"] + [e.name for e in newParamStructs]
136  newFunctionParams = ""
137  for (p1, p2) in zip(paramPrototypesList, paramNamesList):
138  newFunctionParams += p1 + " " + p2 + ", "
139  newFunctionParams = newFunctionParams[:-2]
140  return newFunctionParams
141 
142 
143 
144 
145 
146 
147 #Main
148 #=========================================================================
149 #Execution starts here...
150 #=========================================================================
151 if len(sys.argv) != 4:
152  print "cryptlibConverter.py <inFile> <outDir> <language>"
153  sys.exit()
154 
155 inFile = sys.argv[1]
156 outDir = sys.argv[2]
157 language = sys.argv[3]
158 
159 if not os.path.exists(outDir):
160  print "Making output directory..."
161  os.mkdir(outDir)
162 
163 if not language in ("java", "python", "net"):
164  print "only java, python, and net are supported!"
165  sys.exit()
166 
167 if language == "java":
168  #ENUM IDIOM
169  #typedefEnumTemplate = "public static class %(typedefName)s\n{public int getValue(){return m_value;}private %(typedefName)s(int value){m_value = value;}int m_value;}"
170  #typedefEnumElementTemplate = "public static final %(typedefName)s %(name)-NPADs = new %(typedefName)s(%(value)-VPADs);"
171  #ENUMs as ints
172  typedefEnumTemplate = "// %(typedefName)s"
173  typedefEnumElementTemplate = "public static final int %(name)-NPADs = %(value)-VPADs;"
174 
175  typedefEnumElementTemplateComment = typedefEnumElementTemplate + " // %(comment)s"
176  simpleEnumElementTemplate = "public static final int %(name)-NPADs = %(value)-VPADs;"
177  simpleEnumElementTemplateComment = simpleEnumElementTemplate + " // %(comment)s"
178  defineNPad = "40"
179  defineVPad = "4"
180  defineTemplate = simpleEnumElementTemplate
181  defineTemplateComment = simpleEnumElementTemplateComment
182  exceptionPrefix = """
183 package cryptlib;
184 
185 public class CryptException extends Exception
186 {
187  private int m_status;
188  private String m_message;
189  public CryptException(int status)
190  {
191  m_status = status;
192  String prefix = Integer.toString(status) + ": ";
193 
194 """
195  exceptionPostfix = """\
196  m_message = prefix + "Unknown Exception ?!?!";
197  }
198 
199  public int getStatus()
200  {
201  return m_status;
202  }
203 
204  public String getMessage()
205  {
206  return m_message;
207  }
208 };"""
209  exceptionTemplate = """\
210  if (m_status == crypt.%(name)s) {
211  m_message = prefix + "%(comment)s";
212  return; }
213 """
214  cryptQueryInfoString = """
215 package cryptlib;
216 
217 public class CRYPT_QUERY_INFO
218 {
219  public String algoName;
220  public int blockSize;
221  public int minKeySize;
222  public int keySize;
223  public int maxKeySize;
224 
225  public CRYPT_QUERY_INFO(String newAlgoName, int newBlockSize, int newMinKeySize, int newKeySize, int newMaxKeySize)
226  {
227  algoName = newAlgoName;
228  blockSize = newBlockSize;
229  minKeySize = newMinKeySize;
230  keySize = newKeySize;
231  maxKeySize = newMaxKeySize;
232  }
233 };"""
234  cryptObjectInfoString = """
235 package cryptlib;
236 
237 public class CRYPT_OBJECT_INFO
238 {
239  public int objectType;
240  public int cryptAlgo;
241  public int cryptMode;
242  public int hashAlgo;
243  public byte[] salt;
244 
245  public CRYPT_OBJECT_INFO(int newObjectType, int newCryptAlgo, int newCryptMode, int newHashAlgo, byte[] newSalt)
246  {
247  objectType = newObjectType;
248  cryptAlgo = newCryptAlgo;
249  cryptMode = newCryptMode;
250  hashAlgo = newHashAlgo;
251  salt = newSalt;
252  }
253 };"""
254  addFunctionWrappers = 1
255  wholeFunctionDeclaration = None
256  functionDeclaration = "public static native "
257  returnIntDeclaration = "int "
258  returnVoidDeclaration = "void "
259  paramsPrefix = "("
260  paramsPostfix = ") throws CryptException;"
261  paramWhiteSpace = "\t\t\t\t\t\t"
262  paramVoidPtrTemplate = "java.nio.ByteBuffer %(name)s,\n"
263  addFunctionAlternate = 1
264  paramVoidPtrAlternate = ("java.nio.ByteBuffer", "byte[]")
265  paramCharPtrTemplate = "String %(name)s,\n"
266  paramIntTemplate = "int %(name)s,\n"
267  paramIntTypeTemplate = "int %(name)s, // %(type)s\n"
268  #wrapperLengthTemplate = "%s.capacity(), "
269  #wrapperStringLengthTemplate = "%s.length(), "
270  wrapperLengthTemplate = "%(1)s == null ? 0 : %(1)s.capacity(), "
271  wrapperStringLengthTemplate = "%(1)s == null ? 0 : %(1)s.getBytes().length, "
272  wrapperStringReplace = ("java.nio.ByteBuffer", "String")
273  wrapperStringTemplate = '%(1)s == null ? null : %(1)s.getBytes()'
274  #ENUM IDIOM
275  #paramEnumTypeTemplate = "%(type)s %(name)s,\n"
276  #ENUMs as ints
277  paramEnumTypeTemplate = "int %(name)s, // %(type)s\n"
278  commentPrefix = "//"
279  classPrefix = "package cryptlib;\n\nimport java.nio.*;\n\npublic class crypt\n{\n"
280  classPostfix = "\n};"
281  sFuncs = None
282  sInts = None
283 elif language == "python":
284  typedefEnumTemplate = ""
285  #typedefEnumElementTemplate = "%(name)-NPADs = %(value)-VPADs"
286  typedefEnumElementTemplate = """\
287 
288  v = Py_BuildValue("i", %(value)s);
289  PyDict_SetItemString(moduleDict, "CRYPT_%(name)s", v);
290  Py_DECREF(v);"""
291  typedefEnumElementTemplateComment = typedefEnumElementTemplate + " /* %(comment)s */"
292  simpleEnumElementTemplate = typedefEnumElementTemplate
293  simpleEnumElementTemplateComment = typedefEnumElementTemplateComment
294  defineNPad = "40"
295  defineVPad = "4"
296  defineTemplate = typedefEnumElementTemplate
297  defineTemplateComment = typedefEnumElementTemplateComment
298  exceptionPrefix = ""
299  exceptionPostfix = ""
300  exceptionTemplate = """\
301  else if (status == CRYPT_%(name)s)
302  o = Py_BuildValue("(is)", CRYPT_%(name)s, "%(comment)s");
303 """
304  addFunctionWrappers = 0
305  wholeFunctionDeclaration = """\
306 static PyObject* python_crypt%s(PyObject* self, PyObject* args)
307 {
308 }
309 """
310  moduleFunctionEntry = "\t{ \"crypt%s\", python_crypt%s, METH_VARARGS }, "
311  pyBeforeExceptions = r"""
312 #include <Python.h>
313 #include "../cryptlib.h"
314 
315 
316 static PyObject* cryptHandleClass;
317 static PyObject* cryptQueryInfoClass;
318 static PyObject* cryptObjectInfoClass;
319 static PyObject *CryptException;
320 
321 static int getPointerWrite(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)
322 {
323  if (objPtr == Py_None)
324  {
325  *bytesPtrPtr = NULL;
326  *lengthPtr = 0;
327  return 1;
328  }
329 
330  Py_ssize_t size = 0;
331 
332  /*See if it's an array object*/
333  if (PyObject_AsWriteBuffer(objPtr, (void **)bytesPtrPtr, &size) == -1)
334  return 0;
335  *lengthPtr = size;
336  return 1;
337 }
338 
339 static int getPointerRead(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)
340 {
341  if (objPtr == Py_None)
342  {
343  *bytesPtrPtr = NULL;
344  *lengthPtr = 0;
345  return 1;
346  }
347 
348  Py_ssize_t size = 0;
349 
350  /*See if it's an array object*/
351  if (PyObject_AsWriteBuffer(objPtr, (void **)bytesPtrPtr, &size) == -1)
352  {
353  PyErr_Clear();
354  /*See if it's a string object*/
355  /*This returns the length excluding the NULL if it's a string,
356  which is what we want*/
357  if (PyObject_AsCharBuffer(objPtr, (const char **)bytesPtrPtr, &size) == -1)
358  return 0;
359  }
360  *lengthPtr = size;
361  return 1;
362 }
363 
364 static int getPointerReadNoLength(PyObject* objPtr, unsigned char** bytesPtrPtr)
365 {
366  int length;
367  return getPointerRead(objPtr, bytesPtrPtr, &length);
368 }
369 
370 static int getPointerWriteCheckIndices(PyObject* objPtr, unsigned char** bytesPtrPtr, int* lengthPtr)
371 {
372  int checkLength = *lengthPtr;
373 
374  if (getPointerWrite(objPtr, bytesPtrPtr, lengthPtr) == 0)
375  return 0;
376 
377  //If sequence is non-NULL and too short...
378  if (*bytesPtrPtr && (*lengthPtr < checkLength))
379  {
380  PyErr_SetString(PyExc_IndexError, "A sequence passed to cryptlib was too small");
381  return 0;
382  }
383  return 1;
384 }
385 
386 static int getPointerReadString(PyObject* objPtr, char** charPtrPtr)
387 {
388  Py_ssize_t length = 0;
389  char* newPtr = NULL;
390 
391  if (objPtr == Py_None)
392  {
393  *charPtrPtr = NULL;
394  return 1;
395  }
396 
397  /*See if it's a string or a buffer object*/
398  if (PyObject_AsCharBuffer(objPtr, charPtrPtr, &length) == -1)
399  {
400  /*See if it's an array*/
401  PyErr_Clear();
402  if (PyObject_AsWriteBuffer(objPtr, charPtrPtr, &length) == -1)
403  return 0;
404  }
405  /*This code isn't necessary for a string, but it is for arrays and buffers,
406  so we do it always anyway, since the PyObject_AsCharBuffer apparently doesn't
407  guarantee us null-terminated data, and this way releasePointerString() doesn't
408  have to differentiate */
409  newPtr = malloc(length+1);
410  if (newPtr == NULL)
411  {
412  PyErr_NoMemory();
413  return 0;
414  }
415  memcpy(newPtr, *charPtrPtr, length);
416  newPtr[length] = 0;
417  *charPtrPtr = newPtr;
418  return 1;
419 }
420 
421 static void releasePointer(PyObject* objPtr, unsigned char* bytesPtr)
422 {
423 }
424 
425 static void releasePointerString(PyObject* objPtr, char* charPtr)
426 {
427  free(charPtr);
428 }
429 
430 static PyObject* processStatus(int status)
431 {
432  PyObject* o = NULL;
433 
434  /* If an error has already occurred, ignore the status and just fall through */
435  if (PyErr_Occurred())
436  return(NULL);
437 
438  if (status >= CRYPT_OK)
439  return(Py_BuildValue(""));
440 """
441  pyBeforeFuncs = """\
442  PyErr_SetObject(CryptException, o);
443  Py_DECREF(o);
444  return(NULL);
445 }
446 
447 static int processStatusBool(int status)
448 {
449  PyObject* o = processStatus(status);
450  if (o == NULL)
451  return(0);
452  else
453  {
454  Py_DECREF(o);
455  return(1);
456  }
457 }
458 
459 static PyObject* processStatusReturnInt(int status, int returnValue)
460 {
461  PyObject* o = processStatus(status);
462  if (o == NULL)
463  return(0);
464  else
465  {
466  Py_DECREF(o);
467  o = Py_BuildValue("i", returnValue);
468  return(o);
469  }
470 }
471 
472 static PyObject* processStatusReturnCryptHandle(int status, int returnValue)
473 {
474  PyObject* o2;
475  PyObject* o = processStatus(status);
476 
477  if (o == NULL)
478  return(0);
479  else
480  {
481  Py_DECREF(o);
482  o2 = Py_BuildValue("(i)", returnValue);
483  o = PyObject_CallObject(cryptHandleClass, o2);
484  Py_DECREF(o2);
485  return(o);
486  }
487 }
488 
489 static PyObject* processStatusReturnCryptQueryInfo(int status, CRYPT_QUERY_INFO returnValue)
490 {
491  PyObject* o2;
492  PyObject* o = processStatus(status);
493 
494  if (o == NULL)
495  return(0);
496  else
497  {
498  Py_DECREF(o);
499  o2 = Py_BuildValue("(siiii)", returnValue.algoName, returnValue.blockSize, returnValue.minKeySize, returnValue.keySize, returnValue.maxKeySize);
500  o = PyObject_CallObject(cryptQueryInfoClass, o2);
501  Py_DECREF(o2);
502  return(o);
503  }
504 }
505 
506 static PyObject* processStatusReturnCryptObjectInfo(int status, CRYPT_OBJECT_INFO returnValue)
507 {
508  PyObject* o2;
509  PyObject* o = processStatus(status);
510 
511  if (o == NULL)
512  return(0);
513  else
514  {
515  Py_DECREF(o);
516  o2 = Py_BuildValue("(iiiis#)", returnValue.objectType, returnValue.cryptAlgo, returnValue.cryptMode, returnValue.hashAlgo, returnValue.salt, returnValue.saltSize);
517  o = PyObject_CallObject(cryptObjectInfoClass, o2);
518  Py_DECREF(o2);
519  return(o);
520  }
521 }
522 """
523  pyBeforeModuleFunctions = """
524 
525 static PyMethodDef module_functions[] =
526 {
527 """
528  pyBeforeInts = r""" {0, 0}
529 };
530 
531 DL_EXPORT(void) initcryptlib_py(void)
532 {
533  PyObject* module;
534  PyObject* moduleDict;
535 
536  PyObject* v = NULL;
537  PyObject *globalsDict;
538 
539  module = Py_InitModule("cryptlib_py", module_functions);
540  moduleDict = PyModule_GetDict(module);
541 
542  CryptException = PyErr_NewException("cryptlib_py.CryptException", NULL, NULL);
543  PyDict_SetItemString(moduleDict, "CryptException", CryptException);
544 
545  globalsDict = PyEval_GetGlobals();
546  PyRun_String(
547 "from array import *\n\
548 import types\n\
549 class CryptHandle:\n\
550  def __init__(self, value):\n\
551  self.__dict__['value'] = value\n\
552  def __int__(self):\n\
553  return self.value\n\
554  def __str__(self):\n\
555  return str(self.value)\n\
556  def __repr__(self):\n\
557  return str(self.value)\n\
558  def __getattr__(self, name):\n\
559  name = name.upper()\n\
560  if not name.startswith('CRYPT_'):\n\
561  name = 'CRYPT_' + name\n\
562  nameVal = globals()[name]\n\
563  try:\n\
564  return cryptGetAttribute(self, nameVal)\n\
565  except CryptException, ex:\n\
566  length = cryptGetAttributeString(self, nameVal, None)\n\
567  buf = array('c', '0' * length)\n\
568  length = cryptGetAttributeString(self, nameVal, buf)\n\
569  return ''.join(buf[:length])\n\
570  def __setattr__(self, name, value):\n\
571  name = name.upper()\n\
572  if not name.startswith('CRYPT_'):\n\
573  name = 'CRYPT_' + name\n\
574  nameVal = globals()[name]\n\
575  if isinstance(value, types.IntType) or isinstance(value, CryptHandle):\n\
576  cryptSetAttribute(self, nameVal, value)\n\
577  else:\n\
578  cryptSetAttributeString(self, nameVal, value)\n",
579  Py_file_input, globalsDict, moduleDict);
580 
581 
582  PyRun_String(
583 "class CRYPT_QUERY_INFO:\n\
584  def __init__(self, algoName, blockSize, minKeySize, keySize, maxKeySize):\n\
585  self.algoName = algoName\n\
586  self.blockSize = blockSize\n\
587  self.minKeySize = minKeySize\n\
588  self.keySize = keySize\n\
589  self.maxKeySize = maxKeySize\n",
590  Py_file_input, globalsDict, moduleDict);
591 
592  PyRun_String(
593 "class CRYPT_OBJECT_INFO:\n\
594  def __init__(self, objectType, cryptAlgo, cryptMode, hashAlgo, salt):\n\
595  self.objectType = objectType\n\
596  self.cryptAlgo = cryptAlgo\n\
597  self.cryptMode = cryptMode\n\
598  self.hashAlgo = hashAlgo\n\
599  self.salt = salt\n",
600  Py_file_input, globalsDict, moduleDict);
601 
602  cryptHandleClass = PyMapping_GetItemString(moduleDict, "CryptHandle");
603  cryptQueryInfoClass = PyMapping_GetItemString(moduleDict, "CRYPT_QUERY_INFO");
604  cryptObjectInfoClass = PyMapping_GetItemString(moduleDict, "CRYPT_OBJECT_INFO");
605 
606  Py_DECREF(globalsDict);
607 
608 """
609  pyAfterInts = "}"
610 
611  paramCharPtrTemplate = "%(name)s, # string\n"
612  paramIntTemplate = "%(name)s, # integer\n"
613  paramIntTypeTemplate = "%(name)s, # %(type)s\n"
614  paramEnumTypeTemplate = "%(name)s, # %(type)s\n"
615  commentPrefix = "# " #pad to 2-characters for formatting consistency
616  classPrefix = "class crypt:\n"
617  classPostfix= ""
618  outFile = os.path.join(outDir, "cryptlib.py")
619  sFuncs = "\n"
620  sInts = "\n"
621  sModFuncs = ""
622  setupPy = r"""#!/usr/bin/env python
623 
624 from distutils.core import setup, Extension
625 import sys
626 
627 if sys.platform == "win32":
628  ext = Extension("cryptlib_py",
629  sources=["python.c"],
630  library_dirs=['../binaries'],
631  libraries=['cl32'])
632 else:
633  ext = Extension("cryptlib_py",
634  sources=["python.c"],
635  library_dirs=['..'],
636  libraries=['cl'])
637 
638 setup(name="cryptlib_py", ext_modules=[ext])
639 """
640 
641 elif language == "net":
642  typedefEnumTemplate = "// %(typedefName)s"
643  typedefEnumElementTemplate = "public const int %(name)-NPADs = %(value)-VPADs;"
644 
645  typedefEnumElementTemplateComment = typedefEnumElementTemplate + " // %(comment)s"
646  simpleEnumElementTemplate = "public const int %(name)-NPADs = %(value)-VPADs;"
647  simpleEnumElementTemplateComment = simpleEnumElementTemplate + " // %(comment)s"
648  defineNPad = "40"
649  defineVPad = "4"
650  defineTemplate = simpleEnumElementTemplate
651  defineTemplateComment = simpleEnumElementTemplateComment
652  exceptionPrefix = """
653 [StructLayout(LayoutKind.Sequential, Pack=0, CharSet=CharSet.Ansi)]
654 public class CRYPT_QUERY_INFO
655 {
656  [MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]public String algoName;
657  public int blockSize;
658  public int minKeySize;
659  public int keySize;
660  public int maxKeySize;
661 
662  public CRYPT_QUERY_INFO(){}
663 
664  public CRYPT_QUERY_INFO(String newAlgoName, int newBlockSize, int newMinKeySize, int newKeySize, int newMaxKeySize)
665  {
666  algoName = newAlgoName;
667  blockSize = newBlockSize;
668  minKeySize = newMinKeySize;
669  keySize = newKeySize;
670  maxKeySize = newMaxKeySize;
671  }
672 }
673 
674 [StructLayout(LayoutKind.Sequential, Pack=0, CharSet=CharSet.Ansi)]
675 public class CRYPT_OBJECT_INFO
676 {
677  public int objectType;
678  public int cryptAlgo;
679  public int cryptMode;
680  public int hashAlgo;
681  [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]public byte[] salt;
682  public int saltSize;
683 
684  public CRYPT_OBJECT_INFO()
685  {
686  salt = new byte[64];
687  saltSize = 64;
688  }
689 
690  public CRYPT_OBJECT_INFO(int newObjectType, int newCryptAlgo, int newCryptMode, int newHashAlgo, byte[] newSalt)
691  {
692  objectType = newObjectType;
693  cryptAlgo = newCryptAlgo;
694  cryptMode = newCryptMode;
695  hashAlgo = newHashAlgo;
696  }
697 }
698 
699 public class CryptException : ApplicationException
700 {
701  public int Status { get { return (int)Data["Status"]; } }
702 
703  public int ExtraInfo { get { return (int)Data["ExtraInfo"]; } }
704 
705  public CryptException(int status)
706  : base(convertMessage(status))
707  {
708  Data.Add("Status", status);
709  }
710 
711  public CryptException(int status, int extra)
712  : base(convertMessage(status))
713  {
714  Data.Add("Status", status);
715  Data.Add("ExtraInfo", extra);
716  }
717 
718  private static string convertMessage(int status)
719  {
720  String prefix = Convert.ToString(status) + ": ";
721  switch (status)
722  {
723 """
724  exceptionPostfix = """\
725  default: return prefix + "Unknown Exception ?!?!";
726  }
727  }
728 }"""
729  exceptionTemplate = """\
730  case crypt.%(name)s: return prefix + "%(comment)s";
731 """
732  addFunctionWrappers = 1
733  wholeFunctionDeclaration = None
734  functionDeclaration = "public static "
735  returnIntDeclaration = "int "
736  returnVoidDeclaration = "void "
737  paramsPrefix = "("
738  paramsPostfix = ");"
739  paramWhiteSpace = "\t\t\t\t\t\t"
740  paramVoidPtrTemplate = "byte[] %(name)s,\n"
741  addFunctionAlternate = 0
742  paramCharPtrTemplate = "String %(name)s,\n"
743  paramIntTemplate = "int %(name)s,\n"
744  paramIntTypeTemplate = "int %(name)s, // %(type)s\n"
745  wrapperLengthTemplate = "%(1)s == null ? 0 : %(1)s.Length, "
746  wrapperStringLengthTemplate = "%(1)s == null ? 0 : new UTF8Encoding().GetByteCount(%(1)s), "
747  wrapperStringReplace = ("byte[]", "String")
748  wrapperStringTemplate = "%(1)s == null ? null : new UTF8Encoding().GetBytes(%(1)s)"
749  #ENUM IDIOM
750  #paramEnumTypeTemplate = "%(type)s %(name)s,\n"
751  #ENUMs as ints
752  paramEnumTypeTemplate = "int %(name)s, // %(type)s\n"
753  commentPrefix = "//"
754  classPrefix = """using System;
755 using System.Runtime.InteropServices;
756 using System.Text;
757 
758 namespace cryptlib
759 {
760 
761 public class crypt
762 {
763  """
764  classPostfix = """
765  /* Helper Functions */
766 
767  private static void processStatus(int status)
768  {
769  if (status < crypt.OK)
770  throw new CryptException(status);
771  }
772 
773 
774  private static void processStatus(int status, int extraInfo)
775  {
776  if (status < crypt.OK)
777  throw new CryptException(status, extraInfo);
778  }
779 
780  private static void checkIndices(byte[] array, int sequenceOffset, int sequenceLength)
781  {
782  if (array == null)
783  {
784  if (sequenceOffset == 0)
785  return;
786  else
787  throw new IndexOutOfRangeException();
788  }
789 
790  int arrayLength = array.Length;
791 
792  if (sequenceOffset < 0 ||
793  sequenceOffset >= arrayLength ||
794  sequenceOffset + sequenceLength > arrayLength)
795  throw new IndexOutOfRangeException();
796  }
797 
798  private static void getPointer(byte[] buffer, int bufferOffset, ref GCHandle bufferHandle, ref IntPtr bufferPtr)
799  {
800  if (buffer == null)
801  return;
802  bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
803  bufferPtr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, bufferOffset);
804  }
805 
806  private static void releasePointer(GCHandle bufferHandle)
807  {
808  if (bufferHandle.IsAllocated)
809  bufferHandle.Free();
810  }
811 }
812 """
813  sFuncs = None
814  sInts = None
815 
816 
817 
818 s = open(inFile).read()
819 inFileTabSize = 4
820 
821 #Global variables
822 #These accumulate information about the types in the input file
823 #----------------------------------------------------------------
824 nameSpace = {} #Accumulate enum'd values here and use them to eval() the RHS of new ones
825 enumTypes = [] #Accumulate typedef'd enum types here
826 intTypes = [] #Accumulate typedef'd int types here
827 structTypes = []#Accumulate typedef'd struct types here
828 rawTypes = ["char", "int", "void"]
829 functionNames = [] #Accumulate function names here
830 rawParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of original c code)
831 newParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of new java/python code)
832 newReturnStructsDict = {} #Accumulate function name -> ParamStruct of return parameter (of new java/python code)
833 newDiscardedStructsDict = {} #Accumulate function name -> ParamStruct of discarded parameter
834 lengthIndicesDict = {} #Accumulate function name -> indices in newParamStructs of lengths (used for python)
835 offsetIndicesDict= {} #Accumulate function name -> indices in newParamStructs of offsets (used for python)
836 errors = {} #Dictionary mapping return values to exception objects
837 
838 print "Parsing input file and generating %s files..." % language
839 
840 #Removing enclosing include guard
841 #---------------------------------
842 s = re.search(r"#ifndef _CRYPTLIB_DEFINED\n(.*)\n#endif", s, re.DOTALL).group(1)
843 
844 #Ignore anything before "#define C_INOUT..."
845 #--------------------------------------------
846 s = s[re.search(r"#define C_INOUT.*?\n", s, re.DOTALL).end() : ]
847 
848 #Remove all conditionals
849 #------------------------
850 while 1:
851  endifMatch = re.search(r"#endif.*?\n", s, re.DOTALL)
852  if endifMatch == None:
853  break
854  ifdefIndex = s.rfind("#if", 0, endifMatch.start())
855  s = s[ : ifdefIndex] + s[endifMatch.end() : ]
856 
857 
858 #Delete lines used for extended function and function-parameter checking
859 #like C_CHECK_RETVAL C_NONNULL_ARG( ( 3 ) ) \
860 #--------------------------------------------
861 functionParamterPattern = re.compile(r"((C_CHECK_RETVAL|C_NONNULL_ARG\s*\(\s*\([ \t0-9,]+\s*\)\s*\))\s+(\\\n)?)", re.DOTALL)
862 while 1:
863  deleteExtended = functionParamterPattern.search(s)
864  if deleteExtended == None:
865  break
866  s = s[ : deleteExtended.start(1) ] + s[ deleteExtended.end(1) : ]
867 
868 
869 #Replace typedef enums
870 #----------------------
871 typedefEnumPattern = re.compile(r"typedef[ \t]+enum[ \t]+{([^}]*)}\s*(\w*);", re.DOTALL) # typedef enum { %1 } %2;
872 
873 #Find the next typedef enum
874 typedefEnumMatch = typedefEnumPattern.search(s)
875 while typedefEnumMatch:
876 
877  #Extract its contents and type name
878  enumContents, typedefName = typedefEnumMatch.groups()
879  enumTypes.append(typedefName)
880 
881  #Parse its contents
882  enumTuples = parseEnumContents(enumContents, nameSpace, "typedef")
883 
884  #Determine the length to pad names to
885  namePad = str( max( [len(e[0]) for e in enumTuples] ) )
886  valuePad = str( max( [len(e[1]) for e in enumTuples] ) )
887 
888  #Construct its output equivalent from language-specific string templates
889  newTypedefEnum = typedefEnumTemplate % vars()
890  for enumTuple in enumTuples:
891  name, value, comment = enumTuple
892  if not comment:
893  paddedTemplate = typedefEnumElementTemplate.replace("NPAD", namePad).replace("VPAD", valuePad)
894  newEnum = paddedTemplate % vars()
895  else:
896  paddedTemplate = typedefEnumElementTemplateComment.replace("NPAD", namePad).replace("VPAD", valuePad)
897  newEnum = paddedTemplate % vars()
898  if newTypedefEnum:
899  newTypedefEnum += "\n" #Don't always add this or we'll get extraneous newlines in python
900  newTypedefEnum += newEnum
901 
902  #print "Output Equivalent of Typedef Enum====\n", newTypedefEnum
903  #raw_input()
904 
905  if sInts:
906  sInts += newTypedefEnum + "\n"
907 
908  #Substitute the output equivalent for the input
909  s = s[ : typedefEnumMatch.start()] + newTypedefEnum + s[typedefEnumMatch.end() : ]
910 
911  #Get next typedef
912  typedefEnumMatch = typedefEnumPattern.search(s, typedefEnumMatch.start() + len(newTypedefEnum))
913 #print "ENUMTYPES:\n",enumTypes
914 
915 #Replace simple enums
916 #---------------------
917 #This works on the theory that we've already replaced all typedef enums with
918 #something that doesn't use the word "enum", so any remaining occurrences of
919 #enum will belong to simple enums.
920 
921 simpleEnumPattern = re.compile(r"enum[ \t]+{([^}]*)};", re.DOTALL) # enum { %1 };
922 
923 #Find the next simple enum
924 simpleEnumMatch = simpleEnumPattern.search(s)
925 while simpleEnumMatch:
926 
927  #Extract its contents
928  enumContents = simpleEnumMatch.group(1)
929 
930  #Parse its contents
931  enumTuples = parseEnumContents(enumContents, nameSpace, "simple")
932 
933  #Determine the length to pad names to
934  namePad = str( max( [len(e[0]) for e in enumTuples] ) )
935  valuePad = str( max( [len(e[1]) for e in enumTuples] ) )
936 
937  #Construct its output equivalent from language-specific string templates
938  newSimpleEnum = ""
939  for enumTuple in enumTuples:
940  name, value, comment = enumTuple
941  if not comment:
942  paddedTemplate = simpleEnumElementTemplate.replace("NPAD", namePad).replace("VPAD", valuePad)
943  newEnum = paddedTemplate % vars()
944  else:
945  paddedTemplate = simpleEnumElementTemplateComment.replace("NPAD", namePad).replace("VPAD", valuePad)
946  newEnum = paddedTemplate % vars()
947  if newSimpleEnum:
948  newSimpleEnum += "\n" #Don't always add this or we'll get extraneous newlines in python
949  newSimpleEnum += newEnum
950 
951  #print "Output Equivalent of Simple Enum====\n", newSimpleEnum
952  #raw_input()
953 
954  if sInts:
955  sInts += newSimpleEnum + "\n"
956 
957  #Substitute the output equivalent for the input
958  s = s[ : simpleEnumMatch.start()] + newSimpleEnum + s[simpleEnumMatch.end() : ]
959 
960  #Get next typedef
961  simpleEnumMatch = simpleEnumPattern.search(s, simpleEnumMatch.start() + len(newSimpleEnum))
962 
963 
964 #Replace #define'd constants
965 #----------------------------
966 definePattern = re.compile(r"#define[ \t]+(\w+)[ \t]+([-\w]+)[ \t]*(/\*.*\*/*)?") # #define %1 %2 [/*%3*/]
967 
968 exceptionString = exceptionPrefix
969 
970 #Find the next #define
971 defineMatch = definePattern.search(s)
972 while defineMatch:
973 
974  #Parse its contents
975  name, value, comment = defineMatch.groups()
976  if not name.startswith("CRYPT_"):
977  raise "name doesn't start with CRYPT_"+name
978  name = name.replace("CRYPT_", "")
979 
980  #Construct its output equivalent from language-specific string templates
981  if not comment:
982  paddedTemplate = defineTemplate.replace("NPAD", defineNPad).replace("VPAD", defineVPad)
983  newDefine = paddedTemplate % vars()
984  else:
985  comment = comment[2:-2].strip()
986  paddedTemplate = defineTemplateComment.replace("NPAD", defineNPad).replace("VPAD", defineVPad)
987  newDefine = paddedTemplate % vars()
988 
989  #print "define: " + newDefine
990  #raw_input()
991 
992  if sInts:
993  sInts += newDefine + "\n"
994 
995  #Substitute the output equivalent for the input
996  s = s[ : defineMatch.start()] + newDefine + s[defineMatch.end() : ]
997 
998  #Append to exception string if error
999  if name.startswith("ERROR_") or name.startswith("ENVELOPE_RESOURCE"):
1000  exceptionString += exceptionTemplate % vars()
1001 
1002  #Get next #define
1003  defineMatch = definePattern.search(s, defineMatch.start() + len(newDefine))
1004 
1005 exceptionString += exceptionPostfix
1006 
1007 #Replace #define'd constants with parenthesis
1008 #--------------------------------------------
1009 definePattern = re.compile(r"#define[ \t]+(\w+)[ \t]+\([ \t]*([-0-9]+)[ \)]*\)[ \t]*(/\*.*\*/*)?") # #define %1 ( %2 ) [/*%3*/]
1010 
1011 exceptionString = exceptionPrefix
1012 
1013 #Find the next #define
1014 defineMatch = definePattern.search(s)
1015 while defineMatch:
1016 
1017  #Parse its contents
1018  name, value, comment = defineMatch.groups()
1019  if not name.startswith("CRYPT_"):
1020  raise "name doesn't start with CRYPT_"+name
1021  name = name.replace("CRYPT_", "")
1022 
1023  #Construct its output equivalent from language-specific string templates
1024  if not comment:
1025  paddedTemplate = defineTemplate.replace("NPAD", defineNPad).replace("VPAD", defineVPad)
1026  newDefine = paddedTemplate % vars()
1027  else:
1028  comment = comment[2:-2].strip()
1029  paddedTemplate = defineTemplateComment.replace("NPAD", defineNPad).replace("VPAD", defineVPad)
1030  newDefine = paddedTemplate % vars()
1031 
1032  #print "define: " + newDefine
1033  #raw_input()
1034 
1035  if sInts:
1036  sInts += newDefine + "\n"
1037 
1038  #Substitute the output equivalent for the input
1039  s = s[ : defineMatch.start()] + newDefine + s[defineMatch.end() : ]
1040 
1041  #Append to exception string if error
1042  if name.startswith("ERROR_") or name.startswith("ENVELOPE_RESOURCE"):
1043  exceptionString += exceptionTemplate % vars()
1044 
1045  #Get next #define
1046  defineMatch = definePattern.search(s, defineMatch.start() + len(newDefine))
1047 
1048 exceptionString += exceptionPostfix
1049 
1050 #Comment out #define'd macros
1051 #-----------------------------
1052 definePattern = re.compile(r"#define[ \t]+[^(]+\([^\)]*\)([^\n]*\\\n)*[^\n]*")
1053 defineMatch = definePattern.search(s)
1054 while defineMatch:
1055  #print "defined macros:", defineMatch.group()
1056  #raw_input()
1057  define = defineMatch.group()
1058  newDefine = commentPrefix + "CRYPTLIBCONVERTER - NOT SUPPORTED:\n" + define
1059  newDefine = newDefine.replace("\n", "\n"+commentPrefix)
1060  s = s[ : defineMatch.start()] + newDefine + s[defineMatch.end() : ]
1061  defineMatch = definePattern.search(s, defineMatch.start() + len(newDefine))
1062 
1063 #Comment out typedef integer types
1064 #----------------------------------
1065 typedefIntPattern = re.compile(r"typedef[ \t]+int[ \t]+([^ \t]*)[ \t]*;[ \t]*\n")
1066 typedefIntMatch = typedefIntPattern.search(s)
1067 while typedefIntMatch:
1068  typedefInt = typedefIntMatch.group()
1069  typedefIntName = typedefIntMatch.group(1)
1070  intTypes.append(typedefIntName)
1071  #print "typedef int:", typedefInt
1072  #raw_input()
1073  newTypedefInt = commentPrefix + "CRYPTLIBCONVERTER - NOT NEEDED: " + typedefInt
1074  s = s[ : typedefIntMatch.start()] + newTypedefInt + s[typedefIntMatch.end() : ]
1075  typedefIntMatch = typedefIntPattern.search(s, typedefIntMatch.start() + len(newTypedefInt))
1076 #print "INTTYPES:\n",intTypes
1077 
1078 #Comment out typedef structs
1079 #----------------------------
1080 typedefStructPattern = re.compile(r"typedef[ \t]+struct[ \t]\{[^}]*}[ \t]*([^;]+);")
1081 typedefStructMatch = typedefStructPattern.search(s)
1082 while typedefStructMatch:
1083  typedefStruct = typedefStructMatch.group()
1084  typedefStructName = typedefStructMatch.group(1)
1085  structTypes.append(typedefStructName)
1086  #print "typedef struct:", typedefStructName
1087  #raw_input()
1088  newTypedefStruct = commentPrefix + "CRYPTLIBCONVERTER - NOT SUPPORTED:\n" + typedefStruct
1089  newTypedefStruct = newTypedefStruct.replace("\n", "\n"+commentPrefix)
1090  s = s[ : typedefStructMatch.start()] + newTypedefStruct + s[typedefStructMatch.end() : ]
1091  typedefStructMatch = typedefStructPattern.search(s, typedefStructMatch.start() + len(newTypedefStruct))
1092 #print "STRUCTTYPES:\n",structTypes
1093 #raw_input()
1094 
1095 #Translate functions
1096 #--------------------
1097 functionPattern = re.compile(r"C_RET[ \t]+([^ \t]+)[ \t]*\(([^\)]*)\);", re.DOTALL)
1098 functionMatch = functionPattern.search(s)
1099 while functionMatch:
1100  function = functionMatch.group()
1101  functionName, functionParams = functionMatch.groups()
1102  if not functionName.startswith("crypt"):
1103  raise "name doesn't start with crypt"+functionName
1104  functionName = functionName[len("crypt") : ]
1105  functionNames.append(functionName)
1106  #print "function:", functionName, functionParams
1107  #raw_input()
1108 
1109  #Parse its parameters
1110  paramStructs = parseFunctionParams(functionParams)
1111 
1112  #Add raw list of ParamStructs to dictionary
1113  #This will be used later, when generating the .c glue code
1114  rawParamStructsDict[functionName] = paramStructs
1115 
1116  # Since java and python don't have pass-by-reference, what we do is migrate the
1117  # output int parameter in certain functions into the return value. If the function
1118  # creates or returns values such as integers or a (void*, int*) pair, we record
1119  # the indexes of the parameters to migrate. We do this in functions like:
1120  # cryptCreate*() # return handle of new object
1121  # cryptGetAttribute() # return integer value of attribute
1122  # cryptGetAttributeString() # convert (void*, int*) to python string or java byte array
1123  # cryptExportKey() # convert (void*, int*) "
1124  # cryptCreateSignature() # convert (void*, int*)
1125  # cryptKeysetOpen() # return handle
1126  # cryptGetPublicKey() # return handle
1127  # cryptGetPrivateKey() # return handle
1128  # cryptGetCertExtension() # convert (void*, int) but DISCARD criticalFlag (the int* before)!
1129  # cryptImportCert() # return handle
1130  # cryptExportCert() # convert (void*, int)
1131  # cryptCAGetItem() # return handle
1132  # cryptCACertManagement() # return handle
1133  # cryptPushData() # return integer (# of bytes copied)
1134  # cryptPopData() # convert (void*, int*) even though they're not adjacent
1135  discardIntIndex = -1
1136  returnIntIndex = -1
1137  returnVoidPtrIndex = -1
1138  discardInLengthIndex1 = -1 # To discard input lengths, since python don't need these
1139  discardInLengthIndex2 = -1
1140 
1141  #Scan through looking for a void pointer preceded by "keyIDtype"
1142  #Convert it into a char*
1143  index = 1
1144  for p in paramStructs[1:]:
1145  p2 = paramStructs[index-1]
1146  if p.isPtr and p.type=="void" and p2.type=="CRYPT_KEYID_TYPE":
1147  p.type = "char"
1148  index += 1
1149 
1150  #Scan through looking for output int pointers (or structs)?!
1151  #If there's two, we will migrate the second occurrence to the return value
1152  #and discard the first so as to handle cryptGetCertExtension()
1153  index = 0
1154  for p in paramStructs:
1155  if p.isOut and p.isPtr and (p.category=="intType" or p.type=="int" or p.category=="structType"):
1156  if returnIntIndex != -1:
1157  if discardIntIndex != -1:
1158  raise "Found two returned ints to discard?!"
1159  discardIntIndex = returnIntIndex
1160  returnIntIndex = index
1161  index += 1
1162 
1163  #Record the migrated return value's ParamStruct
1164  if returnIntIndex != -1:
1165  newReturnStructsDict[functionName] = paramStructs[returnIntIndex]
1166 
1167  #Return the discarded value's ParamStruct
1168  if discardIntIndex != -1:
1169  newDiscardedStructsDict[functionName] = paramStructs[discardIntIndex]
1170 
1171  #Copy the parsed parameters and remove those we're going to migrate or discard
1172  newParamStructs = [paramStructs[count]
1173  for count in range(len(paramStructs))
1174  if count not in (discardIntIndex, returnIntIndex)]
1175 
1176  #Indices of input offsets and lengths
1177  offsetIndices = []
1178  lengthIndices = []
1179 
1180  #Scan through looking for void pointer, add an int offset
1181  index = 0
1182  while 1:
1183  if index >= len(newParamStructs):
1184  break
1185  p = newParamStructs[index]
1186  if p.isPtr and p.type=="void":
1187  newp = ParamStruct()
1188  newp.type = "int"
1189  newp.isPtr = 0
1190  newp.isOut = 0
1191  newp.category = "rawType"
1192  newp.name = p.name+"Offset"
1193  newParamStructs = newParamStructs[:index+1] + [newp] + newParamStructs[index+1:]
1194  offsetIndices.append(index+1)
1195  if not p.isOut and len(newParamStructs)> index+2 and newParamStructs[index+2].type == "int":
1196  lengthIndices.append(index+2)
1197  index += 1
1198 
1199  #Add processed list of ParamStructs to dictionary
1200  #This will be used later, when generating the .c glue code
1201  newParamStructsDict[functionName] = newParamStructs
1202  lengthIndicesDict[functionName] = lengthIndices
1203  offsetIndicesDict[functionName] = offsetIndices
1204 
1205  #Used for Python
1206  if wholeFunctionDeclaration:
1207  newFunction = wholeFunctionDeclaration % functionName
1208  if sFuncs:
1209  sFuncs += newFunction + "\n"
1210  else: assert(0)
1211  sModFuncs += (moduleFunctionEntry % (functionName, functionName)) + "\n"
1212  else: #Java
1213 
1214  #Construct new function declaration from language-specific templates
1215  newFunction = functionDeclaration
1216  if returnIntIndex != -1:
1217  if newReturnStructsDict.get(functionName).category == "structType":
1218  newFunction += newReturnStructsDict.get(functionName).type + " "
1219  else:
1220  newFunction += returnIntDeclaration
1221  else:
1222  newFunction += returnVoidDeclaration
1223  newFunction += functionName + paramsPrefix
1224  if len(newParamStructs):
1225  newFunction += "\n" + paramWhiteSpace
1226  if offsetIndices or lengthIndices:
1227  newFunctionWrapper = newFunction
1228  newFunctionWrapperArgs = ""
1229  else:
1230  newFunctionWrapper = None
1231  #At this point I'm just getting lazy. Basically, we automatically generate
1232  #String wrappers for function that take void* input parameters. Encrypt and
1233  #Decrypt take void* in/out parameters. We should be smart enough to detect
1234  #these and not generate wrappers for them, but instead, since we don't otherwise
1235  #differentiate between C_IN and C_INOUT, we just hardcodedly exclude these
1236  #from having String wrappers
1237  if offsetIndices and lengthIndices and functionName not in ("Encrypt", "Decrypt"):
1238  newFunctionStringWrapper = newFunction
1239  newFunctionStringWrapperArgs = ""
1240  else:
1241  newFunctionStringWrapper = None
1242  newFunctionStringWrapperArgs = ""
1243  index = 0
1244  for p in newParamStructs:
1245  if p.category == "rawType" and p.type == "void" and p.isPtr:
1246  template = paramVoidPtrTemplate
1247  previousBufferName = p.name
1248  elif p.category == "rawType" and p.type == "char" and p.isPtr:
1249  template = paramCharPtrTemplate
1250  elif p.category == "rawType" and p.type == "int" and not p.isPtr:
1251  template = paramIntTemplate
1252  elif p.category == "intType" and not p.isPtr:
1253  template = paramIntTypeTemplate
1254  elif p.category == "enumType" and not p.isPtr:
1255  template = paramEnumTypeTemplate
1256  #elif p.category == "structType"
1257  else:
1258  raise "Unrecognized parameter type! " + str(p)
1259 
1260  #Strip out commas from the last param template, kind of a hack..
1261  if index == len(newParamStructs)-1:
1262  template = template[:].replace(",", "")
1263 
1264  #Update the main function with this new param
1265  newFunction += template % vars(p)
1266  newFunction += paramWhiteSpace
1267 
1268  #Update the wrapper function with this new param
1269  #If this is not a special param...
1270  if addFunctionWrappers and newFunctionWrapper and \
1271  index not in offsetIndices and index not in lengthIndices:
1272  #Determine if this is the last param in the wrapper function
1273  anyMoreParams = [e for e in range(index+1, len(newParamStructs))
1274  if e not in offsetIndices and e not in lengthIndices]
1275 
1276  #Update the wrapper function's param list
1277  if not anyMoreParams:
1278  template = template[:].replace(",", "")
1279  newFunctionWrapper += template % vars(p)
1280  newFunctionWrapper += paramWhiteSpace
1281 
1282  #Update the wrapper function's args that it uses to call the main function
1283  newFunctionWrapperArgs += p.name
1284  newFunctionWrapperArgs += ", "
1285 
1286  #Do the same things for the string wrapper
1287  if newFunctionStringWrapper:
1288  newFunctionStringWrapper += template % vars(p)
1289  newFunctionStringWrapper += paramWhiteSpace
1290  if p.type=="void" and p.isPtr and not p.isOut:
1291  newFunctionStringWrapperArgs += wrapperStringTemplate % {"1":p.name};
1292  else:
1293  newFunctionStringWrapperArgs += p.name
1294  newFunctionStringWrapperArgs += ", "
1295  else:
1296  #If this is a special param (an offset or length)...
1297  if index in offsetIndices:
1298  newFunctionWrapperArgs += "0, "
1299  newFunctionStringWrapperArgs += "0, "
1300  elif index in lengthIndices:
1301  newFunctionWrapperArgs += wrapperLengthTemplate % {"1":previousBufferName}
1302  newFunctionStringWrapperArgs += wrapperStringLengthTemplate % {"1":previousBufferName}
1303  index += 1
1304 
1305  #Add final postfix of ); to the main and wrapper param lists
1306  newFunction += paramsPostfix
1307  if newFunctionWrapper:
1308  newFunctionWrapper += paramsPostfix
1309  if newFunctionStringWrapper:
1310  newFunctionStringWrapper += paramsPostfix
1311 
1312  #If this function takes a void* parameter, and we want to convert this
1313  #into two different versions, duplicate and modify the version here
1314  if addFunctionAlternate:
1315  if newFunction.find(paramVoidPtrAlternate[0]) != -1:
1316  newFunction += "\n" + newFunction.replace(*paramVoidPtrAlternate)
1317 
1318  #If we've prepared a wrapper function to eliminate need for offset[, length]:
1319  if addFunctionWrappers and newFunctionWrapper:
1320  newFunctionWrapper = newFunctionWrapper.replace("native ", "")
1321  newFunctionWrapper = newFunctionWrapper[:-1] + " { return %s(%s); }" % (functionName, newFunctionWrapperArgs[:-2])
1322  if returnIntIndex == -1:
1323  newFunctionWrapper = newFunctionWrapper.replace("return ", "")
1324  #Duplicate and modify the wrapper function
1325  if addFunctionAlternate:
1326  newFunctionWrapper2 = newFunctionWrapper.replace(*paramVoidPtrAlternate)
1327  newFunctionWrapper2 = newFunctionWrapper2.replace("capacity()", "length")
1328  newFunctionWrapper += "\n" + newFunctionWrapper2
1329  newFunction += "\n" + newFunctionWrapper
1330  if addFunctionWrappers and newFunctionStringWrapper:
1331  newFunctionStringWrapper = newFunctionStringWrapper.replace("native ", "")
1332  newFunctionStringWrapper = newFunctionStringWrapper[:-1] + " { return %s(%s); }" % (functionName, newFunctionStringWrapperArgs[:-2])
1333  newFunctionStringWrapper = newFunctionStringWrapper.replace(*wrapperStringReplace)
1334  if returnIntIndex == -1:
1335  newFunctionStringWrapper = newFunctionStringWrapper.replace("return ", "")
1336  newFunction += "\n" + newFunctionStringWrapper
1337 
1338  #Add a special-case string accessor for GetAttributeString() to Java and .NET
1339  if functionName == "GetAttributeString" and language == "java":
1340  newFunction += """
1341 public static String GetAttributeString(
1342  int cryptHandle, // CRYPT_HANDLE
1343  int attributeType // CRYPT_ATTRIBUTE_TYPE
1344  ) throws CryptException
1345  {
1346  int length = GetAttributeString(cryptHandle, attributeType, (byte[])null);
1347  byte[] bytes = new byte[length];
1348  length = GetAttributeString(cryptHandle, attributeType, bytes);
1349  return new String(bytes, 0, length);
1350  }
1351 """
1352  elif functionName == "GetAttributeString" and language == "net":
1353  newFunction += """
1354 public static String GetAttributeString(
1355  int cryptHandle, // CRYPT_HANDLE
1356  int attributeType // CRYPT_ATTRIBUTE_TYPE
1357  )
1358  {
1359  int length = GetAttributeString(cryptHandle, attributeType, null);
1360  byte[] bytes = new byte[length];
1361  length = GetAttributeString(cryptHandle, attributeType, bytes);
1362  return new UTF8Encoding().GetString(bytes, 0, length);
1363  }
1364 """
1365  #Add special-case functions for cryptAddRandom(), since it allows NULL as a
1366  #first parameter, and a pollType constant in place of the length
1367  elif functionName == "AddRandom":
1368  if language == "java":
1369  newFunction += """
1370 public static native void AddRandom(
1371  int pollType
1372  ) throws CryptException;
1373 """
1374  elif language == "net":
1375  newFunction += """
1376 public static void AddRandom(
1377  int pollType
1378  );
1379 """
1380 
1381  # Add an extra linebreak between functions
1382  # This isn't in cryptlib.h, but it makes the converted files more readable
1383  if s[functionMatch.end()+1] != "\n":
1384  newFunction += "\n"
1385 
1386  s = s[ : functionMatch.start()] + newFunction + s[functionMatch.end() : ]
1387  functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))
1388 
1389 #Translate comments
1390 #-------------------
1391 if language != "java" and language != "net":
1392  while 1:
1393  match = re.search(r"/\*(.*?)\*/", s, re.DOTALL)
1394  if match == None:
1395  break
1396  #print match.group()
1397  #raw_input()
1398  commentStrings = (commentPrefix + match.group(1) + " ").split("\n")
1399  newComment = commentStrings[0]
1400  for commentString in commentStrings[1:]:
1401  if commentString.startswith("\t"):
1402  newComment += "\n" + commentPrefix + (" " * (inFileTabSize-2)) + commentString[1:]
1403  elif commentString.startswith(" "):
1404  newComment += "\n" + commentPrefix + commentString[1:]
1405  else:
1406  newComment += "\n" + commentPrefix + commentString
1407  #print "building up:\n", newComment
1408  #raw_input()
1409  idx = commentString.find("\n")
1410  s = s[ : match.start()] + newComment + s[match.end() : ]
1411 
1412 #Indent each line by one tab
1413 #---------------------------
1414 s = s.replace("\n", "\n\t")
1415 
1416 #Write out file(s)
1417 #Then generate the .h/.c files necessary for language integration
1418 #At this point it's easier to just hardcode constants and have
1419 #separate python and java codepaths
1420 #---------------
1421 if language=="java":
1422 
1423  #Add enclosing class syntax
1424  #---------------------------
1425  s = classPrefix + s + classPostfix
1426 
1427  os.chdir(outDir)
1428  if not os.path.exists("cryptlib"):
1429  os.mkdir("./cryptlib")
1430  os.chdir("./cryptlib")
1431 
1432  print "Writing java files..."
1433  f = open("crypt.java", "w")
1434  f.write(s)
1435  f.close()
1436  f = open("CryptException.java", "w")
1437  f.write(exceptionString)
1438  f.close()
1439  f = open("CRYPT_QUERY_INFO.java", "w")
1440  f.write(cryptQueryInfoString)
1441  f.close()
1442  f = open("CRYPT_OBJECT_INFO.java", "w")
1443  f.write(cryptObjectInfoString)
1444  f.close()
1445 
1446 
1447  print "Compiling java files..."
1448  print os.popen4("javac -classpath .. crypt.java")[1].read() #Compile java file
1449  print os.popen4("javac -classpath .. CryptException.java")[1].read() #Compile java file
1450  print os.popen4("javac -classpath .. CRYPT_QUERY_INFO.java")[1].read() #Compile java file
1451  print os.popen4("javac -classpath .. CRYPT_OBJECT_INFO.java")[1].read() #Compile java file
1452 
1453  os.chdir("..")
1454 
1455  print "Generating jar file..."
1456  print os.popen4("jar cf cryptlib.jar cryptlib/crypt.class cryptlib/CryptException.class cryptlib/CRYPT_QUERY_INFO.class cryptlib/CRYPT_OBJECT_INFO.class cryptlib")[1].read()
1457 
1458  print "Generating JNI header file..."
1459  print os.popen4("javah -classpath . -o cryptlib_jni.h -jni cryptlib.crypt")[1].read() #Generate C header
1460 
1461  s = open("cryptlib_jni.h").read()
1462  os.remove("cryptlib_jni.h")
1463 
1464  print "Generating JNI source file..."
1465 
1466  #Now we take cryptlib_jni.h and derive the .c file from it
1467 
1468  #Strip off headers and footers
1469  #startIndex = s.find("/*\n * Class")
1470  #endIndex = s.find("#ifdef", startIndex)
1471  #s = s[startIndex : endIndex]
1472 
1473  startIndex = s.find("#undef")
1474  endIndex = s.find("/*\n * Class", startIndex)
1475  sold = s
1476  s = s[startIndex : endIndex]
1477 
1478  startIndex = endIndex
1479  endIndex = sold.find("#ifdef", startIndex)
1480  s2 = sold[startIndex : endIndex]
1481 
1482  #Add includes and helper functions
1483  #Note that we assume "cryptlib.h" is one directory behind us
1484  s = r"""
1485 #include "../crypt.h"
1486 
1487 #ifdef USE_JAVA
1488 
1489 #include <jni.h>
1490 #include <stdio.h> //printf
1491 #include <stdlib.h> //malloc, free
1492 
1493 %s
1494 
1495 /* Helper Functions */
1496 
1497 int processStatus(JNIEnv *env, jint status)
1498 {
1499  jclass exClass;
1500  jmethodID exConstructor;
1501  jthrowable obj;
1502 
1503  if (status >= cryptlib_crypt_OK)
1504  return 1;
1505 
1506  exClass = (*env)->FindClass(env, "cryptlib/CryptException");
1507  if (exClass == 0)
1508  {
1509  printf("java_jni.c:processStatus - no class?!\n");
1510  return 0;
1511  }
1512 
1513  exConstructor = (*env)->GetMethodID(env, exClass, "<init>", "(I)V");
1514  if (exConstructor == 0)
1515  {
1516  printf("java_jni.c:processStatus - no constructor?!\n");
1517  return 0;
1518  }
1519 
1520  obj = (*env)->NewObject(env, exClass, exConstructor, status);
1521  if (obj == 0)
1522  {
1523  printf("java_jni.c:processStatus - no object?!\n");
1524  return 0;
1525  }
1526 
1527  if ((*env)->Throw(env, obj) < 0)
1528  {
1529  printf("java_jni.c:processStatus - failed to throw?!\n");
1530  return 0;
1531  }
1532  return 0;
1533 }
1534 
1535 jobject processStatusReturnCryptQueryInfo(JNIEnv *env, int status, CRYPT_QUERY_INFO returnValue)
1536 {
1537  jclass exClass;
1538  jmethodID exConstructor;
1539  jstring algoName;
1540  jobject obj;
1541 
1542  if (status < cryptlib_crypt_OK)
1543  return NULL;
1544 
1545  exClass = (*env)->FindClass(env, "cryptlib/CRYPT_QUERY_INFO");
1546  if (exClass == 0)
1547  {
1548  printf("java_jni.c:processStatusReturnCryptQueryInfo - no class?!\n");
1549  return NULL;
1550  }
1551 
1552  exConstructor = (*env)->GetMethodID(env, exClass, "<init>", "(Ljava/lang/String;IIII)V");
1553  if (exConstructor == 0)
1554  {
1555  printf("java_jni.c:processStatusReturnCryptQueryInfo - no constructor?!\n");
1556  return NULL;
1557  }
1558 
1559  algoName = (*env)->NewStringUTF(env, returnValue.algoName);
1560 
1561  obj = (*env)->NewObject(env, exClass, exConstructor, algoName, returnValue.blockSize, returnValue.minKeySize, returnValue.keySize, returnValue.maxKeySize);
1562  if (obj == 0)
1563  {
1564  printf("java_jni.c:processStatusReturnCryptQueryInfo - no object?!\n");
1565  return NULL;
1566  }
1567 
1568  return obj;
1569 }
1570 
1571 jobject processStatusReturnCryptObjectInfo(JNIEnv *env, int status, CRYPT_OBJECT_INFO returnValue)
1572 {
1573  jclass exClass;
1574  jmethodID exConstructor;
1575  jbyteArray salt;
1576  jobject obj;
1577 
1578  if (status < cryptlib_crypt_OK)
1579  return NULL;
1580 
1581  exClass = (*env)->FindClass(env, "cryptlib/CRYPT_OBJECT_INFO");
1582  if (exClass == 0)
1583  {
1584  printf("java_jni.c:processStatusReturnCryptObjectInfo - no class?!\n");
1585  return NULL;
1586  }
1587 
1588  exConstructor = (*env)->GetMethodID(env, exClass, "<init>", "(IIII[B)V");
1589  if (exConstructor == 0)
1590  {
1591  printf("java_jni.c:processStatusReturnCryptObjectInfo - no constructor?!\n");
1592  return NULL;
1593  }
1594 
1595  salt = (*env)->NewByteArray(env, returnValue.saltSize);
1596  (*env)->SetByteArrayRegion(env, salt, 0, returnValue.saltSize, returnValue.salt);
1597 
1598  obj = (*env)->NewObject(env, exClass, exConstructor, returnValue.objectType, returnValue.cryptAlgo, returnValue.cryptMode, returnValue.hashAlgo, salt);
1599  if (obj == 0)
1600  {
1601  printf("java_jni.c:processStatusReturnCryptObjectInfo - no object?!\n");
1602  return NULL;
1603  }
1604 
1605  return obj;
1606 }
1607 
1608 int checkIndicesArray(JNIEnv *env, jbyteArray array, int sequenceOffset, int sequenceLength)
1609 {
1610  jsize arrayLength;
1611  jclass exClass;
1612 
1613  if (array == NULL)
1614  {
1615  if (sequenceOffset == 0)
1616  return 1;
1617  else
1618  {
1619  exClass = (*env)->FindClass(env, "java/lang/ArrayIndexOutOfBoundsException");
1620  if (exClass == 0)
1621  printf("java_jni.c:checkIndicesArray - no class?!\n");
1622  else
1623  if ((*env)->ThrowNew(env, exClass, "") < 0)
1624  printf("java_jni.c:checkIndicesArray - failed to throw?!\n");
1625  return 0;
1626  }
1627  }
1628 
1629  arrayLength = (*env)->GetArrayLength(env, array);
1630 
1631  if (sequenceOffset < 0 ||
1632  sequenceOffset >= arrayLength ||
1633  sequenceOffset + sequenceLength > arrayLength)
1634  {
1635  exClass = (*env)->FindClass(env, "java/lang/ArrayIndexOutOfBoundsException");
1636  if (exClass == 0)
1637  printf("java_jni.c:checkIndicesArray - no class?!\n");
1638  else
1639  if ((*env)->ThrowNew(env, exClass, "") < 0)
1640  printf("java_jni.c:checkIndicesArray - failed to throw?!\n");
1641  return 0;
1642  }
1643  return 1;
1644 }
1645 
1646 int getPointerArray(JNIEnv* env, jbyteArray array, jbyte** bytesPtrPtr)
1647 {
1648  jboolean isCopy;
1649 
1650  if (array == NULL)
1651  {
1652  (*bytesPtrPtr) = NULL;
1653  return 1;
1654  }
1655 
1656  (*bytesPtrPtr) = (*env)->GetByteArrayElements(env, array, &isCopy);
1657 
1658  if (*bytesPtrPtr == NULL)
1659  {
1660  printf("java_jni.c:getPointer - failed to get elements of array?!\n");
1661  return 0;
1662  }
1663  return 1;
1664 }
1665 
1666 void releasePointerArray(JNIEnv* env,jbyteArray array, jbyte* bytesPtr)
1667 {
1668  if (bytesPtr == NULL)
1669  return;
1670  (*env)->ReleaseByteArrayElements(env, array, bytesPtr, 0);
1671 }
1672 
1673 int checkIndicesNIO(JNIEnv *env, jobject byteBuffer, int sequenceOffset, int sequenceLength)
1674 {
1675  jlong byteBufferLength;
1676  jclass exClass;
1677 
1678  if (byteBuffer == NULL)
1679  {
1680  if (sequenceOffset == 0)
1681  return 1;
1682  else
1683  {
1684  exClass = (*env)->FindClass(env, "java/lang/ArrayIndexOutOfBoundsException");
1685  if (exClass == 0)
1686  printf("java_jni.c:checkIndicesNIO - no class?!\n");
1687  else
1688  if ((*env)->ThrowNew(env, exClass, "") < 0)
1689  printf("java_jni.c:checkIndicesNIO - failed to throw?!\n");
1690  return 0;
1691  }
1692  }
1693 
1694  byteBufferLength = (*env)->GetDirectBufferCapacity(env, byteBuffer);
1695  if (byteBufferLength == -1)
1696  {
1697  exClass = (*env)->FindClass(env, "java/lang/UnsupportedOperationException");
1698  if (exClass == 0)
1699  printf("java_jni.c:checkIndicesNIO - no class?!\n");
1700  else
1701  if ((*env)->ThrowNew(env, exClass,
1702 "Either a non-direct ByteBuffer was passed or your JVM doesn't support JNI access to direct ByteBuffers") < 0)
1703  printf("java_jni.c:checkIndicesNIO - failed to throw?!\n");
1704  return 0;
1705  }
1706 
1707  if (sequenceOffset < 0 ||
1708  sequenceOffset >= byteBufferLength ||
1709  sequenceOffset + sequenceLength > byteBufferLength)
1710  {
1711  exClass = (*env)->FindClass(env, "java/lang/ArrayIndexOutOfBoundsException");
1712  if (exClass == 0)
1713  printf("java_jni.c:checkIndicesNIO - no class?!\n");
1714  else
1715  if ((*env)->ThrowNew(env, exClass, "") < 0)
1716  printf("java_jni.c:checkIndicesNIO - failed to throw?!\n");
1717  return 0;
1718  }
1719  return 1;
1720 }
1721 
1722 int getPointerNIO(JNIEnv* env, jobject byteBuffer, jbyte** bytesPtrPtr)
1723 {
1724  jclass exClass;
1725 
1726  if (byteBuffer == NULL)
1727  {
1728  (*bytesPtrPtr) = NULL;
1729  return 1;
1730  }
1731 
1732  (*bytesPtrPtr) = (*env)->GetDirectBufferAddress(env, byteBuffer);
1733 
1734  if (*bytesPtrPtr == NULL)
1735  {
1736  exClass = (*env)->FindClass(env, "java/lang/UnsupportedOperationException");
1737  if (exClass == 0)
1738  printf("java_jni.c:getPointerNIO - no class?!\n");
1739  else
1740  if ((*env)->ThrowNew(env, exClass, "Your JVM doesn't support JNI access to direct ByteBuffers") < 0)
1741  printf("java_jni.c:getPointerNIO - failed to throw?!\n");
1742  return 0;
1743  }
1744  return 1;
1745 }
1746 
1747 void releasePointerNIO(JNIEnv* env,jbyteArray array, jbyte* bytesPtr)
1748 {
1749 }
1750 
1751 int getPointerString(JNIEnv* env, jstring str, jbyte** bytesPtrPtr)
1752 {
1753  jboolean isCopy;
1754  jsize strLength;
1755  const jbyte* rawBytesPtr;
1756  jclass exClass;
1757 #ifdef __WINCE__
1758  int status;
1759 #endif // __WINCE__
1760 
1761 
1762  if (str == NULL)
1763  {
1764  (*bytesPtrPtr) = NULL;
1765  return 1;
1766  }
1767 
1768  rawBytesPtr = (*env)->GetStringUTFChars(env, str, &isCopy);
1769 
1770  if (rawBytesPtr == NULL)
1771  {
1772  printf("java_jni.c:getPointerString - failed to get elements of String?!\n");
1773  return 0;
1774  }
1775 
1776  strLength = (*env)->GetStringUTFLength(env, str);
1777 
1778 #ifdef __WINCE__
1779  (*bytesPtrPtr) = (jbyte*)malloc(strLength*2+2); // this is unicode, therefore \0 is two bytes long
1780 #else
1781  (*bytesPtrPtr) = (jbyte*)malloc(strLength+1);
1782 #endif // __WINCE__
1783 
1784  if (*bytesPtrPtr == NULL)
1785  {
1786  exClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
1787  if (exClass == 0)
1788  printf("java_jni.c:getPointerString - no class?!\n");
1789  else
1790  if ((*env)->ThrowNew(env, exClass, "") < 0)
1791  printf("java_jni.c:getPointerString - failed to throw?!\n");
1792  (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);
1793  return 0;
1794  }
1795 
1796 #ifdef __WINCE__
1797  status = asciiToUnicode (*bytesPtrPtr, strLength*2+2, rawBytesPtr, strLength+1);
1798  if (status == CRYPT_ERROR_BADDATA) {
1799  (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);
1800  return 0;
1801  }
1802 #else
1803  memcpy(*bytesPtrPtr, rawBytesPtr, strLength);
1804  (*bytesPtrPtr)[strLength] = 0;
1805 #endif // __WINCE__
1806 
1807  (*env)->ReleaseStringUTFChars(env, str, rawBytesPtr);
1808 
1809  return 1;
1810 }
1811 
1812 void releasePointerString(JNIEnv* env, jstring str, jbyte* bytesPtr)
1813 {
1814  if (bytesPtr == NULL)
1815  return;
1816  free(bytesPtr);
1817 }
1818 
1819 %s
1820 
1821 #endif /* USE_JAVA */
1822 """ % (s, s2)
1823 
1824  functionPattern = re.compile(r"JNIEXPORT ([^ \t]+) JNICALL Java_cryptlib_crypt_([^ \t\n]+)\n[ \t]*\(([^\)]*)\);")
1825  functionMatch = functionPattern.search(s)
1826  while functionMatch:
1827  #print functionMatch.groups()
1828 
1829  #Extract the returnType, name, and prototype for this function
1830  function = functionMatch.group()
1831  functionReturnType, functionName, functionPrototype = functionMatch.groups()
1832 
1833  #Handle special-case AddRandom(pollType) function
1834  if functionName == "AddRandom__I":
1835  p = ParamStruct()
1836  p.type = "int"
1837  p.isPtr = 0
1838  p.isOut = 0
1839  p.category = "intType"
1840  p.name = "NULL"
1841  p.rawIndex = 0
1842  p2 = ParamStruct()
1843  p2.type = "int"
1844  p2.isPtr = 0
1845  p2.isOut = 0
1846  p2.category = "intType"
1847  p2.name = "pollType"
1848  p2.rawIndex = 1
1849  rawParamStructs = [p,p2]
1850  newParamStructs = [p2,p2]
1851  voidTag = "Array"
1852  functionName = functionName.split("__")[0]
1853  returnName = None
1854  discardName = None
1855  else:
1856  #Strip JNI decoration off function name
1857  #But record which variety of tagged helper functions to use
1858  if functionName.find("__") != -1:
1859  if functionName.find("ByteBuffer") != -1:
1860  voidTag = "NIO"
1861  else:
1862  voidTag = "Array"
1863  functionName = functionName.split("__")[0]
1864 
1865  #Look up the parameters we've previously determined for this function
1866  rawParamStructs = rawParamStructsDict[functionName]
1867  newParamStructs = newParamStructsDict[functionName]
1868  if newReturnStructsDict.get(functionName):
1869  returnName = newReturnStructsDict.get(functionName).name
1870  returnType = newReturnStructsDict.get(functionName).type
1871  returnCategory = newReturnStructsDict.get(functionName).category
1872  else:
1873  returnName = None
1874 
1875  if newDiscardedStructsDict.get(functionName):
1876  discardName = newDiscardedStructsDict.get(functionName).name
1877  else:
1878  discardName = None
1879 
1880  #for p in newParamStructs: print " "+str(p)
1881 
1882  #Substitute parameter names into the function prototype
1883  newFunctionParams = expandFunctionPrototype(functionPrototype, newParamStructs)
1884  startIndex = functionMatch.start(3) - functionMatch.start()
1885  endIndex = functionMatch.end(3) - functionMatch.start()
1886  function = function[ : startIndex] + newFunctionParams + function[ endIndex : ]
1887 
1888  newFunctionBody = "\nint status = 0;\n"
1889 
1890  arguments = ""
1891  for p in rawParamStructs:
1892  if p.name == returnName or p.name == discardName:
1893  arguments += "&"
1894  if p.isPtr and p.type=="void":
1895  arguments += "%sPtr + %sOffset, " % (p.name, p.name)
1896  elif p.isPtr and p.type=="char":
1897  arguments += "%sPtr, " % p.name
1898  else:
1899  arguments += p.name + ", "
1900  arguments = arguments[:-2]
1901 
1902  if returnName:
1903  if returnCategory == "intType" or returnType=="int":
1904  newFunctionBody += "jint %s = 0;\n" % returnName
1905  else:
1906  newFunctionBody += returnType +" %s;\n" % returnName
1907  if discardName:
1908  newFunctionBody += "jint %s = 0;\n" % discardName
1909 
1910  #If we have arrays, add the code to handle them
1911  arrayNames = [p.name for p in newParamStructs if p.isPtr]
1912  charArrayNames = [p.name for p in newParamStructs if p.isPtr and p.type=="char"]
1913  voidArrayNames = [p.name for p in newParamStructs if p.isPtr and p.type=="void"]
1914  outVoidArrayNames = [p.name for p in newParamStructs if p.isPtr and p.type=="void" and p.isOut]
1915  if arrayNames:
1916  #Declare C pointers to retrieve array contents
1917  for n in arrayNames:
1918  newFunctionBody += "jbyte* " + n + "Ptr = 0;\n"
1919  newFunctionBody += "\n"
1920  #Retrieve the contents for strings
1921  #We need to do this first cause in one case this char* is needed as an argument
1922  if charArrayNames:
1923  for n in charArrayNames:
1924  newFunctionBody += "if (!getPointerString(env, %(n)s, &%(n)sPtr))\n\tgoto finish;\n" % vars()
1925  newFunctionBody += "\n"
1926  #Query the length of output data
1927  #CryptPopData is the only exception that produces output data
1928  #but doesn't require this cause an explicit length is passed in
1929  if outVoidArrayNames and functionName.find("PopData") == -1:
1930  for n in outVoidArrayNames:
1931  argumentsWithNull = arguments.replace("%sPtr + %sOffset" % (n,n), "NULL")
1932  newFunctionBody += "if (!processStatus(env, crypt%s(%s)))\n\tgoto finish;\n" % (functionName, argumentsWithNull)
1933  newFunctionBody += "\n"
1934  elif functionName.find("PopData") != -1:
1935  newFunctionBody += "//CryptPopData is a special case that doesn't have the length querying call\n\n"
1936  if voidArrayNames:
1937  for n in voidArrayNames:
1938  index = [p.name for p in newParamStructs].index(n)
1939  if n in outVoidArrayNames:
1940  lengthName = returnName
1941  else:
1942  if len(newParamStructs)<=index+2 or newParamStructs[index+2].category != "rawType" or newParamStructs[index+2].type != "int":
1943  lengthName = "1" #CheckSignature and ImportKey don't have a length, so we can't do a good check!
1944  else:
1945  lengthName = newParamStructs[index+2].name
1946  newFunctionBody += "if (!checkIndices%(voidTag)s(env, %(n)s, %(n)sOffset, %(lengthName)s))\n\tgoto finish;\n" % vars()
1947  newFunctionBody += "\n"
1948  for n in voidArrayNames:
1949  newFunctionBody += "if (!getPointer%(voidTag)s(env, %(n)s, &%(n)sPtr))\n\tgoto finish;\n" % vars()
1950 
1951  if newFunctionBody[-2] != "\n":
1952  newFunctionBody += "\n"
1953  newFunctionBody += "status = crypt%s(%s);\n\n" % (functionName, arguments)
1954 
1955  if arrayNames:
1956  newFunctionBody += "finish:\n"
1957  if arrayNames:
1958  for n in voidArrayNames:
1959  newFunctionBody += "releasePointer%(voidTag)s(env, %(n)s, %(n)sPtr);\n" % vars()
1960  for n in charArrayNames:
1961  newFunctionBody += "releasePointerString(env, %(n)s, %(n)sPtr);\n" % vars()
1962 
1963  #newFunctionBody += "processStatus(env, status);\n"
1964 
1965  #if returnName:
1966  # newFunctionBody += "return(%s);\n" % returnName
1967  if returnName:
1968  if returnCategory == "intType" or returnType == "int":
1969  newFunctionBody += "processStatus(env, status);\n"
1970  newFunctionBody += "return(%s);\n" % returnName
1971  elif returnType == "CRYPT_QUERY_INFO":
1972  newFunctionBody += "return(processStatusReturnCryptQueryInfo(env, status, %s));\n" % returnName
1973  elif returnType == "CRYPT_OBJECT_INFO":
1974  newFunctionBody += "return(processStatusReturnCryptObjectInfo(env, status, %s));\n" % returnName
1975  else:
1976  newFunctionBody += "processStatus(env, status);\n"
1977 
1978  newFunctionBody = newFunctionBody[:-1] #Strip off last \n
1979  newFunctionBody = newFunctionBody.replace("\n", "\n\t");
1980  newFunction = function[:-1]+"\n{" + newFunctionBody + "\n}"
1981 
1982  #Substitute the output equivalent for the input
1983  s = s[ : functionMatch.start()] + newFunction + s[functionMatch.end() : ]
1984 
1985  #Get next function
1986  functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))
1987 
1988  f = open("java_jni.c", "w")
1989  f.write(s)
1990  f.close()
1991 
1992 
1993 
1994 elif language == "python":
1995  os.chdir(outDir)
1996 
1997  #print sInts
1998  #raw_input()
1999  #print sFuncs
2000  #raw_input()
2001 
2002  moduleFunctions = ""
2003  s = pyBeforeExceptions + exceptionString + pyBeforeFuncs + sFuncs + \
2004  pyBeforeModuleFunctions + moduleFunctions + sModFuncs + \
2005  pyBeforeInts + sInts + \
2006  pyAfterInts
2007 
2008  #print s
2009  #raw_input()
2010  functionPattern = re.compile(r"static PyObject\* python_crypt([^\(]+)[^{]+{([^}]*)}", re.DOTALL)
2011  functionMatch = functionPattern.search(s)
2012  while functionMatch:
2013  #print functionMatch.group()
2014  #print functionMatch.groups()
2015  #raw_input()
2016 
2017  #Most of the code in this loop is copied-then-modified from the java code above, ugly..
2018  voidTag = ""
2019 
2020  #Extract the function name and body
2021  functionName, functionBody = functionMatch.groups()
2022 
2023  #Look up the parameters we've previously determined for this function
2024  rawParamStructs = rawParamStructsDict[functionName]
2025  newParamStructs = newParamStructsDict[functionName]
2026  lengthIndices = lengthIndicesDict[functionName]
2027  offsetIndices = offsetIndicesDict[functionName]
2028  #print functionName, lengthIndices, offsetIndices
2029  #raw_input()
2030  if newReturnStructsDict.get(functionName):
2031  returnName = newReturnStructsDict.get(functionName).name
2032  returnType = newReturnStructsDict.get(functionName).type
2033  returnCategory = newReturnStructsDict.get(functionName).category
2034  else:
2035  returnName = None
2036  if newDiscardedStructsDict.get(functionName):
2037  discardName = newDiscardedStructsDict.get(functionName).name
2038  else:
2039  discardName = None
2040 
2041  newFunctionBody = "\nint status = 0;\n"
2042 
2043  #Arguments to pass to the C cryptlib function
2044  arguments = ""
2045  for p in rawParamStructs:
2046  if p.name == returnName or p.name == discardName:
2047  arguments += "&"
2048  if p.isPtr and p.type=="void":
2049  arguments += "%sPtr, " % (p.name)
2050  elif p.isPtr and p.type=="char":
2051  arguments += "%sPtr, " % p.name
2052  else:
2053  arguments += p.name + ", "
2054  arguments = arguments[:-2]
2055 
2056  if returnName:
2057  if returnCategory == "intType" or returnType=="int":
2058  newFunctionBody += "int %s = 0;\n" % returnName
2059  else:
2060  newFunctionBody += returnType +" %s;\n" % returnName
2061  if discardName:
2062  newFunctionBody += "int %s = 0;\n" % discardName
2063  #Declare variables to parse args tuple into
2064  index = 0
2065  for p in newParamStructs:
2066  if index not in offsetIndices: #Python doesn't use the offsets
2067  if p.isPtr:
2068  newFunctionBody += "PyObject* %s = NULL;\n" % p.name
2069  else:
2070  newFunctionBody += "int %s = 0;\n" % p.name
2071  index += 1
2072 
2073  #If we have arrays, add the code to handle them
2074  arrayNames = [p.name for p in newParamStructs if p.isPtr]
2075  charArrayNames = [p.name for p in newParamStructs if p.isPtr and p.type=="char"]
2076  voidArrayNames = [p.name for p in newParamStructs if p.isPtr and p.type=="void"]
2077  outVoidArrayNames = [p.name for p in newParamStructs if p.isPtr and p.type=="void" and p.isOut]
2078  if arrayNames:
2079  #Declare C pointers to retrieve array contents
2080  for n in arrayNames:
2081  newFunctionBody += "unsigned char* " + n + "Ptr = 0;\n"
2082  newFunctionBody += "\n"
2083  #Retrieve the contents for strings
2084  #We need to do this first cause in one case this char* is needed as an argument
2085 
2086  #Parse the input arguments from the python user
2087  #Arguments to parse from the python args tuple
2088  if newParamStructs:
2089  parseFormatString = ""
2090  parseArgsList = []
2091  index = 0
2092  for p in newParamStructs:
2093  if index not in lengthIndices and index not in offsetIndices:
2094  if p.isPtr and p.type=="char":
2095  parseFormatString += "O"
2096  parseArgsList.append("&" + p.name)
2097  elif p.isPtr and p.type=="void":
2098  parseFormatString += "O"
2099  parseArgsList.append("&" + p.name)
2100  else:
2101  parseFormatString += "i"
2102  parseArgsList.append("&" + p.name)
2103 
2104  index += 1
2105 
2106  if newFunctionBody[-2] != "\n":
2107  newFunctionBody += "\n"
2108 
2109 
2110  if functionName == "AddRandom":
2111  newFunctionBody += """\
2112 //Special case to handle SLOWPOLL / FASTPOLL values
2113 if (PyArg_ParseTuple(args, "i", &randomDataLength))
2114  return processStatus(cryptAddRandom(NULL, randomDataLength));\n\n"""
2115 
2116  newFunctionBody += """\
2117 if (!PyArg_ParseTuple(args, "%s", %s))
2118  return(NULL);\n\n""" % (parseFormatString, ", ".join(parseArgsList))
2119  #for p in newParamStructs:
2120  # print p.name,
2121 
2122  if arrayNames:
2123  if charArrayNames:
2124  for n in charArrayNames:
2125  newFunctionBody += "if (!getPointerReadString(%(n)s, &%(n)sPtr))\n\tgoto finish;\n" % vars()
2126  newFunctionBody += "\n"
2127  #Query the length of output data
2128  #CryptPopData is the only exception that produces output data
2129  #but doesn't require this cause an explicit length is passed in
2130  if outVoidArrayNames and functionName.find("PopData") == -1:
2131  for n in outVoidArrayNames:
2132  argumentsWithNull = arguments.replace("%sPtr" % (n), "NULL")
2133  newFunctionBody += "if (!processStatusBool(crypt%s(%s)))\n\tgoto finish;\n" % (functionName, argumentsWithNull)
2134  newFunctionBody += "\n"
2135  elif functionName.find("PopData") != -1:
2136  newFunctionBody += "//CryptPopData is a special case that doesn't have the length querying call\n\n"
2137 
2138  #Go through and get the pointers for translated void*
2139  if voidArrayNames:
2140  for n in voidArrayNames:
2141  index = [p.name for p in newParamStructs].index(n)
2142  #Determine the name of its length parameter
2143  if n in outVoidArrayNames:
2144  lengthName = returnName
2145  else:
2146  if len(newParamStructs)<=index+2 or newParamStructs[index+2].category != "rawType" or newParamStructs[index+2].type != "int":
2147  lengthName = "1" #QueryObject, CheckSignature and ImportKey don't have a length, so we can't do a good check!
2148  else:
2149  lengthName = newParamStructs[index+2].name
2150  if n in outVoidArrayNames and functionName.find("PopData") == -1:
2151  newFunctionBody += "if (!getPointerWriteCheckIndices%(voidTag)s(%(n)s, &%(n)sPtr, &%(lengthName)s))\n\tgoto finish;\n" % vars()
2152  else:
2153  if lengthName == "1": #Handle the #CheckSignature/ImportKey case
2154  newFunctionBody += "if (!getPointerReadNoLength%(voidTag)s(%(n)s, &%(n)sPtr))\n\tgoto finish;\n" % vars()
2155  else:
2156  #If the pointer is C_IN and not C_INOUT
2157  #(we check against Encrypt/Decrypt directory for this latter check)
2158  #We only need it for reading, not writing
2159  if n not in outVoidArrayNames and functionName not in ("Encrypt", "Decrypt"):
2160  newFunctionBody += "if (!getPointerRead(%(n)s, &%(n)sPtr, &%(lengthName)s))\n\tgoto finish;\n" % vars()
2161  else:
2162  newFunctionBody += "if (!getPointerWrite(%(n)s, &%(n)sPtr, &%(lengthName)s))\n\tgoto finish;\n" % vars()
2163 
2164  if newFunctionBody[-2] != "\n":
2165  newFunctionBody += "\n"
2166  newFunctionBody += "status = crypt%s(%s);\n\n" % (functionName, arguments)
2167 
2168  if arrayNames:
2169  newFunctionBody += "finish:\n"
2170  if arrayNames:
2171  for n in voidArrayNames:
2172  newFunctionBody += "releasePointer(%(n)s, %(n)sPtr);\n" % vars()
2173  for n in charArrayNames:
2174  newFunctionBody += "releasePointerString(%(n)s, %(n)sPtr);\n" % vars()
2175 
2176  if returnName:
2177  if returnCategory == "intType":
2178  newFunctionBody += "return(processStatusReturnCryptHandle(status, %s));" % returnName
2179  elif returnType == "CRYPT_QUERY_INFO":
2180  newFunctionBody += "return(processStatusReturnCryptQueryInfo(status, %s));" % returnName
2181  elif returnType == "CRYPT_OBJECT_INFO":
2182  newFunctionBody += "return(processStatusReturnCryptObjectInfo(status, %s));" % returnName
2183  elif returnType == "int":
2184  newFunctionBody += "return(processStatusReturnInt(status, %s));" % returnName
2185  else:
2186  newFunctionBody += "return(processStatus(status));"
2187 
2188  newFunctionBody = newFunctionBody.replace("\n", "\n\t")
2189 
2190  #Substitute the output equivalent for the input
2191  s = s[ : functionMatch.start(2)] + newFunctionBody + "\n" + s[functionMatch.end(2) : ]
2192 
2193  #Get next function
2194  functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))
2195 
2196  f = open("python.c", "w")
2197  f.write(s)
2198  f.close()
2199 
2200 
2201  f = open("setup.py", "w")
2202  f.write(setupPy)
2203  f.close()
2204 
2205 elif language == "net":
2206  flagForAddRandomHack = 0
2207 
2208  #functionPattern = re.compile(r"public static ([^ \t]+) ([^ \t\n]+)\([ \t\n]*\(([^\)]*)\) throws CryptException;")
2209  functionPattern = re.compile(r"public static ([^ \t]+) ([^ \t\n]+)\([ \t\n]*([^\)]*)\);")
2210  functionMatch = functionPattern.search(s)
2211  while functionMatch:
2212  #print functionMatch.groups()
2213 
2214  #Extract the returnType, name, and prototype for this function
2215  function = functionMatch.group()
2216  functionReturnType, functionName, functionPrototype = functionMatch.groups()
2217 
2218  #Handle special-case AddRandom(pollType) function
2219  if functionName == "AddRandom":
2220  flagForAddRandomHack += 1
2221  if flagForAddRandomHack == 2:
2222  p = ParamStruct()
2223  p.type = "int"
2224  p.isPtr = 0
2225  p.isOut = 0
2226  p.category = "intType"
2227  p.name = "IntPtr.Zero"
2228  p.rawIndex = 0
2229  p2 = ParamStruct()
2230  p2.type = "int"
2231  p2.isPtr = 0
2232  p2.isOut = 0
2233  p2.category = "intType"
2234  p2.name = "pollType"
2235  p2.rawIndex = 1
2236  rawParamStructs = [p,p2]
2237  newParamStructs = [p2,p2]
2238  voidTag = "Array"
2239  functionName = functionName.split("__")[0]
2240  returnName = None
2241  discardName = None
2242  flagForAddRandomHack = None
2243  else:
2244  #Look up the parameters we've previously determined for this function
2245  rawParamStructs = rawParamStructsDict[functionName]
2246  newParamStructs = newParamStructsDict[functionName]
2247  if newReturnStructsDict.get(functionName):
2248  returnName = newReturnStructsDict.get(functionName).name
2249  returnType = newReturnStructsDict.get(functionName).type
2250  returnCategory = newReturnStructsDict.get(functionName).category
2251  else:
2252  returnName = None
2253  if newDiscardedStructsDict.get(functionName):
2254  discardName = newDiscardedStructsDict.get(functionName).name
2255  else:
2256  discardName = None
2257 
2258  #for p in newParamStructs: print " "+str(p)
2259 
2260  #Substitute parameter names into the function prototype
2261  newFunctionParams = functionPrototype #expandFunctionPrototype(functionPrototype, newParamStructs)
2262  startIndex = functionMatch.start(3) - functionMatch.start()
2263  endIndex = functionMatch.end(3) - functionMatch.start()
2264  function = function[ : startIndex] + newFunctionParams + function[ endIndex : ]
2265 
2266  newFunctionBody = "\n"
2267 
2268  arguments = ""
2269  for p in rawParamStructs:
2270  if p.name == returnName or p.name == discardName:
2271  arguments += "%sPtr, " % p.name
2272  elif p.isPtr and p.type=="void":
2273  arguments += "%sPtr, " % p.name
2274  elif p.isPtr and p.type=="char":
2275  arguments += "%sPtr, " % p.name
2276  else:
2277  arguments += p.name + ", "
2278  arguments = arguments[:-2]
2279 
2280  if returnName:
2281  if returnCategory == "structType":
2282  newFunctionBody += "IntPtr %sPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(%s)));\n" % (returnName, returnType)
2283  newFunctionBody += "%s %s = new %s();\n" % (returnType, returnName, returnType)
2284  else:
2285  newFunctionBody += "IntPtr %sPtr = Marshal.AllocHGlobal(4);\n" % returnName
2286  if discardName:
2287  newFunctionBody += "IntPtr %sPtr = Marshal.AllocHGlobal(4);\n" % discardName
2288 
2289  #If we have arrays, add the code to handle them
2290  arrayNames = [p.name for p in newParamStructs if p.isPtr]
2291  charArrayNames = [p.name for p in newParamStructs if p.isPtr and p.type=="char"]
2292  voidArrayNames = [p.name for p in newParamStructs if p.isPtr and p.type=="void"]
2293  outVoidArrayNames = [p.name for p in newParamStructs if p.isPtr and p.type=="void" and p.isOut]
2294  if arrayNames:
2295  #Declare C pointers to retrieve array contents
2296  for n in arrayNames:
2297  #newFunctionBody += "jbyte* " + n + "Ptr = 0;\n"
2298  newFunctionBody += "GCHandle %sHandle = new GCHandle();\nIntPtr %sPtr = IntPtr.Zero;\n" % (n,n)
2299  if n in charArrayNames:
2300  newFunctionBody += "byte[] %sArray = new UTF8Encoding().GetBytes(%s);\n" % (n,n)
2301 
2302  newFunctionBody += "try\n{\n"
2303 
2304  #Retrieve the contents for strings
2305  #We need to do this first cause in one case this char* is needed as an argument
2306  if charArrayNames:
2307  for n in charArrayNames:
2308  newFunctionBody += "getPointer(%(n)sArray, 0, ref %(n)sHandle, ref %(n)sPtr);\n" % vars()
2309  #Query the length of output data
2310  #CryptPopData is the only exception that produces output data
2311  #but doesn't require this cause an explicit length is passed in
2312  if outVoidArrayNames and functionName.find("PopData") == -1:
2313  for n in outVoidArrayNames:
2314  argumentsWithNull = arguments.replace("%sPtr + %sOffset" % (n,n), "NULL")
2315  newFunctionBody += "processStatus(wrapped_%s(%s));\n" % (functionName, argumentsWithNull)
2316  newFunctionBody += "int %s = Marshal.ReadInt32(%sPtr);\n" % (returnName, returnName)
2317  elif functionName.find("PopData") != -1 or functionName.find("PushData") != -1:
2318  newFunctionBody += "int %s = 0;\n" % returnName
2319  newFunctionBody += "int status;\n"
2320  if voidArrayNames:
2321  for n in voidArrayNames:
2322  index = [p.name for p in newParamStructs].index(n)
2323  if n in outVoidArrayNames:
2324  lengthName = returnName
2325  else:
2326  if len(newParamStructs)<=index+2 or newParamStructs[index+2].category != "rawType" or newParamStructs[index+2].type != "int":
2327  lengthName = "1" #CheckSignature and ImportKey don't have a length, so we can't do a good check!
2328  else:
2329  lengthName = newParamStructs[index+2].name
2330  newFunctionBody += "checkIndices(%(n)s, %(n)sOffset, %(lengthName)s);\n" % vars()
2331  for n in voidArrayNames:
2332  newFunctionBody += "getPointer(%(n)s, %(n)sOffset, ref %(n)sHandle, ref %(n)sPtr);\n" % vars()
2333  elif returnName:
2334  newFunctionBody += "try\n{\n"
2335 
2336  if functionName.find("PopData") == -1 and functionName.find("PushData") == -1:
2337  newFunctionBody += "processStatus(wrapped_%s(%s));\n" % (functionName, arguments)
2338  else:
2339  newFunctionBody += "status = wrapped_%s(%s);\n" % (functionName, arguments)
2340  newFunctionBody += "%s = Marshal.ReadInt32(%sPtr);\n" % (returnName, returnName)
2341  newFunctionBody += "processStatus(status, %s);\n" %returnName
2342 
2343  #if newFunctionBody[-2] != "\n":
2344  # newFunctionBody += "\n"
2345  if returnName:
2346  if returnCategory == "structType":
2347  newFunctionBody += "Marshal.PtrToStructure(%sPtr, %s);\n" % (returnName, returnName)
2348  newFunctionBody += "return %s;\n" % returnName
2349  else:
2350  if functionName.find("PopData") == -1 and functionName.find("PushData") == -1:
2351  newFunctionBody += "return Marshal.ReadInt32(%sPtr);\n" % returnName
2352  else:
2353  newFunctionBody += "return %s;\n" %returnName
2354 
2355  if arrayNames or returnName:
2356  newFunctionBody += "}\nfinally\n{\n"
2357  if returnName:
2358  newFunctionBody += "Marshal.FreeHGlobal(%sPtr);\n" % returnName
2359  if arrayNames:
2360  for n in voidArrayNames:
2361  newFunctionBody += "releasePointer(%(n)sHandle);\n" % vars()
2362  for n in charArrayNames:
2363  newFunctionBody += "releasePointer(%(n)sHandle);\n" % vars()
2364  newFunctionBody += "}\n"
2365 
2366  #Add tabs to lines inside brackets:
2367  lines = newFunctionBody.split("\n")
2368  brackets = 0
2369  for count in range(len(lines)):
2370  line = lines[count]
2371  if line.startswith("}"):
2372  brackets -= 1
2373  lines[count] = ("\t" * brackets) + line
2374  if line.startswith("{"):
2375  brackets += 1
2376  newFunctionBody = "\n".join(lines)
2377 
2378  newFunctionBody = newFunctionBody[:-1] #Strip off last \n
2379  newFunctionBody = newFunctionBody.replace("\n", "\n\t");
2380  newFunction = function[:-1]+"\n{" + newFunctionBody + "\n}"
2381  newFunction = newFunction.replace("\n", "\n\t");
2382 
2383  #Substitute the output equivalent for the input
2384  s = s[ : functionMatch.start()] + newFunction + s[functionMatch.end() : ]
2385 
2386  #Get next function
2387  functionMatch = functionPattern.search(s, functionMatch.start() + len(newFunction))
2388 
2389  #Add enclosing class syntax
2390  #---------------------------
2391  s = classPrefix + s
2392 
2393  for functionName in functionNames:
2394  rawParamStructs = rawParamStructsDict[functionName]
2395  parameters = ""
2396  for p in rawParamStructs:
2397  if p.isPtr:
2398  parameters += "IntPtr %s, " % p.name
2399  else:
2400  parameters += "int %s, " % p.name
2401  parameters = parameters[:-2]
2402 
2403  s += '\t[DllImport("cl32.dll", EntryPoint="crypt%s")]\n\tprivate static extern int wrapped_%s(%s);\n\n' % (functionName, functionName, parameters)
2404  functionNames = [] #Accumulate function names here
2405  #rawParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of original c code)
2406  #newParamStructsDict = {} #Accumulate function name -> list of ParamStructs (of new java/python code)
2407 
2408 
2409 
2410  s += classPostfix + exceptionString + "\n\n}"
2411 
2412  os.chdir(outDir)
2413  print "Writing .NET file..."
2414  f = open("cryptlib.cs", "w")
2415  f.write(s)
2416  f.close()
2417 
2418