| 
									
										
										
										
											2014-03-06 21:25:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | """ 
 | 
					
						
							|  |  |  |     demo_dynamic.py                                     v1 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     This program demonstrates Python's use of the dynamic  | 
					
						
							|  |  |  |     language support additions to LTC, namely access to LTC  | 
					
						
							|  |  |  |     constants, struct and union sizes, and the binding of a  | 
					
						
							|  |  |  |     math package to LTC.  Also provided are simple code  | 
					
						
							|  |  |  |     fragments to illustrate how one might write a Python  | 
					
						
							|  |  |  |     wrapper for LTC and how an app might call the wrapper.  | 
					
						
							|  |  |  |     This or a similar model should work for Ruby and other  | 
					
						
							|  |  |  |     dynamic languages. | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     This instance uses Python's ctypes and requires a single  | 
					
						
							| 
									
										
										
										
											2014-03-08 12:16:58 -08:00
										 |  |  |     .dylib linking together LTC and a math library.  Building  | 
					
						
							|  |  |  |     a single .dylib is needed because LTC wants a fairly tight  | 
					
						
							|  |  |  |     relationship between itself and the mathlib.  (ctypes can  | 
					
						
							|  |  |  |     load multiple .dylibs, but it does not support this level  | 
					
						
							|  |  |  |     of tight coupling between otherwise independent libraries.) | 
					
						
							| 
									
										
										
										
											2014-03-06 21:25:31 -08:00
										 |  |  |      | 
					
						
							|  |  |  |     My .dylib was created on OSX with the following steps: | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       1- compile LTC to a .a static lib: | 
					
						
							| 
									
										
										
										
											2014-03-08 12:16:58 -08:00
										 |  |  |            CFLAGS="-DLTM_DESC -DUSE_LTM" make | 
					
						
							| 
									
										
										
										
											2014-03-06 21:25:31 -08:00
										 |  |  |        | 
					
						
							| 
									
										
										
										
											2014-03-08 12:16:58 -08:00
										 |  |  |       2- link LTC and LTM into a single .dylib: | 
					
						
							|  |  |  |            ar2dylib_with  tomcrypt  tommath | 
					
						
							|  |  |  |          where ar2dylib_with is a shell script that combines  | 
					
						
							|  |  |  |          the LTC .a with the LTM .dylib | 
					
						
							| 
									
										
										
										
											2014-03-06 21:25:31 -08:00
										 |  |  |      | 
					
						
							|  |  |  |     Reminder: you don't need to bind in a math library unless | 
					
						
							|  |  |  |               you are going to use LTC functions that depend  | 
					
						
							|  |  |  |               on a mathlib.  For example, public key crypto  | 
					
						
							|  |  |  |               needs a mathlib; hashing and symmetric encryption  | 
					
						
							| 
									
										
										
										
											2014-03-08 12:16:58 -08:00
										 |  |  |               do not. | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     This code was written for Python 2.7. | 
					
						
							| 
									
										
										
										
											2014-03-06 21:25:31 -08:00
										 |  |  |      | 
					
						
							|  |  |  |     Larry Bugbee | 
					
						
							|  |  |  |     March 2014 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from ctypes import * | 
					
						
							|  |  |  | from ctypes.util import find_library | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #--------------------------------------------------------------- | 
					
						
							|  |  |  | # load the .dylib | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | libname = 'tomcrypt' | 
					
						
							|  |  |  | libpath = find_library(libname) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | print | 
					
						
							|  |  |  | print('  demo_dynamic.py') | 
					
						
							|  |  |  | print | 
					
						
							|  |  |  | print('  path to library %s: %s' % (libname, libpath)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LTC = cdll.LoadLibrary(libpath) | 
					
						
							|  |  |  | print('  loaded: %s' % LTC) | 
					
						
							|  |  |  | print | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #--------------------------------------------------------------- | 
					
						
							|  |  |  | # get list of all supported constants followed by a list of all  | 
					
						
							|  |  |  | # supported sizes.  One alternative: these lists may be parsed  | 
					
						
							|  |  |  | # and used as needed. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if 1: | 
					
						
							|  |  |  |     print '  all supported constants and their values:' | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     # get size to allocate for constants output list | 
					
						
							|  |  |  |     str_len = c_int(0) | 
					
						
							|  |  |  |     ret = LTC.crypt_list_all_constants(None, byref(str_len)) | 
					
						
							|  |  |  |     print '    need to allocate %d bytes \n' % str_len.value | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     # allocate that size and get (name, size) pairs, each pair | 
					
						
							|  |  |  |     # separated by a newline char. | 
					
						
							|  |  |  |     names_sizes = c_buffer(str_len.value) | 
					
						
							|  |  |  |     ret = LTC.crypt_list_all_constants(names_sizes, byref(str_len)) | 
					
						
							|  |  |  |     print names_sizes.value | 
					
						
							|  |  |  |     print | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  | if 1: | 
					
						
							|  |  |  |     print '  all supported sizes:' | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     # get size to allocate for sizes output list | 
					
						
							|  |  |  |     str_len = c_int(0) | 
					
						
							|  |  |  |     ret = LTC.crypt_list_all_sizes(None, byref(str_len)) | 
					
						
							|  |  |  |     print '    need to allocate %d bytes \n' % str_len.value | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     # allocate that size and get (name, size) pairs, each pair | 
					
						
							|  |  |  |     # separated by a newline char. | 
					
						
							|  |  |  |     names_sizes = c_buffer(str_len.value) | 
					
						
							|  |  |  |     ret = LTC.crypt_list_all_sizes(names_sizes, byref(str_len)) | 
					
						
							|  |  |  |     print names_sizes.value | 
					
						
							|  |  |  |     print | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #--------------------------------------------------------------- | 
					
						
							|  |  |  | # get individually named constants and sizes | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # print selected constants | 
					
						
							|  |  |  | if 1: | 
					
						
							|  |  |  |     print '\n  selected constants:' | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     names = [ | 
					
						
							| 
									
										
										
										
											2014-03-13 21:07:25 -07:00
										 |  |  |         'ENDIAN_LITTLE', | 
					
						
							|  |  |  |         'ENDIAN_64BITWORD', | 
					
						
							| 
									
										
										
										
											2014-03-06 21:25:31 -08:00
										 |  |  |         'PK_PUBLIC', | 
					
						
							|  |  |  |         'MAX_RSA_SIZE', | 
					
						
							|  |  |  |         'CTR_COUNTER_BIG_ENDIAN', | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     for name in names: | 
					
						
							|  |  |  |         const_value = c_int(0) | 
					
						
							|  |  |  |         rc = LTC.crypt_get_constant(name, byref(const_value)) | 
					
						
							|  |  |  |         value = const_value.value | 
					
						
							|  |  |  |         print '    %-25s  %d' % (name, value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # print selected sizes | 
					
						
							|  |  |  | if 1: | 
					
						
							|  |  |  |     print '\n  selected sizes:' | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     names = [ | 
					
						
							| 
									
										
										
										
											2014-07-15 15:28:29 +02:00
										 |  |  |         'rijndael_key', | 
					
						
							|  |  |  |         'rsa_key', | 
					
						
							|  |  |  |         'symmetric_CTR', | 
					
						
							|  |  |  |         'twofish_key', | 
					
						
							|  |  |  |         'ecc_point', | 
					
						
							|  |  |  |         'gcm_state', | 
					
						
							|  |  |  |         'sha512_state', | 
					
						
							| 
									
										
										
										
											2014-03-06 21:25:31 -08:00
										 |  |  |     ] | 
					
						
							|  |  |  |     for name in names: | 
					
						
							|  |  |  |         size_value = c_int(0) | 
					
						
							|  |  |  |         rc = LTC.crypt_get_size(name, byref(size_value)) | 
					
						
							|  |  |  |         value = size_value.value | 
					
						
							|  |  |  |         print '    %-25s  %d' % (name, value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #--------------------------------------------------------------- | 
					
						
							|  |  |  | #--------------------------------------------------------------- | 
					
						
							|  |  |  | # ctypes getting a list of this build's supported algorithms  | 
					
						
							|  |  |  | # and compiler switches | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_named_string(lib, name): | 
					
						
							|  |  |  |     return c_char_p.in_dll(lib, name).value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if 0: | 
					
						
							|  |  |  |     print '\n%s' % ('-'*60) | 
					
						
							|  |  |  |     print 'This is a string compiled into LTC showing compile ' | 
					
						
							|  |  |  |     print 'options and algorithms supported by this build \n' | 
					
						
							|  |  |  |     print get_named_string(LTC, 'crypt_build_settings') | 
					
						
							|  |  |  |     print | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #--------------------------------------------------------------- | 
					
						
							|  |  |  | #--------------------------------------------------------------- | 
					
						
							|  |  |  | # here is an example of how a wrapper can make Python access  | 
					
						
							|  |  |  | # more Pythonic | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # - - - - - - - - - - - - - | 
					
						
							|  |  |  | # a wrapper fragment... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _get_size(name): | 
					
						
							|  |  |  |     size = c_int(0) | 
					
						
							|  |  |  |     rc = LTC.crypt_get_size(name, byref(size)) | 
					
						
							|  |  |  |     return size.value | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-15 15:28:29 +02:00
										 |  |  | sha256_state_struct_size = _get_size('sha256_state') | 
					
						
							|  |  |  | sha512_state_struct_size = _get_size('sha512_state') | 
					
						
							| 
									
										
										
										
											2014-03-06 21:25:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class SHA256(object): | 
					
						
							|  |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.state = c_buffer(sha256_state_struct_size) | 
					
						
							|  |  |  |         LTC.sha256_init(byref(self.state)) | 
					
						
							|  |  |  |     def update(self, data): | 
					
						
							|  |  |  |         LTC.sha256_process(byref(self.state), data, len(data)) | 
					
						
							|  |  |  |     def digest(self): | 
					
						
							|  |  |  |         md = c_buffer(32) | 
					
						
							|  |  |  |         LTC.sha256_done(byref(self.state), byref(md)) | 
					
						
							|  |  |  |         return md.raw | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # - - - - - - - - - - - - - | 
					
						
							|  |  |  | # an app fragment... | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # from wrapper import *         # uncomment in real life | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | data = 'hello world' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sha256 = SHA256() | 
					
						
							|  |  |  | sha256.update(data) | 
					
						
							|  |  |  | md = sha256.digest() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template = '\n\n  the SHA256 digest for "%s" is %s \n' | 
					
						
							|  |  |  | print template % (data, md.encode('hex')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #--------------------------------------------------------------- | 
					
						
							|  |  |  | #--------------------------------------------------------------- | 
					
						
							|  |  |  | #--------------------------------------------------------------- |