| \documentclass[b5paper]{book} |
| \usepackage{hyperref} |
| \usepackage{makeidx} |
| \usepackage{amssymb} |
| \usepackage{color} |
| \usepackage{alltt} |
| \usepackage{graphicx} |
| \usepackage{layout} |
| \def\union{\cup} |
| \def\intersect{\cap} |
| \def\getsrandom{\stackrel{\rm R}{\gets}} |
| \def\cross{\times} |
| \def\cat{\hspace{0.5em} \| \hspace{0.5em}} |
| \def\catn{$\|$} |
| \def\divides{\hspace{0.3em} | \hspace{0.3em}} |
| \def\nequiv{\not\equiv} |
| \def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}} |
| \def\lcm{{\rm lcm}} |
| \def\gcd{{\rm gcd}} |
| \def\log{{\rm log}} |
| \def\ord{{\rm ord}} |
| \def\abs{{\mathit abs}} |
| \def\rep{{\mathit rep}} |
| \def\mod{{\mathit\ mod\ }} |
| \renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})} |
| \newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor} |
| \newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil} |
| \def\Or{{\rm\ or\ }} |
| \def\And{{\rm\ and\ }} |
| \def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}} |
| \def\implies{\Rightarrow} |
| \def\undefined{{\rm ``undefined"}} |
| \def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}} |
| \let\oldphi\phi |
| \def\phi{\varphi} |
| \def\Pr{{\rm Pr}} |
| \newcommand{\str}[1]{{\mathbf{#1}}} |
| \def\F{{\mathbb F}} |
| \def\N{{\mathbb N}} |
| \def\Z{{\mathbb Z}} |
| \def\R{{\mathbb R}} |
| \def\C{{\mathbb C}} |
| \def\Q{{\mathbb Q}} |
| |
| \def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}} |
| |
| \def\gap{\vspace{0.5ex}} |
| \makeindex |
| \begin{document} |
| \title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.96} |
| \author{Tom St Denis \\ |
| \\ |
| tomstdenis@iahu.ca \\ |
| http://libtomcrypt.org \\ \\ |
| Phone: 1-613-836-3160\\ |
| 111 Banning Rd \\ |
| Kanata, Ontario \\ |
| K2L 1C3 \\ |
| Canada |
| } |
| \maketitle |
| This text and source code library are both hereby placed in the public domain. This book has been |
| formatted for B5 [176x250] paper using the \LaTeX{} {\em book} macro package. |
| |
| \vspace{10cm} |
| |
| \begin{flushright}Open Source. Open Academia. Open Minds. |
| |
| \mbox{ } |
| |
| Tom St Denis, |
| |
| Ontario, Canada |
| \end{flushright} |
| \newpage |
| \tableofcontents |
| \chapter{Introduction} |
| \section{What is the LibTomCrypt?} |
| LibTomCrypt is a portable ANSI C cryptographic library that supports symmetric ciphers, one-way hashes, |
| pseudo-random number generators, public key cryptography (via RSA,DH or ECC/DH) and a plethora of support |
| routines. It is designed to compile out of the box with the GNU C Compiler (GCC) version 2.95.3 (and higher) |
| and with MSVC version 6 in win32. |
| |
| The library has been successfully tested on quite a few other platforms ranging from the ARM7TDMI in a |
| Gameboy Advanced to various PowerPC processors and even the MIPS processor in the PlayStation 2. Suffice it |
| to say the code is portable. |
| |
| The library is designed so new ciphers/hashes/PRNGs can be added at runtime and the existing API (and helper API functions) will |
| be able to use the new designs automatically. There exist self-check functions for each cipher and hash to ensure that |
| they compile and execute to the published design specifications. The library also performs extensive parameter error checking |
| and will give verbose error messages when possible. |
| |
| Essentially the library saves the time of having to implement the ciphers, hashes, prngs yourself. Typically implementing |
| useful cryptography is an error prone business which means anything that can save considerable time and effort is a good |
| thing. |
| |
| \subsection{What the library IS for?} |
| |
| The library typically serves as a basis for other protocols and message formats. For example, it should be possible to |
| take the RSA routines out of this library, apply the appropriate message padding and get PKCS compliant RSA routines. |
| Similarly SSL protocols could be formed on top of the low-level symmetric cipher functions. The goal of this package is |
| to provide these low level core functions in a robust and easy to use fashion. |
| |
| The library also serves well as a toolkit for applications where they don't need to be OpenPGP, PKCS, etc. compliant. |
| Included are fully operational public key routines for encryption, decryption, signature generation and verification. |
| These routines are fully portable but are not conformant to any known set of standards\footnote{With the exception of |
| the RSA code which is based on the PKCS \#1 standards.}. They are all based on established |
| number theory and cryptography. |
| |
| \subsection{What the library IS NOT for?} |
| |
| The library is not designed to be in anyway an implementation of the SSL or OpenPGP standards. The library |
| is not designed to be compliant with any known form of API or programming hierarchy. It is not a port of any other |
| library and it is not platform specific (like the MS CSP). So if you're looking to drop in some buzzword |
| compliant crypto library this is not for you. The library has been written from scratch to provide basic functions as |
| well as non-standard higher level functions. |
| |
| This is not to say that the library is a ``homebrew'' project. All of the symmetric ciphers and one-way hash functions |
| conform to published test vectors. The public key functions are derived from publicly available material and the majority |
| of the code has been reviewed by a growing community of developers. |
| |
| \subsubsection{Why not?} |
| You may be asking why I didn't choose to go all out and support standards like P1363, PKCS and the whole lot. The reason |
| is quite simple too much money gets in the way. When I tried to access the P1363 draft documents and was denied (it |
| requires a password) I realized that they're just a business anyways. See what happens is a company will sit down and |
| invent a ``standard''. Then they try to sell it to as many people as they can. All of a sudden this ``standard'' is |
| everywhere. Then the standard is updated every so often to keep people dependent. Then you become RSA. If people are |
| supposed to support these standards they had better make them more accessible. |
| |
| \section{Why did I write it?} |
| You may be wondering, ``Tom, why did you write a crypto library. I already have one.''. Well the reason falls into |
| two categories: |
| \begin{enumerate} |
| \item I am too lazy to figure out someone else's API. I'd rather invent my own simpler API and use that. |
| \item It was (still is) good coding practice. |
| \end{enumerate} |
| |
| The idea is that I am not striving to replace OpenSSL or Crypto++ or Cryptlib or etc. I'm trying to write my |
| {\bf own} crypto library and hopefully along the way others will appreciate the work. |
| |
| With this library all core functions (ciphers, hashes, prngs) have the {\bf exact} same prototype definition. They all load |
| and store data in a format independent of the platform. This means if you encrypt with Blowfish on a PPC it should decrypt |
| on an x86 with zero problems. The consistent API also means that if you learn how to use blowfish with my library you |
| know how to use Safer+ or RC6 or Serpent or ... as well. With all of the core functions there are central descriptor tables |
| that can be used to make a program automatically pick between ciphers, hashes and PRNGs at runtime. That means your |
| application can support all ciphers/hashes/prngs without changing the source code. |
| |
| \subsection{Modular} |
| The LibTomCrypt package has also been written to be very modular. The block ciphers, one-way hashes and |
| pseudo-random number generators (PRNG) are all used within the API through ``descriptor'' tables which |
| are essentially structures with pointers to functions. While you can still call particular functions |
| directly (\textit{e.g. sha256\_process()}) this descriptor interface allows the developer to customize their |
| usage of the library. |
| |
| For example, consider a hardware platform with a specialized RNG device. Obviously one would like to tap |
| that for the PRNG needs within the library (\textit{e.g. making a RSA key}). All the developer has todo |
| is write a descriptor and the few support routines required for the device. After that the rest of the |
| API can make use of it without change. Similiarly imagine a few years down the road when AES2 (\textit{or whatever they call it}) is |
| invented. It can be added to the library and used within applications with zero modifications to the |
| end applications provided they are written properly. |
| |
| This flexibility within the library means it can be used with any combination of primitive algorithms and |
| unlike libraries like OpenSSL is not tied to direct routines. For instance, in OpenSSL there are CBC block |
| mode routines for every single cipher. That means every time you add or remove a cipher from the library |
| you have to update the associated support code as well. In LibTomCrypt the associated code (\textit{chaining modes in this case}) |
| are not directly tied to the ciphers. That is a new cipher can be added to the library by simply providing |
| the key setup, ECB decrypt and encrypt and test vector routines. After that all five chaining mode routines |
| can make use of the cipher right away. |
| |
| |
| \section{License} |
| |
| All of the source code except for the following files have been written by the author or donated to the project |
| under a public domain license: |
| |
| \begin{enumerate} |
| \item rc2.c |
| \item safer.c |
| \end{enumerate} |
| |
| `mpi.c'' was originally written by Michael Fromberger (sting@linguist.dartmouth.edu) but has since been replaced with my LibTomMath |
| library. |
| |
| ``rc2.c'' is based on publicly available code that is not attributed to a person from the given source. ``safer.c'' |
| was written by Richard De Moliner (demoliner@isi.ee.ethz.ch) and is public domain. |
| |
| The project is hereby released as public domain. |
| |
| \section{Patent Disclosure} |
| |
| The author (Tom St Denis) is not a patent lawyer so this section is not to be treated as legal advice. To the best |
| of the authors knowledge the only patent related issues within the library are the RC5 and RC6 symmetric block ciphers. |
| They can be removed from a build by simply commenting out the two appropriate lines in the makefile script. The rest |
| of the ciphers and hashes are patent free or under patents that have since expired. |
| |
| The RC2 and RC4 symmetric ciphers are not under patents but are under trademark regulations. This means you can use |
| the ciphers you just can't advertise that you are doing so. |
| |
| \section{Building the library} |
| |
| To build the library on a GCC equipped platform simply type ``make'' at your command prompt. It will build the library |
| file ``libtomcrypt.a''. |
| |
| To install the library copy all of the ``.h'' files into your ``\#include'' path and the single libtomcrypt.a file into |
| your library path. |
| |
| With MSVC you can build the library with ``nmake -f makefile.msvc''. This will produce a ``tomcrypt.lib'' file which |
| is the core library. Copy the header files into your MSVC include path and the library in the lib path (typically |
| under where VC98 is installed). |
| |
| \section{Building against the library} |
| |
| In the recent versions the build steps have changed. The build options are now stored in ``mycrypt\_custom.h'' and |
| no longer in the makefile. If you change a build option in that file you must re-build the library from clean to |
| ensure the build is intact. The perl script ``config.pl'' will help setup the custom header and a custom makefile |
| if you want one (the provided ``makefile'' will work with custom configs). |
| |
| \section{Thanks} |
| I would like to give thanks to the following people (in no particular order) for helping me develop this project: |
| \begin{enumerate} |
| \item Richard van de Laarschot |
| \item Richard Heathfield |
| \item Ajay K. Agrawal |
| \item Brian Gladman |
| \item Svante Seleborg |
| \item Clay Culver |
| \item Jason Klapste |
| \item Dobes Vandermeer |
| \item Daniel Richards |
| \item Wayne Scott |
| \item Andrew Tyler |
| \item Sky Schulz |
| \item Christopher Imes |
| \end{enumerate} |
| |
| \chapter{The Application Programming Interface (API)} |
| \section{Introduction} |
| \index{CRYPT\_ERROR} \index{CRYPT\_OK} |
| |
| In general the API is very simple to memorize and use. Most of the functions return either {\bf void} or {\bf int}. Functions |
| that return {\bf int} will return {\bf CRYPT\_OK} if the function was successful or one of the many error codes |
| if it failed. Certain functions that return int will return $-1$ to indicate an error. These functions will be explicitly |
| commented upon. When a function does return a CRYPT error code it can be translated into a string with |
| |
| \index{error\_to\_string()} |
| \begin{verbatim} |
| const char *error_to_string(int err); |
| \end{verbatim} |
| |
| An example of handling an error is: |
| \begin{verbatim} |
| void somefunc(void) |
| { |
| int err; |
| |
| /* call a cryptographic function */ |
| if ((err = some_crypto_function(...)) != CRYPT_OK) { |
| printf("A crypto error occured, %s\n", error_to_string(err)); |
| /* perform error handling */ |
| } |
| /* continue on if no error occured */ |
| } |
| \end{verbatim} |
| |
| There is no initialization routine for the library and for the most part the code is thread safe. The only thread |
| related issue is if you use the same symmetric cipher, hash or public key state data in multiple threads. Normally |
| that is not an issue. |
| |
| To include the prototypes for ``LibTomCrypt.a'' into your own program simply include ``mycrypt.h'' like so: |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) { |
| return 0; |
| } |
| \end{verbatim} |
| |
| The header file ``mycrypt.h'' also includes ``stdio.h'', ``string.h'', ``stdlib.h'', ``time.h'', ``ctype.h'' and ``mpi.h'' |
| (the bignum library routines). |
| |
| \section{Macros} |
| |
| There are a few helper macros to make the coding process a bit easier. The first set are related to loading and storing |
| 32/64-bit words in little/big endian format. The macros are: |
| |
| \index{STORE32L} \index{STORE64L} \index{LOAD32L} \index{LOAD64L} |
| \index{STORE32H} \index{STORE64H} \index{LOAD32H} \index{LOAD64H} \index{BSWAP} |
| \begin{small} |
| \begin{center} |
| \begin{tabular}{|c|c|c|} |
| \hline STORE32L(x, y) & {\bf unsigned long} x, {\bf unsigned char} *y & $x \to y[0 \ldots 3]$ \\ |
| \hline STORE64L(x, y) & {\bf unsigned long long} x, {\bf unsigned char} *y & $x \to y[0 \ldots 7]$ \\ |
| \hline LOAD32L(x, y) & {\bf unsigned long} x, {\bf unsigned char} *y & $y[0 \ldots 3] \to x$ \\ |
| \hline LOAD64L(x, y) & {\bf unsigned long long} x, {\bf unsigned char} *y & $y[0 \ldots 7] \to x$ \\ |
| \hline STORE32H(x, y) & {\bf unsigned long} x, {\bf unsigned char} *y & $x \to y[3 \ldots 0]$ \\ |
| \hline STORE64H(x, y) & {\bf unsigned long long} x, {\bf unsigned char} *y & $x \to y[7 \ldots 0]$ \\ |
| \hline LOAD32H(x, y) & {\bf unsigned long} x, {\bf unsigned char} *y & $y[3 \ldots 0] \to x$ \\ |
| \hline LOAD64H(x, y) & {\bf unsigned long long} x, {\bf unsigned char} *y & $y[7 \ldots 0] \to x$ \\ |
| \hline BSWAP(x) & {\bf unsigned long} x & Swaps the byte order of x. \\ |
| \hline |
| \end{tabular} |
| \end{center} |
| \end{small} |
| |
| There are 32-bit cyclic rotations as well: |
| \index{ROL} \index{ROR} |
| \begin{center} |
| \begin{tabular}{|c|c|c|} |
| \hline ROL(x, y) & {\bf unsigned long} x, {\bf unsigned long} y & $x << y$ \\ |
| \hline ROR(x, y) & {\bf unsigned long} x, {\bf unsigned long} y & $x >> y$ \\ |
| \hline |
| \end{tabular} |
| \end{center} |
| |
| \section{Functions with Variable Length Output} |
| Certain functions such as (for example) ``rsa\_export()'' give an output that is variable length. To prevent buffer overflows you |
| must pass it the length of the buffer\footnote{Extensive error checking is not in place but it will be in future releases so it is a good idea to follow through with these guidelines.} where |
| the output will be stored. For example: |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) { |
| rsa_key key; |
| unsigned char buffer[1024]; |
| unsigned long x; |
| int err; |
| |
| /* ... Make up the RSA key somehow */ |
| |
| /* lets export the key, set x to the size of the output buffer */ |
| x = sizeof(buffer); |
| if ((err = rsa_export(buffer, &x, PK_PUBLIC, &key)) != CRYPT_OK) { |
| printf("Export error: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| /* if rsa_export() was successful then x will have the size of the output */ |
| printf("RSA exported key takes %d bytes\n", x); |
| |
| /* ... do something with the buffer */ |
| |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| In the above example if the size of the RSA public key was more than 1024 bytes this function would not store anything in |
| either ``buffer'' or ``x'' and simply return an error code. If the function suceeds it stores the length of the output |
| back into ``x'' so that the calling application will know how many bytes used. |
| |
| \section{Functions that need a PRNG} |
| Certain functions such as ``rsa\_make\_key()'' require a PRNG. These functions do not setup the PRNG themselves so it is |
| the responsibility of the calling function to initialize the PRNG before calling them. |
| |
| \section{Functions that use Arrays of Octets} |
| Most functions require inputs that are arrays of the data type ``unsigned char''. Whether it is a symmetric key, IV |
| for a chaining mode or public key packet it is assumed that regardless of the actual size of ``unsigned char'' only the |
| lower eight bits contain data. For example, if you want to pass a 256 bit key to a symmetric ciphers setup routine |
| you must pass it in (a pointer to) an array of 32 ``unsigned char'' variables. Certain routines |
| (such as SAFER+) take special care to work properly on platforms where an ``unsigned char'' is not eight bits. |
| |
| For the purposes of this library the term ``byte'' will refer to an octet or eight bit word. Typically an array of |
| type ``byte'' will be synonymous with an array of type ``unsigned char''. |
| |
| \chapter{Symmetric Block Ciphers} |
| \section{Core Functions} |
| |
| Libtomcrypt provides several block ciphers all in a plain vanilla ECB block mode. Its important to first note that you |
| should never use the ECB modes directly to encrypt data. Instead you should use the ECB functions to make a chaining mode |
| or use one of the provided chaining modes. All of the ciphers are written as ECB interfaces since it allows the rest of |
| the API to grow in a modular fashion. |
| |
| All ciphers store their scheduled keys in a single data type called ``symmetric\_key''. This allows all ciphers to |
| have the same prototype and store their keys as naturally as possible. All ciphers provide five visible functions which |
| are (given that XXX is the name of the cipher): |
| \index{Cipher Setup} |
| \begin{verbatim} |
| int XXX_setup(const unsigned char *key, int keylen, int rounds, |
| symmetric_key *skey); |
| \end{verbatim} |
| |
| The XXX\_setup() routine will setup the cipher to be used with a given number of rounds and a given key length (in bytes). |
| The number of rounds can be set to zero to use the default, which is generally a good idea. |
| |
| If the function returns successfully the variable ``skey'' will have a scheduled key stored in it. Its important to note |
| that you should only used this scheduled key with the intended cipher. For example, if you call |
| ``blowfish\_setup()'' do not pass the scheduled key onto ``rc5\_ecb\_encrypt()''. All setup functions do not allocate |
| memory off the heap so when you are done with a key you can simply discard it (e.g. they can be on the stack). |
| |
| To encrypt or decrypt a block in ECB mode there are these two functions: |
| \index{Cipher Encrypt} \index{Cipher Decrypt} |
| \begin{verbatim} |
| void XXX_ecb_encrypt(const unsigned char *pt, unsigned char *ct, |
| symmetric_key *skey); |
| |
| void XXX_ecb_decrypt(const unsigned char *ct, unsigned char *pt, |
| symmetric_key *skey); |
| \end{verbatim} |
| These two functions will encrypt or decrypt (respectively) a single block of text\footnote{The size of which depends on |
| which cipher you are using.} and store the result where you want it. It is possible that the input and output buffer are |
| the same buffer. For the encrypt function ``pt''\footnote{pt stands for plaintext.} is the input and ``ct'' is the output. |
| For the decryption function its the opposite. To test a particular cipher against test vectors\footnote{As published in their design papers.} call: \index{Cipher Testing} |
| \begin{verbatim} |
| int XXX_test(void); |
| \end{verbatim} |
| This function will return {\bf CRYPT\_OK} if the cipher matches the test vectors from the design publication it is |
| based upon. Finally for each cipher there is a function which will help find a desired key size: |
| \begin{verbatim} |
| int XXX_keysize(int *keysize); |
| \end{verbatim} |
| Essentially it will round the input keysize in ``keysize'' down to the next appropriate key size. This function |
| return {\bf CRYPT\_OK} if the key size specified is acceptable. For example: |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| int keysize, err; |
| |
| /* now given a 20 byte key what keysize does Twofish want to use? */ |
| keysize = 20; |
| if ((err = twofish_keysize(&keysize)) != CRYPT_OK) { |
| printf("Error getting key size: %s\n", error_to_string(err)); |
| return -1; |
| } |
| printf("Twofish suggested a key size of %d\n", keysize); |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| This should indicate a keysize of sixteen bytes is suggested. An example snippet that encodes a block with |
| Blowfish in ECB mode is below. |
| |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| unsigned char pt[8], ct[8], key[8]; |
| symmetric_key skey; |
| int err; |
| |
| /* ... key is loaded appropriately in ``key'' ... */ |
| /* ... load a block of plaintext in ``pt'' ... */ |
| |
| /* schedule the key */ |
| if ((err = blowfish_setup(key, /* the key we will use */ |
| 8, /* key is 8 bytes (64-bits) long */ |
| 0, /* 0 == use default # of rounds */ |
| &skey) /* where to put the scheduled key */ |
| ) != CRYPT_OK) { |
| printf("Setup error: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| /* encrypt the block */ |
| blowfish_ecb_encrypt(pt, /* encrypt this 8-byte array */ |
| ct, /* store encrypted data here */ |
| &skey); /* our previously scheduled key */ |
| |
| /* decrypt the block */ |
| blowfish_ecb_decrypt(ct, /* decrypt this 8-byte array */ |
| pt, /* store decrypted data here */ |
| &skey); /* our previously scheduled key */ |
| |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| |
| \section{Key Sizes and Number of Rounds} |
| \index{Symmetric Keys} |
| As a general rule of thumb do not use symmetric keys under 80 bits if you can. Only a few of the ciphers support smaller |
| keys (mainly for test vectors anyways). Ideally your application should be making at least 256 bit keys. This is not |
| because you're supposed to be paranoid. Its because if your PRNG has a bias of any sort the more bits the better. For |
| example, if you have $\mbox{Pr}\left[X = 1\right] = {1 \over 2} \pm \gamma$ where $\vert \gamma \vert > 0$ then the |
| total amount of entropy in N bits is $N \cdot -log_2\left ({1 \over 2} + \vert \gamma \vert \right)$. So if $\gamma$ |
| were $0.25$ (a severe bias) a 256-bit string would have about 106 bits of entropy whereas a 128-bit string would have |
| only 53 bits of entropy. |
| |
| The number of rounds of most ciphers is not an option you can change. Only RC5 allows you to change the number of |
| rounds. By passing zero as the number of rounds all ciphers will use their default number of rounds. Generally the |
| ciphers are configured such that the default number of rounds provide adequate security for the given block size. |
| |
| \section{The Cipher Descriptors} |
| \index{Cipher Descriptor} |
| To facilitate automatic routines an array of cipher descriptors is provided in the array ``cipher\_descriptor''. An element |
| of this array has the following format: |
| |
| \begin{verbatim} |
| struct _cipher_descriptor { |
| char *name; |
| unsigned long min_key_length, max_key_length, |
| block_length, default_rounds; |
| int (*setup) (const unsigned char *key, int keylength, |
| int num_rounds, symmetric_key *skey); |
| void (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, |
| symmetric_key *key); |
| void (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, |
| symmetric_key *key); |
| int (*test) (void); |
| int (*keysize) (int *desired_keysize); |
| }; |
| \end{verbatim} |
| |
| Where ``name'' is the lower case ASCII version of the name. The fields ``min\_key\_length'', ``max\_key\_length'' and |
| ``block\_length'' are all the number of bytes not bits. As a good rule of thumb it is assumed that the cipher supports |
| the min and max key lengths but not always everything in between. The ``default\_rounds'' field is the default number |
| of rounds that will be used. |
| |
| The remaining fields are all pointers to the core functions for each cipher. The end of the cipher\_descriptor array is |
| marked when ``name'' equals {\bf NULL}. |
| |
| As of this release the current cipher\_descriptors elements are |
| |
| \index{Cipher descriptor table} |
| \begin{small} |
| \begin{center} |
| \begin{tabular}{|c|c|c|c|c|c|} |
| \hline Name & Descriptor Name & Block Size & Key Range & Rounds \\ |
| \hline Blowfish & blowfish\_desc & 8 & 8 $\ldots$ 56 & 16 \\ |
| \hline X-Tea & xtea\_desc & 8 & 16 & 32 \\ |
| \hline RC2 & rc2\_desc & 8 & 8 $\ldots$ 128 & 16 \\ |
| \hline RC5-32/12/b & rc5\_desc & 8 & 8 $\ldots$ 128 & 12 $\ldots$ 24 \\ |
| \hline RC6-32/20/b & rc6\_desc & 16 & 8 $\ldots$ 128 & 20 \\ |
| \hline SAFER+ & saferp\_desc &16 & 16, 24, 32 & 8, 12, 16 \\ |
| \hline Safer K64 & safer\_k64\_desc & 8 & 8 & 6 $\ldots$ 13 \\ |
| \hline Safer SK64 & safer\_sk64\_desc & 8 & 8 & 6 $\ldots$ 13 \\ |
| \hline Safer K128 & safer\_k128\_desc & 8 & 16 & 6 $\ldots$ 13 \\ |
| \hline Safer SK128 & safer\_sk128\_desc & 8 & 16 & 6 $\ldots$ 13 \\ |
| \hline AES & aes\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\ |
| & aes\_enc\_desc & 16 & 16, 24, 32 & 10, 12, 14 \\ |
| \hline Twofish & twofish\_desc & 16 & 16, 24, 32 & 16 \\ |
| \hline DES & des\_desc & 8 & 7 & 16 \\ |
| \hline 3DES (EDE mode) & des3\_desc & 8 & 21 & 16 \\ |
| \hline CAST5 (CAST-128) & cast5\_desc & 8 & 5 $\ldots$ 16 & 12, 16 \\ |
| \hline Noekeon & noekeon\_desc & 16 & 16 & 16 \\ |
| \hline Skipjack & skipjack\_desc & 8 & 10 & 32 \\ |
| \hline |
| \end{tabular} |
| \end{center} |
| \end{small} |
| |
| \subsection{Notes} |
| \begin{small} |
| \begin{enumerate} |
| \item |
| For AES (also known as Rijndael) there are four descriptors which complicate issues a little. The descriptors |
| rijndael\_desc and rijndael\_enc\_desc provide the cipher named ``rijndael''. The descriptors aes\_desc and |
| aes\_enc\_desc provide the cipher name ``aes''. Functionally both ``rijndael'' and ``aes'' are the same cipher. The |
| only difference is when you call find\_cipher() you have to pass the correct name. The cipher descriptors with ``enc'' |
| in the middle (e.g. rijndael\_enc\_desc) are related to an implementation of Rijndael with only the encryption routine |
| and tables. The decryption and self--test function pointers of both ``encrypt only'' descriptors are set to \textbf{NULL} and |
| should not be called. |
| |
| The ``encrypt only'' descriptors are useful for applications that only use the encryption function of the cipher. Algorithms such |
| as EAX, PMAC and OMAC only require the encryption function. So far this ``encrypt only'' functionality has only been implemented for |
| Rijndael as it makes the most sense for this cipher. |
| |
| \item |
| For the 64-bit SAFER famliy of ciphers (e.g K64, SK64, K128, SK128) the ecb\_encrypt() and ecb\_decrypt() |
| functions are the same. So if you want to use those functions directly just call safer\_ecb\_encrypt() |
| or safer\_ecb\_decrypt() respectively. |
| |
| \item |
| Note that for ``DES'' and ``3DES'' they use 8 and 24 byte keys but only 7 and 21 [respectively] bytes of the keys are in |
| fact used for the purposes of encryption. My suggestion is just to use random 8/24 byte keys instead of trying to make a 8/24 |
| byte string from the real 7/21 byte key. |
| |
| \item |
| Note that ``Twofish'' has additional configuration options that take place at build time. These options are found in |
| the file ``mycrypt\_cfg.h''. The first option is ``TWOFISH\_SMALL'' which when defined will force the Twofish code |
| to not pre-compute the Twofish ``$g(X)$'' function as a set of four $8 \times 32$ s-boxes. This means that a scheduled |
| key will require less ram but the resulting cipher will be slower. The second option is ``TWOFISH\_TABLES'' which when |
| defined will force the Twofish code to use pre-computed tables for the two s-boxes $q_0, q_1$ as well as the multiplication |
| by the polynomials 5B and EF used in the MDS multiplication. As a result the code is faster and slightly larger. The |
| speed increase is useful when ``TWOFISH\_SMALL'' is defined since the s-boxes and MDS multiply form the heart of the |
| Twofish round function. |
| |
| \index{Twofish build options} |
| \begin{small} |
| \begin{center} |
| \begin{tabular}{|l|l|l|} |
| \hline TWOFISH\_SMALL & TWOFISH\_TABLES & Speed and Memory (per key) \\ |
| \hline undefined & undefined & Very fast, 4.2KB of ram. \\ |
| \hline undefined & defined & As above, faster keysetup, larger code (1KB more). \\ |
| \hline defined & undefined & Very slow, 0.2KB of ram. \\ |
| \hline defined & defined & Somewhat faster, 0.2KB of ram, larger code. \\ |
| \hline |
| \end{tabular} |
| \end{center} |
| \end{small} |
| |
| \end{enumerate} |
| \end{small} |
| |
| To work with the cipher\_descriptor array there is a function: |
| \index{find\_cipher()} |
| \begin{verbatim} |
| int find_cipher(char *name) |
| \end{verbatim} |
| Which will search for a given name in the array. It returns negative one if the cipher is not found, otherwise it returns |
| the location in the array where the cipher was found. For example, to indirectly setup Blowfish you can also use: |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| unsigned char key[8]; |
| symmetric_key skey; |
| int err; |
| |
| /* you must register a cipher before you use it */ |
| if (register_cipher(&blowfish_desc)) == -1) { |
| printf("Unable to register Blowfish cipher."); |
| return -1; |
| } |
| |
| /* generic call to function (assuming the key in key[] was already setup) */ |
| if ((err = cipher_descriptor[find_cipher("blowfish")].setup(key, 8, 0, &skey)) != CRYPT_OK) { |
| printf("Error setting up Blowfish: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| /* ... use cipher ... */ |
| } |
| \end{verbatim} |
| \end{small} |
| |
| A good safety would be to check the return value of ``find\_cipher()'' before accessing the desired function. In order |
| to use a cipher with the descriptor table you must register it first using: |
| \index{register\_cipher()} |
| \begin{verbatim} |
| int register_cipher(const struct _cipher_descriptor *cipher); |
| \end{verbatim} |
| Which accepts a pointer to a descriptor and returns the index into the global descriptor table. If an error occurs such |
| as there is no more room (it can have 32 ciphers at most) it will return {\bf{-1}}. If you try to add the same cipher more |
| than once it will just return the index of the first copy. To remove a cipher call: |
| \index{unregister\_cipher()} |
| \begin{verbatim} |
| int unregister_cipher(const struct _cipher_descriptor *cipher); |
| \end{verbatim} |
| Which returns {\bf CRYPT\_OK} if it removes it otherwise it returns {\bf CRYPT\_ERROR}. Consider: |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| int err; |
| |
| /* register the cipher */ |
| if (register_cipher(&rijndael_desc) == -1) { |
| printf("Error registering Rijndael\n"); |
| return -1; |
| } |
| |
| /* use Rijndael */ |
| |
| /* remove it */ |
| if ((err = unregister_cipher(&rijndael_desc)) != CRYPT_OK) { |
| printf("Error removing Rijndael: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| This snippet is a small program that registers only Rijndael only. |
| |
| \section{Symmetric Modes of Operations} |
| \subsection{Background} |
| A typical symmetric block cipher can be used in chaining modes to effectively encrypt messages larger than the block |
| size of the cipher. Given a key $k$, a plaintext $P$ and a cipher $E$ we shall denote the encryption of the block |
| $P$ under the key $k$ as $E_k(P)$. In some modes there exists an initial vector denoted as $C_{-1}$. |
| |
| \subsubsection{ECB Mode} |
| \index{ECB mode} |
| ECB or Electronic Codebook Mode is the simplest method to use. It is given as: |
| \begin{equation} |
| C_i = E_k(P_i) |
| \end{equation} |
| This mode is very weak since it allows people to swap blocks and perform replay attacks if the same key is used more |
| than once. |
| |
| \subsubsection{CBC Mode} |
| \index{CBC mode} |
| CBC or Cipher Block Chaining mode is a simple mode designed to prevent trivial forms of replay and swap attacks on ciphers. |
| It is given as: |
| \begin{equation} |
| C_i = E_k(P_i \oplus C_{i - 1}) |
| \end{equation} |
| It is important that the initial vector be unique and preferably random for each message encrypted under the same key. |
| |
| \subsubsection{CTR Mode} |
| \index{CTR mode} |
| CTR or Counter Mode is a mode which only uses the encryption function of the cipher. Given a initial vector which is |
| treated as a large binary counter the CTR mode is given as: |
| \begin{eqnarray} |
| C_{-1} = C_{-1} + 1\mbox{ }(\mbox{mod }2^W) \nonumber \\ |
| C_i = P_i \oplus E_k(C_{-1}) |
| \end{eqnarray} |
| Where $W$ is the size of a block in bits (e.g. 64 for Blowfish). As long as the initial vector is random for each message |
| encrypted under the same key replay and swap attacks are infeasible. CTR mode may look simple but it is as secure |
| as the block cipher is under a chosen plaintext attack (provided the initial vector is unique). |
| |
| \subsubsection{CFB Mode} |
| \index{CFB mode} |
| CFB or Ciphertext Feedback Mode is a mode akin to CBC. It is given as: |
| \begin{eqnarray} |
| C_i = P_i \oplus C_{-1} \nonumber \\ |
| C_{-1} = E_k(C_i) |
| \end{eqnarray} |
| Note that in this library the output feedback width is equal to the size of the block cipher. That is this mode is used |
| to encrypt whole blocks at a time. However, the library will buffer data allowing the user to encrypt or decrypt partial |
| blocks without a delay. When this mode is first setup it will initially encrypt the initial vector as required. |
| |
| \subsubsection{OFB Mode} |
| \index{OFB mode} |
| OFB or Output Feedback Mode is a mode akin to CBC as well. It is given as: |
| \begin{eqnarray} |
| C_{-1} = E_k(C_{-1}) \nonumber \\ |
| C_i = P_i \oplus C_{-1} |
| \end{eqnarray} |
| Like the CFB mode the output width in CFB mode is the same as the width of the block cipher. OFB mode will also |
| buffer the output which will allow you to encrypt or decrypt partial blocks without delay. |
| |
| \subsection{Choice of Mode} |
| My personal preference is for the CTR mode since it has several key benefits: |
| \begin{enumerate} |
| \item No short cycles which is possible in the OFB and CFB modes. |
| \item Provably as secure as the block cipher being used under a chosen plaintext attack. |
| \item Technically does not require the decryption routine of the cipher. |
| \item Allows random access to the plaintext. |
| \item Allows the encryption of block sizes that are not equal to the size of the block cipher. |
| \end{enumerate} |
| The CTR, CFB and OFB routines provided allow you to encrypt block sizes that differ from the ciphers block size. They |
| accomplish this by buffering the data required to complete a block. This allows you to encrypt or decrypt any size |
| block of memory with either of the three modes. |
| |
| The ECB and CBC modes process blocks of the same size as the cipher at a time. Therefore they are less flexible than the |
| other modes. |
| |
| \subsection{Implementation} |
| \index{CBC Mode} \index{CTR Mode} |
| \index{OFB Mode} \index{CFB Mode} |
| The library provides simple support routines for handling CBC, CTR, CFB, OFB and ECB encoded messages. Assuming the mode |
| you want is XXX there is a structure called ``symmetric\_XXX'' that will contain the information required to |
| use that mode. They have identical setup routines (except ECB mode for obvious reasons): |
| \index{ecb\_start()} \index{cfb\_start()} \index{cbc\_start()} \index{ofb\_start()} \index{ctr\_start()} |
| \begin{verbatim} |
| int XXX_start(int cipher, const unsigned char *IV, |
| const unsigned char *key, int keylen, |
| int num_rounds, symmetric_XXX *XXX); |
| |
| int ecb_start(int cipher, const unsigned char *key, int keylen, |
| int num_rounds, symmetric_ECB *ecb); |
| \end{verbatim} |
| |
| In each case ``cipher'' is the index into the cipher\_descriptor array of the cipher you want to use. The ``IV'' value is |
| the initialization vector to be used with the cipher. You must fill the IV yourself and it is assumed they are the same |
| length as the block size\footnote{In otherwords the size of a block of plaintext for the cipher, e.g. 8 for DES, 16 for AES, etc.} |
| of the cipher you choose. It is important that the IV be random for each unique message you want to encrypt. The |
| parameters ``key'', ``keylen'' and ``num\_rounds'' are the same as in the XXX\_setup() function call. The final parameter |
| is a pointer to the structure you want to hold the information for the mode of operation. |
| |
| Both routines return {\bf CRYPT\_OK} if the cipher initialized correctly, otherwise they return an error code. To |
| actually encrypt or decrypt the following routines are provided: |
| \index{ecb\_encrypt()} \index{ecb\_decrypt()} \index{cfb\_encrypt()} \index{cfb\_decrypt()} |
| \index{cbc\_encrypt()} \index{cbc\_decrypt()} \index{ofb\_encrypt()} \index{ofb\_decrypt()} \index{ctr\_encrypt()} \index{ctr\_decrypt()} |
| \begin{verbatim} |
| int XXX_encrypt(const unsigned char *pt, unsigned char *ct, |
| symmetric_XXX *XXX); |
| int XXX_decrypt(const unsigned char *ct, unsigned char *pt, |
| symmetric_XXX *XXX); |
| |
| int YYY_encrypt(const unsigned char *pt, unsigned char *ct, |
| unsigned long len, symmetric_YYY *YYY); |
| int YYY_decrypt(const unsigned char *ct, unsigned char *pt, |
| unsigned long len, symmetric_YYY *YYY); |
| \end{verbatim} |
| Where ``XXX'' is one of (ecb, cbc) and ``YYY'' is one of (ctr, ofb, cfb). In the CTR, OFB and CFB cases ``len'' is the |
| size of the buffer (as number of chars) to encrypt or decrypt. The CTR, OFB and CFB modes are order sensitive but not |
| chunk sensitive. That is you can encrypt ``ABCDEF'' in three calls like ``AB'', ``CD'', ``EF'' or two like ``ABCDE'' and ``F'' |
| and end up with the same ciphertext. However, encrypting ``ABC'' and ``DABC'' will result in different ciphertexts. All |
| five of the modes will return {\bf CRYPT\_OK} on success from the encrypt or decrypt functions. |
| |
| To decrypt in either mode you simply perform the setup like before (recall you have to fetch the IV value you used) |
| and use the decrypt routine on all of the blocks. |
| |
| To change or read the IV of a previously initialized chaining mode use the following two functions. |
| |
| \index{cbc\_setiv()} \index{cbc\_getiv()} \index{ofb\_setiv()} \index{ofb\_getiv()} \index{cfb\_setiv()} \index{cfb\_getiv()} |
| \index{ctr\_setiv()} \index{ctr\_getiv()} |
| \begin{verbatim} |
| int XXX_getiv(unsigned char *IV, unsigned long *len, symmetric_XXX *XXX); |
| int XXX_setiv(const unsigned char *IV, unsigned long len, symmetric_XXX *XXX); |
| \end{verbatim} |
| |
| The XXX\_getiv function will read the IV out of the chaining mode and store it into ``IV'' along with the length of the IV |
| stored in ``len''. The XXX\_setiv will initialize the chaining mode state as if the original IV were the new IV specified. The length |
| of the IV passed in must be the size of the ciphers block size. |
| |
| The XXX\_setiv functions are handy if you wish to change the IV without re--keying the cipher. |
| |
| \newpage |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| unsigned char key[16], IV[16], buffer[512]; |
| symmetric_CTR ctr; |
| int x, err; |
| |
| /* register twofish first */ |
| if (register_cipher(&twofish_desc) == -1) { |
| printf("Error registering cipher.\n"); |
| return -1; |
| } |
| |
| /* somehow fill out key and IV */ |
| |
| /* start up CTR mode */ |
| if ((err = ctr_start(find_cipher("twofish"), /* index of desired cipher */ |
| IV, /* the initial vector */ |
| key, /* the secret key */ |
| 16, /* length of secret key (16 bytes, 128 bits) */ |
| 0, /* 0 == default # of rounds */ |
| &ctr) /* where to store initialized CTR state */ |
| ) != CRYPT_OK) { |
| printf("ctr_start error: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| /* somehow fill buffer than encrypt it */ |
| if ((err = ctr_encrypt( buffer, /* plaintext */ |
| buffer, /* ciphertext */ |
| sizeof(buffer), /* length of data to encrypt */ |
| &ctr) /* previously initialized CTR state */ |
| ) != CRYPT_OK) { |
| printf("ctr_encrypt error: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| /* make use of ciphertext... */ |
| |
| /* now we want to decrypt so let's use ctr_setiv */ |
| if ((err = ctr_setiv( IV, /* the initial IV we gave to ctr_start */ |
| 16, /* the IV is 16 bytes long */ |
| &ctr) /* the ctr state we wish to modify */ |
| ) != CRYPT_OK) { |
| printf("ctr_setiv error: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| if ((err = ctr_decrypt( buffer, /* ciphertext */ |
| buffer, /* plaintext */ |
| sizeof(buffer), /* length of data to encrypt */ |
| &ctr) /* previously initialized CTR state */ |
| ) != CRYPT_OK) { |
| printf("ctr_decrypt error: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| /* clear up and return */ |
| zeromem(key, sizeof(key)); |
| zeromem(&ctr, sizeof(ctr)); |
| |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| |
| \section{Encrypt and Authenticate Modes} |
| |
| \subsection{EAX Mode} |
| LibTomCrypt provides support for a mode called EAX\footnote{See |
| M. Bellare, P. Rogaway, D. Wagner, A Conventional Authenticated-Encryption Mode.} in a manner similar to the |
| way it was intended to be used by the designers. First a short description of what EAX mode is before I explain how to use it. |
| EAX is a mode that requires a cipher, CTR and OMAC support and provides encryption and authentication\footnote{Note that since EAX only requires OMAC and CTR you may use ``encrypt only'' cipher descriptors with this mode.}. |
| It is initialized with a random ``nonce'' that can be shared publicly as well as a ``header'' which can be fixed and public as well as a random |
| secret symmetric key. |
| |
| The ``header'' data is meant to be meta-data associated with a stream that isn't private (e.g. protocol messages). It can |
| be added at anytime during an EAX stream and is part of the authentication tag. That is, changes in the meta-data can |
| be detected by changes in the output tag. |
| |
| The mode can then process plaintext producing ciphertext as well as compute a partial checksum. The actual checksum |
| called a ``tag'' is only emitted when the message is finished. In the interim though the user can process any arbitrary |
| sized message block to send to the recipient as ciphertext. This makes the EAX mode especially suited for streaming modes |
| of operation. |
| |
| The mode is initialized with the following function. |
| \index{eax\_init()} |
| \begin{verbatim} |
| int eax_init(eax_state *eax, int cipher, |
| const unsigned char *key, unsigned long keylen, |
| const unsigned char *nonce, unsigned long noncelen, |
| const unsigned char *header, unsigned long headerlen); |
| \end{verbatim} |
| |
| Where ``eax'' is the EAX state. ``cipher'' is the index of the desired cipher in the descriptor table. |
| ``key'' is the shared secret symmetric key of length ``keylen''. ``nonce'' is the random public string of |
| length ``noncelen''. ``header'' is the random (or fixed or \textbf{NULL}) header for the message of length |
| ``headerlen''. |
| |
| When this function completes ``eax'' will be initialized such that you can now either have data decrypted or |
| encrypted in EAX mode. Note that if ``headerlen'' is zero you may pass ``header'' as \textbf{NULL} to indicate |
| there is no initial header data. |
| |
| To encrypt or decrypt data in a streaming mode use the following. |
| \index{eax\_encrypt()} \index{eax\_decrypt()} |
| \begin{verbatim} |
| int eax_encrypt(eax_state *eax, const unsigned char *pt, |
| unsigned char *ct, unsigned long length); |
| |
| int eax_decrypt(eax_state *eax, const unsigned char *ct, |
| unsigned char *pt, unsigned long length); |
| \end{verbatim} |
| The function ``eax\_encrypt'' will encrypt the bytes in ``pt'' of ``length'' bytes and store the ciphertext in |
| ``ct''. Note that ``ct'' and ``pt'' may be the same region in memory. This function will also send the ciphertext |
| through the OMAC function. The function ``eax\_decrypt'' decrypts ``ct'' and stores it in ``pt''. This also allows |
| ``pt'' and ``ct'' to be the same region in memory. |
| |
| You cannot both encrypt or decrypt with the same ``eax'' context. For bi-directional communication you |
| will need to initialize two EAX contexts (preferably with different headers and nonces). |
| |
| Note that both of these functions allow you to send the data in any granularity but the order is important. While |
| the eax\_init() function allows you to add initial header data to the stream you can also add header data during the |
| EAX stream with the following. |
| |
| \index{eax\_addheader()} |
| \begin{verbatim} |
| int eax_addheader(eax_state *eax, |
| const unsigned char *header, unsigned long length); |
| \end{verbatim} |
| |
| This will add the ``length'' bytes from ``header'' to the given ``eax'' stream. Once the message is finished the |
| ``tag'' (checksum) may be computed with the following function. |
| |
| \index{eax\_done()} |
| \begin{verbatim} |
| int eax_done(eax_state *eax, |
| unsigned char *tag, unsigned long *taglen); |
| \end{verbatim} |
| This will terminate the EAX state ``eax'' and store upto ``taglen'' bytes of the message tag in ``tag''. The function |
| then stores how many bytes of the tag were written out back into ``taglen''. |
| |
| The EAX mode code can be tested to ensure it matches the test vectors by calling the following function. |
| \index{eax\_test()} |
| \begin{verbatim} |
| int eax_test(void); |
| \end{verbatim} |
| This requires that the AES (or Rijndael) block cipher be registered with the cipher\_descriptor table first. |
| |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| int err; |
| eax_state eax; |
| unsigned char pt[64], ct[64], nonce[16], key[16], tag[16]; |
| unsigned long taglen; |
| |
| if (register_cipher(&rijndael_desc) == -1) { |
| printf("Error registering Rijndael"); |
| return EXIT_FAILURE; |
| } |
| |
| /* ... make up random nonce and key ... */ |
| |
| /* initialize context */ |
| if ((err = eax_init( &eax, /* the context */ |
| find_cipher("rijndael"), /* cipher we want to use */ |
| nonce, /* our state nonce */ |
| 16, /* none is 16 bytes */ |
| "TestApp", /* example header, identifies this program */ |
| 7) /* length of the header */ |
| ) != CRYPT_OK) { |
| printf("Error eax_init: %s", error_to_string(err)); |
| return EXIT_FAILURE; |
| } |
| |
| /* now encrypt data, say in a loop or whatever */ |
| if ((err = eax_encrypt( &eax, /* eax context */ |
| pt, /* plaintext (source) */ |
| ct, /* ciphertext (destination) */ |
| sizeof(pt) /* size of plaintext */ |
| ) != CRYPT_OK) { |
| printf("Error eax_encrypt: %s", error_to_string(err)); |
| return EXIT_FAILURE; |
| } |
| |
| /* finish message and get authentication tag */ |
| taglen = sizeof(tag); |
| if ((err = eax_done( &eax, /* eax context */ |
| tag, /* where to put tag */ |
| &taglen /* length of tag space */ |
| ) != CRYPT_OK) { |
| printf("Error eax_done: %s", error_to_string(err)); |
| return EXIT_FAILURE; |
| } |
| |
| /* now we have the authentication tag in "tag" and it's taglen bytes long */ |
| |
| } |
| \end{verbatim} |
| |
| You can also perform an entire EAX state on a block of memory in a single function call with the |
| following functions. |
| |
| |
| \index{eax\_encrypt\_authenticate\_memory} \index{eax\_decrypt\_verify\_memory} |
| \begin{verbatim} |
| int eax_encrypt_authenticate_memory(int cipher, |
| const unsigned char *key, unsigned long keylen, |
| const unsigned char *nonce, unsigned long noncelen, |
| const unsigned char *header, unsigned long headerlen, |
| const unsigned char *pt, unsigned long ptlen, |
| unsigned char *ct, |
| unsigned char *tag, unsigned long *taglen); |
| |
| int eax_decrypt_verify_memory(int cipher, |
| const unsigned char *key, unsigned long keylen, |
| const unsigned char *nonce, unsigned long noncelen, |
| const unsigned char *header, unsigned long headerlen, |
| const unsigned char *ct, unsigned long ctlen, |
| unsigned char *pt, |
| unsigned char *tag, unsigned long taglen, |
| int *res); |
| \end{verbatim} |
| |
| Both essentially just call eax\_init() followed by eax\_encrypt() (or eax\_decrypt() respectively) and eax\_done(). The parameters |
| have the same meaning as with those respective functions. |
| |
| The only difference is eax\_decrypt\_verify\_memory() does not emit a tag. Instead you pass it a tag as input and it compares it against |
| the tag it computed while decrypting the message. If the tags match then it stores a $1$ in ``res'', otherwise it stores a $0$. |
| |
| \subsection{OCB Mode} |
| LibTomCrypt provides support for a mode called OCB\footnote{See |
| P. Rogaway, M. Bellare, J. Black, T. Krovetz, ``OCB: A Block Cipher Mode of Operation for Efficient Authenticated Encryption''.} |
| . OCB is an encryption protocol that simultaneously provides authentication. It is slightly faster to use than EAX mode |
| but is less flexible. Let's review how to initialize an OCB context. |
| |
| \index{ocb\_init()} |
| \begin{verbatim} |
| int ocb_init(ocb_state *ocb, int cipher, |
| const unsigned char *key, unsigned long keylen, |
| const unsigned char *nonce); |
| \end{verbatim} |
| |
| This will initialize the ``ocb'' context using cipher descriptor ``cipher''. It will use a ``key'' of length ``keylen'' |
| and the random ``nonce''. Note that ``nonce'' must be a random (public) string the same length as the block ciphers |
| block size (e.g. 16 bytes for AES). |
| |
| This mode has no ``Associated Data'' like EAX mode does which means you cannot authenticate metadata along with the stream. |
| To encrypt or decrypt data use the following. |
| |
| \index{ocb\_encrypt()} \index{ocb\_decrypt()} |
| \begin{verbatim} |
| int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct); |
| int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt); |
| \end{verbatim} |
| |
| This will encrypt (or decrypt for the latter) a fixed length of data from ``pt'' to ``ct'' (vice versa for the latter). |
| They assume that ``pt'' and ``ct'' are the same size as the block cipher's block size. Note that you cannot call |
| both functions given a single ``ocb'' state. For bi-directional communication you will have to initialize two ``ocb'' |
| states (with different nonces). Also ``pt'' and ``ct'' may point to the same location in memory. |
| |
| When you are finished encrypting the message you call the following function to compute the tag. |
| |
| \index{ocb\_done\_encrypt()} |
| \begin{verbatim} |
| int ocb_done_encrypt(ocb_state *ocb, |
| const unsigned char *pt, unsigned long ptlen, |
| unsigned char *ct, |
| unsigned char *tag, unsigned long *taglen); |
| \end{verbatim} |
| |
| This will terminate an encrypt stream ``ocb''. If you have trailing bytes of plaintext that will not complete a block |
| you can pass them here. This will also encrypt the ``ptlen'' bytes in ``pt'' and store them in ``ct''. It will also |
| store upto ``taglen'' bytes of the tag into ``tag''. |
| |
| Note that ``ptlen'' must be less than or equal to the block size of block cipher chosen. Also note that if you have |
| an input message equal to the length of the block size then you pass the data here (not to ocb\_encrypt()) only. |
| |
| To terminate a decrypt stream and compared the tag you call the following. |
| |
| \index{ocb\_done\_decrypt()} |
| \begin{verbatim} |
| int ocb_done_decrypt(ocb_state *ocb, |
| const unsigned char *ct, unsigned long ctlen, |
| unsigned char *pt, |
| const unsigned char *tag, unsigned long taglen, |
| int *res); |
| \end{verbatim} |
| |
| Similarly to the previous function you can pass trailing message bytes into this function. This will compute the |
| tag of the message (internally) and then compare it against the ``taglen'' bytes of ``tag'' provided. By default |
| ``res'' is set to zero. If all ``taglen'' bytes of ``tag'' can be verified then ``res'' is set to one (authenticated |
| message). |
| |
| To make life simpler the following two functions are provided for memory bound OCB. |
| |
| \index{ocb\_encrypt\_authenticate\_memory()} |
| \begin{verbatim} |
| int ocb_encrypt_authenticate_memory(int cipher, |
| const unsigned char *key, unsigned long keylen, |
| const unsigned char *nonce, |
| const unsigned char *pt, unsigned long ptlen, |
| unsigned char *ct, |
| unsigned char *tag, unsigned long *taglen); |
| \end{verbatim} |
| |
| This will OCB encrypt the message ``pt'' of length ``ptlen'' and store the ciphertext in ``ct''. The length ``ptlen'' |
| can be any arbitrary length. |
| |
| \index{ocb\_decrypt\_verify\_memory()} |
| \begin{verbatim} |
| int ocb_decrypt_verify_memory(int cipher, |
| const unsigned char *key, unsigned long keylen, |
| const unsigned char *nonce, |
| const unsigned char *ct, unsigned long ctlen, |
| unsigned char *pt, |
| const unsigned char *tag, unsigned long taglen, |
| int *res); |
| \end{verbatim} |
| |
| Similarly this will OCB decrypt and compare the internally computed tag against the tag provided. ``res'' is set |
| appropriately. |
| |
| \chapter{One-Way Cryptographic Hash Functions} |
| \section{Core Functions} |
| |
| Like the ciphers there are hash core functions and a universal data type to hold the hash state called ``hash\_state''. |
| To initialize hash XXX (where XXX is the name) call: |
| \index{Hash Functions} |
| \begin{verbatim} |
| void XXX_init(hash_state *md); |
| \end{verbatim} |
| |
| This simply sets up the hash to the default state governed by the specifications of the hash. To add data to the |
| message being hashed call: |
| \begin{verbatim} |
| int XXX_process(hash_state *md, const unsigned char *in, unsigned long len); |
| \end{verbatim} |
| |
| Essentially all hash messages are virtually infinitely\footnote{Most hashes are limited to $2^{64}$ bits or 2,305,843,009,213,693,952 bytes.} long message which |
| are buffered. The data can be passed in any sized chunks as long as the order of the bytes are the same the message digest |
| (hash output) will be the same. For example, this means that: |
| \begin{verbatim} |
| md5_process(&md, "hello ", 6); |
| md5_process(&md, "world", 5); |
| \end{verbatim} |
| Will produce the same message digest as the single call: |
| \index{Message Digest} |
| \begin{verbatim} |
| md5_process(&md, "hello world", 11); |
| \end{verbatim} |
| |
| To finally get the message digest (the hash) call: |
| \begin{verbatim} |
| int XXX_done(hash_state *md, |
| unsigned char *out); |
| \end{verbatim} |
| |
| This function will finish up the hash and store the result in the ``out'' array. You must ensure that ``out'' is long |
| enough for the hash in question. Often hashes are used to get keys for symmetric ciphers so the ``XXX\_done()'' functions |
| will wipe the ``md'' variable before returning automatically. |
| |
| To test a hash function call: |
| \begin{verbatim} |
| int XXX_test(void); |
| \end{verbatim} |
| |
| This will return {\bf CRYPTO\_OK} if the hash matches the test vectors, otherwise it returns an error code. An |
| example snippet that hashes a message with md5 is given below. |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| hash_state md; |
| unsigned char *in = "hello world", out[16]; |
| |
| /* setup the hash */ |
| md5_init(&md); |
| |
| /* add the message */ |
| md5_process(&md, in, strlen(in)); |
| |
| /* get the hash in out[0..15] */ |
| md5_done(&md, out); |
| |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| |
| \section{Hash Descriptors} |
| Like the set of ciphers the set of hashes have descriptors too. They are stored in an array called ``hash\_descriptor'' and |
| are defined by: |
| \begin{verbatim} |
| struct _hash_descriptor { |
| char *name; |
| unsigned long hashsize; /* digest output size in bytes */ |
| unsigned long blocksize; /* the block size the hash uses */ |
| void (*init) (hash_state *); |
| int (*process)(hash_state *, const unsigned char *, unsigned long); |
| int (*done) (hash_state *, unsigned char *); |
| int (*test) (void); |
| }; |
| \end{verbatim} |
| |
| Similarly ``name'' is the name of the hash function in ASCII (all lowercase). ``hashsize'' is the size of the digest output |
| in bytes. The remaining fields are pointers to the functions that do the respective tasks. There is a function to |
| search the array as well called ``int find\_hash(char *name)''. It returns -1 if the hash is not found, otherwise the |
| position in the descriptor table of the hash. |
| |
| You can use the table to indirectly call a hash function that is chosen at runtime. For example: |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| unsigned char buffer[100], hash[MAXBLOCKSIZE]; |
| int idx, x; |
| hash_state md; |
| |
| /* register hashes .... */ |
| if (register_hash(&md5_desc) == -1) { |
| printf("Error registering MD5.\n"); |
| return -1; |
| } |
| |
| /* register other hashes ... */ |
| |
| /* prompt for name and strip newline */ |
| printf("Enter hash name: \n"); |
| fgets(buffer, sizeof(buffer), stdin); |
| buffer[strlen(buffer) - 1] = 0; |
| |
| /* get hash index */ |
| idx = find_hash(buffer); |
| if (idx == -1) { |
| printf("Invalid hash name!\n"); |
| return -1; |
| } |
| |
| /* hash input until blank line */ |
| hash_descriptor[idx].init(&md); |
| while (fgets(buffer, sizeof(buffer), stdin) != NULL) |
| hash_descriptor[idx].process(&md, buffer, strlen(buffer)); |
| hash_descriptor[idx].done(&md, hash); |
| |
| /* dump to screen */ |
| for (x = 0; x < hash_descriptor[idx].hashsize; x++) |
| printf("%02x ", hash[x]); |
| printf("\n"); |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| |
| Note the usage of ``MAXBLOCKSIZE''. In Libtomcrypt no symmetric block, key or hash digest is larger than MAXBLOCKSIZE in |
| length. This provides a simple size you can set your automatic arrays to that will not get overrun. |
| |
| There are three helper functions as well: |
| \index{hash\_memory()} \index{hash\_file()} |
| \begin{verbatim} |
| int hash_memory(int hash, const unsigned char *data, |
| unsigned long len, unsigned char *dst, |
| unsigned long *outlen); |
| |
| int hash_file(int hash, const char *fname, |
| unsigned char *dst, |
| unsigned long *outlen); |
| |
| int hash_filehandle(int hash, FILE *in, |
| unsigned char *dst, unsigned long *outlen); |
| \end{verbatim} |
| |
| The ``hash'' parameter is the location in the descriptor table of the hash (\textit{e.g. the return of find\_hash()}). |
| The ``*outlen'' variable is used to keep track of the output size. You |
| must set it to the size of your output buffer before calling the functions. When they complete succesfully they store |
| the length of the message digest back in it. The functions are otherwise straightforward. The ``hash\_filehandle'' |
| function assumes that ``in'' is an file handle opened in binary mode. It will hash to the end of file and not reset |
| the file position when finished. |
| |
| To perform the above hash with md5 the following code could be used: |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| int idx, err; |
| unsigned long len; |
| unsigned char out[MAXBLOCKSIZE]; |
| |
| /* register the hash */ |
| if (register_hash(&md5_desc) == -1) { |
| printf("Error registering MD5.\n"); |
| return -1; |
| } |
| |
| /* get the index of the hash */ |
| idx = find_hash("md5"); |
| |
| /* call the hash */ |
| len = sizeof(out); |
| if ((err = hash_memory(idx, "hello world", 11, out, &len)) != CRYPT_OK) { |
| printf("Error hashing data: %s\n", error_to_string(err)); |
| return -1; |
| } |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| |
| The following hashes are provided as of this release: |
| \index{Hash descriptor table} |
| \begin{center} |
| \begin{tabular}{|c|c|c|} |
| \hline Name & Descriptor Name & Size of Message Digest (bytes) \\ |
| \hline WHIRLPOOL & whirlpool\_desc & 64 \\ |
| \hline SHA-512 & sha512\_desc & 64 \\ |
| \hline SHA-384 & sha384\_desc & 48 \\ |
| \hline SHA-256 & sha256\_desc & 32 \\ |
| \hline SHA-224 & sha224\_desc & 28 \\ |
| \hline TIGER-192 & tiger\_desc & 24 \\ |
| \hline SHA-1 & sha1\_desc & 20 \\ |
| \hline RIPEMD-160 & rmd160\_desc & 20 \\ |
| \hline RIPEMD-128 & rmd128\_desc & 16 \\ |
| \hline MD5 & md5\_desc & 16 \\ |
| \hline MD4 & md4\_desc & 16 \\ |
| \hline MD2 & md2\_desc & 16 \\ |
| \hline |
| \end{tabular} |
| \end{center} |
| |
| Similar to the cipher descriptor table you must register your hash algorithms before you can use them. These functions |
| work exactly like those of the cipher registration code. The functions are: |
| \index{register\_hash()} \index{unregister\_hash()} |
| \begin{verbatim} |
| int register_hash(const struct _hash_descriptor *hash); |
| int unregister_hash(const struct _hash_descriptor *hash); |
| \end{verbatim} |
| |
| \subsection{Notice} |
| It is highly recommended that you \textbf{not} use the MD4 or MD5 hashes for the purposes of digital signatures or authentication codes. |
| These hashes are provided for completeness and they still can be used for the purposes of password hashing or one-way accumulators |
| (e.g. Yarrow). |
| |
| The other hashes such as the SHA-1, SHA-2 (that includes SHA-512, SHA-384 and SHA-256) and TIGER-192 are still considered secure |
| for all purposes you would normally use a hash for. |
| |
| \chapter{Message Authentication Codes} |
| \section{HMAC Protocol} |
| Thanks to Dobes Vandermeer the library now includes support for hash based message authenication codes or HMAC for short. An HMAC |
| of a message is a keyed authenication code that only the owner of a private symmetric key will be able to verify. The purpose is |
| to allow an owner of a private symmetric key to produce an HMAC on a message then later verify if it is correct. Any impostor or |
| eavesdropper will not be able to verify the authenticity of a message. |
| |
| The HMAC support works much like the normal hash functions except that the initialization routine requires you to pass a key |
| and its length. The key is much like a key you would pass to a cipher. That is, it is simply an array of octets stored in |
| chars. The initialization routine is: |
| \index{hmac\_init()} |
| \begin{verbatim} |
| int hmac_init(hmac_state *hmac, int hash, |
| const unsigned char *key, unsigned long keylen); |
| \end{verbatim} |
| The ``hmac'' parameter is the state for the HMAC code. ``hash'' is the index into the descriptor table of the hash you want |
| to use to authenticate the message. ``key'' is the pointer to the array of chars that make up the key. ``keylen'' is the |
| length (in octets) of the key you want to use to authenticate the message. To send octets of a message through the HMAC system you must use the following function: |
| \index{hmac\_process()} |
| \begin{verbatim} |
| int hmac_process(hmac_state *hmac, const unsigned char *buf, |
| unsigned long len); |
| \end{verbatim} |
| ``hmac'' is the HMAC state you are working with. ``buf'' is the array of octets to send into the HMAC process. ``len'' is the |
| number of octets to process. Like the hash process routines you can send the data in arbitrarly sized chunks. When you |
| are finished with the HMAC process you must call the following function to get the HMAC code: |
| \index{hmac\_done()} |
| \begin{verbatim} |
| int hmac_done(hmac_state *hmac, unsigned char *hashOut, |
| unsigned long *outlen); |
| \end{verbatim} |
| ``hmac'' is the HMAC state you are working with. ``hashOut'' is the array of octets where the HMAC code should be stored. You must |
| set ``outlen'' to the size of the destination buffer before calling this function. It is updated with the length of the HMAC code |
| produced (depending on which hash was picked). If ``outlen'' is less than the size of the message digest (and ultimately |
| the HMAC code) then the HMAC code is truncated as per FIPS-198 specifications (e.g. take the first ``outlen'' bytes). |
| |
| There are two utility functions provided to make using HMACs easier todo. They accept the key and information about the |
| message (file pointer, address in memory) and produce the HMAC result in one shot. These are useful if you want to avoid |
| calling the three step process yourself. |
| |
| \index{hmac\_memory()} |
| \begin{verbatim} |
| int hmac_memory(int hash, const unsigned char *key, unsigned long keylen, |
| const unsigned char *data, unsigned long len, |
| unsigned char *dst, unsigned long *dstlen); |
| \end{verbatim} |
| This will produce an HMAC code for the array of octets in ``data'' of length ``len''. The index into the hash descriptor |
| table must be provided in ``hash''. It uses the key from ``key'' with a key length of ``keylen''. |
| The result is stored in the array of octets ``dst'' and the length in ``dstlen''. The value of ``dstlen'' must be set |
| to the size of the destination buffer before calling this function. Similarly for files there is the following function: |
| \index{hmac\_file()} |
| \begin{verbatim} |
| int hmac_file(int hash, const char *fname, const unsigned char *key, |
| unsigned long keylen, |
| unsigned char *dst, unsigned long *dstlen); |
| \end{verbatim} |
| ``hash'' is the index into the hash descriptor table of the hash you want to use. ``fname'' is the filename to process. |
| ``key'' is the array of octets to use as the key of length ``keylen''. ``dst'' is the array of octets where the |
| result should be stored. |
| |
| To test if the HMAC code is working there is the following function: |
| \index{hmac\_test()} |
| \begin{verbatim} |
| int hmac_test(void); |
| \end{verbatim} |
| Which returns {\bf CRYPT\_OK} if the code passes otherwise it returns an error code. Some example code for using the |
| HMAC system is given below. |
| |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| int idx, err; |
| hmac_state hmac; |
| unsigned char key[16], dst[MAXBLOCKSIZE]; |
| unsigned long dstlen; |
| |
| /* register SHA-1 */ |
| if (register_hash(&sha1_desc) == -1) { |
| printf("Error registering SHA1\n"); |
| return -1; |
| } |
| |
| /* get index of SHA1 in hash descriptor table */ |
| idx = find_hash("sha1"); |
| |
| /* we would make up our symmetric key in "key[]" here */ |
| |
| /* start the HMAC */ |
| if ((err = hmac_init(&hmac, idx, key, 16)) != CRYPT_OK) { |
| printf("Error setting up hmac: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| /* process a few octets */ |
| if((err = hmac_process(&hmac, "hello", 5) != CRYPT_OK) { |
| printf("Error processing hmac: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| /* get result (presumably to use it somehow...) */ |
| dstlen = sizeof(dst); |
| if ((err = hmac_done(&hmac, dst, &dstlen)) != CRYPT_OK) { |
| printf("Error finishing hmac: %s\n", error_to_string(err)); |
| return -1; |
| } |
| printf("The hmac is %lu bytes long\n", dstlen); |
| |
| /* return */ |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| |
| \section{OMAC Support} |
| OMAC\footnote{\url{http://crypt.cis.ibaraki.ac.jp/omac/omac.html}}, which stands for \textit{One-Key CBC MAC} is an |
| algorithm which produces a Message Authentication Code (MAC) using only a block cipher such as AES. From an API |
| standpoint the OMAC routines work much like the HMAC routines do. Instead in this case a cipher is used instead of a hash. |
| |
| To start an OMAC state you call |
| \index{omac\_init()} |
| \begin{verbatim} |
| int omac_init(omac_state *omac, int cipher, |
| const unsigned char *key, unsigned long keylen); |
| \end{verbatim} |
| The ``omac'' variable is the state for the OMAC algorithm. ``cipher'' is the index into the cipher\_descriptor table |
| of the cipher\footnote{The cipher must have a 64 or 128 bit block size. Such as CAST5, Blowfish, DES, AES, Twofish, etc.} you |
| wish to use. ``key'' and ``keylen'' are the keys used to authenticate the data. |
| |
| To send data through the algorithm call |
| \index{omac\_process()} |
| \begin{verbatim} |
| int omac_process(omac_state *state, |
| const unsigned char *buf, unsigned long len); |
| \end{verbatim} |
| This will send ``len'' bytes from ``buf'' through the active OMAC state ``state''. Returns \textbf{CRYPT\_OK} if the |
| function succeeds. The function is not sensitive to the granularity of the data. For example, |
| |
| \begin{verbatim} |
| omac_process(&mystate, "hello", 5); |
| omac_process(&mystate, " world", 6); |
| \end{verbatim} |
| |
| Would produce the same result as, |
| |
| \begin{verbatim} |
| omac_process(&mystate, "hello world", 11); |
| \end{verbatim} |
| |
| When you are done processing the message you can call the following to compute the message tag. |
| |
| \index{omac\_done()} |
| \begin{verbatim} |
| int omac_done(omac_state *state, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| Which will terminate the OMAC and output the \textit{tag} (MAC) to ``out''. Note that unlike the HMAC and other code |
| ``outlen'' can be smaller than the default MAC size (for instance AES would make a 16-byte tag). Part of the OMAC |
| specification states that the output may be truncated. So if you pass in $outlen = 5$ and use AES as your cipher than |
| the output MAC code will only be five bytes long. If ``outlen'' is larger than the default size it is set to the default |
| size to show how many bytes were actually used. |
| |
| Similar to the HMAC code the file and memory functions are also provided. To OMAC a buffer of memory in one shot use the |
| following function. |
| |
| \index{omac\_memory()} |
| \begin{verbatim} |
| int omac_memory(int cipher, |
| const unsigned char *key, unsigned long keylen, |
| const unsigned char *msg, unsigned long msglen, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| This will compute the OMAC of ``msglen'' bytes of ``msg'' using the key ``key'' of length ``keylen'' bytes and the cipher |
| specified by the ``cipher'''th entry in the cipher\_descriptor table. It will store the MAC in ``out'' with the same |
| rules as omac\_done. |
| |
| To OMAC a file use |
| \index{omac\_file()} |
| \begin{verbatim} |
| int omac_file(int cipher, |
| const unsigned char *key, unsigned long keylen, |
| const char *filename, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| |
| Which will OMAC the entire contents of the file specified by ``filename'' using the key ``key'' of length ``keylen'' bytes |
| and the cipher specified by the ``cipher'''th entry in the cipher\_descriptor table. It will store the MAC in ``out'' with |
| the same rules as omac\_done. |
| |
| To test if the OMAC code is working there is the following function: |
| \index{omac\_test()} |
| \begin{verbatim} |
| int omac_test(void); |
| \end{verbatim} |
| Which returns {\bf CRYPT\_OK} if the code passes otherwise it returns an error code. Some example code for using the |
| OMAC system is given below. |
| |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| int idx, err; |
| omac_state omac; |
| unsigned char key[16], dst[MAXBLOCKSIZE]; |
| unsigned long dstlen; |
| |
| /* register Rijndael */ |
| if (register_cipher(&rijndael_desc) == -1) { |
| printf("Error registering Rijndael\n"); |
| return -1; |
| } |
| |
| /* get index of Rijndael in cipher descriptor table */ |
| idx = find_cipher("rijndael"); |
| |
| /* we would make up our symmetric key in "key[]" here */ |
| |
| /* start the OMAC */ |
| if ((err = omac_init(&omac, idx, key, 16)) != CRYPT_OK) { |
| printf("Error setting up omac: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| /* process a few octets */ |
| if((err = omac_process(&omac, "hello", 5) != CRYPT_OK) { |
| printf("Error processing omac: %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| /* get result (presumably to use it somehow...) */ |
| dstlen = sizeof(dst); |
| if ((err = omac_done(&omac, dst, &dstlen)) != CRYPT_OK) { |
| printf("Error finishing omac: %s\n", error_to_string(err)); |
| return -1; |
| } |
| printf("The omac is %lu bytes long\n", dstlen); |
| |
| /* return */ |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| |
| \section{PMAC Support} |
| The PMAC\footnote{J.Black, P.Rogaway, ``A Block--Cipher Mode of Operation for Parallelizable Message Authentication''} |
| protocol is another MAC algorithm that relies solely on a symmetric-key block cipher. It uses essentially the same |
| API as the provided OMAC code. |
| |
| A PMAC state is initialized with the following. |
| |
| \index{pmac\_init()} |
| \begin{verbatim} |
| int pmac_init(pmac_state *pmac, int cipher, |
| const unsigned char *key, unsigned long keylen); |
| \end{verbatim} |
| Which initializes the ``pmac'' state with the given ``cipher'' and ``key'' of length ``keylen'' bytes. The chosen cipher |
| must have a 64 or 128 bit block size (e.x. AES). |
| |
| To MAC data simply send it through the process function. |
| |
| \index{pmac\_process()} |
| \begin{verbatim} |
| int pmac_process(pmac_state *state, |
| const unsigned char *buf, unsigned long len); |
| \end{verbatim} |
| This will process ``len'' bytes of ``buf'' in the given ``state''. The function is not sensitive to the granularity of the |
| data. For example, |
| |
| \begin{verbatim} |
| pmac_process(&mystate, "hello", 5); |
| pmac_process(&mystate, " world", 6); |
| \end{verbatim} |
| |
| Would produce the same result as, |
| |
| \begin{verbatim} |
| pmac_process(&mystate, "hello world", 11); |
| \end{verbatim} |
| |
| When a complete message has been processed the following function can be called to compute the message tag. |
| |
| \index{pmac\_done()} |
| \begin{verbatim} |
| int pmac_done(pmac_state *state, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| This will store upto ``outlen'' bytes of the tag for the given ``state'' into ``out''. Note that if ``outlen'' is larger |
| than the size of the tag it is set to the amount of bytes stored in ``out''. |
| |
| Similar to the PMAC code the file and memory functions are also provided. To PMAC a buffer of memory in one shot use the |
| following function. |
| |
| \index{pmac\_memory()} |
| \begin{verbatim} |
| int pmac_memory(int cipher, |
| const unsigned char *key, unsigned long keylen, |
| const unsigned char *msg, unsigned long msglen, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| This will compute the PMAC of ``msglen'' bytes of ``msg'' using the key ``key'' of length ``keylen'' bytes and the cipher |
| specified by the ``cipher'''th entry in the cipher\_descriptor table. It will store the MAC in ``out'' with the same |
| rules as omac\_done. |
| |
| To PMAC a file use |
| \index{pmac\_file()} |
| \begin{verbatim} |
| int pmac_file(int cipher, |
| const unsigned char *key, unsigned long keylen, |
| const char *filename, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| |
| Which will PMAC the entire contents of the file specified by ``filename'' using the key ``key'' of length ``keylen'' bytes |
| and the cipher specified by the ``cipher'''th entry in the cipher\_descriptor table. It will store the MAC in ``out'' with |
| the same rules as omac\_done. |
| |
| To test if the PMAC code is working there is the following function: |
| \begin{verbatim} |
| int pmac_test(void); |
| \end{verbatim} |
| Which returns {\bf CRYPT\_OK} if the code passes otherwise it returns an error code. |
| |
| |
| \chapter{Pseudo-Random Number Generators} |
| \section{Core Functions} |
| |
| The library provides an array of core functions for Pseudo-Random Number Generators (PRNGs) as well. A cryptographic PRNG is |
| used to expand a shorter bit string into a longer bit string. PRNGs are used wherever random data is required such as Public Key (PK) |
| key generation. There is a universal structure called ``prng\_state''. To initialize a PRNG call: |
| \begin{verbatim} |
| int XXX_start(prng_state *prng); |
| \end{verbatim} |
| |
| This will setup the PRNG for future use and not seed it. In order |
| for the PRNG to be cryptographically useful you must give it entropy. Ideally you'd have some OS level source to tap |
| like in UNIX (see section 5.3). To add entropy to the PRNG call: |
| \begin{verbatim} |
| int XXX_add_entropy(const unsigned char *in, unsigned long len, |
| prng_state *prng); |
| \end{verbatim} |
| |
| Which returns {\bf CRYPTO\_OK} if the entropy was accepted. Once you think you have enough entropy you call another |
| function to put the entropy into action. |
| \begin{verbatim} |
| int XXX_ready(prng_state *prng); |
| \end{verbatim} |
| |
| Which returns {\bf CRYPTO\_OK} if it is ready. Finally to actually read bytes call: |
| \begin{verbatim} |
| unsigned long XXX_read(unsigned char *out, unsigned long len, |
| prng_state *prng); |
| \end{verbatim} |
| |
| Which returns the number of bytes read from the PRNG. |
| |
| \subsection{Remarks} |
| |
| It is possible to be adding entropy and reading from a PRNG at the same time. For example, if you first seed the PRNG |
| and call ready() you can now read from it. You can also keep adding new entropy to it. The new entropy will not be used |
| in the PRNG until ready() is called again. This allows the PRNG to be used and re-seeded at the same time. No real error |
| checking is guaranteed to see if the entropy is sufficient or if the PRNG is even in a ready state before reading. |
| |
| \subsection{Example} |
| |
| Below is a simple snippet to read 10 bytes from yarrow. Its important to note that this snippet is {\bf NOT} secure since |
| the entropy added is not random. |
| |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| prng_state prng; |
| unsigned char buf[10]; |
| int err; |
| |
| /* start it */ |
| if ((err = yarrow_start(&prng)) != CRYPT_OK) { |
| printf("Start error: %s\n", error_to_string(err)); |
| } |
| /* add entropy */ |
| if ((err = yarrow_add_entropy("hello world", 11, &prng)) != CRYPT_OK) { |
| printf("Add_entropy error: %s\n", error_to_string(err)); |
| } |
| /* ready and read */ |
| if ((err = yarrow_ready(&prng)) != CRYPT_OK) { |
| printf("Ready error: %s\n", error_to_string(err)); |
| } |
| printf("Read %lu bytes from yarrow\n", yarrow_read(buf, 10, &prng)); |
| return 0; |
| } |
| \end{verbatim} |
| |
| \section{PRNG Descriptors} |
| \index{PRNG Descriptor} |
| PRNGs have descriptors too (surprised?). Stored in the structure ``prng\_descriptor''. The format of an element is: |
| \begin{verbatim} |
| struct _prng_descriptor { |
| char *name; |
| int (*start) (prng_state *); |
| int (*add_entropy)(const unsigned char *, unsigned long, prng_state *); |
| int (*ready) (prng_state *); |
| unsigned long (*read)(unsigned char *, unsigned long len, prng_state *); |
| }; |
| \end{verbatim} |
| |
| There is a ``int find\_prng(char *name)'' function as well. Returns -1 if the PRNG is not found, otherwise it returns |
| the position in the prng\_descriptor array. |
| |
| Just like the ciphers and hashes you must register your prng before you can use it. The two functions provided work |
| exactly as those for the cipher registry functions. They are: |
| \begin{verbatim} |
| int register_prng(const struct _prng_descriptor *prng); |
| int unregister_prng(const struct _prng_descriptor *prng); |
| \end{verbatim} |
| |
| \subsubsection{PRNGs Provided} |
| Currently Yarrow (yarrow\_desc), RC4 (rc4\_desc) and the secure RNG (sprng\_desc) are provided as PRNGs within the |
| library. |
| |
| RC4 is provided with a PRNG interface because it is a stream cipher and not well suited for the symmetric block cipher |
| interface. You provide the key for RC4 via the rc4\_add\_entropy() function. By calling rc4\_ready() the key will be used |
| to setup the RC4 state for encryption or decryption. The rc4\_read() function has been modified from RC4 since it will |
| XOR the output of the RC4 keystream generator against the input buffer you provide. The following snippet will demonstrate |
| how to encrypt a buffer with RC4: |
| |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| prng_state prng; |
| unsigned char buf[32]; |
| int err; |
| |
| if ((err = rc4_start(&prng)) != CRYPT_OK) { |
| printf("RC4 init error: %s\n", error_to_string(err)); |
| exit(-1); |
| } |
| |
| /* use ``key'' as the key */ |
| if ((err = rc4_add_entropy("key", 3, &prng)) != CRYPT_OK) { |
| printf("RC4 add entropy error: %s\n", error_to_string(err)); |
| exit(-1); |
| } |
| |
| /* setup RC4 for use */ |
| if ((err = rc4_ready(&prng)) != CRYPT_OK) { |
| printf("RC4 ready error: %s\n", error_to_string(err)); |
| exit(-1); |
| } |
| |
| /* encrypt buffer */ |
| strcpy(buf,"hello world"); |
| if (rc4_read(buf, 11, &prng) != 11) { |
| printf("RC4 read error\n"); |
| exit(-1); |
| } |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| To decrypt you have to do the exact same steps. |
| |
| \section{The Secure RNG} |
| \index{Secure RNG} |
| An RNG is related to a PRNG except that it doesn't expand a smaller seed to get the data. They generate their random bits |
| by performing some computation on fresh input bits. Possibly the hardest thing to get correctly in a cryptosystem is the |
| PRNG. Computers are deterministic beasts that try hard not to stray from pre-determined paths. That makes gathering |
| entropy needed to seed the PRNG a hard task. |
| |
| There is one small function that may help on certain platforms: |
| \index{rng\_get\_bytes()} |
| \begin{verbatim} |
| unsigned long rng_get_bytes(unsigned char *buf, unsigned long len, |
| void (*callback)(void)); |
| \end{verbatim} |
| |
| Which will try one of three methods of getting random data. The first is to open the popular ``/dev/random'' device which |
| on most *NIX platforms provides cryptographic random bits\footnote{This device is available in Windows through the Cygwin compiler suite. It emulates ``/dev/random'' via the Microsoft CSP.}. |
| The second method is to try the Microsoft Cryptographic Service Provider and read the RNG. The third method is an ANSI C |
| clock drift method that is also somewhat popular but gives bits of lower entropy. The ``callback'' parameter is a pointer to a function that returns void. Its used when the slower ANSI C RNG must be |
| used so the calling application can still work. This is useful since the ANSI C RNG has a throughput of three |
| bytes a second. The callback pointer may be set to {\bf NULL} to avoid using it if you don't want to. The function |
| returns the number of bytes actually read from any RNG source. There is a function to help setup a PRNG as well: |
| \index{rng\_make\_prng()} |
| \begin{verbatim} |
| int rng_make_prng(int bits, int wprng, prng_state *prng, |
| void (*callback)(void)); |
| \end{verbatim} |
| This will try to setup the prng with a state of at least ``bits'' of entropy. The ``callback'' parameter works much like |
| the callback in ``rng\_get\_bytes()''. It is highly recommended that you use this function to setup your PRNGs unless you have a |
| platform where the RNG doesn't work well. Example usage of this function is given below. |
| |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| ecc_key mykey; |
| prng_state prng; |
| int err; |
| |
| /* register yarrow */ |
| if (register_prng(&yarrow_desc) == -1) { |
| printf("Error registering Yarrow\n"); |
| return -1; |
| } |
| |
| /* setup the PRNG */ |
| if ((err = rng_make_prng(128, find_prng("yarrow"), &prng, NULL)) != CRYPT_OK) { |
| printf("Error setting up PRNG, %s\n", error_to_string(err)); |
| return -1; |
| } |
| |
| /* make a 192-bit ECC key */ |
| if ((err = ecc_make_key(&prng, find_prng("yarrow"), 24, &mykey)) != CRYPT_OK) { |
| printf("Error making key: %s\n", error_to_string(err)); |
| return -1; |
| } |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| |
| \subsection{The Secure PRNG Interface} |
| It is possible to access the secure RNG through the PRNG interface and in turn use it within dependent functions such |
| as the PK API. This simplifies the cryptosystem on platforms where the secure RNG is fast. The secure PRNG never |
| requires to be started, that is you need not call the start, add\_entropy or ready functions. For example, consider |
| the previous example using this PRNG. |
| |
| \begin{small} |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| ecc_key mykey; |
| int err; |
| |
| /* register SPRNG */ |
| if (register_prng(&sprng_desc) == -1) { |
| printf("Error registering SPRNG\n"); |
| return -1; |
| } |
| |
| /* make a 192-bit ECC key */ |
| if ((err = ecc_make_key(NULL, find_prng("sprng"), 24, &mykey)) != CRYPT_OK) { |
| printf("Error making key: %s\n", error_to_string(err)); |
| return -1; |
| } |
| return 0; |
| } |
| \end{verbatim} |
| \end{small} |
| |
| \chapter{RSA Public Key Cryptography} |
| |
| \section{Introduction} |
| RSA wrote the PKCS \#1 specifications which detail RSA Public Key Cryptography. In the specifications are |
| padding algorithms for encryption and signatures. The standard includes ``v1.5'' and ``v2.0'' algorithms. |
| To simplify matters a little the v2.0 encryption and signature padding algorithms are called OAEP and PSS |
| respectively. |
| |
| \section{PKCS \#1 Encryption} |
| |
| PKCS \#1 RSA Encryption amounts to OAEP padding of the input message followed by the modular exponentiation. As far as this portion of |
| the library is concerned we are only dealing with th OAEP padding of the message. |
| |
| \subsection{OAEP Encoding} |
| |
| \index{pkcs\_1\_oaep\_encode()} |
| \begin{alltt} |
| int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, |
| const unsigned char *lparam, unsigned long lparamlen, |
| unsigned long modulus_bitlen, prng_state *prng, |
| int prng_idx, int hash_idx, |
| unsigned char *out, unsigned long *outlen); |
| \end{alltt} |
| |
| This accepts ``msg'' as input of length ``msglen'' which will be OAEP padded. The ``lparam'' variable is an additional system specific |
| tag that can be applied to the encoding. This is useful to identify which system encoded the message. If no variance is desired then |
| ``lparam'' can be set to \textbf{NULL}. |
| |
| OAEP encoding requires the length of the modulus in bits in order to calculate the size of the output. This is passed as the parameter |
| ``modulus\_bitlen''. ``hash\_idx'' is the index into the hash descriptor table of the hash desired. PKCS \#1 allows any hash to be |
| used but both the encoder and decoder must use the same hash in order for this to succeed. The size of hash output affects the maximum |
| sized input message. ``prng\_idx'' and ``prng'' are the random number generator arguments required to randomize the padding process. |
| The padded message is stored in ``out'' along with the length in ``outlen''. |
| |
| If $h$ is the length of the hash and $m$ the length of the modulus (both in octets) then the maximum payload for ``msg'' is |
| $m - 2h - 2$. For example, with a $1024$--bit RSA key and SHA--1 as the hash the maximum payload is $86$ bytes. |
| |
| Note that when the message is padded it still has not been RSA encrypted. You must pass the output of this function to |
| rsa\_exptmod() to encrypt it. |
| |
| \subsection{OAEP Decoding} |
| |
| \index{pkcs\_1\_oaep\_decode()} |
| \begin{alltt} |
| int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, |
| const unsigned char *lparam, unsigned long lparamlen, |
| unsigned long modulus_bitlen, int hash_idx, |
| unsigned char *out, unsigned long *outlen, |
| int *res); |
| \end{alltt} |
| |
| This function decodes an OAEP encoded message and outputs the original message that was passed to the OAEP encoder. ``msg'' is the |
| output of pkcs\_1\_oaep\_encode() of length ``msglen''. ``lparam'' is the same system variable passed to the OAEP encoder. If it does not |
| match what was used during encoding this function will not decode the packet. ``modulus\_bitlen'' is the size of the RSA modulus in bits |
| and must match what was used during encoding. Similarly the ``hash\_idx'' index into the hash descriptor table must match what was used |
| during encoding. |
| |
| If the function succeeds it decodes the OAEP encoded message into ``out'' of length ``outlen'' and stores a |
| $1$ in ``res''. If the packet is invalid it stores $0$ in ``res'' and if the function fails for another reason |
| it returns an error code. |
| |
| \subsection{PKCS \#1 v1.5 Encoding} |
| |
| \index{pkcs\_1\_v15\_es\_encode()} |
| \begin{verbatim} |
| int pkcs_1_v15_es_encode(const unsigned char *msg, unsigned long msglen, |
| unsigned long modulus_bitlen, |
| prng_state *prng, int prng_idx, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| |
| This will PKCS v1.5 encode the data in ``msg'' of length ``msglen''. Pass the length (in bits) of your |
| RSA modulus in ``modulus\_bitlen''. The encoded data will be stored in ``out'' of length ``outlen''. |
| |
| \subsection{PKCS \#1 v1.5 Decoding} |
| \index{pkcs\_1\_v15\_es\_decode()} |
| \begin{verbatim} |
| int pkcs_1_v15_es_decode(const unsigned char *msg, unsigned long msglen, |
| unsigned long modulus_bitlen, |
| unsigned char *out, unsigned long outlen, |
| int *res); |
| \end{verbatim} |
| |
| This will PKCS v1.5 decode the message in ``msg'' of length ``msglen''. It will store the output in ``out''. Note |
| that the length of the output ``outlen'' is a constant. This decoder cannot determine the original message |
| length. If the data in ``msg'' is a valid packet then a $1$ is stored in ``res'', otherwise a $0$ is |
| stored. |
| |
| \section{PKCS \#1 Digital Signatures} |
| |
| \subsection{PSS Encoding} |
| PSS encoding is the second half of the PKCS \#1 standard which is padding to be applied to messages that are signed. |
| |
| \index{pkcs\_1\_pss\_encode()} |
| \begin{alltt} |
| int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, |
| unsigned long saltlen, prng_state *prng, |
| int prng_idx, int hash_idx, |
| unsigned long modulus_bitlen, |
| unsigned char *out, unsigned long *outlen); |
| \end{alltt} |
| |
| This function assumes the message to be PSS encoded has previously been hashed. The input hash ``msghash'' is of length |
| ``msghashlen''. PSS allows a variable length random salt (it can be zero length) to be introduced in the signature process. |
| ``hash\_idx'' is the index into the hash descriptor table of the hash to use. ``prng\_idx'' and ``prng'' are the random |
| number generator information required for the salt. |
| |
| Similar to OAEP encoding ``modulus\_bitlen'' is the size of the RSA modulus (in bits). It limits the size of the salt. If $m$ is the length |
| of the modulus $h$ the length of the hash output (in octets) then there can be $m - h - 2$ bytes of salt. |
| |
| This function does not actually sign the data it merely pads the hash of a message so that it can be processed by rsa\_exptmod(). |
| |
| \subsection{PSS Decoding} |
| |
| To decode a PSS encoded signature block you have to use the following. |
| |
| \index{pkcs\_1\_pss\_decode()} |
| \begin{alltt} |
| int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, |
| const unsigned char *sig, unsigned long siglen, |
| unsigned long saltlen, int hash_idx, |
| unsigned long modulus_bitlen, int *res); |
| \end{alltt} |
| This will decode the PSS encoded message in ``sig'' of length ``siglen'' and compare it to values in ``msghash'' of length |
| ``msghashlen''. If the block is a valid PSS block and the decoded hash equals the hash supplied ``res'' is set to non--zero. Otherwise, |
| it is set to zero. The rest of the parameters are as in the PSS encode call. |
| |
| It's important to use the same ``saltlen'' and hash for both encoding and decoding as otherwise the procedure will not work. |
| |
| \subsection{PKCS \#1 v1.5 Encoding} |
| |
| \index{pkcs\_1\_v15\_sa\_encode()} |
| \begin{verbatim} |
| int pkcs_1_v15_sa_encode(const unsigned char *msghash, unsigned long msghashlen, |
| int hash_idx, unsigned long modulus_bitlen, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| |
| This will PKCS \#1 v1.5 signature encode the message hash ``msghash'' of length ``msghashlen''. You have |
| to tell this routine which hash produced the message hash in ``hash\_idx''. The encoded hash is stored |
| in ``out'' of length ``outlen''. |
| |
| \subsection{PKCS \#1 v1.5 Decoding} |
| |
| \index{pkcs\_1\_v15\_sa\_decode()} |
| \begin{verbatim} |
| int pkcs_1_v15_sa_decode(const unsigned char *msghash, unsigned long msghashlen, |
| const unsigned char *sig, unsigned long siglen, |
| int hash_idx, unsigned long modulus_bitlen, |
| int *res); |
| \end{verbatim} |
| |
| This will PKCS \#1 v1.5 signature decode the data in ``sig'' of length ``siglen'' and compare the extracted |
| hash against ``msghash'' of length ``msghashlen''. You have to tell this routine which hash produced the |
| message digest in ``hash\_idx''. If the packet is valid and the hashes match ``res'' is set to $1$. Otherwise, |
| it is set to $0$. |
| |
| \section{RSA Operations} |
| \subsection{Background} |
| |
| RSA is a public key algorithm that is based on the inability to find the ``e-th'' root modulo a composite of unknown |
| factorization. Normally the difficulty of breaking RSA is associated with the integer factoring problem but they are |
| not strictly equivalent. |
| |
| The system begins with with two primes $p$ and $q$ and their product $N = pq$. The order or ``Euler totient'' of the |
| multiplicative sub-group formed modulo $N$ is given as $\phi(N) = (p - 1)(q - 1)$ which can be reduced to |
| $\mbox{lcm}(p - 1, q - 1)$. The public key consists of the composite $N$ and some integer $e$ such that |
| $\mbox{gcd}(e, \phi(N)) = 1$. The private key consists of the composite $N$ and the inverse of $e$ modulo $\phi(N)$ |
| often simply denoted as $de \equiv 1\mbox{ }(\mbox{mod }\phi(N))$. |
| |
| A person who wants to encrypt with your public key simply forms an integer (the plaintext) $M$ such that |
| $1 < M < N-2$ and computes the ciphertext $C = M^e\mbox{ }(\mbox{mod }N)$. Since finding the inverse exponent $d$ |
| given only $N$ and $e$ appears to be intractable only the owner of the private key can decrypt the ciphertext and compute |
| $C^d \equiv \left (M^e \right)^d \equiv M^1 \equiv M\mbox{ }(\mbox{mod }N)$. Similarly the owner of the private key |
| can sign a message by ``decrypting'' it. Others can verify it by ``encrypting'' it. |
| |
| Currently RSA is a difficult system to cryptanalyze provided that both primes are large and not close to each other. |
| Ideally $e$ should be larger than $100$ to prevent direct analysis. For example, if $e$ is three and you do not pad |
| the plaintext to be encrypted than it is possible that $M^3 < N$ in which case finding the cube-root would be trivial. |
| The most often suggested value for $e$ is $65537$ since it is large enough to make such attacks impossible and also well |
| designed for fast exponentiation (requires 16 squarings and one multiplication). |
| |
| It is important to pad the input to RSA since it has particular mathematical structure. For instance |
| $M_1^dM_2^d = (M_1M_2)^d$ which can be used to forge a signature. Suppose $M_3 = M_1M_2$ is a message you want |
| to have a forged signature for. Simply get the signatures for $M_1$ and $M_2$ on their own and multiply the result |
| together. Similar tricks can be used to deduce plaintexts from ciphertexts. It is important not only to sign |
| the hash of documents only but also to pad the inputs with data to remove such structure. |
| |
| \subsection{RSA Key Generation} |
| |
| For RSA routines a single ``rsa\_key'' structure is used. To make a new RSA key call: |
| \index{rsa\_make\_key()} |
| \begin{verbatim} |
| int rsa_make_key(prng_state *prng, |
| int wprng, int size, |
| long e, rsa_key *key); |
| \end{verbatim} |
| |
| Where ``wprng'' is the index into the PRNG descriptor array. ``size'' is the size in bytes of the RSA modulus desired. |
| ``e'' is the encryption exponent desired, typical values are 3, 17, 257 and 65537. I suggest you stick with 65537 since its big |
| enough to prevent trivial math attacks and not super slow. ``key'' is where the key is placed. All keys must be at |
| least 128 bytes and no more than 512 bytes in size (\textit{that is from 1024 to 4096 bits}). |
| |
| Note that the ``rsa\_make\_key()'' function allocates memory at runtime when you make the key. Make sure to call |
| ``rsa\_free()'' (see below) when you are finished with the key. If ``rsa\_make\_key()'' fails it will automatically |
| free the ram allocated itself. |
| |
| There are three types of RSA keys. The types are {\bf PK\_PRIVATE\_OPTIMIZED}, {\bf PK\_PRIVATE} and {\bf PK\_PUBLIC}. The first |
| two are private keys where the ``optimized'' type uses the Chinese Remainder Theorem to speed up decryption/signatures. By |
| default all new keys are of the ``optimized'' type. The non-optimized private type is provided for backwards compatibility |
| as well as to save space since the optimized key requires about four times as much memory. |
| |
| \subsection{RSA Exponentiation} |
| |
| To do raw work with the RSA function call: |
| \index{rsa\_exptmod()} |
| \begin{verbatim} |
| int rsa_exptmod(const unsigned char *in, unsigned long inlen, |
| unsigned char *out, unsigned long *outlen, int which, |
| prng_state *prng, int prng_idx, |
| rsa_key *key); |
| \end{verbatim} |
| This loads the bignum from ``in'' as a big endian word in the format PKCS specifies, raises it to either ``e'' or ``d'' and stores the result |
| in ``out'' and the size of the result in ``outlen''. ``which'' is set to {\bf PK\_PUBLIC} to use ``e'' |
| (i.e. for encryption/verifying) and set to {\bf PK\_PRIVATE} to use ``d'' as the exponent (i.e. for decrypting/signing). |
| |
| Note that the output of his function is zero-padded as per PKCS \#1 specifications. This allows this routine to |
| interoprate with PKCS \#1 padding functions properly. |
| |
| \subsection{RSA Key Encryption} |
| Normally RSA is used to encrypt short symmetric keys which are then used in block ciphers to encrypt a message. |
| To facilitate encrypting short keys the following functions have been provided. |
| |
| \index{rsa\_encrypt\_key()} |
| \begin{verbatim} |
| int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen, |
| unsigned char *outkey, unsigned long *outlen, |
| const unsigned char *lparam, unsigned long lparamlen, |
| prng_state *prng, int prng_idx, int hash_idx, rsa_key *key); |
| \end{verbatim} |
| This function will OAEP pad ``inkey'' of length inlen bytes then RSA encrypt it and store the ciphertext |
| in ``outkey'' of length ``outlen''. The ``lparam'' and ``lparamlen'' are the same parameters you would pass |
| to pkcs\_1\_oaep\_encode(). |
| |
| \index{rsa\_decrypt\_key()} |
| \begin{verbatim} |
| int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, |
| unsigned char *outkey, unsigned long *keylen, |
| const unsigned char *lparam, unsigned long lparamlen, |
| prng_state *prng, int prng_idx, |
| int hash_idx, int *res, |
| rsa_key *key); |
| \end{verbatim} |
| This function will RSA decrypt ``in'' of length ``inlen'' then OAEP depad the resulting data and store it in |
| ``outkey'' of length ``outlen''. The ``lparam'' and ``lparamlen'' are the same parameters you would pass |
| to pkcs\_1\_oaep\_decode(). |
| |
| If the RSA decrypted data isn't a valid OAEP packet then ``res'' is set to $0$. Otherwise, it is set to $1$. |
| |
| \subsection{RSA Hash Signatures} |
| Similar to RSA key encryption RSA is also used to ``digitally sign'' message digests (hashes). To facilitate this |
| process the following functions have been provided. |
| |
| \index{rsa\_sign\_hash()} |
| \begin{verbatim} |
| int rsa_sign_hash(const unsigned char *msghash, unsigned long msghashlen, |
| unsigned char *sig, unsigned long *siglen, |
| prng_state *prng, int prng_idx, |
| int hash_idx, unsigned long saltlen, |
| rsa_key *key); |
| \end{verbatim} |
| |
| This will PSS encode the message hash ``msghash'' of length ``msghashlen''. Next the PSS encoded message is |
| RSA ``signed'' and the output is stored in ``sig'' of length ``siglen''. |
| |
| |
| \index{rsa\_verify\_hash()} |
| \begin{verbatim} |
| int rsa_verify_hash(const unsigned char *sig, unsigned long siglen, |
| const unsigned char *msghash, unsigned long msghashlen, |
| prng_state *prng, int prng_idx, |
| int hash_idx, unsigned long saltlen, |
| int *stat, rsa_key *key); |
| \end{verbatim} |
| |
| This will RSA ``verify'' the signature in ``sig'' of length ``siglen''. Next the RSA decoded data is PSS decoded |
| and the extracted hash is compared against the message hash ``msghash'' of length ``msghashlen''. |
| |
| If the RSA decoded data is not a valid PSS message or if the PSS decoded hash does not match the ``msghash'' |
| the value ``res'' is set to $0$. Otherwise, if the function succeeds and signature is valid ``res'' is set |
| to $1$. |
| |
| \begin{verbatim} |
| #include <mycrypt.h> |
| int main(void) |
| { |
| int err, hash_idx, prng_idx, res; |
| unsigned long l1, l2; |
| unsigned char pt[16], pt2[16], out[1024]; |
| rsa_key key; |
| |
| /* register prng/hash */ |
| if (register_prng(&sprng_desc) == -1) { |
| printf("Error registering sprng"); |
| return EXIT_FAILURE; |
| } |
| |
| if (register_hash(&sha1_desc) == -1) { |
| printf("Error registering sha1"); |
| return EXIT_FAILURE; |
| } |
| hash_idx = find_hash("sha1"); |
| prng_idx = find_prng("sprng"); |
| |
| /* make an RSA-1024 key */ |
| if ((err = rsa_make_key(NULL, /* PRNG state */ |
| prng_idx, /* PRNG idx */ |
| 1024/8, /* 1024-bit key */ |
| 65537, /* we like e=65537 */ |
| &key) /* where to store the key */ |
| ) != CRYPT_OK) { |
| printf("rsa_make_key %s", error_to_string(err)); |
| return EXIT_FAILURE; |
| } |
| |
| /* fill in pt[] with a key we want to send ... */ |
| l1 = sizeof(out); |
| if ((err = rsa_encrypt_key(pt, /* data we wish to encrypt */ |
| 16, /* data is 16 bytes long */ |
| out, /* where to store ciphertext */ |
| &l1, /* length of ciphertext */ |
| "TestApp", /* our lparam for this program */ |
| 7, /* lparam is 7 bytes long */ |
| NULL, /* PRNG state */ |
| prng_idx, /* prng idx */ |
| hash_idx, /* hash idx */ |
| &key) /* our RSA key */ |
| ) != CRYPT_OK) { |
| printf("rsa_encrypt_key %s", error_to_string(err)); |
| return EXIT_FAILURE; |
| } |
| |
| /* now let's decrypt the encrypted key */ |
| l2 = sizeof(pt2); |
| if ((err = rsa_decrypt_key(out, /* encrypted data */ |
| l1, /* length of ciphertext */ |
| pt2, /* where to put plaintext */ |
| &l2, /* plaintext length */ |
| "TestApp", /* lparam for this program */ |
| 7, /* lparam is 7 bytes long */ |
| NULL, /* PRNG state */ |
| prng_idx, /* prng idx */ |
| hash_idx, /* hash idx */ |
| &res, /* validity of data */ |
| &key) /* our RSA key */ |
| ) != CRYPT_OK) { |
| printf("rsa_decrypt_key %s", error_to_string(err)); |
| return EXIT_FAILURE; |
| } |
| /* if all went well pt == pt2, l2 == 16, res == 1 */ |
| } |
| \end{verbatim} |
| |
| \chapter{Password Based Cryptography} |
| \section{PKCS \#5} |
| In order to securely handle user passwords for the purposes of creating session keys and chaining IVs the PKCS \#5 was drafted. PKCS \#5 |
| is made up of two algorithms, Algorithm One and Algorithm Two. Algorithm One is the older fairly limited algorithm which has been implemented |
| for completeness. Algorithm Two is a bit more modern and more flexible to work with. |
| |
| \section{Algorithm One} |
| Algorithm One accepts as input a password, an 8--byte salt and an iteration counter. The iteration counter is meant to act as delay for |
| people trying to brute force guess the password. The higher the iteration counter the longer the delay. This algorithm also requires a hash |
| algorithm and produces an output no longer than the output of the hash. |
| |
| \index{pkcs\_5\_alg1()} |
| \begin{alltt} |
| int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, |
| const unsigned char *salt, |
| int iteration_count, int hash_idx, |
| unsigned char *out, unsigned long *outlen) |
| \end{alltt} |
| Where ``password'' is the users password. Since the algorithm allows binary passwords you must also specify the length in ``password\_len''. |
| The ``salt'' is a fixed size 8--byte array which should be random for each user and session. The ``iteration\_count'' is the delay desired |
| on the password. The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table. |
| |
| The output of length upto ``outlen'' is stored in ``out''. If ``outlen'' is initially larger than the size of the hash functions output |
| it is set to the number of bytes stored. If it is smaller than not all of the hash output is stored in ``out''. |
| |
| \section{Algorithm Two} |
| |
| Algorithm Two is the recommended algorithm for this task. It allows variable length salts and can produce outputs larger than the |
| hash functions output. As such it can easily be used to derive session keys for ciphers and MACs as well initial vectors as required |
| from a single password and invokation of this algorithm. |
| |
| \index{pkcs\_5\_alg2()} |
| \begin{alltt} |
| int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, |
| const unsigned char *salt, unsigned long salt_len, |
| int iteration_count, int hash_idx, |
| unsigned char *out, unsigned long *outlen) |
| \end{alltt} |
| Where ``password'' is the users password. Since the algorithm allows binary passwords you must also specify the length in ``password\_len''. |
| The ``salt'' is an array of size ``salt\_len''. It should be random for each user and session. The ``iteration\_count'' is the delay desired |
| on the password. The ``hash\_idx'' is the index of the hash you wish to use in the descriptor table. The output of length upto |
| ``outlen'' is stored in ``out''. |
| |
| \begin{alltt} |
| /* demo to show how to make session state material from a password */ |
| #include <mycrypt.h> |
| int main(void) |
| \{ |
| unsigned char password[100], salt[100], |
| cipher_key[16], cipher_iv[16], |
| mac_key[16], outbuf[48]; |
| int err, hash_idx; |
| unsigned long outlen, password_len, salt_len; |
| |
| /* register hash and get it's idx .... */ |
| |
| /* get users password and make up a salt ... */ |
| |
| /* create the material (100 iterations in algorithm) */ |
| outlen = sizeof(outbuf); |
| if ((err = pkcs_5_alg2(password, password_len, salt, salt_len, |
| 100, hash_idx, outbuf, &outlen)) != CRYPT_OK) \{ |
| /* error handle */ |
| \} |
| |
| /* now extract it */ |
| memcpy(cipher_key, outbuf, 16); |
| memcpy(cipher_iv, outbuf+16, 16); |
| memcpy(mac_key, outbuf+32, 16); |
| |
| /* use material (recall to store the salt in the output) */ |
| \} |
| \end{alltt} |
| |
| \chapter{Diffie-Hellman Key Exchange} |
| |
| \section{Background} |
| |
| Diffie-Hellman was the original public key system proposed. The system is based upon the group structure |
| of finite fields. For Diffie-Hellman a prime $p$ is chosen and a ``base'' $b$ such that $b^x\mbox{ }(\mbox{mod }p)$ |
| generates a large sub-group of prime order (for unique values of $x$). |
| |
| A secret key is an exponent $x$ and a public key is the value of $y \equiv g^x\mbox{ }(\mbox{mod }p)$. The term |
| ``discrete logarithm'' denotes the action of finding $x$ given only $y$, $g$ and $p$. The key exchange part of |
| Diffie-Hellman arises from the fact that two users A and B with keys $(A_x, A_y)$ and $(B_x, B_y)$ can exchange |
| a shared key $K \equiv B_y^{A_x} \equiv A_y^{B_x} \equiv g^{A_xB_x}\mbox{ }(\mbox{mod }p)$. |
| |
| From this public encryption and signatures can be developed. The trivial way to encrypt (for example) using a public key |
| $y$ is to perform the key exchange offline. The sender invents a key $k$ and its public copy |
| $k' \equiv g^k\mbox{ }(\mbox{mod }p)$ and uses $K \equiv k'^{A_x}\mbox{ }(\mbox{mod }p)$ as a key to encrypt |
| the message with. Typically $K$ would be sent to a one-way hash and the message digested used as a key in a |
| symmetric cipher. |
| |
| It is important that the order of the sub-group that $g$ generates not only be large but also prime. There are |
| discrete logarithm algorithms that take $\sqrt r$ time given the order $r$. The discrete logarithm can be computed |
| modulo each prime factor of $r$ and the results combined using the Chinese Remainder Theorem. In the cases where |
| $r$ is ``B-Smooth'' (e.g. all small factors or powers of small prime factors) the solution is trivial to find. |
| |
| To thwart such attacks the primes and bases in the library have been designed and fixed. Given a prime $p$ the order of |
| the sub-group generated is a large prime namely ${p - 1} \over 2$. Such primes are known as ``strong primes'' and the |
| smaller prime (e.g. the order of the base) are known as Sophie-Germaine primes. |
| |
| \section{Core Functions} |
| |
| This library also provides core Diffie-Hellman functions so you can negotiate keys over insecure mediums. The routines |
| provided are relatively easy to use and only take two function calls to negotiate a shared key. There is a structure |
| called ``dh\_key'' which stores the Diffie-Hellman key in a format these routines can use. The first routine is to |
| make a Diffie-Hellman private key pair: |
| \index{dh\_make\_key()} |
| \begin{verbatim} |
| int dh_make_key(prng_state *prng, int wprng, |
| int keysize, dh_key *key); |
| \end{verbatim} |
| The ``keysize'' is the size of the modulus you want in bytes. Currently support sizes are 96 to 512 bytes which correspond |
| to key sizes of 768 to 4096 bits. The smaller the key the faster it is to use however it will be less secure. When |
| specifying a size not explicitly supported by the library it will round {\em up} to the next key size. If the size is |
| above 512 it will return an error. So if you pass ``keysize == 32'' it will use a 768 bit key but if you pass |
| ``keysize == 20000'' it will return an error. The primes and generators used are built-into the library and were designed |
| to meet very specific goals. The primes are strong primes which means that if $p$ is the prime then |
| $p-1$ is equal to $2r$ where $r$ is a large prime. The bases are chosen to generate a group of order $r$ to prevent |
| leaking a bit of the key. This means the bases generate a very large prime order group which is good to make cryptanalysis |
| hard. |
| |
| The next two routines are for exporting/importing Diffie-Hellman keys in a binary format. This is useful for transport |
| over communication mediums. |
| |
| \index{dh\_export()} \index{dh\_import()} |
| \begin{verbatim} |
| int dh_export(unsigned char *out, unsigned long *outlen, |
| int type, dh_key *key); |
| |
| int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key); |
| \end{verbatim} |
| |
| These two functions work just like the ``rsa\_export()'' and ``rsa\_import()'' functions except these work with |
| Diffie-Hellman keys. Its important to note you do not have to free the ram for a ``dh\_key'' if an import fails. You can free a |
| ``dh\_key'' using: |
| \begin{verbatim} |
| void dh_free(dh_key *key); |
| \end{verbatim} |
| After you have exported a copy of your public key (using {\bf PK\_PUBLIC} as ``type'') you can now create a shared secret |
| with the other user using: |
| \index{dh\_shared\_secret()} |
| \begin{verbatim} |
| int dh_shared_secret(dh_key *private_key, |
| dh_key *public_key, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| |
| Where ``private\_key'' is the key you made and ``public\_key'' is the copy of the public key the other user sent you. The result goes |
| into ``out'' and the length into ``outlen''. If all went correctly the data in ``out'' should be identical for both parties. It is important to |
| note that the two keys have to be the same size in order for this to work. There is a function to get the size of a |
| key: |
| \index{dh\_get\_size()} |
| \begin{verbatim} |
| int dh_get_size(dh_key *key); |
| \end{verbatim} |
| This returns the size in bytes of the modulus chosen for that key. |
| |
| \subsection{Remarks on Usage} |
| Its important that you hash the shared key before trying to use it as a key for a symmetric cipher or something. An |
| example program that communicates over sockets, using MD5 and 1024-bit DH keys is\footnote{This function is a small example. It is suggested that proper packaging be used. For example, if the public key sent is truncated these routines will not detect that.}: |
| \newpage |
| \begin{small} |
| \begin{verbatim} |
| int establish_secure_socket(int sock, int mode, unsigned char *key, |
| prng_state *prng, int wprng) |
| { |
| unsigned char buf[4096], buf2[4096]; |
| unsigned long x, len; |
| int res, err, inlen; |
| dh_key mykey, theirkey; |
| |
| /* make up our private key */ |
| if ((err = dh_make_key(prng, wprng, 128, &mykey)) != CRYPT_OK) { |
| return err; |
| } |
| |
| /* export our key as public */ |
| x = sizeof(buf); |
| if ((err = dh_export(buf, &x, PK_PUBLIC, &mykey)) != CRYPT_OK) { |
| res = err; |
| goto done2; |
| } |
| |
| if (mode == 0) { |
| /* mode 0 so we send first */ |
| if (send(sock, buf, x, 0) != x) { |
| res = CRYPT_ERROR; |
| goto done2; |
| } |
| |
| /* get their key */ |
| if ((inlen = recv(sock, buf2, sizeof(buf2), 0)) <= 0) { |
| res = CRYPT_ERROR; |
| goto done2; |
| } |
| } else { |
| /* mode >0 so we send second */ |
| if ((inlen = recv(sock, buf2, sizeof(buf2), 0)) <= 0) { |
| res = CRYPT_ERROR; |
| goto done2; |
| } |
| |
| if (send(sock, buf, x, 0) != x) { |
| res = CRYPT_ERROR; |
| goto done2; |
| } |
| } |
| |
| if ((err = dh_import(buf2, inlen, &theirkey)) != CRYPT_OK) { |
| res = err; |
| goto done2; |
| } |
| |
| /* make shared secret */ |
| x = sizeof(buf); |
| if ((err = dh_shared_secret(&mykey, &theirkey, buf, &x)) != CRYPT_OK) { |
| res = err; |
| goto done; |
| } |
| |
| /* hash it */ |
| len = 16; /* default is MD5 so "key" must be at least 16 bytes long */ |
| if ((err = hash_memory(find_hash("md5"), buf, x, key, &len)) != CRYPT_OK) { |
| res = err; |
| goto done; |
| } |
| |
| /* clean up and return */ |
| res = CRYPT_OK; |
| done: |
| dh_free(&theirkey); |
| done2: |
| dh_free(&mykey); |
| zeromem(buf, sizeof(buf)); |
| zeromem(buf2, sizeof(buf2)); |
| return res; |
| } |
| \end{verbatim} |
| \end{small} |
| \newpage |
| \subsection{Remarks on The Snippet} |
| When the above code snippet is done (assuming all went well) their will be a shared 128-bit key in the ``key'' array |
| passed to ``establish\_secure\_socket()''. |
| |
| \section{Other Diffie-Hellman Functions} |
| In order to test the Diffie-Hellman function internal workings (e.g. the primes and bases) their is a test function made |
| available: |
| \index{dh\_test()} |
| \begin{verbatim} |
| int dh_test(void); |
| \end{verbatim} |
| |
| This function returns {\bf CRYPT\_OK} if the bases and primes in the library are correct. There is one last helper |
| function: |
| \index{dh\_sizes()} |
| \begin{verbatim} |
| void dh_sizes(int *low, int *high); |
| \end{verbatim} |
| Which stores the smallest and largest key sizes support into the two variables. |
| |
| \section{DH Packet} |
| Similar to the RSA related functions there are functions to encrypt or decrypt symmetric keys using the DH public key |
| algorithms. |
| \index{dh\_encrypt\_key()} \index{dh\_decrypt\_key()} |
| \begin{verbatim} |
| int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen, |
| unsigned char *out, unsigned long *len, |
| prng_state *prng, int wprng, int hash, |
| dh_key *key); |
| |
| int dh_decrypt_key(const unsigned char *in, unsigned long inlen, |
| unsigned char *outkey, unsigned long *keylen, |
| dh_key *key); |
| \end{verbatim} |
| Where ``inkey'' is an input symmetric key of no more than 32 bytes. Essentially these routines created a random public key |
| and find the hash of the shared secret. The message digest is than XOR'ed against the symmetric key. All of the |
| required data is placed in ``out'' by ``dh\_encrypt\_key()''. The hash must produce a message digest at least as large |
| as the symmetric key you are trying to share. |
| |
| Similar to the RSA system you can sign and verify a hash of a message. |
| \index{dh\_sign\_hash()} \index{dh\_verify\_hash()} |
| \begin{verbatim} |
| int dh_sign_hash(const unsigned char *in, unsigned long inlen, |
| unsigned char *out, unsigned long *outlen, |
| prng_state *prng, int wprng, dh_key *key); |
| |
| int dh_verify_hash(const unsigned char *sig, unsigned long siglen, |
| const unsigned char *hash, unsigned long hashlen, |
| int *stat, dh_key *key); |
| \end{verbatim} |
| |
| The ``dh\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a DH packet in ``out''. |
| The ``dh\_verify\_hash'' function verifies the DH signature in ``sig'' against the hash in ``hash''. It sets ``stat'' |
| to non-zero if the signature passes or zero if it fails. |
| |
| \chapter{Elliptic Curve Cryptography} |
| |
| \section{Background} |
| The library provides a set of core ECC functions as well that are designed to be the Elliptic Curve analogy of all of the |
| Diffie-Hellman routines in the previous chapter. Elliptic curves (of certain forms) have the benefit that they are harder |
| to attack (no sub-exponential attacks exist unlike normal DH crypto) in fact the fastest attack requires the square root |
| of the order of the base point in time. That means if you use a base point of order $2^{192}$ (which would represent a |
| 192-bit key) then the work factor is $2^{96}$ in order to find the secret key. |
| |
| The curves in this library are taken from the following website: |
| \begin{verbatim} |
| http://csrc.nist.gov/cryptval/dss.htm |
| \end{verbatim} |
| |
| They are all curves over the integers modulo a prime. The curves have the basic equation that is: |
| \begin{equation} |
| y^2 = x^3 - 3x + b\mbox{ }(\mbox{mod }p) |
| \end{equation} |
| |
| The variable $b$ is chosen such that the number of points is nearly maximal. In fact the order of the base points $\beta$ |
| provided are very close to $p$ that is $\vert \vert \phi(\beta) \vert \vert \approx \vert \vert p \vert \vert$. The curves |
| range in order from $\approx 2^{192}$ points to $\approx 2^{521}$. According to the source document any key size greater |
| than or equal to 256-bits is sufficient for long term security. |
| |
| \section{Core Functions} |
| |
| Like the DH routines there is a key structure ``ecc\_key'' used by the functions. There is a function to make a key: |
| \index{ecc\_make\_key()} |
| \begin{verbatim} |
| int ecc_make_key(prng_state *prng, int wprng, |
| int keysize, ecc_key *key); |
| \end{verbatim} |
| |
| The ``keysize'' is the size of the modulus in bytes desired. Currently directly supported values are 20, 24, 28, 32, 48 and 65 bytes which |
| correspond to key sizes of 160, 192, 224, 256, 384 and 521 bits respectively. If you pass a key size that is between any key size |
| it will round the keysize up to the next available one. The rest of the parameters work like they do in the ``dh\_make\_key()'' function. |
| To free the ram allocated by a key call: |
| \index{ecc\_free()} |
| \begin{verbatim} |
| void ecc_free(ecc_key *key); |
| \end{verbatim} |
| |
| To import and export a key there are: |
| \index{ecc\_export()} |
| \index{ecc\_import()} |
| \begin{verbatim} |
| int ecc_export(unsigned char *out, unsigned long *outlen, |
| int type, ecc_key *key); |
| |
| int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key); |
| \end{verbatim} |
| These two work exactly like there DH counterparts. Finally when you share your public key you can make a shared secret |
| with: |
| \index{ecc\_shared\_secret()} |
| \begin{verbatim} |
| int ecc_shared_secret(ecc_key *private_key, |
| ecc_key *public_key, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| Which works exactly like the DH counterpart, the ``private\_key'' is your own key and ``public\_key'' is the key the other |
| user sent you. Note that this function stores both $x$ and $y$ co-ordinates of the shared |
| elliptic point. You should hash the output to get a shared key in a more compact and useful form (most of the entropy is |
| in $x$ anyways). Both keys have to be the same size for this to work, to help there is a function to get the size in bytes |
| of a key. |
| \index{ecc\_get\_size()} |
| \begin{verbatim} |
| int ecc_get_size(ecc_key *key); |
| \end{verbatim} |
| |
| To test the ECC routines and to get the minimum and maximum key sizes there are these two functions: |
| \index{ecc\_test()} |
| \begin{verbatim} |
| int ecc_test(void); |
| void ecc_sizes(int *low, int *high); |
| \end{verbatim} |
| Which both work like their DH counterparts. |
| |
| \section{ECC Packet} |
| Similar to the RSA API there are two functions which encrypt and decrypt symmetric keys using the ECC public key |
| algorithms. |
| |
| \index{ecc\_encrypt\_key()} \index{ecc\_decrypt\_key()} |
| \begin{verbatim} |
| int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen, |
| unsigned char *out, unsigned long *len, |
| prng_state *prng, int wprng, int hash, |
| ecc_key *key); |
| |
| int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, |
| unsigned char *outkey, unsigned long *keylen, |
| ecc_key *key); |
| \end{verbatim} |
| |
| Where ``inkey'' is an input symmetric key of no more than 32 bytes. Essentially these routines created a random public key |
| and find the hash of the shared secret. The message digest is than XOR'ed against the symmetric key. All of the required |
| data is placed in ``out'' by ``ecc\_encrypt\_key()''. The hash chosen must produce a message digest at least as large |
| as the symmetric key you are trying to share. |
| |
| There are also functions to sign and verify the hash of a message. |
| \index{ecc\_sign\_hash()} \index{ecc\_verify\_hash()} |
| \begin{verbatim} |
| int ecc_sign_hash(const unsigned char *in, unsigned long inlen, |
| unsigned char *out, unsigned long *outlen, |
| prng_state *prng, int wprng, ecc_key *key); |
| |
| int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, |
| const unsigned char *hash, unsigned long hashlen, |
| int *stat, ecc_key *key); |
| \end{verbatim} |
| |
| The ``ecc\_sign\_hash'' function signs the message hash in ``in'' of length ``inlen'' and forms a ECC packet in ``out''. |
| The ``ecc\_verify\_hash'' function verifies the ECC signature in ``sig'' against the hash in ``hash''. It sets ``stat'' |
| to non-zero if the signature passes or zero if it fails. |
| |
| |
| \section{ECC Keysizes} |
| With ECC if you try and sign a hash that is bigger than your ECC key you can run into problems. The math will still work |
| and in effect the signature will still work. With ECC keys the strength of the signature is limited by the size of |
| the hash or the size of they key, whichever is smaller. For example, if you sign with SHA256 and a ECC-160 key in effect |
| you have 160-bits of security (e.g. as if you signed with SHA-1). |
| |
| The library will not warn you if you make this mistake so it is important to check yourself before using the |
| signatures. |
| |
| \chapter{Digital Signature Algorithm} |
| \section{Introduction} |
| The Digital Signature Algorithm (or DSA) is a variant of the ElGamal Signature scheme which has been modified to |
| reduce the bandwidth of a signature. For example, to have ``80-bits of security'' with ElGamal you need a group of |
| order at least 1024-bits. With DSA you need a group of order at least 160-bits. By comparison the ElGamal signature |
| would require at least 256 bytes where as the DSA signature would require only at least 40 bytes. |
| |
| The API for the DSA is essentially the same as the other PK algorithms. Except in the case of DSA no encryption or |
| decryption routines are provided. |
| |
| \section{Key Generation} |
| To make a DSA key you must call the following function |
| \begin{verbatim} |
| int dsa_make_key(prng_state *prng, int wprng, |
| int group_size, int modulus_size, |
| dsa_key *key); |
| \end{verbatim} |
| The variable ``prng'' is an active PRNG state and ``wprng'' the index to the descriptor. ``group\_size'' and |
| ``modulus\_size'' control the difficulty of forging a signature. Both parameters are in bytes. The larger the |
| ``group\_size'' the more difficult a forgery becomes upto a limit. The value of $group\_size$ is limited by |
| $15 < group\_size < 1024$ and $modulus\_size - group\_size < 512$. Suggested values for the pairs are as follows. |
| |
| \begin{center} |
| \begin{tabular}{|c|c|c|} |
| \hline \textbf{Bits of Security} & \textbf{group\_size} & \textbf{modulus\_size} \\ |
| \hline 80 & 20 & 128 \\ |
| \hline 120 & 30 & 256 \\ |
| \hline 140 & 35 & 384 \\ |
| \hline 160 & 40 & 512 \\ |
| \hline |
| \end{tabular} |
| \end{center} |
| |
| When you are finished with a DSA key you can call the following function to free the memory used. |
| \index{dsa\_free()} |
| \begin{verbatim} |
| void dsa_free(dsa_key *key); |
| \end{verbatim} |
| |
| \section{Key Verification} |
| Each DSA key is composed of the following variables. |
| |
| \begin{enumerate} |
| \item $q$ a small prime of magnitude $256^{group\_size}$. |
| \item $p = qr + 1$ a large prime of magnitude $256^{modulus\_size}$ where $r$ is a random even integer. |
| \item $g = h^r \mbox{ (mod }p\mbox{)}$ a generator of order $q$ modulo $p$. $h$ can be any non-trivial random |
| value. For this library they start at $h = 2$ and step until $g$ is not $1$. |
| \item $x$ a random secret (the secret key) in the range $1 < x < q$ |
| \item $y = g^x \mbox{ (mod }p\mbox{)}$ the public key. |
| \end{enumerate} |
| |
| A DSA key is considered valid if it passes all of the following tests. |
| |
| \begin{enumerate} |
| \item $q$ must be prime. |
| \item $p$ must be prime. |
| \item $g$ cannot be one of $\lbrace -1, 0, 1 \rbrace$ (modulo $p$). |
| \item $g$ must be less than $p$. |
| \item $(p-1) \equiv 0 \mbox{ (mod }q\mbox{)}$. |
| \item $g^q \equiv 1 \mbox{ (mod }p\mbox{)}$. |
| \item $1 < y < p - 1$ |
| \item $y^q \equiv 1 \mbox{ (mod }p\mbox{)}$. |
| \end{enumerate} |
| |
| Tests one and two ensure that the values will at least form a field which is required for the signatures to |
| function. Tests three and four ensure that the generator $g$ is not set to a trivial value which would make signature |
| forgery easier. Test five ensures that $q$ divides the order of multiplicative sub-group of $\Z/p\Z$. Test six |
| ensures that the generator actually generates a prime order group. Tests seven and eight ensure that the public key |
| is within range and belongs to a group of prime order. Note that test eight does not prove that $g$ generated $y$ only |
| that $y$ belongs to a multiplicative sub-group of order $q$. |
| |
| The following function will perform these tests. |
| |
| \index{dsa\_verify\_key()} |
| \begin{verbatim} |
| int dsa_verify_key(dsa_key *key, int *stat); |
| \end{verbatim} |
| |
| This will test ``key'' and store the result in ``stat''. If the result is $stat = 0$ the DSA key failed one of the tests |
| and should not be used at all. If the result is $stat = 1$ the DSA key is valid (as far as valid mathematics are concerned). |
| |
| |
| |
| \section{Signatures} |
| To generate a DSA signature call the following function |
| |
| \index{dsa\_sign\_hash()} |
| \begin{verbatim} |
| int dsa_sign_hash(const unsigned char *in, unsigned long inlen, |
| unsigned char *out, unsigned long *outlen, |
| prng_state *prng, int wprng, dsa_key *key); |
| \end{verbatim} |
| |
| Which will sign the data in ``in'' of length ``inlen'' bytes. The signature is stored in ``out'' and the size |
| of the signature in ``outlen''. If the signature is longer than the size you initially specify in ``outlen'' nothing |
| is stored and the function returns an error code. The DSA ``key'' must be of the \textbf{PK\_PRIVATE} persuasion. |
| |
| To verify a hash created with that function use the following function |
| |
| \index{dsa\_verify\_hash()} |
| \begin{verbatim} |
| int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, |
| const unsigned char *hash, unsigned long inlen, |
| int *stat, dsa_key *key); |
| \end{verbatim} |
| Which will verify the data in ``hash'' of length ``inlen'' against the signature stored in ``sig'' of length ``siglen''. |
| It will set ``stat'' to $1$ if the signature is valid, otherwise it sets ``stat'' to $0$. |
| |
| \section{Import and Export} |
| |
| To export a DSA key so that it can be transported use the following function |
| \index{dsa\_export()} |
| \begin{verbatim} |
| int dsa_export(unsigned char *out, unsigned long *outlen, |
| int type, |
| dsa_key *key); |
| \end{verbatim} |
| This will export the DSA ``key'' to the buffer ``out'' and set the length in ``outlen'' (which must have been previously |
| initialized to the maximum buffer size). The ``type`` variable may be either \textbf{PK\_PRIVATE} or \textbf{PK\_PUBLIC} |
| depending on whether you want to export a private or public copy of the DSA key. |
| |
| To import an exported DSA key use the following function |
| |
| \index{dsa\_import()} |
| \begin{verbatim} |
| int dsa_import(const unsigned char *in, unsigned long inlen, |
| dsa_key *key); |
| \end{verbatim} |
| |
| This will import the DSA key from the buffer ``in'' of length ``inlen'' to the ``key''. If the process fails the function |
| will automatically free all of the heap allocated in the process (you don't have to call dsa\_free()). |
| |
| \chapter{Miscellaneous} |
| \section{Base64 Encoding and Decoding} |
| The library provides functions to encode and decode a RFC1521 base64 coding scheme. This means that it can decode what it |
| encodes but the format used does not comply to any known standard. The characters used in the mappings are: |
| \begin{verbatim} |
| ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ |
| \end{verbatim} |
| Those characters should are supported in virtually any 7-bit ASCII system which means they can be used for transport over |
| common e-mail, usenet and HTTP mediums. The format of an encoded stream is just a literal sequence of ASCII characters |
| where a group of four represent 24-bits of input. The first four chars of the encoders output is the length of the |
| original input. After the first four characters is the rest of the message. |
| |
| Often it is desirable to line wrap the output to fit nicely in an e-mail or usenet posting. The decoder allows you to |
| put any character (that is not in the above sequence) in between any character of the encoders output. You may not however, |
| break up the first four characters. |
| |
| To encode a binary string in base64 call: |
| \index{base64\_encode()} \index{base64\_decode()} |
| \begin{verbatim} |
| int base64_encode(const unsigned char *in, unsigned long len, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| Where ``in'' is the binary string and ``out'' is where the ASCII output is placed. You must set the value of ``outlen'' prior |
| to calling this function and it sets the length of the base64 output in ``outlen'' when it is done. To decode a base64 |
| string call: |
| \begin{verbatim} |
| int base64_decode(const unsigned char *in, unsigned long len, |
| unsigned char *out, unsigned long *outlen); |
| \end{verbatim} |
| |
| \section{The Multiple Precision Integer Library (MPI)} |
| The library comes with a copy of LibTomMath which is a multiple precision integer library written by the |
| author of LibTomCrypt. LibTomMath is a trivial to use ANSI C compatible large integer library which is free |
| for all uses and is distributed freely. |
| |
| At the heart of all the functions is the data type ``mp\_int'' (defined in tommath.h). This data type is what |
| will hold all large integers. In order to use an mp\_int one must initialize it first, for example: |
| \begin{verbatim} |
| #include <mycrypt.h> /* mycrypt.h includes mpi.h automatically */ |
| int main(void) |
| { |
| mp_int bignum; |
| |
| /* initialize it */ |
| mp_init(&bignum); |
| |
| return 0; |
| } |
| \end{verbatim} |
| If you are unfamiliar with the syntax of C the \& symbol is used to pass the address of ``bignum'' to the function. All |
| LibTomMath functions require the address of the parameters. To free the memory of a mp\_int use (for example): |
| \begin{verbatim} |
| mp_clear(&bignum); |
| \end{verbatim} |
| |
| The functions also have the basic form of one of the following: |
| \begin{verbatim} |
| mp_XXX(mp_int *a); |
| mp_XXX(mp_int *a, mp_int *b, mp_int *c); |
| mp_XXX(mp_int *a, mp_int *b, mp_int *c, mp_int *d); |
| \end{verbatim} |
| |
| Where they perform some operation and store the result in the mp\_int variable passed on the far right. |
| For example, to compute $c = a + b \mbox{ }(\mbox{mod }m)$ you would call: |
| \begin{verbatim} |
| mp_addmod(&a, &b, &m, &c); |
| \end{verbatim} |
| |
| \subsection{Binary Forms of ``mp\_int'' Variables} |
| |
| Often it is required to store a ``mp\_int'' in binary form for transport (e.g. exporting a key, packet |
| encryption, etc.). LibTomMath includes two functions to help when exporting numbers: |
| \begin{verbatim} |
| int mp_raw_size(mp_int *num); |
| mp_toraw(&num, buf); |
| \end{verbatim} |
| |
| The former function gives the size in bytes of the raw format and the latter function actually stores the raw data. All |
| ``mp\_int'' numbers are stored in big endian form (like PKCS demands) with the first byte being the sign of the number. The |
| ``rsa\_exptmod()'' function differs slightly since it will take the input in the form exactly as PKCS demands (without the |
| leading sign byte). All other functions include the sign byte (since its much simpler just to include it). The sign byte |
| must be zero for positive numbers and non-zero for negative numbers. For example, |
| the sequence: |
| \begin{verbatim} |
| 00 FF 30 04 |
| \end{verbatim} |
| Represents the integer $255 \cdot 256^2 + 48 \cdot 256^1 + 4 \cdot 256^0$ or 16,723,972. |
| |
| To read a binary string back into a ``mp\_int'' call: |
| \begin{verbatim} |
| mp_read_raw(mp_int *num, unsigned char *str, int len); |
| \end{verbatim} |
| Where ``num'' is where to store it, ``str'' is the binary string (including the leading sign byte) and ``len'' is the |
| length of the binary string. |
| |
| \subsection{Primality Testing} |
| \index{Primality Testing} |
| The library includes primality testing and random prime functions as well. The primality tester will perform the test in |
| two phases. First it will perform trial division by the first few primes. Second it will perform eight rounds of the |
| Rabin-Miller primality testing algorithm. If the candidate passes both phases it is declared prime otherwise it is declared |
| composite. No prime number will fail the two phases but composites can. Each round of the Rabin-Miller algorithm reduces |
| the probability of a pseudo-prime by $1 \over 4$ therefore after sixteen rounds the probability is no more than |
| $\left ( { 1 \over 4 } \right )^{8} = 2^{-16}$. In practice the probability of error is in fact much lower than that. |
| |
| When making random primes the trial division step is in fact an optimized implementation of ``Implementation of Fast RSA Key Generation on Smart Cards''\footnote{Chenghuai Lu, Andre L. M. dos Santos and Francisco R. Pimentel}. |
| In essence a table of machine-word sized residues are kept of a candidate modulo a set of primes. When the candiate |
| is rejected and ultimately incremented to test the next number the residues are updated without using multi-word precision |
| math operations. As a result the routine can scan ahead to the next number required for testing with very little work |
| involved. |
| |
| In the event that a composite did make it through it would most likely cause the the algorithm trying to use it to fail. For |
| instance, in RSA two primes $p$ and $q$ are required. The order of the multiplicative sub-group (modulo $pq$) is given |
| as $\phi(pq)$ or $(p - 1)(q - 1)$. The decryption exponent $d$ is found as $de \equiv 1\mbox{ }(\mbox{mod } \phi(pq))$. If either $p$ or $q$ is composite the value of $d$ will be incorrect and the user |
| will not be able to sign or decrypt messages at all. Suppose $p$ was prime and $q$ was composite this is just a variation of |
| the multi-prime RSA. Suppose $q = rs$ for two primes $r$ and $s$ then $\phi(pq) = (p - 1)(r - 1)(s - 1)$ which clearly is |
| not equal to $(p - 1)(rs - 1)$. |
| |
| These are not technically part of the LibTomMath library but this is the best place to document them. |
| To test if a ``mp\_int'' is prime call: |
| \begin{verbatim} |
| int is_prime(mp_int *N, int *result); |
| \end{verbatim} |
| This puts a one in ``result'' if the number is probably prime, otherwise it places a zero in it. It is assumed that if |
| it returns an error that the value in ``result'' is undefined. To make |
| a random prime call: |
| \begin{verbatim} |
| int rand_prime(mp_int *N, unsigned long len, prng_state *prng, int wprng); |
| \end{verbatim} |
| Where ``len'' is the size of the prime in bytes ($2 \le len \le 256$). You can set ``len'' to the negative size you want |
| to get a prime of the form $p \equiv 3\mbox{ }(\mbox{mod } 4)$. So if you want a 1024-bit prime of this sort pass |
| ``len = -128'' to the function. Upon success it will return {\bf CRYPT\_OK} and ``N'' will contain an integer which |
| is very likely prime. |
| |
| \chapter{Programming Guidelines} |
| |
| \section{Secure Pseudo Random Number Generators} |
| Probably the singal most vulnerable point of any cryptosystem is the PRNG. Without one generating and protecting secrets |
| would be impossible. The requirement that one be setup correctly is vitally important and to address this point the library |
| does provide two RNG sources that will address the largest amount of end users as possible. The ``sprng'' PRNG provided |
| provides and easy to access source of entropy for any application on a *NIX or Windows computer. |
| |
| However, when the end user is not on one of these platforms the application developer must address the issue of finding |
| entropy. This manual is not designed to be a text on cryptography. I would just like to highlight that when you design |
| a cryptosystem make sure the first problem you solve is getting a fresh source of entropy. |
| |
| \section{Preventing Trivial Errors} |
| Two simple ways to prevent trivial errors is to prevent overflows and to check the return values. All of the functions |
| which output variable length strings will require you to pass the length of the destination. If the size of your output |
| buffer is smaller than the output it will report an error. Therefore, make sure the size you pass is correct! |
| |
| Also virtually all of the functions return an error code or {\bf CRYPT\_OK}. You should detect all errors as simple |
| typos or such can cause algorithms to fail to work as desired. |
| |
| \section{Registering Your Algorithms} |
| To avoid linking and other runtime errors it is important to register the ciphers, hashes and PRNGs you intend to use |
| before you try to use them. This includes any function which would use an algorithm indirectly through a descriptor table. |
| |
| A neat bonus to the registry system is that you can add external algorithms that are not part of the library without |
| having to hack the library. For example, suppose you have a hardware specific PRNG on your system. You could easily |
| write the few functions required plus a descriptor. After registering your PRNG all of the library functions that |
| need a PRNG can instantly take advantage of it. |
| |
| \section{Key Sizes} |
| |
| \subsection{Symmetric Ciphers} |
| For symmetric ciphers use as large as of a key as possible. For the most part ``bits are cheap'' so using a 256-bit key |
| is not a hard thing todo. |
| |
| \subsection{Assymetric Ciphers} |
| The following chart gives the work factor for solving a DH/RSA public key using the NFS. The work factor for a key of order |
| $n$ is estimated to be |
| \begin{equation} |
| e^{1.923 \cdot ln(n)^{1 \over 3} \cdot ln(ln(n))^{2 \over 3}} |
| \end{equation} |
| |
| Note that $n$ is not the bit-length but the magnitude. For example, for a 1024-bit key $n = 2^{1024}$. The work required |
| is: |
| \begin{center} |
| \begin{tabular}{|c|c|} |
| \hline RSA/DH Key Size (bits) & Work Factor ($log_2$) \\ |
| \hline 512 & 63.92 \\ |
| \hline 768 & 76.50 \\ |
| \hline 1024 & 86.76 \\ |
| \hline 1536 & 103.37 \\ |
| \hline 2048 & 116.88 \\ |
| \hline 2560 & 128.47 \\ |
| \hline 3072 & 138.73 \\ |
| \hline 4096 & 156.49 \\ |
| \hline |
| \end{tabular} |
| \end{center} |
| |
| The work factor for ECC keys is much higher since the best attack is still fully exponentional. Given a key of magnitude |
| $n$ it requires $\sqrt n$ work. The following table sumarizes the work required: |
| \begin{center} |
| \begin{tabular}{|c|c|} |
| \hline ECC Key Size (bits) & Work Factor ($log_2$) \\ |
| \hline 160 & 80 \\ |
| \hline 192 & 96 \\ |
| \hline 224 & 112 \\ |
| \hline 256 & 128 \\ |
| \hline 384 & 192 \\ |
| \hline 521 & 260.5 \\ |
| \hline |
| \end{tabular} |
| \end{center} |
| |
| Using the above tables the following suggestions for key sizes seems appropriate: |
| \begin{center} |
| \begin{tabular}{|c|c|c|} |
| \hline Security Goal & RSA/DH Key Size (bits) & ECC Key Size (bits) \\ |
| \hline Short term (less than a year) & 1024 & 160 \\ |
| \hline Short term (less than five years) & 1536 & 192 \\ |
| \hline Long Term (less than ten years) & 2560 & 256 \\ |
| \hline |
| \end{tabular} |
| \end{center} |
| |
| \section{Thread Safety} |
| The library is not thread safe but several simple precautions can be taken to avoid any problems. The registry functions |
| such as register\_cipher() are not thread safe no matter what you do. Its best to call them from your programs initializtion |
| code before threads are initiated. |
| |
| The rest of the code uses state variables you must pass it such as hash\_state, hmac\_state, etc. This means that if each |
| thread has its own state variables then they will not affect each other. This is fairly simple with symmetric ciphers |
| and hashes. However, the keyring and PRNG support is something the threads will want to share. The simplest workaround |
| is create semaphores or mutexes around calls to those functions. |
| |
| Since C does not have standard semaphores this support is not native to Libtomcrypt. Even a C based semaphore is not entire |
| possible as some compilers may ignore the ``volatile'' keyword or have multiple processors. Provide your host application |
| is modular enough putting the locks in the right place should not bloat the code significantly and will solve all thread |
| safety issues within the library. |
| |
| \chapter{Configuring the Library} |
| \section{Introduction} |
| The library is fairly flexible about how it can be built, used and generally distributed. Additions are being made with |
| each new release that will make the library even more flexible. Most options are placed in the makefile and others |
| are in ``mycrypt\_cfg.h''. All are used when the library is built from scratch. |
| |
| For GCC platforms the file ``makefile'' is the makefile to be used. On MSVC platforms ``makefile.vc'' and on PS2 platforms |
| ``makefile.ps2''. |
| |
| \section{mycrypt\_cfg.h} |
| The file ``mycrypt\_cfg.h'' is what lets you control what functionality you want to remove from the library. By default, |
| everything the library has to offer it built. |
| |
| \subsubsection{ARGTYPE} |
| This lets you control how the \_ARGCHK macro will behave. The macro is used to check pointers inside the functions against |
| NULL. There are three settings for ARGTYPE. When set to 0 it will have the default behaviour of printing a message to |
| stderr and raising a SIGABRT signal. This is provided so all platforms that use libtomcrypt can have an error that functions |
| similarly. When set to 1 it will simply pass on to the assert() macro. When set to 2 it will resolve to a empty macro |
| and no error checking will be performed. |
| |
| \subsubsection{Endianess} |
| There are five macros related to endianess issues. For little endian platforms define, ENDIAN\_LITTLE. For big endian |
| platforms define ENDIAN\_BIG. Similarly when the default word size of an ``unsigned long'' is 32-bits define ENDIAN\_32BITWORD |
| or define ENDIAN\_64BITWORD when its 64-bits. If you do not define any of them the library will automatically use ENDIAN\_NEUTRAL |
| which will work on all platforms. Currently the system will automatically detect GCC or MSVC on a windows platform as well |
| as GCC on a PS2 platform. |
| |
| \section{The Configure Script} |
| There are also options you can specify from the configure script or ``mycrypt\_config.h''. |
| |
| \subsubsection{X memory routines} |
| The makefiles must define three macros denoted as XMALLOC, XCALLOC and XFREE which resolve to the name of the respective |
| functions. This lets you substitute in your own memory routines. If you substitute in your own functions they must behave |
| like the standard C library functions in terms of what they expect as input and output. By default the library uses the |
| standard C routines. |
| |
| \subsubsection{X clock routines} |
| The rng\_get\_bytes() function can call a function that requires the clock() function. These macros let you override |
| the default clock() used with a replacement. By default the standard C library clock() function is used. |
| |
| \subsubsection{NO\_FILE} |
| During the build if NO\_FILE is defined then any function in the library that uses file I/O will not call the file I/O |
| functions and instead simply return CRYPT\_ERROR. This should help resolve any linker errors stemming from a lack of |
| file I/O on embedded platforms. |
| |
| \subsubsection{CLEAN\_STACK} |
| When this functions is defined the functions that store key material on the stack will clean up afterwards. Assumes that |
| you have no memory paging with the stack. |
| |
| \subsubsection{Symmetric Ciphers, One-way Hashes, PRNGS and Public Key Functions} |
| There are a plethora of macros for the ciphers, hashes, PRNGs and public key functions which are fairly self-explanatory. |
| When they are defined the functionality is included otherwise it is not. There are some dependency issues which are |
| noted in the file. For instance, Yarrow requires CTR chaining mode, a block cipher and a hash function. |
| |
| \subsubsection{TWOFISH\_SMALL and TWOFISH\_TABLES} |
| Twofish is a 128-bit symmetric block cipher that is provided within the library. The cipher itself is flexible enough |
| to allow some tradeoffs in the implementation. When TWOFISH\_SMALL is defined the scheduled symmetric key for Twofish |
| requires only 200 bytes of memory. This is achieved by not pre-computing the substitution boxes. Having this |
| defined will also greatly slow down the cipher. When this macro is not defined Twofish will pre-compute the |
| tables at a cost of 4KB of memory. The cipher will be much faster as a result. |
| |
| When TWOFISH\_TABLES is defined the cipher will use pre-computed (and fixed in code) tables required to work. This is |
| useful when TWOFISH\_SMALL is defined as the table values are computed on the fly. When this is defined the code size |
| will increase by approximately 500 bytes. If this is defined but TWOFISH\_SMALL is not the cipher will still work but |
| it will not speed up the encryption or decryption functions. |
| |
| \subsubsection{SMALL\_CODE} |
| When this is defined some of the code such as the Rijndael and SAFER+ ciphers are replaced with smaller code variants. |
| These variants are slower but can save quite a bit of code space. |
| |
| \input{crypt.ind} |
| |
| \end{document} |