Browse Source

Merge pull request #263 from libtom/pr/crypt_sizes

missing items in crypt sizes
Steffen Jaeckel 8 years ago
parent
commit
daaab843f3

+ 55 - 21
demos/constants.c

@@ -8,6 +8,12 @@
  */
 #include "tomcrypt.h"
 
+#if _POSIX_C_SOURCE >= 200112L
+#include <libgen.h>
+#else
+#define basename(x) x
+#endif
+
 /**
   @file demo_crypt_constants.c
 
@@ -17,33 +23,61 @@
   Larry Bugbee, February 2013
 */
 
+static void _print_line(const char* cmd, const char* desc)
+{
+   printf("  %-16s - %s\n", cmd, desc);
+}
 
-int main(void) {
-    /* given a specific constant name, get and print its value */
-    char name[] = "CTR_COUNTER_BIG_ENDIAN";
-    int  value;
-    char *names_list;
-    unsigned int names_list_len;
+int main(int argc, char **argv)
+{
+   if (argc == 1) {
+      /* given a specific constant name, get and print its value */
+      char name[] = "CTR_COUNTER_BIG_ENDIAN";
+      int value;
+      char *names_list;
+      unsigned int names_list_len;
 
-    if (crypt_get_constant(name, &value) != 0)
-      exit(EXIT_FAILURE);
-    printf("\n  %s is %d \n\n", name, value);
+      if (crypt_get_constant(name, &value) != 0) exit(EXIT_FAILURE);
+      printf("\n  %s is %d \n\n", name, value);
 
-    /* get and print the length of the names (and values) list */
+      /* get and print the length of the names (and values) list */
 
-    if (crypt_list_all_constants(NULL, &names_list_len) != 0)
-      exit(EXIT_FAILURE);
-    printf("  need to allocate %u bytes \n\n", names_list_len);
+      if (crypt_list_all_constants(NULL, &names_list_len) != 0) exit(EXIT_FAILURE);
+      printf("  need to allocate %u bytes \n\n", names_list_len);
 
-    /* get and print the names (and values) list */
-    if ((names_list = malloc(names_list_len)) == NULL)
-      exit(EXIT_FAILURE);
-    if (crypt_list_all_constants(names_list, &names_list_len) != 0)
-      exit(EXIT_FAILURE);
-    printf("  supported constants:\n\n%s\n\n", names_list);
-    free(names_list);
+      /* get and print the names (and values) list */
+      if ((names_list = malloc(names_list_len)) == NULL) exit(EXIT_FAILURE);
+      if (crypt_list_all_constants(names_list, &names_list_len) != 0) exit(EXIT_FAILURE);
+      printf("  supported constants:\n\n%s\n\n", names_list);
+      free(names_list);
+   } else if (argc == 2) {
+      if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
+         char* base = strdup(basename(argv[0]));
+         printf("Usage: %s [-a] [-s name]\n\n", base);
+         _print_line("<no argument>", "The old behavior of the demo");
+         _print_line("-a", "Only lists all constants");
+         _print_line("-s name", "List a single constant given as argument");
+         _print_line("-h", "The help you're looking at");
+         free(base);
+      } else if (strcmp(argv[1], "-a") == 0) {
+         char *names_list;
+         unsigned int names_list_len;
+         /* get and print the length of the names (and values) list */
+         if (crypt_list_all_constants(NULL, &names_list_len) != 0) exit(EXIT_FAILURE);
+         /* get and print the names (and values) list */
+         names_list = malloc(names_list_len);
+         if (crypt_list_all_constants(names_list, &names_list_len) != 0) exit(EXIT_FAILURE);
+         printf("%s\n", names_list);
+      }
+   } else if (argc == 3) {
+      if (strcmp(argv[1], "-s") == 0) {
+         int value;
+         if (crypt_get_constant(argv[2], &value) != 0) exit(EXIT_FAILURE);
+         printf("%s,%u\n", argv[2], value);
+      }
+   }
 
-    return 0;
+   return 0;
 }
 
 

+ 131 - 54
demos/demo_dynamic.py

@@ -1,7 +1,7 @@
 
 
 """
-    demo_dynamic.py                                     v1
+    demo_dynamic.py                                     v2b
 
     This program demonstrates Python's use of the dynamic
     language support additions to LTC, namely access to LTC
@@ -19,26 +19,26 @@
     load multiple .dylibs, but it does not support this level
     of tight coupling between otherwise independent libraries.)
 
-    My .dylib was created on OSX with the following steps:
+    My .dylib was created on OSX/macOS with the following:
+        sudo make -j5 -f makefile.shared                        \
+            CFLAGS="-DUSE_TFM -DTFM_DESC -I/usr/local/include"  \
+            EXTRALIBS=/usr/local/lib/libtfm.a  install
 
-      1- compile LTC to a .a static lib:
-           CFLAGS="-DLTM_DESC -DUSE_LTM" make
-
-      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
+    For python 2.7.12 on Ubuntu Xenial the following worked for
+    me (without MPI support):
+        sudo make -f makefile.shared install PREFIX="/usr"
 
     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
-              do not.
+              you are going to use LTC functions that need a
+              mathlib.  For example, public key crypto requires
+              a mathlib; hashing and symmetric encryption do not.
 
-    This code was written for Python 2.7.
+    This code was written for Python 2.7 with the ctypes standard
+    library.
 
     Larry Bugbee
-    March 2014
+    March 2014      v1
+    August 2017     v2b
 
 """
 
@@ -46,15 +46,24 @@
 from ctypes import *
 from ctypes.util import find_library
 
+# switches to enable/disable selected output
+SHOW_ALL_CONSTANTS      = True
+SHOW_ALL_SIZES          = True
+SHOW_SELECTED_CONSTANTS = True
+SHOW_SELECTED_SIZES     = True
+SHOW_BUILD_OPTIONS_ALGS = True
+SHOW_SHA256_EXAMPLE     = True
+SHOW_CHACHA_EXAMPLE     = True
+
+print
+print('  demo_dynamic.py')
+
 
-#---------------------------------------------------------------
+#-------------------------------------------------------------------------------
 # load the .dylib
 
 libname = 'tomcrypt'
 libpath = find_library(libname)
-
-print
-print('  demo_dynamic.py')
 print
 print('  path to library %s: %s' % (libname, libpath))
 
@@ -63,19 +72,19 @@ 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:
+if SHOW_ALL_CONSTANTS:
+    print '-'*60
     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
+    print '    need to allocate %d bytes to build list \n' % str_len.value
 
     # allocate that size and get (name, size) pairs, each pair
     # separated by a newline char.
@@ -85,13 +94,14 @@ if 1:
     print
 
 
-if 1:
+if SHOW_ALL_SIZES:
+    print '-'*60
     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
+    print '    need to allocate %d bytes to build list \n' % str_len.value
 
     # allocate that size and get (name, size) pairs, each pair
     # separated by a newline char.
@@ -101,11 +111,12 @@ if 1:
     print
 
 
-#---------------------------------------------------------------
+#-------------------------------------------------------------------------------
 # get individually named constants and sizes
 
 # print selected constants
-if 1:
+if SHOW_SELECTED_CONSTANTS:
+    print '-'*60
     print '\n  selected constants:'
 
     names = [
@@ -120,9 +131,11 @@ if 1:
         rc = LTC.crypt_get_constant(name, byref(const_value))
         value = const_value.value
         print '    %-25s  %d' % (name, value)
+    print
 
 # print selected sizes
-if 1:
+if SHOW_SELECTED_SIZES:
+    print '-'*60
     print '\n  selected sizes:'
 
     names = [
@@ -139,44 +152,62 @@ if 1:
         rc = LTC.crypt_get_size(name, byref(size_value))
         value = size_value.value
         print '    %-25s  %d' % (name, value)
+    print
 
 
-#---------------------------------------------------------------
-#---------------------------------------------------------------
-# ctypes getting a list of this build's supported algorithms
-# and compiler switches
+#-------------------------------------------------------------------------------
+#-------------------------------------------------------------------------------
+# LibTomCrypt exposes one interesting string that can be accessed
+# via Python's ctypes module, "crypt_build_settings", which
+# provides a list of this build's compiler switches and supported
+# algorithms.  If someday LTC exposes other interesting strings,
+# they can be found with:
+#   nm /usr/local/lib/libtomcrypt.dylib | grep " D "
 
 def get_named_string(lib, name):
     return c_char_p.in_dll(lib, name).value
 
-if 0:
-    print '\n%s' % ('-'*60)
+if SHOW_BUILD_OPTIONS_ALGS:
+    print '-'*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
+#-------------------------------------------------------------------------------
+#-------------------------------------------------------------------------------
+# here is an example of how Python code can be written to access
+# LTC's implementation of SHA256 and ChaCha,
 
 # - - - - - - - - - - - - -
-# a wrapper fragment...
+# definitions
 
 def _get_size(name):
     size = c_int(0)
     rc = LTC.crypt_get_size(name, byref(size))
+    if rc != 0:
+        raise Exception('LTC.crypt_get_size(%s) rc = %d' % (name, rc))
     return size.value
 
-sha256_state_struct_size = _get_size('sha256_state')
-sha512_state_struct_size = _get_size('sha512_state')
+def _get_constant(name):
+    constant = c_int(0)
+    rc = LTC.crypt_get_constant(name, byref(constant))
+    if rc != 0:
+        raise Exception('LTC.crypt_get_constant(%s) rc = %d' % (name, rc))
+    return constant.value
+
+def _err2str(err):
+    # define return type
+    errstr = LTC.error_to_string
+    errstr.restype = c_char_p
+    # get and return err string
+    return errstr(err)
+
+CRYPT_OK = _get_constant('CRYPT_OK')
 
 class SHA256(object):
     def __init__(self):
-        self.state = c_buffer(sha256_state_struct_size)
+        self.state = c_buffer(_get_size('sha256_state'))
         LTC.sha256_init(byref(self.state))
     def update(self, data):
         LTC.sha256_process(byref(self.state), data, len(data))
@@ -185,22 +216,68 @@ class SHA256(object):
         LTC.sha256_done(byref(self.state), byref(md))
         return md.raw
 
+class ChaCha(object):
+    def __init__(self, key, rounds):
+        self.state   = c_buffer(_get_size('chacha_state'))
+        self.counter = c_int(1)
+        err = LTC.chacha_setup(byref(self.state), key, len(key), rounds)
+        if err != CRYPT_OK:
+            raise Exception('LTC.chacha_setup(), err = %d, "%s"' % (err, _err2str(err)))
+    def set_iv32(self, iv):
+        err = LTC.chacha_ivctr32(byref(self.state), iv, len(iv), byref(self.counter))
+        if err != CRYPT_OK:
+            raise Exception('LTC.chacha_ivctr32(), err = %d, "%s"' % (err, _err2str(err)))
+    def crypt(self, datain):
+        dataout = c_buffer(len(datain))
+        err = LTC.chacha_crypt(byref(self.state), datain, len(datain), byref(dataout))
+        if err != CRYPT_OK:
+            raise Exception('LTC.chacha_crypt(), err = %d, "%s"' % (err, _err2str(err)))
+        return dataout.raw
+
 # - - - - - - - - - - - - -
-# an app fragment...
+# a SHA256 app fragment
 
 # from wrapper import *         # uncomment in real life
 
-data = 'hello world'
+if SHOW_SHA256_EXAMPLE:
+    print '-'*60
+    data = 'hello world'
+
+    sha256 = SHA256()
+    sha256.update(data)
+    md = sha256.digest()
+
+    template = '\n  the SHA256 digest for "%s" is %s \n'
+    print template % (data, md.encode('hex'))
+
+# - - - - - - - - - - - - -
+# a ChaCha app fragment
+
+if SHOW_CHACHA_EXAMPLE:
+    print '-'*60
+    key     = 'hownowbrowncow\x00\x00'  # exactly 16 or 32 bytes
+    rounds  = 12                        # common values: 8, 12, 20
+    iv      = '123456789012'            # exactly 12 bytes
+    plain   = 'Kilroy was here, there, and everywhere!'
+
+    cha = ChaCha(key, rounds)
+    cha.set_iv32(iv)
+    cipher = cha.crypt(plain)
 
-sha256 = SHA256()
-sha256.update(data)
-md = sha256.digest()
+    template = '\n  ChaCha%d ciphertext   for "%s" is "%s"'
+    print template % (rounds, plain, cipher.encode('hex'))
 
-template = '\n\n  the SHA256 digest for "%s" is %s \n'
-print template % (data, md.encode('hex'))
+    # reset to decrypt
+    cha.set_iv32(iv)
+    decrypted = cha.crypt(cipher)
 
+    template = '  ChaCha%d decoded text for "%s" is "%s" \n'
+    print template % (rounds, plain, decrypted)
 
+# Footnote: Keys should be erased fm memory as soon as possible after use,
+# and that includes Python.  For a tip on how to do that in Python, see
+# http://buggywhip.blogspot.com/2010/12/erase-keys-and-credit-card-numbers-in.html
 
-#---------------------------------------------------------------
-#---------------------------------------------------------------
-#---------------------------------------------------------------
+#-------------------------------------------------------------------------------
+#-------------------------------------------------------------------------------
+#-------------------------------------------------------------------------------

+ 314 - 0
demos/demo_dynamic.py3

@@ -0,0 +1,314 @@
+
+
+"""
+    demo_dynamic.py3                                    v2b
+
+    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
+    .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.)
+
+    My .dylib was created on OSX/macOS with the following:
+        sudo make -j5 -f makefile.shared                        \
+            CFLAGS="-DUSE_TFM -DTFM_DESC -I/usr/local/include"  \
+            EXTRALIBS=/usr/local/lib/libtfm.a  install
+
+    For python 2.7.12 on Ubuntu Xenial the following worked for
+    me (without MPI support):
+        sudo make -f makefile.shared install PREFIX="/usr"
+
+    Reminder: you don't need to bind in a math library unless
+              you are going to use LTC functions that need a
+              mathlib.  For example, public key crypto requires
+              a mathlib; hashing and symmetric encryption do not.
+
+    ------
+    
+    This code was originally written for Python 2.7 with the
+    ctypes standard library.  This version was modified so that
+    it would run under both Python 2.7 and 3.6.  You might want
+    to run a diff on the .py and .py3 files to see the differences
+    between the two languages.    
+    
+    Arguably the biggest change for Python3 has to do with
+    strings.  Under Python2, native strings are ASCII bytes and
+    passing them to LTC is natural and requires no conversion.
+    Under Python3 all native strings are Unicode which requires 
+    they be converted to bytes before use by LTC.
+
+    Note the following for Python3.
+        - ASCII keys, IVs and other string arguments must be
+          'bytes'.  Define them with a 'b' prefix or convert
+          via the 'bytes()' function.
+        - "strings" returned from LTC are bytes and conversion
+          to Unicode might be necessary for proper printing.
+          If so, use <string>.decode('utf-8').
+        - The Python2 'print' statement becomes a function in
+          Python3 which requires parenthesis, eg. 'print()'.
+        
+    NB: Unicode is achieved under Python2 by either defining
+        a Unicode string with a 'u' prefix or passing ASCII
+        strings thru the 'unicode()' function.
+    
+
+    Larry Bugbee
+    March 2014      v1
+    August 2017     v2b
+
+"""
+
+
+import sys
+from ctypes import *
+from ctypes.util import find_library
+
+# switches to enable/disable selected output
+SHOW_ALL_CONSTANTS      = True
+SHOW_ALL_SIZES          = True
+SHOW_SELECTED_CONSTANTS = True
+SHOW_SELECTED_SIZES     = True
+SHOW_BUILD_OPTIONS_ALGS = True
+SHOW_SHA256_EXAMPLE     = True
+SHOW_CHACHA_EXAMPLE     = True
+
+print(' ')
+print('  demo_dynamic.py')
+
+def inprint(s, indent=0):
+    "prints strings indented, including multline strings"
+    for line in s.split('\n'):
+        print(' '*indent + line)
+
+#-------------------------------------------------------------------------------
+# load the .dylib
+
+libname = 'tomcrypt'
+libpath = find_library(libname)
+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 SHOW_ALL_CONSTANTS:
+    print('-'*60)
+    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 to build list \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.decode("utf-8"))
+    print(' ')
+
+
+if SHOW_ALL_SIZES:
+    print('-'*60)
+    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 to build list \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.decode("utf-8"))
+    print(' ')
+
+
+#-------------------------------------------------------------------------------
+# get individually named constants and sizes
+
+# print selected constants
+if SHOW_SELECTED_CONSTANTS:
+    print('-'*60)
+    print('\n  selected constants:')
+
+    names = [
+        b'ENDIAN_LITTLE',
+        b'ENDIAN_64BITWORD',
+        b'PK_PUBLIC',
+        b'MAX_RSA_SIZE',
+        b'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.decode("utf-8"), value))
+    print(' ')
+
+# print selected sizes
+if SHOW_SELECTED_SIZES:
+    print('-'*60)
+    print('\n  selected sizes:')
+
+    names = [
+        b'rijndael_key',
+        b'rsa_key',
+        b'symmetric_CTR',
+        b'twofish_key',
+        b'ecc_point',
+        b'gcm_state',
+        b'sha512_state',
+    ]
+    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.decode("utf-8"), value))
+    print(' ')
+
+
+#-------------------------------------------------------------------------------
+#-------------------------------------------------------------------------------
+# LibTomCrypt exposes one interesting string that can be accessed
+# via Python's ctypes module, "crypt_build_settings", which
+# provides a list of this build's compiler switches and supported
+# algorithms.  If someday LTC exposes other interesting strings,
+# they can be found with:
+#   nm /usr/local/lib/libtomcrypt.dylib | grep " D "
+
+def get_named_string(lib, name):
+    return c_char_p.in_dll(lib, name).value.decode("utf-8")
+
+if SHOW_BUILD_OPTIONS_ALGS:
+    print('-'*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'))
+    inprint(get_named_string(LTC, 'crypt_build_settings'), 4)
+
+
+#-------------------------------------------------------------------------------
+#-------------------------------------------------------------------------------
+# here is an example of how Python code can be written to access
+# LTC's implementation of SHA256 and ChaCha,
+
+# - - - - - - - - - - - - -
+# definitions
+
+from binascii import hexlify, unhexlify
+
+def _err2str(err):
+    # define return type
+    errstr = LTC.error_to_string
+    errstr.restype = c_char_p
+    # get and return err string
+    return errstr(err)
+
+def _get_size(name):
+    size = c_int(0)
+    rc = LTC.crypt_get_size(bytes(name), byref(size))
+    if rc != 0:
+        raise Exception('LTC.crypt_get_size(%s) rc = %d' % (name, rc))
+    return size.value
+
+def _get_constant(name):
+    constant = c_int(0)
+    rc = LTC.crypt_get_constant(bytes(name), byref(constant))
+    if rc != 0:
+        raise Exception('LTC.crypt_get_constant(%s) rc = %d' % (name, rc))
+    return constant.value
+
+CRYPT_OK = _get_constant(b'CRYPT_OK')
+
+class SHA256(object):
+    def __init__(self):
+        self.state = c_buffer(_get_size(b'sha256_state'))
+        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
+
+class ChaCha(object):
+    def __init__(self, key, rounds):
+        self.state   = c_buffer(_get_size(b'chacha_state'))
+        self.counter = c_int(1)
+        err = LTC.chacha_setup(byref(self.state), key, len(key), rounds)
+        if err != CRYPT_OK:
+            raise Exception('LTC.chacha_setup(), err = %d, "%s"' % (err, _err2str(err)))
+    def set_iv32(self, iv):
+        err = LTC.chacha_ivctr32(byref(self.state), iv, len(iv), byref(self.counter))
+        if err != CRYPT_OK:
+            raise Exception('LTC.chacha_ivctr32(), err = %d, "%s"' % (err, _err2str(err)))
+    def crypt(self, datain):
+        dataout = c_buffer(len(datain))
+        err = LTC.chacha_crypt(byref(self.state), datain, len(datain), byref(dataout))
+        if err != CRYPT_OK:
+            raise Exception('LTC.chacha_crypt(), err = %d, "%s"' % (err, _err2str(err)))
+        return dataout.raw
+
+# - - - - - - - - - - - - -
+# a SHA256 app fragment
+
+if SHOW_SHA256_EXAMPLE:
+    print('-'*60)
+    data = b'hello world'               # we want bytes, not Unicode
+
+    sha256 = SHA256()
+    sha256.update(data)
+    md = sha256.digest()
+
+    template = '\n  the SHA256 digest for "%s" is %s \n'
+    print(template % (data, hexlify(md)))
+
+# - - - - - - - - - - - - -
+# a ChaCha app fragment
+
+if SHOW_CHACHA_EXAMPLE:
+    print('-'*60)
+    key     = b'hownowbrowncow\x00\x00' # exactly 16 or 32 bytes
+    rounds  = 12                        # common values: 8, 12, 20
+    iv      = b'123456789012'           # exactly 12 bytes
+    plain   = b'Kilroy was here, there, and everywhere!'
+
+    cha = ChaCha(key, rounds)
+    cha.set_iv32(iv)
+    cipher = cha.crypt(plain)
+
+    template = '\n  ChaCha%d ciphertext   for "%s" is "%s"'
+    print(template % (rounds, plain, hexlify(cipher)))
+
+    cha.set_iv32(iv)                    # reset to decrypt
+    decrypted = cha.crypt(cipher)
+
+    template = '  ChaCha%d decoded text for "%s" is "%s" \n'
+    print(template % (rounds, plain, decrypted.decode("utf-8")))
+
+# Footnote: Keys should be erased fm memory as soon as possible after use,
+# and that includes Python.  For a tip on how to do that in Python, see
+# http://buggywhip.blogspot.com/2010/12/erase-keys-and-credit-card-numbers-in.html
+
+#-------------------------------------------------------------------------------
+#-------------------------------------------------------------------------------
+#-------------------------------------------------------------------------------

+ 56 - 22
demos/sizes.c

@@ -6,8 +6,14 @@
  * The library is free for all purposes without any express
  * guarantee it works.
  */
+
 #include "tomcrypt.h"
 
+#if _POSIX_C_SOURCE >= 200112L
+#include <libgen.h>
+#else
+#define basename(x) x
+#endif
 /**
   @file demo_crypt_sizes.c
 
@@ -15,29 +21,57 @@
   like Python - Larry Bugbee, February 2013
 */
 
+static void _print_line(const char* cmd, const char* desc)
+{
+   printf("  %-16s - %s\n", cmd, desc);
+}
+
+int main(int argc, char **argv)
+{
+   if (argc == 1) {
+      /* given a specific size name, get and print its size */
+      char name[] = "ltc_hash_descriptor";
+      unsigned int size;
+      char *sizes_list;
+      unsigned int sizes_list_len;
+      if (crypt_get_size(name, &size) != 0) exit(EXIT_FAILURE);
+      printf("\n  size of '%s' is %u \n\n", name, size);
+
+      /* get and print the length of the names (and sizes) list */
+      if (crypt_list_all_sizes(NULL, &sizes_list_len) != 0) exit(EXIT_FAILURE);
+      printf("  need to allocate %u bytes \n\n", sizes_list_len);
 
-int main(void) {
-
-    /* given a specific size name, get and print its size */
-    char name[] = "ltc_hash_descriptor";
-    unsigned int size;
-    char *sizes_list;
-    unsigned int sizes_list_len;
-    if(crypt_get_size(name, &size) != 0)
-      exit(EXIT_FAILURE);
-    printf("\n  size of '%s' is %u \n\n", name, size);
-
-    /* get and print the length of the names (and sizes) list */
-    if(crypt_list_all_sizes(NULL, &sizes_list_len) != 0)
-       exit(EXIT_FAILURE);
-    printf("  need to allocate %u bytes \n\n", sizes_list_len);
-
-    /* get and print the names (and sizes) list */
-    sizes_list = malloc(sizes_list_len);
-    if(crypt_list_all_sizes(sizes_list, &sizes_list_len) != 0)
-       exit(EXIT_FAILURE);
-    printf("  supported sizes:\n\n%s\n\n", sizes_list);
-    return 0;
+      /* get and print the names (and sizes) list */
+      sizes_list = malloc(sizes_list_len);
+      if (crypt_list_all_sizes(sizes_list, &sizes_list_len) != 0) exit(EXIT_FAILURE);
+      printf("  supported sizes:\n\n%s\n\n", sizes_list);
+   } else if (argc == 2) {
+      if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
+         char* base = strdup(basename(argv[0]));
+         printf("Usage: %s [-a] [-s name]\n\n", base);
+         _print_line("<no argument>", "The old behavior of the demo");
+         _print_line("-a", "Only lists all sizes");
+         _print_line("-s name", "List a single size given as argument");
+         _print_line("-h", "The help you're looking at");
+         free(base);
+      } else if (strcmp(argv[1], "-a") == 0) {
+         char *sizes_list;
+         unsigned int sizes_list_len;
+         /* get and print the length of the names (and sizes) list */
+         if (crypt_list_all_sizes(NULL, &sizes_list_len) != 0) exit(EXIT_FAILURE);
+         /* get and print the names (and sizes) list */
+         sizes_list = malloc(sizes_list_len);
+         if (crypt_list_all_sizes(sizes_list, &sizes_list_len) != 0) exit(EXIT_FAILURE);
+         printf("%s\n", sizes_list);
+      }
+   } else if (argc == 3) {
+      if (strcmp(argv[1], "-s") == 0) {
+         unsigned int size;
+         if (crypt_get_size(argv[2], &size) != 0) exit(EXIT_FAILURE);
+         printf("%s,%u\n", argv[2], size);
+      }
+   }
+   return 0;
 }
 
 /* ref:         $Format:%D$ */

+ 5 - 0
src/headers/tomcrypt_cfg.h

@@ -64,6 +64,11 @@ LTC_EXPORT int   LTC_CALL XSTRCMP(const char *s1, const char *s2);
    #define ARGTYPE  0
 #endif
 
+#undef LTC_ENCRYPT
+#define LTC_ENCRYPT 0
+#undef LTC_DECRYPT
+#define LTC_DECRYPT 1
+
 /* Controls endianess and size of registers.  Leave uncommented to get platform neutral [slower] code
  *
  * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes.

+ 2 - 2
src/headers/tomcrypt_cipher.h

@@ -875,8 +875,8 @@ int ctr_test(void);
 
 #ifdef LTC_LRW_MODE
 
-#define LRW_ENCRYPT 0
-#define LRW_DECRYPT 1
+#define LRW_ENCRYPT LTC_ENCRYPT
+#define LRW_DECRYPT LTC_DECRYPT
 
 int lrw_start(               int   cipher,
               const unsigned char *IV,

+ 6 - 6
src/headers/tomcrypt_mac.h

@@ -311,8 +311,8 @@ void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const
 
 #ifdef LTC_CCM_MODE
 
-#define CCM_ENCRYPT 0
-#define CCM_DECRYPT 1
+#define CCM_ENCRYPT LTC_ENCRYPT
+#define CCM_DECRYPT LTC_DECRYPT
 
 typedef struct {
    symmetric_key       K;
@@ -378,8 +378,8 @@ extern const unsigned char gcm_shift_table[];
 
 #ifdef LTC_GCM_MODE
 
-#define GCM_ENCRYPT 0
-#define GCM_DECRYPT 1
+#define GCM_ENCRYPT LTC_ENCRYPT
+#define GCM_DECRYPT LTC_DECRYPT
 
 #define LTC_GCM_MODE_IV    0
 #define LTC_GCM_MODE_AAD   1
@@ -542,8 +542,8 @@ typedef struct {
    int aadflg;
 } chacha20poly1305_state;
 
-#define CHCHA20POLY1305_ENCRYPT 0
-#define CHCHA20POLY1305_DECRYPT 1
+#define CHCHA20POLY1305_ENCRYPT LTC_ENCRYPT
+#define CHCHA20POLY1305_DECRYPT LTC_DECRYPT
 
 int chacha20poly1305_init(chacha20poly1305_state *st, const unsigned char *key, unsigned long keylen);
 int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen);

+ 7 - 7
src/headers/tomcrypt_pk.h

@@ -198,13 +198,6 @@ int katja_import(const unsigned char *in, unsigned long inlen, katja_key *key);
 /* ---- DH Routines ---- */
 #ifdef LTC_MDH
 
-typedef struct {
-  int size;
-  char *name, *base, *prime;
-} ltc_dh_set_type;
-
-extern const ltc_dh_set_type ltc_dh_sets[];
-
 typedef struct {
     int type;
     void *x;
@@ -235,6 +228,13 @@ void dh_free(dh_key *key);
 int dh_export_key(void *out, unsigned long *outlen, int type, dh_key *key);
 
 #ifdef LTC_SOURCE
+typedef struct {
+  int size;
+  char *name, *base, *prime;
+} ltc_dh_set_type;
+
+extern const ltc_dh_set_type ltc_dh_sets[];
+
 /* internal helper functions */
 int dh_check_pubkey(dh_key *key);
 #endif

+ 64 - 2
src/misc/crypt/crypt_constants.c

@@ -26,11 +26,39 @@ typedef struct {
 #define _C_STRINGIFY(s) { #s, s }
 
 static const crypt_constant _crypt_constants[] = {
+
+    _C_STRINGIFY(CRYPT_OK),
+    _C_STRINGIFY(CRYPT_ERROR),
+    _C_STRINGIFY(CRYPT_NOP),
+    _C_STRINGIFY(CRYPT_INVALID_KEYSIZE),
+    _C_STRINGIFY(CRYPT_INVALID_ROUNDS),
+    _C_STRINGIFY(CRYPT_FAIL_TESTVECTOR),
+    _C_STRINGIFY(CRYPT_BUFFER_OVERFLOW),
+    _C_STRINGIFY(CRYPT_INVALID_PACKET),
+    _C_STRINGIFY(CRYPT_INVALID_PRNGSIZE),
+    _C_STRINGIFY(CRYPT_ERROR_READPRNG),
+    _C_STRINGIFY(CRYPT_INVALID_CIPHER),
+    _C_STRINGIFY(CRYPT_INVALID_HASH),
+    _C_STRINGIFY(CRYPT_INVALID_PRNG),
+    _C_STRINGIFY(CRYPT_MEM),
+    _C_STRINGIFY(CRYPT_PK_TYPE_MISMATCH),
+    _C_STRINGIFY(CRYPT_PK_NOT_PRIVATE),
+    _C_STRINGIFY(CRYPT_INVALID_ARG),
+    _C_STRINGIFY(CRYPT_FILE_NOTFOUND),
+    _C_STRINGIFY(CRYPT_PK_INVALID_TYPE),
+    _C_STRINGIFY(CRYPT_OVERFLOW),
+    _C_STRINGIFY(CRYPT_UNUSED1),
+    _C_STRINGIFY(CRYPT_UNUSED2),
+    _C_STRINGIFY(CRYPT_PK_INVALID_SIZE),
+    _C_STRINGIFY(CRYPT_INVALID_PRIME_SIZE),
+    _C_STRINGIFY(CRYPT_PK_INVALID_PADDING),
+    _C_STRINGIFY(CRYPT_HASH_OVERFLOW),
+
     _C_STRINGIFY(PK_PUBLIC),
     _C_STRINGIFY(PK_PRIVATE),
 
-    _C_STRINGIFY(PKA_RSA),
-    _C_STRINGIFY(PKA_DSA),
+    _C_STRINGIFY(LTC_ENCRYPT),
+    _C_STRINGIFY(LTC_DECRYPT),
 
 #ifdef LTC_PKCS_1
     {"LTC_PKCS_1", 1},
@@ -42,6 +70,7 @@ static const crypt_constant _crypt_constants[] = {
     _C_STRINGIFY(LTC_PKCS_1_V1_5),
     _C_STRINGIFY(LTC_PKCS_1_OAEP),
     _C_STRINGIFY(LTC_PKCS_1_PSS),
+    _C_STRINGIFY(LTC_PKCS_1_V1_5_NA1),
 #else
     {"LTC_PKCS_1", 0},
 #endif
@@ -85,6 +114,31 @@ static const crypt_constant _crypt_constants[] = {
     _C_STRINGIFY(LTC_MILLER_RABIN_REPS),
 #endif
 
+#ifdef LTC_DER
+/* DER handling */
+    _C_STRINGIFY(LTC_ASN1_EOL),
+    _C_STRINGIFY(LTC_ASN1_BOOLEAN),
+    _C_STRINGIFY(LTC_ASN1_INTEGER),
+    _C_STRINGIFY(LTC_ASN1_SHORT_INTEGER),
+    _C_STRINGIFY(LTC_ASN1_BIT_STRING),
+    _C_STRINGIFY(LTC_ASN1_OCTET_STRING),
+    _C_STRINGIFY(LTC_ASN1_NULL),
+    _C_STRINGIFY(LTC_ASN1_OBJECT_IDENTIFIER),
+    _C_STRINGIFY(LTC_ASN1_IA5_STRING),
+    _C_STRINGIFY(LTC_ASN1_PRINTABLE_STRING),
+    _C_STRINGIFY(LTC_ASN1_UTF8_STRING),
+    _C_STRINGIFY(LTC_ASN1_UTCTIME),
+    _C_STRINGIFY(LTC_ASN1_CHOICE),
+    _C_STRINGIFY(LTC_ASN1_SEQUENCE),
+    _C_STRINGIFY(LTC_ASN1_SET),
+    _C_STRINGIFY(LTC_ASN1_SETOF),
+    _C_STRINGIFY(LTC_ASN1_RAW_BIT_STRING),
+    _C_STRINGIFY(LTC_ASN1_TELETEX_STRING),
+    _C_STRINGIFY(LTC_ASN1_CONSTRUCTED),
+    _C_STRINGIFY(LTC_ASN1_CONTEXT_SPECIFIC),
+    _C_STRINGIFY(LTC_ASN1_GENERALIZEDTIME),
+#endif
+
 #ifdef LTC_CTR_MODE
     {"LTC_CTR_MODE", 1},
     _C_STRINGIFY(CTR_COUNTER_LITTLE_ENDIAN),
@@ -93,6 +147,14 @@ static const crypt_constant _crypt_constants[] = {
 #else
     {"LTC_CTR_MODE", 0},
 #endif
+#ifdef LTC_GCM_MODE
+    _C_STRINGIFY(LTC_GCM_MODE_IV),
+    _C_STRINGIFY(LTC_GCM_MODE_AAD),
+    _C_STRINGIFY(LTC_GCM_MODE_TEXT),
+#endif
+
+    _C_STRINGIFY(LTC_MP_NO),
+    _C_STRINGIFY(LTC_MP_YES),
 
     _C_STRINGIFY(MAXBLOCKSIZE),
     _C_STRINGIFY(TAB_SIZE),

+ 66 - 40
src/misc/crypt/crypt_sizes.c

@@ -30,8 +30,11 @@ static const crypt_size _crypt_sizes[] = {
     /* hash state sizes */
     _SZ_STRINGIFY_S(ltc_hash_descriptor),
     _SZ_STRINGIFY_T(hash_state),
-#ifdef LTC_SHA256
-    _SZ_STRINGIFY_S(sha256_state),
+#ifdef LTC_CHC_HASH
+    _SZ_STRINGIFY_S(chc_state),
+#endif
+#ifdef LTC_WHIRLPOOL
+    _SZ_STRINGIFY_S(whirlpool_state),
 #endif
 #ifdef LTC_SHA3
     _SZ_STRINGIFY_S(sha3_state),
@@ -39,17 +42,23 @@ static const crypt_size _crypt_sizes[] = {
 #ifdef LTC_SHA512
     _SZ_STRINGIFY_S(sha512_state),
 #endif
-#ifdef LTC_WHIRLPOOL
-    _SZ_STRINGIFY_S(whirlpool_state),
+#ifdef LTC_SHA256
+    _SZ_STRINGIFY_S(sha256_state),
 #endif
-#ifdef LTC_MD2
-    _SZ_STRINGIFY_S(md2_state),
+#ifdef LTC_SHA1
+    _SZ_STRINGIFY_S(sha1_state),
+#endif
+#ifdef LTC_MD5
+    _SZ_STRINGIFY_S(md5_state),
 #endif
 #ifdef LTC_MD4
     _SZ_STRINGIFY_S(md4_state),
 #endif
-#ifdef LTC_MD5
-    _SZ_STRINGIFY_S(md5_state),
+#ifdef LTC_MD2
+    _SZ_STRINGIFY_S(md2_state),
+#endif
+#ifdef LTC_TIGER
+    _SZ_STRINGIFY_S(tiger_state),
 #endif
 #ifdef LTC_RIPEMD128
     _SZ_STRINGIFY_S(rmd128_state),
@@ -63,21 +72,12 @@ static const crypt_size _crypt_sizes[] = {
 #ifdef LTC_RIPEMD320
     _SZ_STRINGIFY_S(rmd320_state),
 #endif
-#ifdef LTC_SHA1
-    _SZ_STRINGIFY_S(sha1_state),
-#endif
-#ifdef LTC_TIGER
-    _SZ_STRINGIFY_S(tiger_state),
-#endif
 #ifdef LTC_BLAKE2S
     _SZ_STRINGIFY_S(blake2s_state),
 #endif
 #ifdef LTC_BLAKE2B
     _SZ_STRINGIFY_S(blake2b_state),
 #endif
-#ifdef LTC_CHC_HASH
-    _SZ_STRINGIFY_S(chc_state),
-#endif
 
     /* block cipher key sizes */
     _SZ_STRINGIFY_S(ltc_cipher_descriptor),
@@ -142,46 +142,57 @@ static const crypt_size _crypt_sizes[] = {
 #endif
 
     /* mode sizes */
-#ifdef LTC_CBC_MODE
-    _SZ_STRINGIFY_T(symmetric_CBC),
+#ifdef LTC_ECB_MODE
+    _SZ_STRINGIFY_T(symmetric_ECB),
 #endif
 #ifdef LTC_CFB_MODE
     _SZ_STRINGIFY_T(symmetric_CFB),
 #endif
+#ifdef LTC_OFB_MODE
+    _SZ_STRINGIFY_T(symmetric_OFB),
+#endif
+#ifdef LTC_CBC_MODE
+    _SZ_STRINGIFY_T(symmetric_CBC),
+#endif
 #ifdef LTC_CTR_MODE
     _SZ_STRINGIFY_T(symmetric_CTR),
 #endif
-#ifdef LTC_ECB_MODE
-    _SZ_STRINGIFY_T(symmetric_ECB),
+#ifdef LTC_LRW_MODE
+    _SZ_STRINGIFY_T(symmetric_LRW),
 #endif
 #ifdef LTC_F8_MODE
     _SZ_STRINGIFY_T(symmetric_F8),
 #endif
-#ifdef LTC_LRW_MODE
-    _SZ_STRINGIFY_T(symmetric_LRW),
+#ifdef LTC_XTS_MODE
+    _SZ_STRINGIFY_T(symmetric_xts),
 #endif
-#ifdef LTC_OFB_MODE
-    _SZ_STRINGIFY_T(symmetric_OFB),
+
+    /* stream cipher sizes */
+#ifdef LTC_CHACHA
+    _SZ_STRINGIFY_T(chacha_state),
+#endif
+#ifdef LTC_RC4_STREAM
+    _SZ_STRINGIFY_T(rc4_state),
+#endif
+#ifdef LTC_SOBER128_STREAM
+    _SZ_STRINGIFY_T(sober128_state),
 #endif
 
     /* MAC sizes            -- no states for ccm, lrw */
-#ifdef LTC_F9_MODE
-    _SZ_STRINGIFY_T(f9_state),
-#endif
 #ifdef LTC_HMAC
     _SZ_STRINGIFY_T(hmac_state),
 #endif
 #ifdef LTC_OMAC
     _SZ_STRINGIFY_T(omac_state),
 #endif
-#ifdef LTC_PELICAN
-    _SZ_STRINGIFY_T(pelican_state),
-#endif
 #ifdef LTC_PMAC
     _SZ_STRINGIFY_T(pmac_state),
 #endif
-#ifdef LTC_XCBC
-    _SZ_STRINGIFY_T(xcbc_state),
+#ifdef LTC_POLY1305
+    _SZ_STRINGIFY_T(poly1305_state),
+#endif
+#ifdef LTC_EAX_MODE
+    _SZ_STRINGIFY_T(eax_state),
 #endif
 #ifdef LTC_OCB_MODE
     _SZ_STRINGIFY_T(ocb_state),
@@ -189,17 +200,23 @@ static const crypt_size _crypt_sizes[] = {
 #ifdef LTC_OCB3_MODE
     _SZ_STRINGIFY_T(ocb3_state),
 #endif
+#ifdef LTC_CCM_MODE
+    _SZ_STRINGIFY_T(ccm_state),
+#endif
 #ifdef LTC_GCM_MODE
     _SZ_STRINGIFY_T(gcm_state),
 #endif
-#ifdef LTC_EAX_MODE
-    _SZ_STRINGIFY_T(eax_state),
+#ifdef LTC_PELICAN
+    _SZ_STRINGIFY_T(pelican_state),
 #endif
-#ifdef LTC_CCM_MODE
-/* not defined */
+#ifdef LTC_XCBC
+    _SZ_STRINGIFY_T(xcbc_state),
 #endif
-#ifdef LRW_MODE
-/* not defined */
+#ifdef LTC_F9_MODE
+    _SZ_STRINGIFY_T(f9_state),
+#endif
+#ifdef LTC_CHACHA20POLY1305_MODE
+    _SZ_STRINGIFY_T(chacha20poly1305_state),
 #endif
 
     /* asymmetric keys */
@@ -214,13 +231,20 @@ static const crypt_size _crypt_sizes[] = {
 #endif
 #ifdef LTC_MECC
     _SZ_STRINGIFY_T(ltc_ecc_set_type),
-    _SZ_STRINGIFY_T(ecc_key),
     _SZ_STRINGIFY_T(ecc_point),
+    _SZ_STRINGIFY_T(ecc_key),
 #endif
 #ifdef LTC_MKAT
     _SZ_STRINGIFY_T(katja_key),
 #endif
 
+    /* DER handling */
+#ifdef LTC_DER
+    _SZ_STRINGIFY_T(ltc_asn1_list),  /* a list entry */
+    _SZ_STRINGIFY_T(ltc_utctime),
+    _SZ_STRINGIFY_T(ltc_generalizedtime),
+#endif
+
     /* prng state sizes */
     _SZ_STRINGIFY_S(ltc_prng_descriptor),
     _SZ_STRINGIFY_T(prng_state),
@@ -248,6 +272,8 @@ static const crypt_size _crypt_sizes[] = {
 #ifdef LTC_CRC32
     _SZ_STRINGIFY_T(crc32_state),
 #endif
+
+
 };
 
 /* crypt_get_size()