Crypt
Crypt
Developer Manual
Tom St Denis
LibTom Projects
Contents
1 Introduction
1.1 What is the LibTomCrypt? . .
1.1.1 What the library IS for?
1.2 Why did I write it? . . . . . . .
1.2.1 Modular . . . . . . . . .
1.3 License . . . . . . . . . . . . . .
1.4 Patent Disclosure . . . . . . . .
1.5 Thanks . . . . . . . . . . . . .
2 The
2.1
2.2
2.3
2.4
2.5
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
. 7
. 8
. 9
. 10
. 11
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
iii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
2
3
3
4
4
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
13
14
15
15
16
16
17
17
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
20
22
22
24
25
25
26
27
28
29
30
32
34
34
38
41
43
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
51
51
53
56
58
59
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
61
61
64
68
69
70
71
73
73
74
3.4
3.5
3.3.1 Notes . . . . . . . . . . . .
Symmetric Modes of Operations .
3.4.1 Background . . . . . . . . .
3.4.2 Choice of Mode . . . . . . .
3.4.3 Ciphertext Stealing . . . . .
3.4.4 Initialization . . . . . . . .
3.4.5 Encryption and Decryption
3.4.6 IV Manipulation . . . . . .
3.4.7 Stream Termination . . . .
3.4.8 Examples . . . . . . . . . .
3.4.9 LRW Mode . . . . . . . . .
3.4.10 F8 Mode . . . . . . . . . .
Encrypt and Authenticate Modes .
3.5.1 EAX Mode . . . . . . . . .
3.5.2 OCB Mode . . . . . . . . .
3.5.3 CCM Mode . . . . . . . . .
3.5.4 GCM Mode . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
77
77
79
79
80
82
84
86
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
89
89
89
89
90
91
91
92
92
92
93
94
94
95
96
96
97
97
98
99
99
100
101
101
103
103
104
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
105
105
106
107
108
108
108
109
109
109
110
110
110
111
111
111
112
112
113
113
113
114
114
114
115
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
117
117
117
118
119
120
120
121
121
122
122
122
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9.7.1
9.7.2
10 Standards Support
10.1 ASN.1 Formats . . . . . . . . . . . . .
10.1.1 SEQUENCE Type . . . . . . .
10.1.2 SET and SET OF . . . . . . .
10.1.3 ASN.1 INTEGER . . . . . . .
10.1.4 ASN.1 BIT STRING . . . . . .
10.1.5 ASN.1 OCTET STRING . . .
10.1.6 ASN.1 OBJECT IDENTIFIER
10.1.7 ASN.1 IA5 STRING . . . . . .
10.1.8 ASN.1 PRINTABLE STRING
10.1.9 ASN.1 UTF8 STRING . . . . .
10.1.10 ASN.1 UTCTIME . . . . . . .
10.1.11 ASN.1 CHOICE . . . . . . . .
10.1.12 ASN.1 Flexi Decoder . . . . . .
10.2 Password Based Cryptography . . . .
10.2.1 PKCS #5 . . . . . . . . . . . .
10.2.2 Algorithm One . . . . . . . . .
10.2.3 Algorithm Two . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
125
125
126
130
132
132
133
133
134
135
135
136
137
138
140
140
140
141
11 Miscellaneous
143
11.1 Base64 Encoding and Decoding . . . . . . . . . . . . . . 143
11.2 Primality Testing . . . . . . . . . . . . . . . . . . . . . . 144
12 Programming Guidelines
12.1 Secure Pseudo Random Number Generators
12.2 Preventing Trivial Errors . . . . . . . . . .
12.3 Registering Your Algorithms . . . . . . . .
12.4 Key Sizes . . . . . . . . . . . . . . . . . . .
12.4.1 Symmetric Ciphers . . . . . . . . . .
12.4.2 Asymmetric Ciphers . . . . . . . . .
12.5 Thread Safety . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
147
. 147
. 148
. 148
. 148
. 148
. 148
. 150
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
151
151
152
152
152
152
153
154
154
155
155
156
157
157
157
157
157
158
158
159
.
.
.
.
.
.
.
.
.
159
159
159
160
160
160
160
161
161
14 Optimizations
14.1 Introduction . . . . .
14.2 Ciphers . . . . . . .
14.2.1 Name . . . .
14.2.2 Internal ID .
14.2.3 Key Lengths
14.2.4 Block Length
.
.
.
.
.
.
163
163
164
170
170
171
171
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
14.2.5 Rounds . . . . . . . . . . . .
14.2.6 Setup . . . . . . . . . . . . .
14.2.7 Single block ECB . . . . . . .
14.2.8 Testing . . . . . . . . . . . .
14.2.9 Key Sizing . . . . . . . . . .
14.2.10 Acceleration . . . . . . . . . .
14.3 OneWay Hashes . . . . . . . . . . .
14.3.1 Name . . . . . . . . . . . . .
14.3.2 Internal ID . . . . . . . . . .
14.3.3 Digest Size . . . . . . . . . .
14.3.4 Block Size . . . . . . . . . . .
14.3.5 OID Identifier . . . . . . . . .
14.3.6 Initialization . . . . . . . . .
14.3.7 Process . . . . . . . . . . . .
14.3.8 Done . . . . . . . . . . . . . .
14.3.9 Acceleration . . . . . . . . . .
14.3.10 HMAC Acceleration . . . . .
14.4 PseudoRandom Number Generators
14.4.1 Name . . . . . . . . . . . . .
14.4.2 Export Size . . . . . . . . . .
14.4.3 Start . . . . . . . . . . . . . .
14.4.4 Entropy Addition . . . . . . .
14.4.5 Ready . . . . . . . . . . . . .
14.4.6 Read . . . . . . . . . . . . . .
14.4.7 Done . . . . . . . . . . . . . .
14.4.8 Exporting and Importing . .
14.5 BigNum Math Descriptors . . . . . .
14.5.1 Conventions . . . . . . . . . .
14.5.2 ECC Functions . . . . . . . .
14.5.3 RSA Functions . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
171
171
171
172
172
172
175
176
177
177
177
177
177
177
177
177
178
178
180
180
180
180
180
180
180
181
181
191
192
193
List of Figures
2.1
2.2
9
9
3.1
3.2
4.1
6.1
9.1
xi
xii
Chapter 1
Introduction
1.1
1.1.1
The library serves as a toolkit for developers who have to solve cryptographic problems. Out of the box LibTomCrypt does not process
SSL or OpenPGP messages, it doesnt read X.509 certificates, or write
PEM encoded data. It does, however, provide all of the tools required
to build such functionality. LibTomCrypt was designed to be a flexible
library that was not tied to any particular cryptographic problem.
1
www.libtom.org
1.2
You may be wondering, Tom, why did you write a crypto library. I
already have one. Well the reason falls into two categories:
1. I am too lazy to figure out someone elses API. Id rather invent
my own simpler API and use that.
2. It was (still is) good coding practice.
The idea is that I am not striving to replace OpenSSL or Crypto++
or Cryptlib or etc. Im trying to write my own crypto library and
hopefully along the way others will appreciate the work.
With this library all core functions (ciphers, hashes, prngs, and
bignum) have the 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 the library you know how to use Safer+, RC6, or Serpent
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 run-time. That means your application
can support all ciphers/hashes/prngs/bignum without changing the
source code.
Not only did I strive to make a consistent and simple API to work
with but I also attempted to make the library configurable in terms
of its build options. Out of the box the library will build with any
modern version of GCC without having to use configure scripts. This
means that the library will work with platforms where development
tools may be limited (e.g. no autoconf).
On top of making the build simple and the API approachable Ive
also attempted for a reasonably high level of robustness and efficiency.
LibTomCrypt traps and returns a series of errors ranging from invalid
arguments to buffer overflows/overruns. It is mostly thread safe and
has been clocked on various platforms with cycles per byte timings
that are comparable (and often favourable) to other libraries such as
OpenSSL and Crypto++.
1.3 License
1.2.1
Modular
1.3
License
www.libtom.org
1.4
Patent Disclosure
1.5
Thanks
1.5 Thanks
www.libtom.org
Chapter 2
The Application
Programming Interface
(API)
2.1
Introduction
In general the API is very simple to memorize and use. Most of the
functions return either void or int. Functions that return int will
return 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
const char *error_to_string(int err);
An example of handling an error is:
void somefunc(void)
{
int err;
/* call a cryptographic function */
www.libtom.org
if ((err = some_crypto_function(...)) != CRYPT_OK) {
printf("A crypto error occurred, %s\n", error_to_string(err));
/* perform error handling */
}
/* continue on if no error occurred */
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 tomcrypt.h like so:
#include <tomcrypt.h>
int main(void) {
return 0;
}
2.2
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:
x y[0 . . . 3]
x y[0 . . . 7]
y[0 . . . 3] x
y[0 . . . 7] x
x y[3 . . . 0]
x y[7 . . . 0]
y[3 . . . 0] x
y[7 . . . 0] x
Swap bytes
x << y, 0 y
x << y, 0 y
x >> y, 0 y
x >> y, 0 y
31
31
31
31
ROL64(x, y)
ROL64c(x, y)
ROR64(x, y)
ROR64c(x, y)
x << y, 0 y
x << y, 0 y
x >> y, 0 y
x >> y, 0 y
63
63
63
63
2.3
10
www.libtom.org
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;
In the above example if the size of the RSA public key was more than
1024 bytes this function would return an error code indicating a buffer
overflow would have occurred. If the function succeeds, it stores the
length of the output back into x so that the calling application will
know how many bytes were used.
As of v1.13, most functions will update your length on failure to
indicate the size required by the function. Not all functions support
this so please check the source before you rely on it doing that.
2.4
11
2.5
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 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.
12
www.libtom.org
Chapter 3
Symmetric Block
Ciphers
3.1
Core Functions
3.1.1
Key Scheduling
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. This also removes the need
for dynamic memory allocation, and allows you to allocate a fixed
sized buffer for storing scheduled keys. All ciphers must provide six
visible functions which are (given that XXX is the name of the cipher)
the following:
int XXX_setup(const unsigned char *key,
int keylen,
13
14
www.libtom.org
int rounds,
symmetric_key *skey);
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 builtin 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). However, to maintain proper coding
practices you should always call the respective XXX done() function.
This allows for quicker porting to applications with externally supplied
plugins.
3.1.2
To encrypt or decrypt a block in ECB mode there are these two functions per cipher:
int XXX_ecb_encrypt(const unsigned char *pt,
unsigned char *ct,
symmetric_key *skey);
int XXX_ecb_decrypt(const unsigned char *ct,
unsigned char *pt,
symmetric_key *skey);
These two functions will encrypt or decrypt (respectively) a single
block of text1 , storing the result in the ct buffer (pt resp.). It is
possible that the input and output buffer are the same buffer. For
the encrypt function pt 2 is the input and ct 3 is the output. For the
decryption function its the opposite. They both return CRYPT OK
1 The
15
3.1.3
SelfTesting
int XXX_test(void);
This function will return CRYPT OK if the cipher matches the test
vectors from the design publication it is based upon.
3.1.4
Key Sizing
For each cipher there is a function which will help find a desired key
size. It is specified as follows:
int XXX_keysize(int *keysize);
Essentially, it will round the input keysize in keysize down to the next
appropriate key size. This function will return CRYPT OK if the
key size specified is acceptable. For example:
#include <tomcrypt.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;
}
16
www.libtom.org
3.1.5
Cipher Termination
When you are finished with a cipher you can deinitialize it with the
done function.
void XXX_done(symmetric_key *skey);
For the software based ciphers within LibTomCrypt, these functions
will not do anything. However, user supplied cipher descriptors may
require to be called for resource management purposes. To be compliant, all functions which call a cipher setup function must also call the
respective cipher done function when finished.
3.1.6
/*
/*
/*
/*
error_to_string(err));
17
3.2
3.3
To facilitate automatic routines an array of cipher descriptors is provided in the array cipher descriptor. An element of this array has the
18
www.libtom.org
Where name is the lower case ASCII version of the name. The
fields min key length and max key length are the minimum and maximum key sizes in bytes. The block length member is the block size of
the cipher in bytes. 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.
For a plugin to be compliant it must provide at least each function
listed before the accelerators begin. Accelerators are optional, and if
missing will be emulated in software.
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 NULL.
As of this release the current cipher descriptors elements are the
following:
Name
Blowfish
X-Tea
RC2
RC5-32/12/b
RC6-32/20/b
SAFER+
AES
Twofish
DES
3DES (EDE mode)
CAST5 (CAST-128)
Noekeon
Skipjack
Anubis
Khazad
SEED
KASUMI
Descriptor Name
blowfish desc
xtea desc
rc2 desc
rc5 desc
rc6 desc
saferp desc
aes desc
aes enc desc
twofish desc
des desc
des3 desc
cast5 desc
noekeon desc
skipjack desc
anubis desc
khazad desc
kseed desc
kasumi desc
19
Block Size
8
8
8
8
16
16
16
16
16
8
8
8
16
8
16
8
16
8
Key Range
8 . . . 56
16
8 . . . 128
8 . . . 128
8 . . . 128
16, 24, 32
16, 24, 32
16, 24, 32
16, 24, 32
7
21
5 . . . 16
16
10
16 . . . 40
16
16
16
Rounds
16
32
16
12 . . . 24
20
8, 12, 16
10, 12, 14
10, 12, 14
16
16
16
12, 16
16
32
12 . . . 18
8
16
8
20
www.libtom.org
3.3.1
Notes
1. 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 selftest function pointers of
both encrypt only descriptors are set to 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.
2. 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.
3. Note that Twofish has additional configuration options (Figure 3.2)
that take place at build time. These options are found in the file
tomcrypt 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 832 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
q0 , q1 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.
TWOFISH TABLES
undefined
defined
undefined
defined
21
Speed and Memory (per key)
Very fast, 4.2KB of ram.
Faster key setup, larger code.
Very slow, 0.2KB of ram.
Faster, 0.2KB of ram, larger code.
22
www.libtom.org
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 -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:
int unregister_cipher(const struct _cipher_descriptor *cipher);
Which returns CRYPT OK if it removes the cipher, otherwise it
returns CRYPT ERROR.
#include <tomcrypt.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;
}
3.4
3.4.1
23
(3.3)
24
www.libtom.org
CFB Mode
CFB or Ciphertext Feedback Mode is a mode akin to CBC. It is given
as:
Ci = Pi C1
C1 = Ek (Ci )
(3.4)
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.
OFB Mode
OFB or Output Feedback Mode is a mode akin to CBC as well. It is
given as:
C1 = Ek (C1 )
Ci = Pi C1
(3.5)
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.
3.4.2
Choice of Mode
My personal preference is for the CTR mode since it has several key
benefits:
1. No short cycles which is possible in the OFB and CFB modes.
2. Provably as secure as the block cipher being used under a chosen
plaintext attack.
3. Technically does not require the decryption routine of the cipher.
4. Allows random access to the plaintext.
5. Allows the encryption of block sizes that are not equal to the
size of the block cipher.
25
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.
3.4.3
Ciphertext Stealing
3.4.4
Initialization
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 CTR and ECB mode):
int XXX_start(
int
const unsigned char
const unsigned char
int
int
symmetric_XXX
cipher,
*IV,
*key,
keylen,
num_rounds,
*XXX);
int ctr_start(
int cipher,
const unsigned char *IV,
const unsigned char *key,
int keylen,
26
www.libtom.org
int num_rounds,
int ctr_mode,
symmetric_CTR *ctr);
int ecb_start(
int
const unsigned char
int
int
symmetric_ECB
cipher,
*key,
keylen,
num_rounds,
*ecb);
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 size5 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.
In the case of CTR mode there is an additional parameter ctr mode
which specifies the mode that the counter is to be used in. If CTR COUNTER
LITTLE ENDIAN was specified then the counter will be treated as
a little endian value. Otherwise, if CTR COUNTER BIG ENDIAN
was specified the counter will be treated as a big endian value. As
of v1.15 the RFC 3686 style of increment then encrypt is also supported. By ORing LTC CTR RFC3686 with the CTR mode value,
ctr start() will increment the counter before encrypting it for the first
time.
The routines return CRYPT OK if the cipher initialized correctly, otherwise, they return an error code.
3.4.5
27
*ct,
*pt,
len,
*YYY);
3.4.6
IV Manipulation
28
www.libtom.org
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 rekeying the cipher.
What the setiv function will do depends on the mode being changed.
In CBC mode, the new IV replaces the existing IV as if it were the
last ciphertext block. In CFB mode, the IV is encrypted as if it were
the prior encrypted pad. In CTR mode, the IV is encrypted without
first incrementing it (regardless of the LTC RFC 3686 flag presence).
In F8 mode, the IV is encrypted and becomes the new pad. It does
not change the salted IV, and is only meant to allow seeking within a
session. In LRW, it changes the tweak, forcing a computation of the
tweak pad, allowing for seeking within the session. In OFB mode, the
IV is encrypted and becomes the new pad.
3.4.7
Stream Termination
3.4.8
29
Examples
#include <tomcrypt.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) */
0, /* 0 == default # of rounds */
CTR_COUNTER_LITTLE_ENDIAN, /* Little endian counter */
&ctr) /* where to store the 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 plaintext pt */
&ctr) /* CTR state */
) != CRYPT_OK) {
printf("ctr_encrypt error: %s\n", error_to_string(err));
return -1;
}
30
www.libtom.org
/* make use of ciphertext... */
/* now we want to decrypt so lets 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,
buffer,
sizeof(buffer),
&ctr)
/*
/*
/*
/*
ciphertext */
plaintext */
length of plaintext */
CTR state */
) != CRYPT_OK) {
printf("ctr_decrypt error: %s\n", error_to_string(err));
return -1;
}
/* terminate the stream */
if ((err = ctr_done(&ctr)) != CRYPT_OK) {
printf("ctr_done error: %s\n", error_to_string(err));
return -1;
}
/* clear up and return */
zeromem(key, sizeof(key));
zeromem(&ctr, sizeof(ctr));
return 0;
}
3.4.9
LRW Mode
31
The key is specified as two strings the first key K1 is the (normally
AES) key and can be any length (typically 16, 24 or 32 octets long).
The second key K2 is the tweak key and is always 16 octets long. The
tweak value is NOT a nonce or IV value it must be random and secret.
To initialize LRW mode use:
int lrw_start(
int
const unsigned char
const unsigned char
int
const unsigned char
int
symmetric_LRW
cipher,
*IV,
*key,
keylen,
*tweak,
num_rounds,
*lrw);
This will initialize the LRW context with the given (16 octet) IV,
cipher K1 key of length keylen octets and the (16 octet) K2 tweak.
While LRW was specified to be used only with AES, LibTomCrypt will
allow any 128bit block cipher to be specified as indexed by cipher.
The number of rounds for the block cipher num rounds can be 0 to
use the default number of rounds for the given cipher.
To process data use the following functions:
int lrw_encrypt(const unsigned char
unsigned char
unsigned long
symmetric_LRW
*pt,
*ct,
len,
*lrw);
*ct,
*pt,
len,
*lrw);
32
www.libtom.org
3.4.10
F8 Mode
The F8 Chaining mode (see RFC 3711 for instance) is yet another
chaining mode for block ciphers. It behaves much like CTR mode
in that it XORs a keystream against the plaintext to encrypt. F8
mode comes with the additional twist that the counter value is secret,
encrypted by a salt key. We initialize F8 mode with the following
function call:
int f8_start(
int
const unsigned char
const unsigned char
int
const unsigned char
int
int
symmetric_F8
cipher,
*IV,
*key,
keylen,
*salt_key,
skeylen,
num_rounds,
*f8);
This will start the F8 mode state using key as the secret key, IV as
the counter. It uses the salt key as IV encryption key (m in the RFC
3711). The salt key can be shorter than the secret key but it should
not be longer.
To encrypt or decrypt data we use the following two functions:
33
*pt,
*ct,
len,
*f8);
*ct,
*pt,
len,
*f8);
34
3.5
3.5.1
www.libtom.org
eax_state
int
const unsigned char
unsigned long
const unsigned char
unsigned long
const unsigned char
unsigned long
*eax,
cipher,
*key,
keylen,
*nonce,
noncelen,
*header,
headerlen);
Where eax is the EAX state. The cipher parameter is the index
of the desired cipher in the descriptor table. The key parameter is
6 See M. Bellare, P. Rogaway, D. Wagner, A Conventional AuthenticatedEncryption Mode.
7 Note that since EAX only requires OMAC and CTR you may use encrypt only
cipher descriptors with this mode.
35
the shared secret symmetric key of length keylen octets. The nonce
parameter is the random public string of length noncelen octets. The
header parameter is the random (or fixed or NULL) header for the
message of length headerlen octets.
When this function completes, the eax state will be initialized such
that you can now either have data decrypted or encrypted in EAX
mode. Note: if headerlen is zero you may pass header as NULL to
indicate there is no initial header data.
To encrypt or decrypt data in a streaming mode use the following.
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);
The function eax encrypt will encrypt the bytes in pt of length octets,
and store the ciphertext in ct. Note: 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 bidirectional communication you will need to initialize two EAX
contexts (preferably with different headers and nonces).
Note: 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.
int eax_addheader(
eax_state *eax,
const unsigned char *header,
unsigned long length);
This will add the length octet from header to the given eax header.
36
www.libtom.org
/*
/*
/*
/*
/*
context */
cipher id */
the nonce */
nonce is 16 bytes */
example header */
37
7) /* header length */
) != 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
* its taglen bytes long */
}
You can also perform an entire EAX state on a block of memory
in a single function call with the following functions.
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,
38
www.libtom.org
const unsigned char *pt,
unsigned char *ct,
unsigned char *tag,
int eax_decrypt_verify_memory(
int cipher,
const unsigned char *key,
const unsigned char *nonce,
const unsigned char *header,
const unsigned char *ct,
unsigned char *pt,
unsigned char *tag,
int
*res);
unsigned
unsigned
unsigned
unsigned
long
long
long
long
keylen,
noncelen,
headerlen,
ctlen,
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.
3.5.2
OCB Mode
ocb_state *ocb,
int cipher,
const unsigned char *key,
unsigned long keylen,
const unsigned char *nonce);
This will initialize the ocb context using cipher descriptor cipher.
It will use a key of length keylen and the random nonce. Note that
8 See P. Rogaway, M. Bellare, J. Black, T. Krovetz, OCB: A Block Cipher Mode
of Operation for Efficient Authenticated Encryption.
39
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.
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);
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 ciphers 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.
State Termination
When you are finished encrypting the message you call the following
function to compute the tag.
int ocb_done_encrypt(
ocb_state
const unsigned char
unsigned long
unsigned char
unsigned char
unsigned long
*ocb,
*pt,
ptlen,
*ct,
*tag,
*taglen);
40
www.libtom.org
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.
int ocb_done_decrypt(
ocb_state
const unsigned char
unsigned long
unsigned char
const unsigned char
unsigned long
int
*ocb,
*ct,
ctlen,
*pt,
*tag,
taglen,
*res);
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).
Packet Functions
To make life simpler the following two functions are provided for memory bound OCB.
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);
This will OCB encrypt the message pt of length ptlen, and store
the ciphertext in ct. The length ptlen can be any arbitrary length.
int ocb_decrypt_verify_memory(
int cipher,
const unsigned char *key,
unsigned long keylen,
const unsigned char *nonce,
41
unsigned long ctlen,
unsigned long taglen,
Similarly, this will OCB decrypt, and compare the internally computed tag against the tag provided. res is set appropriately.
3.5.3
CCM Mode
int cipher,
char *key,
unsigned
*uskey,
char *nonce, unsigned
char *header, unsigned
char *pt,
unsigned
char *ct,
char *tag,
unsigned
int direction);
long keylen,
long noncelen,
long headerlen,
long ptlen,
long *taglen,
This performs the CCM operation on the data. The cipher variable
indicates which cipher in the descriptor table to use. It must have a
16byte block size for CCM.
The key can be specified in one of two fashions. First, it can be
passed as an array of octets in key of length keylen. Alternatively, it
can be passed in as a previously scheduled key in uskey. The latter
fashion saves time when the same key is used for multiple packets. If
uskey is not NULL, then key may be NULL (and vice-versa).
The nonce or salt is nonce of length noncelen octets. The header is
metadata you want to send with the message but not have encrypted,
it is stored in header of length headerlen octets. The header can be zero
octets long (if headerlen = 0 then you can pass header as NULL).
42
www.libtom.org
The plaintext is stored in pt, and the ciphertext in ct. The length
of both are expected to be equal and is passed in as ptlen. It is allowable that pt = ct. The direction variable indicates whether encryption (direction = CCM ENCRYPT) or decryption (direction
= CCM DECRYPT) is to be performed.
As implemented, this version of CCM cannot handle header or
plaintext data longer than 232 1 octets long.
You can test the implementation of CCM with the following function.
int ccm_test(void);
This will return CRYPT OK if the CCM routine passes known
test vectors. It requires AES or Rijndael to be registered previously,
otherwise it will return CRYPT NOP.
CCM Example
The following is a sample of how to call CCM.
#include <tomcrypt.h>
int main(void)
{
unsigned char key[16], nonce[12], pt[32], ct[32],
tag[16], tagcp[16];
unsigned long taglen;
int
err;
/* register cipher */
register_cipher(&aes_desc);
/* somehow fill key, nonce, pt */
/* encrypt it */
taglen = sizeof(tag);
if ((err =
ccm_memory(find_cipher("aes"),
key, 16,
/* 128-bit key */
NULL,
/* not prescheduled */
nonce, 12, /* 96-bit nonce */
NULL, 0,
/* no header */
43
pt, 32,
/* 32-byte plaintext */
ct,
/* ciphertext */
tag, &taglen,
CCM_ENCRYPT)) != CRYPT_OK) {
printf("ccm_memory error %s\n", error_to_string(err));
return -1;
}
/* ct[0..31] and tag[0..15] now hold the output */
/* decrypt it */
taglen = sizeof(tagcp);
if ((err =
ccm_memory(find_cipher("aes"),
key, 16,
/* 128-bit key */
NULL,
/* not prescheduled */
nonce, 12, /* 96-bit nonce */
NULL, 0,
/* no header */
ct, 32,
/* 32-byte ciphertext */
pt,
/* plaintext */
tagcp, &taglen,
CCM_DECRYPT)) != CRYPT_OK) {
printf("ccm_memory error %s\n", error_to_string(err));
return -1;
}
/* now pt[0..31] should hold the original plaintext,
tagcp[0..15] and tag[0..15] should have the same contents */
}
3.5.4
GCM Mode
44
www.libtom.org
gcm_state *gcm,
int cipher,
const unsigned char *key,
int keylen);
This initializes the GCM state gcm for the given cipher indexed by
cipher, with a secret key key of length keylen octets. The cipher
chosen must have a 16byte block size (e.g., AES).
Initial Vector
After the state has been initialized (or reset) the next step is to add
the session (or packet) initial vector. It should be unique per packet
encrypted.
int gcm_add_iv(
gcm_state *gcm,
const unsigned char *IV,
unsigned long IVlen);
This adds the initial vector octets from IV of length IVlen to the
GCM state gcm. You can call this function as many times as required
to process the entire IV.
Note: the GCM protocols provides a shortcut for 12byte IVs
where no pre-processing is to be done. If you want to minimize per
packet latency it is ideal to only use 12byte IVs. You can just increment it like a counter for each packet.
Additional Authentication Data
After the entire IV has been processed, the additional authentication
data can be processed. Unlike the IV, a packet/session does not require
additional authentication data (AAD) for security. The AAD is meant
45
46
www.libtom.org
State Reset
The call to gcm init() will perform considerable precomputation (when
GCM TABLES is defined) and if youre going to be dealing with a
lot of packets it is very costly to have to call it repeatedly. To aid in
this endeavour, the reset function has been provided.
int gcm_reset(gcm_state *gcm);
This will reset the GCM state gcm to the state that gcm init() left
it. The user would then call gcm add iv(), gcm add aad(), etc.
OneShot Packet
To process a single packet under any given key the following helper
function can be used.
int gcm_memory(
const unsigned
unsigned
const unsigned
const unsigned
unsigned
unsigned
unsigned
int
char
long
char
char
char
char
char
int
cipher,
*key,
keylen,
*IV,
unsigned
*adata, unsigned
*pt,
unsigned
*ct,
*tag,
unsigned
direction);
long IVlen,
long adatalen,
long ptlen,
long *taglen,
This will initialize the GCM state with the given key, IV and AAD
value then proceed to encrypt or decrypt the message text and store
the final message tag. The definition of the variables is the same as it
is for all the manual functions.
If you are processing many packets under the same key you shouldnt
use this function as it invokes the precomputation with each call.
Example Usage
The following is an example usage of how to use GCM over multiple
packets with a shared secret key.
47
#include <tomcrypt.h>
int send_packet(const unsigned char *pt, unsigned long ptlen,
const unsigned char *iv, unsigned long ivlen,
const unsigned char *aad, unsigned long aadlen,
gcm_state
*gcm)
{
int
err;
unsigned long taglen;
unsigned char tag[16];
/* reset the state */
if ((err = gcm_reset(gcm)) != CRYPT_OK) {
return err;
}
/* Add the IV */
if ((err = gcm_add_iv(gcm, iv, ivlen)) != CRYPT_OK) {
return err;
}
/* Add the AAD (note: aad can be NULL if aadlen == 0) */
if ((err = gcm_add_aad(gcm, aad, aadlen)) != CRYPT_OK) {
return err;
}
/* process the plaintext */
if ((err =
gcm_process(gcm, pt, ptlen, pt, GCM_ENCRYPT)) != CRYPT_OK) {
return err;
}
/* Finish up and get the MAC tag */
taglen = sizeof(tag);
if ((err = gcm_done(gcm, tag, &taglen)) != CRYPT_OK) {
return err;
}
/* ... send a header describing the lengths ... */
/* depending on the protocol and how IV is
48
www.libtom.org
* generated you may have to send it too... */
send(socket, iv, ivlen, 0);
/* send the aad */
send(socket, aad, aadlen, 0);
/* send the ciphertext */
send(socket, pt, ptlen, 0);
/* send the tag */
send(socket, tag, taglen, 0);
return CRYPT_OK;
}
int main(void)
{
gcm_state
unsigned char
int
unsigned long
gcm;
key[16], IV[12], pt[PACKET_SIZE];
err, x;
ptlen;
49
}
}
if ((err = send_packet(pt, ptlen, iv, 12, NULL, 0, &gcm))
!= CRYPT_OK) {
whine_and_pout(err);
}
}
return EXIT_SUCCESS;
}
50
www.libtom.org
Chapter 4
One-Way Cryptographic
Hash Functions
4.1
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:
void XXX_init(hash_state *md);
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:
int XXX_process(
hash_state *md,
const unsigned char *in,
unsigned long inlen);
Essentially all hash messages are virtually infinitely1 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:
1 Most
51
52
www.libtom.org
4.2
53
Hash Descriptors
Like the set of ciphers, the set of hashes have descriptors as well. They
are stored in an array called hash descriptor and are defined by:
struct _hash_descriptor {
char *name;
unsigned long hashsize;
unsigned long blocksize;
void (*init)
(hash_state *hash);
int
(*process)(
hash_state *hash,
const unsigned char *in,
unsigned long inlen);
int
(*done)
int
(*test)
(void);
};
The name member is the name of the hash function (all lowercase).
The hashsize member is the size of the digest output in bytes, while
blocksize is the size of blocks the hash expects to the compression function. Technically, this detail is not important for high level developers
but is useful to know for performance reasons.
The init member initializes the hash, process passes data through
the hash, done terminates the hash and retrieves the digest. The test
member tests the hash against the specified test vectors.
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.
In addition, there is also find hash oid() which finds a hash by the
ASN.1 OBJECT IDENTIFIER string.
int find_hash_oid(const unsigned long *ID, unsigned long IDlen);
You can use the table to indirectly call a hash function that is
chosen at run-time. For example:
54
www.libtom.org
#include <tomcrypt.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;
}
55
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 to make working with hashes easier. The first is a function to hash a buffer, and produce the digest in
a single function call.
int hash_memory(
const unsigned
unsigned
unsigned
unsigned
int hash,
char *in,
long inlen,
char *out,
long *outlen);
This will hash the data pointed to by in of length inlen. The hash
used is indexed by the hash parameter. The message digest is stored
in out, and the outlen parameter is updated to hold the message digest
size.
The next helper function allows for the hashing of a file based on
a file name.
int hash_file(
int hash,
const char *fname,
unsigned char *out,
unsigned long *outlen);
This will hash the file named by fname using the hash indexed by
hash. The file named in this function call must be readable by the
user owning the process performing the request. This function can
be omitted by the LTC NO FILE define, which forces it to return
CRYPT NOP when it is called. The message digest is stored in out,
and the outlen parameter is updated to hold the message digest size.
int hash_filehandle(
int hash,
FILE *in,
unsigned char *out,
unsigned long *outlen);
This will hash the file identified by the handle in using the hash
indexed by hash. This will begin hashing from the current file pointer
56
www.libtom.org
position, and will not rewind the file pointer when finished. This
function can be omitted by the LTC NO FILE define, which forces
it to return CRYPT NOP when it is called. The message digest is
stored in out, and the outlen parameter is updated to hold the message
digest size.
To perform the above hash with md5 the following code could be
used:
#include <tomcrypt.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");
*/
4.2.1
Hash Registration
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:
int register_hash(const struct _hash_descriptor *hash);
57
Descriptor Name
whirlpool desc
sha512 desc
sha384 desc
rmd160 desc
sha256 desc
rmd160 desc
sha224 desc
tiger desc
sha1 desc
rmd160 desc
rmd128 desc
md5 desc
md4 desc
md2 desc
58
www.libtom.org
4.3
An addition to the suite of hash functions is the Cipher Hash Construction or CHC mode. In this mode applicable block ciphers (such
as AES) can be turned into hash functions that other LTC functions
can use. In particular this allows a cryptosystem to be designed using
very few moving parts.
In order to use the CHC system the developer will have to take a
few extra steps. First the chc desc hash descriptor must be registered
with register hash(). At this point the CHC hash cannot be used to
hash data. While it is in the hash system you still have to tell the CHC
code which cipher to use. This is accomplished via the chc register()
function.
int chc_register(int cipher);
A cipher has to be registered with CHC (and also in the cipher
descriptor tables with register cipher()). The chc register() function
will bind a cipher to the CHC system. Only one cipher can be bound
to the CHC hash at a time. There are additional requirements for the
system to work.
1. The cipher must have a block size greater than 64bits.
2. The cipher must allow an input key the size of the block size.
Example of using CHC with the AES block cipher.
#include <tomcrypt.h>
int main(void)
{
int err;
/* register cipher and hash */
if (register_cipher(&aes_enc_desc) == -1) {
printf("Could not register cipher\n");
return EXIT_FAILURE;
}
if (register_hash(&chc_desc) == -1) {
printf("Could not register hash\n");
4.4 Notice
59
return EXIT_FAILURE;
}
/* start chc with AES */
if ((err = chc_register(find_cipher("aes"))) != CRYPT_OK) {
printf("Error binding AES to CHC: %s\n",
error_to_string(err));
}
/* now you can use chc_hash in any LTC function
* [aside from pkcs...] */
}
4.4
Notice
It is highly recommended that you 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 SHA512, SHA-384 and SHA-256) and TIGER-192 are still considered secure for all purposes you would normally use a hash for.
60
www.libtom.org
Chapter 5
Message Authentication
Codes
5.1
HMAC Protocol
hmac_state *hmac,
int hash,
const unsigned char *key,
unsigned long keylen);
The hmac parameter is the state for the HMAC code. The hash pa61
62
www.libtom.org
rameter is the index into the descriptor table of the hash you want
to use to authenticate the message. The key parameter is the pointer
to the array of chars that make up the key. The keylen parameter 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:
int hmac_process(
hmac_state *hmac,
const unsigned char *in,
unsigned long inlen);
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 arbitrarily sized chunks. When you are finished with the HMAC
process you must call the following function to get the HMAC code:
int hmac_done(
hmac_state *hmac,
unsigned char *out,
unsigned long *outlen);
The hmac parameter is the HMAC state you are working with. The
out parameter 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 to do. 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.
int hmac_memory(
int hash,
const unsigned char *key, unsigned long keylen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
63
This will produce an HMAC code for the array of octets in in of length
inlen. 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 out and the length in outlen. The value
of outlen must be set to the size of the destination buffer before calling
this function. Similarly for files there is the following function:
int hmac_file(
int hash,
const char *fname,
const unsigned char *key, unsigned long keylen,
unsigned char *out, unsigned long *outlen);
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. out is the array of octets where the
result should be stored.
To test if the HMAC code is working there is the following function:
int hmac_test(void);
Which returns CRYPT OK if the code passes otherwise it returns an
error code. Some example code for using the HMAC system is given
below.
#include <tomcrypt.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 */
64
www.libtom.org
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;
5.2
OMAC Support
65
int omac_init(
omac_state *omac,
int cipher,
const unsigned char *key,
unsigned long keylen);
The omac parameter is the state for the OMAC algorithm. The cipher
parameter is the index into the cipher descriptor table of the cipher2
you wish to use. The key and keylen parameters are the keys used to
authenticate the data.
To send data through the algorithm call
int omac_process(
omac_state *state,
const unsigned char *in,
unsigned long inlen);
This will send inlen bytes from in through the active OMAC state
state. Returns CRYPT OK if the function succeeds. The function
is not sensitive to the granularity of the data. For example,
omac_process(&mystate, "hello", 5);
omac_process(&mystate, " world", 6);
Would produce the same result as,
omac_process(&mystate, "hello world",
11);
When you are done processing the message you can call the following to compute the message tag.
int omac_done(
omac_state *state,
unsigned char *out,
unsigned long *outlen);
Which will terminate the OMAC and output the 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
2 The cipher must have a 64 or 128 bit block size. Such as CAST5, Blowfish,
DES, AES, Twofish, etc.
66
www.libtom.org
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.
int omac_memory(
int cipher,
const unsigned char *key, unsigned long keylen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
This will compute the OMAC of inlen bytes of in 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
int omac_file(
int cipher,
const unsigned char *key,
unsigned long keylen,
const char *filename,
unsigned char *out,
unsigned long *outlen);
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:
int omac_test(void);
Which returns CRYPT OK if the code passes otherwise it returns an
error code. Some example code for using the OMAC system is given
below.
#include <tomcrypt.h>
int main(void)
67
{
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;
}
68
www.libtom.org
5.3
PMAC Support
pmac_state *pmac,
int cipher,
const unsigned char *key,
unsigned long keylen);
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.
int pmac_process(
pmac_state *state,
const unsigned char *in,
unsigned long inlen);
This will process inlen bytes of in in the given state. The function is
not sensitive to the granularity of the data. For example,
pmac_process(&mystate, "hello", 5);
pmac_process(&mystate, " world", 6);
Would produce the same result as,
pmac_process(&mystate, "hello world",
11);
When a complete message has been processed the following function can be called to compute the message tag.
int pmac_done(
pmac_state *state,
unsigned char *out,
unsigned long *outlen);
3 J.Black, P.Rogaway, A BlockCipher Mode of Operation for Parallelizable
Message Authentication
69
This will store up to 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 OMAC code the file and memory functions are also
provided. To PMAC a buffer of memory in one shot use the following
function.
int pmac_memory(
int cipher,
const unsigned char *key, unsigned long keylen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
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 pmac done().
To PMAC a file use
int pmac_file(
int cipher,
const unsigned char *key,
unsigned long keylen,
const char *filename,
unsigned char *out,
unsigned long *outlen);
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 pmac done().
To test if the PMAC code is working there is the following function:
int pmac_test(void);
Which returns CRYPT OK if the code passes otherwise it returns
an error code.
5.4
Pelican MAC
70
www.libtom.org
5.4.1
Example
#include <tomcrypt.h>
int main(void)
{
pelican_state pelstate;
unsigned char key[32], tag[16];
int
err;
/* somehow initialize a key */
/* initialize pelican mac */
if ((err = pelican_init(&pelstate, /* the state */
key,
/* user key */
32
/* key length in octets */
5.5 XCBC-MAC
71
)) != CRYPT_OK) {
printf("Error initializing Pelican: %s",
error_to_string(err));
return EXIT_FAILURE;
}
/* MAC some data */
if ((err = pelican_process(&pelstate,
/* the state */
"hello world",
/* data to mac */
11
/* length of data */
)) != CRYPT_OK) {
printf("Error processing Pelican: %s",
error_to_string(err));
return EXIT_FAILURE;
}
/* Terminate the MAC */
if ((err = pelican_done(&pelstate,/* the state */
tag
/* where to store the tag */
)) != CRYPT_OK) {
printf("Error terminating Pelican: %s",
error_to_string(err));
return EXIT_FAILURE;
}
/* tag[0..15] has the MAC output now */
return EXIT_SUCCESS;
}
5.5
XCBC-MAC
72
www.libtom.org
function:
int xcbc_init(
xcbc_state *xcbc,
int cipher,
const unsigned char *key,
unsigned long keylen);
This will initialize the XCBCMAC state xcbc, with the key specified in key of length keylen octets. The cipher indicated by the cipher
index can be either a 64 or 128bit block cipher. This will return
CRYPT OK on success.
To process data through XCBCMAC use the following function:
int xcbc_process(
xcbc_state *state,
const unsigned char *in,
unsigned long inlen);
This will add the message octets pointed to by in of length inlen
to the XCBCMAC state pointed to by state. Like the other MAC
functions, the granularity of the input is not important but the order
is. This will return CRYPT OK on success.
To compute the MAC tag value use the following function:
int xcbc_done(
xcbc_state *state,
unsigned char *out,
unsigned long *outlen);
This will retrieve the XCBCMAC tag from the state pointed to by
state, and store it in the array pointed to by out. The outlen parameter
specifies the maximum size of the destination buffer, and is updated
to hold the final size of the tag when the function returns. This will
return CRYPT OK on success.
Helper functions are provided to make parsing memory buffers and
files easier. The following functions are provided:
int xcbc_memory(
int cipher,
const unsigned char *key, unsigned long keylen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
5.6 F9MAC
73
5.6
F9MAC
5.6.1
Usage Notice
F9MAC differs slightly from the other MAC functions in that it requires the caller to perform the final message padding. The padding
quite simply is a direction bit followed by a 1 bit and enough zeros
to make the message a multiple of the cipher block size. If the message is byte aligned, the padding takes on the form of a single 0x40 or
74
www.libtom.org
0xC0 byte followed by enough 0x00 bytes to make the message proper
multiple.
If the user simply wants a MAC function (hint: use OMAC) padding
with a single 0x40 byte should be sufficient for security purposes and
still be reasonably compatible with F9MAC.
5.6.2
F9MAC Functions
f9_state *f9,
int cipher,
const unsigned char *key,
unsigned long keylen);
This will initialize the F9MAC state f9, with the key specified
in key of length keylen octets. The cipher indicated by the cipher
index can be either a 64 or 128bit block cipher. This will return
CRYPT OK on success.
To process data through F9MAC use the following function:
int f9_process(
f9_state *state,
const unsigned char *in,
unsigned long inlen);
This will add the message octets pointed to by in of length inlen to
the F9MAC state pointed to by state. Like the other MAC functions,
the granularity of the input is not important but the order is. This
will return CRYPT OK on success.
To compute the MAC tag value use the following function:
int f9_done(
f9_state *state,
unsigned char *out,
unsigned long *outlen);
This will retrieve the F9MAC tag from the state pointed to by
state, and store it in the array pointed to by out. The outlen parameter
specifies the maximum size of the destination buffer, and is updated
to hold the final size of the tag when the function returns. This will
return CRYPT OK on success.
5.6 F9MAC
75
76
www.libtom.org
Chapter 6
Pseudo-Random
Number Generators
6.1
Core Functions
78
www.libtom.org
79
6.1.1
Remarks
6.1.2
Example
80
www.libtom.org
#include <tomcrypt.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, sizeof(buf), &prng));
return 0;
}
6.2
PRNG Descriptors
PRNGs have descriptors that allow plugin driven functions to be created using PRNGs. The plugin descriptors are stored in the structure
prng descriptor. The format of an element is:
struct _prng_descriptor {
char *name;
int export_size;
/* size in bytes of exported state */
int (*start)
(prng_state *);
81
prng_state *);
int (*ready)
(prng_state *);
82
www.libtom.org
Name
Yarrow
Fortuna
RC4
SOBER-128
Descriptor
yarrow desc
fortuna desc
rc4 desc
sober128 desc
Usage
Fast short-term PRNG
Fast long-term PRNG (recommended)
Stream Cipher
Stream Cipher (also very fast PRNG)
6.2.1
PRNGs Provided
Yarrow
Yarrow is fast PRNG meant to collect an unspecified amount of entropy from sources (keyboard, mouse, interrupts, etc), and produce an
unbounded string of random bytes.
Note: This PRNG is still secure for most tasks but is no longer
recommended. Users should use Fortuna instead.
Fortuna
Fortuna is a fast attack tolerant and more thoroughly designed PRNG
suitable for long term usage. It is faster than the default implementation of Yarrow1 while providing more security.
Fortuna is slightly less flexible than Yarrow in the sense that it
only works with the AES block cipher and SHA256 hash function.
Technically, Fortuna will work with any block cipher that accepts a
256bit key, and any hash that produces at least a 256bit output.
However, to make the implementation simpler it has been fixed to
those choices.
Fortuna is more secure than Yarrow in the sense that attackers
who learn parts of the entropy being added to the PRNG learn far less
about the state than that of Yarrow. Without getting into to many
details Fortuna has the ability to recover from state determination
attacks where the attacker starts to learn information from the PRNGs
output about the internal state. Yarrow on the other hand, cannot
1 Yarrow has been implemented to work with most cipher and hash combos
based on which you have chosen to build into the library.
83
recover from that problem until new entropy is added to the pool and
put to use through the ready() function.
RC4
RC4 is an old stream cipher that can also double duty as a PRNG in
a pinch. You key RC4 by calling add entropy(), and setup the key by
calling ready(). You can only add up to 256 bytes via add entropy().
When you read from RC4, the output is XORed against your buffer
you provide. In this manner, you can use rc4 read() as an encrypt (and
decrypt) function.
You really should not use RC4. This is not because RC4 is weak,
(though biases are known to exist) but simply due to the fact that
faster alternatives exist.
SOBER-128
SOBER128 is a stream cipher designed by the QUALCOMM Australia team. Like RC4, you key it by calling add entropy(). There is
no need to call ready() for this PRNG as it does not do anything.
Note: this cipher has several oddities about how it operates. The
first call to add entropy() sets the ciphers key. Every other time call
to the add entropy() function sets the ciphers IV variable. The IV
mechanism allows you to encrypt several messages with the same key,
and not reuse the same key material.
Unlike Yarrow and Fortuna, all of the entropy (and hence security)
of this algorithm rests in the data you pass it on the first call to
add entropy(). All buffers sent to add entropy() must have a length
that is a multiple of four bytes.
Like RC4, the output of SOBER128 is XORed against the buffer
you provide it. In this manner, you can use sober128 read() as an
encrypt (and decrypt) function.
Since SOBER-128 has a fixed keying scheme, and is very fast (faster
than RC4) the ideal usage of SOBER-128 is to key it from the output
of Fortuna (or Yarrow), and use it to encrypt messages. It is also ideal
for simulations which need a high quality (and fast) stream of bytes.
84
www.libtom.org
Example Usage
#include <tomcrypt.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;
}
6.3
85
int bits,
int wprng,
prng_state *prng,
void (*callback)(void));
This will try to initialize 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 does not work
well. Example usage of this function is given below:
2 This device is available in Windows through the Cygwin compiler suite. It
emulates /dev/random via the Microsoft CSP.
86
www.libtom.org
#include <tomcrypt.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;
}
6.3.1
87
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;
}
88
www.libtom.org
Chapter 7
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 the v1.5 and v2.1
algorithms. To simplify matters a little the v2.1 encryption and signature padding algorithms are called OAEP and PSS respectively.
7.2
PKCS #1 Padding
PKCS #1 v1.5 padding is so simple that both signature and encryption padding are performed by the same function. Note: the signature
padding does not include the ASN.1 padding required. That is performed by the rsa sign hash ex() function documented later on in this
chapter.
7.2.1
90
www.libtom.org
int pkcs_1_v1_5_encode(
const unsigned char
unsigned long
int
unsigned long
prng_state
int
unsigned char
unsigned long
*msg,
msglen,
block_type,
modulus_bitlen,
*prng,
prng_idx,
*out,
*outlen);
7.2.2
*msg,
msglen,
block_type,
modulus_bitlen,
*out,
*outlen,
*is_valid);
This will remove the PKCS padding data pointed to by msg of length
msglen. The decoded data is stored in out of length outlen. If the
padding is valid, a 1 is stored in is valid, otherwise, a 0 is stored. The
block type parameter must be set to either LTC PKCS 1 EME or
LTC PKCS 1 EMSA depending on whether encryption or signature padding is being removed.
7.3
91
7.3.1
OAEP Encoding
*msg,
msglen,
*lparam,
lparamlen,
modulus_bitlen,
*prng,
prng_idx,
hash_idx,
*out,
*outlen);
92
www.libtom.org
For example, with a 1024bit RSA key and SHA1 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.
7.3.2
OAEP Decoding
int pkcs_1_oaep_decode(
const unsigned char
unsigned long
const unsigned char
unsigned long
unsigned long
int
unsigned char
unsigned long
int
*msg,
msglen,
*lparam,
lparamlen,
modulus_bitlen,
hash_idx,
*out,
*outlen,
*res);
7.4
7.4.1
93
*msghash,
msghashlen,
saltlen,
*prng,
prng_idx,
hash_idx,
modulus_bitlen,
*out,
*outlen);
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().
7.4.2
PSS Decoding
To decode a PSS encoded signature block you have to use the following.
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);
94
www.libtom.org
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 nonzero. Otherwise, it is set to zero. The rest of the
parameters are as in the PSS encode call.
Its important to use the same saltlen and hash for both encoding
and decoding as otherwise the procedure will not work.
7.5
7.5.1
95
7.5.2
For RSA routines a single rsa key structure is used. To make a new
RSA key call:
int rsa_make_key(prng_state
int
int
long
rsa_key
*prng,
wprng,
size,
e,
*key);
Where wprng is the index into the PRNG descriptor array. The
size parameter is the size in bytes of the RSA modulus desired. The
e parameter is the encryption exponent desired, typical values are 3,
17, 257 and 65537. Stick with 65537 since it is big enough to prevent
trivial math attacks, and not super slow. The key parameter is where
the constructed key is placed. All keys must be at least 128 bytes, and
no more than 512 bytes in size (that is from 1024 to 4096 bits).
Note: 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 memory allocated.
There are two types of RSA keys. The types are PK PRIVATE
and PK PUBLIC. The first type is a private RSA key which includes
the CRT parameters1 in the form of a RSAPrivateKey (PKCS #1 compliant). The second type, is a public RSA key which only includes the
1 As of v0.99 the PK PRIVATE OPTIMIZED type has been deprecated, and
has been replaced by the PK PRIVATE type.
96
www.libtom.org
7.5.3
RSA Exponentiation
To do raw work with the RSA function, that is without padding, use
the following function:
int rsa_exptmod(const unsigned
unsigned
unsigned
unsigned
char
long
char
long
int
rsa_key
*in,
inlen,
*out,
*outlen,
which,
*key);
This will load the bignum from in as a big endian integer in the format
PKCS #1 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 PK PUBLIC
to use e (i.e. for encryption/verifying) and set to PK PRIVATE to
use d as the exponent (i.e. for decrypting/signing).
Note: the output of this function is zeropadded as per PKCS #1
specification. This allows this routine to work with PKCS #1 padding
functions properly.
7.6
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.
int rsa_encrypt_key(
const unsigned char
unsigned long
unsigned char
unsigned long
const unsigned char
unsigned long
prng_state
*in,
inlen,
*out,
*outlen,
*lparam,
lparamlen,
*prng,
97
int prng_idx,
int hash_idx,
rsa_key *key);
This function will OAEP pad in of length inlen bytes, RSA encrypt it,
and store the ciphertext in out of length outlen octets. The lparam and
lparamlen are the same parameters you would pass to pkcs 1 oaep encode().
7.6.1
Extended Encryption
As of v1.15, the library supports both v1.5 and v2.1 PKCS #1 style
paddings in these higher level functions. The following is the extended
encryption function:
int rsa_encrypt_key_ex(
const unsigned char
unsigned long
unsigned char
unsigned long
const unsigned char
unsigned long
prng_state
int
int
int
rsa_key
*in,
inlen,
*out,
*outlen,
*lparam,
lparamlen,
*prng,
prng_idx,
hash_idx,
padding,
*key);
The parameters are all the same as for rsa encrypt key() except for
the addition of the padding parameter. It must be set to LTC PKCS 1 V1 5
to perform v1.5 encryption, or set to LTC PKCS 1 OAEP to perform v2.1 encryption.
When performing v1.5 encryption, the hash and lparam parameters
are totally ignored and can be set to NULL or zero (respectively).
7.7
int rsa_decrypt_key(
const unsigned char *in,
98
www.libtom.org
unsigned
unsigned
unsigned
const unsigned
unsigned
long
char
long
char
long
int
int
rsa_key
inlen,
*out,
*outlen,
*lparam,
lparamlen,
hash_idx,
*stat,
*key);
This function will RSA decrypt in of length inlen then OAEP depad the resulting data and store it in out of length outlen. The
lparam and lparamlen are the same parameters you would pass to
pkcs 1 oaep decode().
If the RSA decrypted data is not a valid OAEP packet then stat
is set to 0. Otherwise, it is set to 1.
7.7.1
Extended Decryption
As of v1.15, the library supports both v1.5 and v2.1 PKCS #1 style
paddings in these higher level functions. The following is the extended
decryption function:
int rsa_decrypt_key_ex(
const unsigned char
unsigned long
unsigned char
unsigned long
const unsigned char
unsigned long
int
int
int
rsa_key
*in,
inlen,
*out,
*outlen,
*lparam,
lparamlen,
hash_idx,
padding,
*stat,
*key);
7.8
99
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.
int rsa_sign_hash(const unsigned char
unsigned long
unsigned char
unsigned long
prng_state
int
int
unsigned long
rsa_key
*in,
inlen,
*out,
*outlen,
*prng,
prng_idx,
hash_idx,
saltlen,
*key);
7.8.1
Extended Signatures
As of v1.15, the library supports both v1.5 and v2.1 signatures. The
extended signature generation function has the following prototype:
int rsa_sign_hash_ex(
const unsigned char *in,
unsigned long inlen,
unsigned char *out,
unsigned long *outlen,
int padding,
100
www.libtom.org
prng_state
*prng,
int prng_idx,
int hash_idx,
unsigned long saltlen,
rsa_key *key);
7.9
char
long
char
long
int
unsigned long
int
rsa_key
*sig,
siglen,
*msghash,
msghashlen,
hash_idx,
saltlen,
*stat,
*key);
This will RSA verify the signature pointed to by sig of length siglen
octets. Next, the RSA decoded data is PSS decoded and the extracted
hash is compared against the message digest pointed to by msghash
of length msghashlen octets.
If the RSA decoded data is not a valid PSS message, or if the
PSS decoded hash does not match the msghash value, res is set to 0.
Otherwise, if the function succeeds, and signature is valid res is set to
1.
7.9.1
101
Extended Verification
As of v1.15, the library supports both v1.5 and v2.1 signature verification. The extended signature verification function has the following
prototype:
int rsa_verify_hash_ex(
const unsigned char
unsigned long
const unsigned char
unsigned long
int
int
unsigned long
int
rsa_key
*sig,
siglen,
*hash,
hashlen,
padding,
hash_idx,
saltlen,
*stat,
*key);
7.10
#include <tomcrypt.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;
102
www.libtom.org
/* register prng/hash */
if (register_prng(&sprng_desc) == -1) {
printf("Error registering sprng");
return EXIT_FAILURE;
}
/* register a math library (in this case TomsFastMath)
ltc_mp = tfm_desc;
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) {
103
7.11
The RSA key format adopted for exporting and importing keys is the
PKCS #1 format defined by the ASN.1 constructs known as RSAPublicKey and RSAPrivateKey. Additionally, the OpenSSL key format is
supported by the import function only.
7.11.1
104
www.libtom.org
7.11.2
Chapter 8
Elliptic Curve
Cryptography
8.1
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 2192 (which would represent a 192-bit key)
then the work factor is 296 in order to find the secret key.
The curves in this library are taken from the following website:
http://csrc.nist.gov/cryptval/dss.htm
As of v1.15 three new curves from the SECG standards are also included they are the secp112r1, secp128r1, and secp160r1 curves. These
curves were added to support smaller devices which do not need as
large keys for security.
They are all curves over the integers modulo a prime. The curves
have the basic equation that is:
y 2 = x3 3x + b (mod p)
105
(8.1)
106
www.libtom.org
8.2
As of v1.12 of LibTomCrypt, support for Fixed Point ECC point multiplication has been added. It is a generic optimization that is supported
by any conforming math plugin. It is enabled by defining MECC FP
during the build, such as
CFLAGS="-DTFM_DESC -DMECC_FP" make
which will build LTC using the TFM math library and enabling
this new feature. The feature is not enabled by default as it is NOT
thread safe (by default). It supports the LTC locking macros (such as
by enabling LTC PTHREAD), but by default is not locked.
The optimization works by using a Fixed Point multiplier on any
base point you use twice or more in a short period of time. It has
a limited size cache (of FP ENTRIES entries) which it uses to hold
recent bases passed to ltc ecc mulmod(). Any base detected to be used
twice is sent through the precomputation phase, and then the fixed
point algorithm can be used. For example, if you use a NIST base
point twice in a row, the 2nd and all subsequent point multiplications
with that point will use the faster algorithm.
The optimization uses a window on the multiplicand of FP LUT
bits (default: 8, min: 2, max: 12), and this controls the memory/time
trade-off. The larger the value the faster the algorithm will be but
the more memory it will take. The memory usage is 3 2F P LUT integers which by default with TFM amounts to about 400kB of memory.
Tuning TFM (by changing FP SIZE) can decrease the usage by a fair
amount. Memory is only used by a cache entry if it is active. Both
FP ENTRIES and FP LUT are definable on the command line if you
wish to override them. For instance,
CFLAGS="-DTFM_DESC -DMECC_FP -DFP_ENTRIES=8 -DFP_LUT=6" make
107
8.3
Key Format
LibTomCrypt uses a unique format for ECC public and private keys.
While ANSI X9.63 partially specifies key formats, it does it in a less
than ideally simple manner. In the case of LibTomCrypt, it is meant
solely for NIST and SECG GF (p) curves. The format of the keys is
as follows:
ECCPublicKey ::= SEQUENCE {
flags
BIT STRING(0), -- public/private flag (always zero),
keySize
INTEGER,
-- Curve size (in bits) divided by eight
-- and rounded down, e.g. 521 => 65
pubkey.x
INTEGER,
-- The X co-ordinate of the public key point
pubkey.y
INTEGER,
-- The Y co-ordinate of the public key point
}
ECCPrivateKey ::= SEQUENCE {
flags
BIT STRING(1), -- public/private flag (always one),
keySize
INTEGER,
-- Curve size (in bits) divided by eight
-- and rounded down, e.g. 521 => 65
pubkey.x
INTEGER,
-- The X co-ordinate of the public key point
pubkey.y
INTEGER,
-- The Y co-ordinate of the public key point
secret.k
INTEGER,
-- The secret key scalar
}
The first flags bit denotes whether the key is public (zero) or private
(one).
108
www.libtom.org
8.4
8.5
8.5.1
Core Functions
ECC Key Generation
There is a key structure called ecc key used by the ECC functions.
There is a function to make a key:
109
*prng,
wprng,
keysize,
*key);
8.5.2
ecc_make_key_ex(
prng_state
int
ecc_key
const ltc_ecc_set_type
*prng,
wprng,
*key,
*dp);
This function generates a random ECC key over the curve specified
by the parameters by dp. The rest of the parameters are equivalent to
those from the original key generation function.
8.5.3
To free the memory allocated by a ecc make key(), ecc make key ex(),
ecc import(), or ecc import ex() call use the following function:
void ecc_free(ecc_key *key);
8.5.4
To export an ECC key using the LibTomCrypt format call the following function:
110
www.libtom.org
8.5.5
8.5.6
*in,
inlen,
*key,
*dp);
This will import the key from the array pointed to by in of length
inlen octets. The key is stored in the ECC structure pointed to by
key. The curve is specified by the parameters pointed to by dp. The
function will free all internally allocated memory upon error.
8.5.7
The following function exports an ECC public key in the ANSI X9.63
format:
111
int ecc_ansi_x963_export(
ecc_key *key,
unsigned char *out,
unsigned long *outlen);
The ECC key pointed to by key is exported in public fashion to the
array pointed to by out. The ANSI X9.63 format used is from section
4.3.6 of the standard. It does not allow for the export of private keys.
8.5.8
8.5.9
*in,
inlen,
*key,
*dp);
This will import the key stored in the array pointed to by in of length
inlen octets using the domain parameters pointed to by dp. The imported key is stored in the ECC key pointed to by key. The function
will free any allocated memory upon error.
8.5.10
112
www.libtom.org
int ecc_shared_secret(
ecc_key
ecc_key
unsigned char
unsigned long
*private_key,
*public_key,
*out,
*outlen);
The private key is typically the local private key, and public key is the
key the remote party has shared. Note: this function stores only the
x co-ordinate of the shared elliptic point as described in ANSI X9.63
ECCDH.
8.6
ECCDH Encryption is performed by producing a random key, hashing it, and XORing the digest against the plaintext. It is not strictly
ANSI X9.63 compliant but it is very similar. It has been extended by
using an ASN.1 sequence and hash object identifiers to allow portable
usage. The following function encrypts a short string (no longer than
the message digest) using this technique:
8.6.1
ECC-DH Encryption
*in,
inlen,
*out,
*outlen,
*prng,
wprng,
hash,
*key);
113
The data is encrypted to the public ECC key such that only the
holder of the private key can decrypt the payload. To have multiple
recipients multiple call to this function for each public ECC key is
required.
8.6.2
ECC-DH Decryption
*in,
inlen,
*out,
*outlen,
*key);
This function will decrypt an encrypted payload. The key provided must be the private key corresponding to the public key used
during encryption. If the wrong key is provided the function will not
specifically return an error code. It is important to use some form
of challenge response in that case (e.g. compute a MAC of a known
string).
8.6.3
The packet format for the encrypted keys is the following ASN.1 SEQUENCE:
ECCEncrypt ::= SEQUENCE {
hashID
OBJECT IDENTIFIER, -- OID of hash used
pubkey
OCTET STRING
, -- Encapsulated ECCPublicKey
skey
OCTET STRING
-- xor of plaintext and
--"hash of shared secret"
}
8.7
EC DSA Signatures
There are also functions to sign and verify messages. They use the
ANSI X9.62 EC-DSA algorithm to generate and verify signatures in
the ANSI X9.62 format.
114
8.7.1
www.libtom.org
*in,
inlen,
*out,
*outlen,
*prng,
wprng,
*key);
This function will ECDSA sign the message digest stored in the
array pointed to by in of length inlen octets. The signature will be
stored in the array pointed to by out of length outlen octets. The
function requires a properly seeded PRNG, and the ECC key provided
must be a private key.
8.7.2
char
long
char
long
int
ecc_key
*sig,
siglen,
*hash,
hashlen,
*stat,
*key);
This function will verify the EC-DSA signature in the array pointed
to by sig of length siglen octets, against the message digest pointed
to by the array hash of length hashlen. It will store a nonzero value
in stat if the signature is valid. Note: the function will not return an
error if the signature is invalid. It will return an error, if the actual
signature payload is an invalid format. The ECC key must be the
public (or private) ECC key corresponding to the key that performed
the signature.
8.7.3
Signature Format
8.8
115
ECC Keysizes
With ECC if you try to 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 an ECC-192 key,
you in effect have 96bits of security.
The library will not warn you if you make this mistake, so it is
important to check yourself before using the signatures.
116
www.libtom.org
Chapter 9
Digital Signature
Algorithm
9.1
Introduction
9.2
Key Format
Since no useful public standard for DSA key storage was presented
to me during the course of this development I made my own ASN.1
SEQUENCE which I document now so that others can interoperate
with this library.
DSAPublicKey ::= SEQUENCE {
publicFlags
BIT STRING(0), -- must be 0
g
INTEGER
, -- base generator
117
118
www.libtom.org
p
q
INTEGER
INTEGER
INTEGER
}
DSAPrivateKey ::= SEQUENCE {
publicFlags
BIT STRING(1), -- must be 1
g
INTEGER
, -- base generator
-- check that g^q mod p == 1
-- and that 1 < g < p - 1
p
INTEGER
, -- prime modulus
q
INTEGER
, -- order of sub-group
-- (must be prime)
y
INTEGER
, -- public key, specifically,
-- g^x mod p,
-- check that y^q mod p == 1
-- and that 1 < y < p - 1
x
INTEGER
-- private key
}
The leading BIT STRING has a single bit in it which is zero for
public keys and one for private keys. This makes the structure uniquely
decodable, and easy to work with.
9.3
Key Generation
*prng,
wprng,
group_size,
modulus_size,
119
dsa_key *key);
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.
Bits of Security
80
120
140
160
group size
20
30
35
40
modulus size
128
256
384
512
9.4
Key Verification
size
size
where r is
120
www.libtom.org
1. q must be prime.
2. p must be prime.
3. g cannot be one of {1, 0, 1} (modulo p).
4. g must be less than p.
5. (p 1) 0 (mod q).
6. g q 1 (mod p).
7. 1 < y < p 1
8. y q 1 (mod p).
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/pZ. 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.
int dsa_verify_key(dsa_key *key, int *stat);
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).
9.5
9.5.1
Signatures
Signature Generation
121
*in,
inlen,
*out,
*outlen,
*prng,
wprng,
*key);
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
PK PRIVATE persuasion.
9.5.2
Signature Verification
To verify a hash created with that function use the following function:
int dsa_verify_hash(const unsigned
unsigned
const unsigned
unsigned
char
long
char
long
int
dsa_key
*sig,
siglen,
*hash,
inlen,
*stat,
*key);
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.
9.6
As of version 1.07, the DSA keys can be used to encrypt and decrypt
small payloads. It works similar to the ECC encryption where a shared
key is computed, and the hash of the shared key XORed against the
plaintext forms the ciphertext. The format used is functional port of
the ECC encryption format to the DSA algorithm.
122
9.6.1
www.libtom.org
DSA Encryption
*in,
inlen,
*out,
*outlen,
*prng,
wprng,
hash,
*key);
This will encrypt the payload in in of length inlen and store the
ciphertext in the output buffer out. The length of the ciphertext outlen
must be originally set to the length of the output buffer. The DSA
key can be a public key.
9.6.2
DSA Decryption
*in,
inlen,
*out,
*outlen,
*key);
This will decrypt the ciphertext in of length inlen, and store the original payload in out of length outlen. The DSA key must be a private
key.
9.7
9.7.1
123
9.7.2
124
www.libtom.org
Chapter 10
Standards Support
10.1
ASN.1 Formats
type;
*data;
size;
used;
*prev, *next,
*child, *parent;
} ltc_asn1_list;
125
126
www.libtom.org
The type field is one of the following ASN.1 field definitions. The
data pointer is a void pointer to the data to be encoded (or the destination) and the size field is specific to what you are encoding (e.g.
number of bits in the BIT STRING data type). The used field is primarily for the CHOICE decoder and reflects if the particular member
of a list was the decoded data type. To help build the lists in an orderly fashion the macro LTC SET ASN1(list, index, Type, Data, Size)
has been provided.
It will assign to the index th position in the list the triplet (Type,
Data, Size). An example usage would be:
...
ltc_asn1_list
unsigned long
sequence[3];
three=3;
LTC_SET_ASN1(sequence, 0, LTC_ASN1_IA5_STRING,
"hello", 5);
LTC_SET_ASN1(sequence, 1, LTC_ASN1_SHORT_INTEGER, &three, 1);
LTC_SET_ASN1(sequence, 2, LTC_ASN1_NULL,
NULL,
0);
10.1.1
SEQUENCE Type
127
ASN.1 Type
End of a ASN.1 list structure.
BOOLEAN type
INTEGER (uses mp int)
INTEGER (32bit using unsigned long)
BIT STRING (one bit per char)
OCTET STRING (one octet per char)
NULL
OBJECT IDENTIFIER
IA5 STRING (one octet per char)
UTF8 STRING (one wchar t per char)
PRINTABLE STRING (one octet per char)
UTCTIME (see ltc utctime structure)
SEQUENCE (and SEQUENCE OF)
SET
SET OF
CHOICE
int der_encode_sequence(ltc_asn1_list
unsigned long
unsigned char
unsigned long
*list,
inlen,
*out,
*outlen);
This encodes a sequence of items pointed to by list where the list has
inlen items in it. The SEQUENCE will be encoded to out and of
length outlen. The function will terminate when it reads all the items
out of the list (upto inlen) or it encounters an item in the list with a
type of LTC ASN1 EOL.
The data pointer in the list would be the same pointer you would
pass to the respective ASN.1 encoder (e.g. der encode bit string())
and it is simply passed on verbatim to the dependent encoder. The
list can contain other SEQUENCE or SET types which enables you
to have nested SEQUENCE and SET definitions. In these cases the
data pointer is simply a pointer to another ltc asn1 list.
128
www.libtom.org
SEQUENCE Decoding
Decoding a SEQUENCE is similar to encoding. You set up an array
of ltc asn1 list where in this case the size member is the maximum
size (in certain cases). For types such as IA5 STRING, BIT STRING,
OCTET STRING (etc) the size field is updated after successful decoding to reflect how many units of the respective type has been loaded.
int der_decode_sequence(const unsigned char
unsigned long
ltc_asn1_list
unsigned long
*in,
inlen,
*list,
outlen);
This will decode upto outlen items from the input buffer in of
length inlen octets. The function will stop (gracefully) when it runs
out of items to decode. It will fail (for among other reasons) when it
runs out of input bytes to read, a data type is invalid or a heap failure
occurred.
For the following types the size field will be updated to reflect the
number of units read of the given type.
1. BIT STRING
2. OCTET STRING
3. OBJECT IDENTIFIER
4. IA5 STRING
5. PRINTABLE STRING
SEQUENCE Length
The length of a SEQUENCE can be determined with the following
function.
int der_length_sequence(ltc_asn1_list *list,
unsigned long inlen,
unsigned long *outlen);
This will get the encoding size for the given list of length inlen and
store it in outlen.
129
130
www.libtom.org
the numbers as the required unsigned long type that the function
expects.
10.1.2
SET and SET OF are related to the SEQUENCE type in that they
can be pretty much be decoded with the same code. However, they
are different, and they should be carefully noted. The SET type is an
unordered array of ASN.1 types sorted by the TAG (type identifier),
whereas the SET OF type is an ordered array of a single ASN.1 object
sorted in ascending order by the DER their respective encodings.
SET Encoding
SETs use the same array structure of ltc asn1 list that the SEQUENCE
functions use. They are encoded with the following function:
int der_encode_set(ltc_asn1_list
unsigned long
unsigned char
unsigned long
*list,
inlen,
*out,
*outlen);
This will encode the list of ASN.1 objects in list of length inlen
objects, and store the output in out of length outlen bytes. The function will make a copy of the list provided, and sort it by the TAG.
Objects with identical TAGs are additionally sorted on their original
placement in the array (to make the process deterministic).
This function will NOT recognize DEFAULT objects, and it is the
responsibility of the caller to remove them as required.
SET Decoding
The SET type can be decoded with the following function.
int der_decode_set(const unsigned char
unsigned long
ltc_asn1_list
unsigned long
*in,
inlen,
*list,
outlen);
131
This will decode the SET specified by list of length outlen objects
from the input buffer in of length inlen octets.
It handles the fact that SETs are not strictly ordered and will make
multiple passes (as required) through the list to decode all the objects.
SET Length
The length of a SET can be determined by calling der length sequence()
since they have the same encoding length.
SET OF Encoding
A SET OF object is an array of identical objects (e.g. OCTET
STRING) sorted in ascending order by the DER encoding of the object. They are used to store objects deterministically based solely on
their encoding. It uses the same array structure of ltc asn1 list that
the SEQUENCE functions use. They are encoded with the following
function.
int der_encode_setof(ltc_asn1_list
unsigned long
unsigned char
unsigned long
*list,
inlen,
*out,
*outlen);
This will encode a SET OF containing the list of inlen ASN.1 objects and store the encoding in the output buffer out of length outlen.
The routine will first encode the SET OF in an unordered fashion (in a temporary buffer) then sort using the XQSORT macro and
copy back to the output buffer. This means you need at least enough
memory to keep an additional copy of the output on the heap.
SET OF Decoding
Since the decoding of a SET OF object is unambiguous it can be
decoded with der decode sequence().
SET OF Length
Like the SET type the der length sequence() function can be used to
determine the length of a SET OF object.
132
10.1.3
www.libtom.org
ASN.1 INTEGER
10.1.4
133
unsigned long inlen,
unsigned char *out,
unsigned long *outlen);
char *in,
long inlen,
char *out,
long *outlen);
10.1.5
char *in,
long inlen,
char *out,
long *outlen);
char *in,
long inlen,
char *out,
long *outlen);
10.1.6
134
www.libtom.org
unsigned long *outlen);
char *in,
long inlen,
long *words,
long *outlen);
10.1.7
char *in,
long inlen,
char *out,
long *outlen);
char *in,
long inlen,
char *out,
long *outlen);
10.1.8
135
char *in,
long inlen,
char *out,
long *outlen);
char *in,
long inlen,
char *out,
long *outlen);
10.1.9
136
www.libtom.org
unsigned long noctets,
unsigned long *outlen);
10.1.10
ASN.1 UTCTIME
137
unsigned long *inlen,
ltc_utctime *out);
10.1.11
ASN.1 CHOICE
*in,
*inlen,
*list,
outlen);
This will decode the input in the in field of length inlen. It uses the
provided ASN.1 list specified in the list field which has outlen elements.
The inlen field will be updated with the length of the decoded data
type, as well as the respective entry in the list field will have the used
flag set to nonzero to reflect it was the data type decoded.
1 Except
it
cannot
have
LTC ASN1 INTEGER
LTC ASN1 SHORT INTEGER simultaneously.
and
138
www.libtom.org
10.1.12
This will decode items in the in buffer of max input length inlen
and store the newly created pointer to the list in out. This function
allocates all required memory for the decoding. It stores the number
of octets read back into inlen.
The function will terminate when either it hits an invalid ASN.1
tag, or it reads inlen octets. An early termination is a soft error,
and returns normally. The decoded list out will point to the very first
element of the list (e.g. both parent and prev pointers will be NULL).
An invalid decoding will terminate the process, and free the allocated memory automatically.
Note: the list decoded by this function is NOT in the correct
form for der encode sequence() to use directly. You will have to first
have to convert the list by first storing all of the siblings in an array
then storing all the children as sub-lists of a sequence using the .data
pointer. Currently no function in LibTomCrypt provides this ability.
Sample Decoding
Suppose we decode the following structure:
139
inbuf[MAXSIZE];
inbuflen;
*list;
err;
Now list points to the Name member (with the tag IA5 STRING).
The data, size, and type members of list should reflect that of an IA5
STRING. The sibbling will now be the LoginToken SEQUENCE. The
sibbling has a child node which points to the passwdHash OCTET
STRING. We can walk to this node with the following code:
/* list already pointing to Name */
list = list->next->child;
At this point, list will point to the passwdHash member of the innermost SEQUENCE. This node has a sibbling, the pubkey member of
the SEQUENCE. The LastOn member of the SEQUENCE is a sibbling of the LoginToken node, if we wanted to walk there we would
have to go up and over via:
140
www.libtom.org
list = list->parent->next;
At this point, we are pointing to the last node of the list. Lists are
terminated in all directions by a NULL pointer. All nodes are doubly
linked so that you can walk up and down the nodes without keeping
pointers lying around.
Freeing a Flexi List
To free the list use the following function.
void der_sequence_free(ltc_asn1_list *in);
This will free all of the memory allocated by der decode sequence flexi().
10.2
10.2.1
PKCS #5
10.2.2
Algorithm One
141
int hash_idx,
unsigned char *out,
unsigned long *outlen)
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 8byte 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 up to 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.
10.2.3
Algorithm Two
char
long
char
long
int
int
unsigned char
unsigned long
*password,
password_len,
*salt,
salt_len,
iteration_count,
hash_idx,
*out,
*outlen)
142
www.libtom.org
Chapter 11
Miscellaneous
11.1
The library provides functions to encode and decode a RFC 1521 base
64 coding scheme. The characters used in the mappings are:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
Those characters are supported in the 7-bit ASCII map, 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:
int base64_encode(const unsigned
unsigned
unsigned
unsigned
143
char *in,
long len,
char *out,
long *outlen);
144
www.libtom.org
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:
int base64_decode(const unsigned
unsigned
unsigned
unsigned
11.2
char *in,
long len,
char *out,
long *outlen);
Primality Testing
145
146
www.libtom.org
Chapter 12
Programming
Guidelines
12.1
148
12.2
www.libtom.org
12.3
12.4
Key Sizes
12.4.1
Symmetric Ciphers
12.4.2
Asymmetric 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
149
to be
e1.923ln(n) 3 ln(ln(n)) 3
(12.1)
Note that n is not the bit-length but the magnitude. For example,
for a 1024-bit key n = 21024 . The work required is:
RSA/DH Key Size (bits)
512
768
1024
1536
2048
2560
3072
4096
150
www.libtom.org
Security Goal
Near term
Short term
Long Term
12.5
Thread Safety
The library is not fully 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. It is best
to call them from your programs initialization 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, and are fully
thread safe. This is fairly simple with symmetric ciphers and hashes.
The only sticky issue is a shared PRNG which can be alleviated
with the careful use of mutex devices. Defining LTC PTHREAD for
instance, enables pthreads based mutex locking in various routines
such as the Yarrow and Fortuna PRNGs, the fixed point ECC multiplier, and other routines.
Chapter 13
Configuring and
Building the Library
13.1
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. Each of the classes of
functions can be disabled during the build process to make a smaller
library. This is particularly useful for shared libraries.
As of v1.06 of the library, the build process has been moved to
two steps for the typical LibTomCrypt application. This is because
LibTomCrypt no longer provides a math API on its own and relies
on third party libraries (such as LibTomMath, GnuMP, or TomsFastMath).
The build process now consists of installing a math library first,
and then building and installing LibTomCrypt with a math library
configured. Note that LibTomCrypt can be built with no internal
math descriptors. This means that one must be provided at either
build, or run time for the application. LibTomCrypt comes with three
math descriptors that provide a standard interface to math libraries.
151
152
13.2
www.libtom.org
Makefile variables
All GNU driven makefiles (including the makefile for ICC) use a set
of common variables to control the build and install process. Most of
the settings can be overwritten from the command line which makes
custom installation a breeze.
13.2.1
MAKE, CC and AR
13.2.2
IGNORE SPEED
13.2.3
153
shared builds. Ideally they should have the same prefix but dont have
to.
Similarly LIBTEST and LIBTEST S are the names for the profiling and testing library. The default is libtomcrypt prof.a for static
and libtomcrypt prof.la for shared.
13.2.4
Installation Directories
Jul
Jul
Jul
Jul
Jul
30
30
30
30
30
16:02
16:02
16:02
16:02
16:02
tomcrypt.h
tomcrypt_argchk.h
tomcrypt_cfg.h
tomcrypt_cipher.h
tomcrypt_custom.h
154
www.libtom.org
-rwxr-xr-x
-rwxr-xr-x
-rwxr-xr-x
-rwxr-xr-x
-rwxr-xr-x
-rwxr-xr-x
-rwxr-xr-x
-rwxr-xr-x
-rwxr-xr-x
1
1
1
1
1
1
1
1
1
tom
tom
tom
tom
tom
tom
tom
tom
tom
users
users
users
users
users
users
users
users
users
11314
11571
13614
14714
632
10934
2634
7067
1467
Jul
Jul
Jul
Jul
Jul
Jul
Jul
Jul
Jul
30
30
30
30
30
30
30
30
30
16:02
16:02
16:02
16:02
16:02
16:02
16:02
16:02
16:02
tomcrypt_hash.h
tomcrypt_mac.h
tomcrypt_macros.h
tomcrypt_math.h
tomcrypt_misc.h
tomcrypt_pk.h
tomcrypt_pkcs.h
tomcrypt_prng.h
tomcrypt_test.h
/home/tom/project/lib:
total 1073
-rwxr-xr-x 1 tom users 1096284 Jul 30 16:02 libtomcrypt.a
13.3
Extra libraries
13.4
Building a static library is fairly trivial as it only requires one invocation of the GNU make command.
CFLAGS="-DTFM_DESC" make install
155
That will build LibTomCrypt (including the TomsFastMath descriptor), and install it in the default locations indicated previously.
You can enable the builtin LibTomMath descriptor as well (or in
place of the TomsFastMath descriptor). Similarly, you can build the
library with no builtin math descriptors.
make install
In this case, no math descriptors are present in the library and
they will have to be made available at build or run time before you
can use any of the public key functions.
Note that even if you include the builtin descriptors you must link
against the source library as well.
gcc -DTFM_DESC myprogram.c -ltomcrypt -ltfm -o myprogram
This will compile myprogram and link it against the LibTomCrypt
library as well as TomsFastMath (which must have been previously
installed). Note that we define TFM DESC for compilation. This
is so that the TFM descriptor symbol will be defined for the client
application to make use of without giving warnings.
13.5
LibTomCrypt can also be built as a shared library through the makefile.shared make script. It is similar to use as the static script except
that you must specify the EXTRALIBS variable at install time.
CFLAGS="-DTFM_DESC" EXTRALIBS=-ltfm make -f makefile.shared install
This will build and install the library and link the shared object
against the TomsFastMath library (which must be installed as a shared
object as well). The shared build process requires libtool to be installed.
13.6
Header Configuration
The file tomcrypt cfg.h is what lets you control various high level
macros which control the behaviour of the library. Build options are
156
www.libtom.org
also stored in tomcrypt custom.h which allow the enabling and disabling of various algorithms.
ARGTYPE
This lets you control how the LTC ARGCHK macro will behave. The
macro is used to check pointers inside the functions against NULL.
There are four 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, the macro will display
the error to stderr then return execution to the caller. This could lead
to a segmentation fault (e.g. when a pointer is NULL) but is useful
if you handle signals on your own. When set to 3, it will resolve to a
empty macro and no error checking will be performed. Finally, when
set to 4, it will return CRYPT INVALID ARG to the caller.
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 LibTomCrypt will detect x86-32, x86-64, MIPS R5900,
SPARC and SPARC64 running GCC as well as x86-32 running MSVC.
13.7
There are also options you can specify from the tomcrypt custom.h
header file.
13.7.1
157
X memory routines
13.7.2
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.
13.7.3
LTC NO FILE
During the build if LTC 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 NOP. This should help resolve any linker errors
stemming from a lack of file I/O on embedded platforms.
13.7.4
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.
13.7.5
LTC TEST
When this has been defined the various selftest functions (for ciphers,
hashes, prngs, etc) are included in the build. This is the default con1 See
http://dev.laptop.org/git?p=bios-crypto;a=summary
158
www.libtom.org
13.7.6
LTC NO FAST
When this has been defined the library will not use faster word oriented
operations. By default, they are only enabled for platforms which can
be auto-detected. This macro ensures that they are never enabled.
13.7.7
LTC FAST
159
data type you can perform integer operations with. Ideally it should
be four or eight bytes since it must properly divide the size of your
block cipher (e.g. 16 bytes for AES). This means sadly if youre on a
platform with 57bit words (or something) you cant use this mode.
So sad.
13.7.8
LTC NO ASM
When this has been defined the library will not use any inline assembler. Only a few platforms support assembler inlines but various
versions of ICC and GCC cannot handle all of the assembler functions.
13.7.9
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.
Also see technical note number five for more details.
13.7.10
LTC EASY
13.7.11
160
www.libtom.org
13.7.12
GCM TABLES
When defined GCM will use a 64KB table (per GCM state) which
will greatly speed up the perpacket latency. It also increases the
initialization time and is not suitable when you are going to use a key
a few times only.
13.7.13
When defined GCM will use the SSE2 instructions to perform the
GF (2x ) multiply using 16 128bit XOR operations. It shaves a few
cycles per byte of GCM output on both the AMD64 and Intel Pentium
4 platforms. Requires GCC and an SSE2 equipped platform.
13.7.14
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.
13.7.15
LTC PTHREAD
When this is activated all of the descriptor table functions will use
pthread locking to ensure thread safe updates to the tables. Note that
it doesnt prevent a thread that is passively using a table from being
messed up by another thread that updates the table.
161
13.7.16
When this has been defined the ECC point multiplier (builtin to
the library) will use a timing resistant point multiplication algorithm
which prevents leaking key bits of the private key (scalar). It is a
slower algorithm but useful for situations where timing side channels
pose a significant threat.
13.7.17
Math Descriptors
The library comes with three math descriptors that allow you to interface the public key cryptography API to freely available math libraries.
When GMP DESC, LTM DESC, or TFM DESC are defined descriptors for the respective library are built and included in the library
as gmp desc, ltm desc, or tfm desc respectively.
In the test demos that use the libraries the additional flags USE GMP,
USE LTM, and USE TFM can be defined to tell the program which
library to use. Only one of the USE flags can be defined at once.
CFLAGS="-DGMP_DESC -DLTM_DESC -DTFM_DESC -DUSE_TFM" \
EXTRALIBS="-lgmp -ltommath -ltfm" make -f makefile.shared install timing
That will build and install the library with all descriptors (and link
against all), but only use TomsFastMath in the timing demo.
162
www.libtom.org
Chapter 14
Optimizations
14.1
Introduction
The entire API was designed with plug and play in mind at the low
level. That is you can swap out any cipher, hash, PRNG or bignum
library and the dependent API will not require updating. This has
the nice benefit that one can add ciphers (etc.) not have to rewrite
portions of the API. For the most part, LibTomCrypt has also been
written to be highly portable and easy to build out of the box on pretty
much any platform. As such there are no assembler inlines throughout
the code, I make no assumptions about the platform, etc...
That works well for most cases but there are times where performance is of the essence. This API allows optimized routines to be
dropped inplace of the existing portable routines. For instance, hand
optimized assembler versions of AES could be provided. Any existing
function that uses the cipher could automatically use the optimized
code without rewriting. This also paves the way for hardware drivers
that can access hardware accelerated cryptographic devices.
At the heart of this flexibility is the descriptor system. A descriptor is essentially just a C struct which describes the algorithm and
provides pointers to functions that do the required work. For a given
class of operation (e.g. cipher, hash, prng, bignum) the functions of
a descriptor have identical prototypes which makes development simple. In most dependent routines all an end developer has to do is
163
164
www.libtom.org
14.2
Ciphers
The ciphers in LibTomCrypt are accessed through the ltc cipher descriptor
structure.
struct ltc_cipher_descriptor {
/** name of cipher */
char *name;
/** internal ID */
unsigned char ID;
/** min keysize (octets) */
int min_key_length,
/** max keysize (octets) */
max_key_length,
/** block size (octets) */
block_length,
/** default number of rounds */
default_rounds;
/** Setup the cipher
@param key
The input symmetric key
@param keylen
The length of the input key (octets)
@param num_rounds The requested number of rounds (0==default)
@param skey
[out] The destination of the scheduled key
@return CRYPT_OK if successful
*/
int (*setup)(const unsigned char *key,
int keylen,
int num_rounds,
symmetric_key *skey);
/** Encrypt a block
@param pt
The plaintext
14.2 Ciphers
165
@param ct
[out] The ciphertext
@param skey
The scheduled key
@return CRYPT_OK if successful
*/
int (*ecb_encrypt)(const unsigned char *pt,
unsigned char *ct,
symmetric_key *skey);
/** Decrypt a block
@param ct
The ciphertext
@param pt
[out] The plaintext
@param skey
The scheduled key
@return CRYPT_OK if successful
*/
int (*ecb_decrypt)(const unsigned char *ct,
unsigned char *pt,
symmetric_key *skey);
/** Test the block cipher
@return CRYPT_OK if successful,
CRYPT_NOP if self-testing has been disabled
*/
int (*test)(void);
/** Terminate the context
@param skey
The scheduled key
*/
void (*done)(symmetric_key *skey);
/** Determine a key size
@param keysize
[in/out] The size of the key desired
The suggested size
@return CRYPT_OK if successful
*/
int (*keysize)(int *keysize);
/** Accelerators **/
/** Accelerated ECB encryption
@param pt
Plaintext
@param ct
Ciphertext
@param blocks The number of complete blocks to process
166
www.libtom.org
@param skey
The scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_ecb_encrypt)(const unsigned char *pt,
unsigned char *ct,
unsigned long blocks,
symmetric_key *skey);
/** Accelerated ECB decryption
@param pt
Plaintext
@param ct
Ciphertext
@param blocks The number of complete blocks to process
@param skey
The scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_ecb_decrypt)(const unsigned char *ct,
unsigned char *pt,
unsigned long blocks,
symmetric_key *skey);
/** Accelerated CBC encryption
@param pt
Plaintext
@param ct
Ciphertext
@param blocks The number of complete blocks to process
@param IV
The initial value (input/output)
@param skey
The scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_cbc_encrypt)(const unsigned char *pt,
unsigned char *ct,
unsigned long blocks,
unsigned char *IV,
symmetric_key *skey);
/** Accelerated CBC decryption
@param pt
Plaintext
@param ct
Ciphertext
@param blocks The number of complete blocks to process
@param IV
The initial value (input/output)
@param skey
The scheduled key context
@return CRYPT_OK if successful
14.2 Ciphers
*/
int (*accel_cbc_decrypt)(const unsigned char
unsigned char
unsigned long
unsigned char
symmetric_key
167
*ct,
*pt,
blocks,
*IV,
*skey);
168
www.libtom.org
@param pt
Plaintext
@param blocks The number of complete blocks to process
@param IV
The initial value (input/output)
@param tweak
The LRW tweak
@param skey
The scheduled key context
@return CRYPT_OK if successful
*/
int (*accel_lrw_decrypt)(const unsigned char
unsigned char
unsigned long
unsigned char
const unsigned char
symmetric_key
*ct,
*pt,
blocks,
*IV,
*tweak,
*skey);
14.2 Ciphers
169
170
www.libtom.org
@param in
The message
@param inlen
Length of message (octets)
@param out
[out] Destination for tag
@param outlen
[in/out] Initial and final size of out
@return CRYPT_OK on success
*/
int (*xcbc_memory)(
const unsigned char *key, unsigned long keylen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
/** Accelerated one shot F9
@param key
The secret key
@param keylen
The key length (octets)
@param in
The message
@param inlen
Length of message (octets)
@param out
[out] Destination for tag
@param outlen
[in/out] Initial and final size of out
@return CRYPT_OK on success
@remark Requires manual padding
*/
int (*f9_memory)(
const unsigned char *key, unsigned long keylen,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
};
14.2.1
Name
The name parameter specifies the name of the cipher. This is what a
developer would pass to find cipher() to find the cipher in the descriptor tables.
14.2.2
Internal ID
14.2 Ciphers
14.2.3
171
Key Lengths
The minimum key length is min key length and is measured in octets.
Similarly the maximum key length is max key length. They can be
equal and both must valid key sizes for the cipher. Values in between
are not assumed to be valid though they may be.
14.2.4
Block Length
14.2.5
Rounds
14.2.6
Setup
To initialize a cipher (for ECB mode) the function setup() was provided. It accepts an array of key octets key of length keylen octets.
The user can specify the number of rounds they want through num rounds
where num rounds = 0 means use the default. The destination of a
scheduled key is stored in skey.
Inside the symmetric key union there is a void *data which you can
use to allocate data if you need a data structure that does not fit with
the existing ones provided. Just make sure in your done() function
that you free the allocated memory.
14.2.7
To process a single block in ECB mode the ecb encrypt() and ecb decrypt()
functions were provided. The plaintext and ciphertext buffers are allowed to overlap so you must make sure you do not overwrite the
output before you are finished with the input.
172
14.2.8
www.libtom.org
Testing
The test() function is used to selftest the device. It takes no arguments and returns CRYPT OK if all is working properly. You may
return CRYPT NOP to indicate that no testing was performed.
14.2.9
Key Sizing
14.2.10
Acceleration
14.2 Ciphers
173
Accelerated CTR
This function is meant for accelerated CTR encryption. It is accessible through the accel ctr encrypt pointer. The blocks value is the
number of complete blocks to process. The IV is the CTR counter
vector. It is an input upon calling this function and must be updated
by the function before returning. The mode value indicates whether
the counter is big (mode = CTR COUNTER BIG ENDIAN) or little
(mode = CTR COUNTER LITTLE ENDIAN) endian.
This function (and the way its called) differs from the other two
since ctr encrypt() allows any size input plaintext. The accelerator
will only be called if the following conditions are met.
1. The accelerator is present
2. The CTR pad is empty
3. The remaining length of the input to process is greater than or
equal to the block size.
The CTR pad is empty when a multiple (including zero) blocks of
text have been processed. That is, if you pass in seven bytes to AES
CTR mode you would have to pass in a minimum of nine extra bytes
before the accelerator could be called. The CTR accelerator must
increment the counter (and store it back into the buffer provided)
before encrypting it to create the pad.
The accelerator will only be used to encrypt whole blocks. Partial
blocks are always handled in software.
Accelerated LRW
These functions are meant for accelerated LRW. They process blocks
of input in lengths of multiples of 16 octets. They must accept the IV
and tweak state variables and updated them prior to returning. Note
that you may want to disable LRW TABLES in tomcrypt custom.h
if you intend to use accelerators for LRW.
While both encrypt and decrypt accelerators are not required it is
suggested as it makes lrw setiv() more efficient.
Note that calling lrw done() will only invoke the cipher descriptor[].done()
function on the symmetric key parameter of the LRW state. That
174
www.libtom.org
means if your device requires any (LRW specific) resources you should
free them in your ciphers() done function. The simplest way to think
of it is to write the plugin solely to do LRW with the cipher. That
way cipher descriptor[].setup() means to init LRW resources and cipher descriptor[].done() means to free them.
Accelerated CCM
This function is meant for accelerated CCM encryption or decryption.
It processes the entire packet in one call. You can optimize the work
flow somewhat by allowing the caller to call the setup() function first
to schedule the key if your accelerator cannot do the key schedule on
the fly (for instance). This function MUST support both key passing
methods.
key
NULL
non-NULL
NULL
non-NULL
uskey
NULL
NULL
non-NULL
non-NULL
Source of key
Error, not supported
Use key, do a key schedule
Use uskey, key schedule not required
Use uskey, key schedule not required
175
Accelerated F9
This function is meant to perform an optimized F9 message authentication code computation when the user calls f9 memory(). Like
f9 memory(), it requires the caller to perform any 3GPP related padding
before calling in order to ensure proper compliance with F9.
14.3
OneWay Hashes
The hash functions are accessed through the ltc hash descriptor structure.
struct ltc_hash_descriptor {
/** name of hash */
char *name;
/** internal ID */
unsigned char ID;
/** Size of digest in octets */
unsigned long hashsize;
/** Input block size in octets */
unsigned long blocksize;
/** ASN.1 OID */
unsigned long OID[16];
/** Length of DER encoding */
unsigned long OIDlen;
/** Init a hash state
@param hash
The hash to initialize
@return CRYPT_OK if successful
*/
int (*init)(hash_state *hash);
/** Process a block of data
@param hash
The hash state
@param in
The data to hash
176
www.libtom.org
@param inlen The length of the data (octets)
@return CRYPT_OK if successful
*/
int (*process)(
hash_state *hash,
const unsigned char *in,
unsigned long inlen);
/** Produce the digest and store it
@param hash
The hash state
@param out
[out] The destination of the digest
@return CRYPT_OK if successful
*/
int (*done)(
hash_state *hash,
unsigned char *out);
/** Self-test
@return CRYPT_OK if successful,
CRYPT_NOP if self-tests have been disabled
*/
int (*test)(void);
/* accelerated hmac callback: if you need to-do
multiple packets just use the generic hmac_memory
and provide a hash callback
*/
int (*hmac_block)(const unsigned char *key,
unsigned long keylen,
const unsigned char *in,
unsigned long inlen,
unsigned char *out,
unsigned long *outlen);
};
14.3.1
Name
This is the name the hash is known by and what find hash() will look
for.
14.3.2
177
Internal ID
This is the internal ID byte used to distinguish the hash from other
hashes.
14.3.3
Digest Size
14.3.4
Block Size
The blocksize variable indicates the length of input (in octets) that the
hash processes in a given invocation.
14.3.5
OID Identifier
14.3.6
Initialization
The init function initializes the hash and prepares it to process message
bytes.
14.3.7
Process
This processes message bytes. The algorithm must accept any length
of input that the hash would allow. The input is not guaranteed to be
a multiple of the block size in length.
14.3.8
Done
The done function terminates the hash and returns the message digest.
14.3.9
Acceleration
178
www.libtom.org
14.3.10
HMAC Acceleration
14.4
179
180
www.libtom.org
*/
int (*test)(void);
};
14.4.1
Name
14.4.2
Export Size
When an PRNG state is to be exported for future use you specify the
space required in this variable.
14.4.3
Start
14.4.4
Entropy Addition
Add entropy to the PRNG state. The exact behaviour of this function
depends on the particulars of the PRNG.
14.4.5
Ready
This function makes the PRNG ready to read from by processing the
entropy added. The behaviour of this function depends on the specific
PRNG used.
14.4.6
Read
Read from the PRNG and return the number of bytes read. This
function does not have to fill the buffer but it is best if it does as
many protocols do not retry reads and will fail on the first try.
14.4.7
Done
14.4.8
181
An exported PRNG state is data that the PRNG can later import to
resume activity. Theyre not meant to resume the same session but
should at least maintain the same level of state entropy.
14.5
The library also makes use of the math descriptors to access math
functions. While bignum math libraries usually differ in implementation it hasnt proven hard to write glue to use math libraries so far.
The basic descriptor looks like.
/** math descriptor */
typedef struct {
/** Name of the math provider */
char *name;
/** Bits per digit, amount of bits must fit in an unsigned long */
int bits_per_digit;
/* ---- init/deinit functions ---- */
/** initialize a bignum
@param
a
The number to initialize
@return CRYPT_OK on success
*/
int (*init)(void **a);
/** init copy
@param dst
The number to initialize and write to
@param src
The number to copy from
@return CRYPT_OK on success
*/
int (*init_copy)(void **dst, void *src);
/** deinit
@param
a
The number to free
@return CRYPT_OK on success
*/
182
www.libtom.org
183
@param b
The right side integer
@return LTC_MP_LT if a < b,
LTC_MP_GT if a > b and
LTC_MP_EQ otherwise. (signed comparison)
*/
int (*compare)(void *a, void *b);
/** compare against int
@param a
The left side integer
@param b
The right side integer (upto bits_per_digit)
@return LTC_MP_LT if a < b,
LTC_MP_GT if a > b and
LTC_MP_EQ otherwise. (signed comparison)
*/
int (*compare_d)(void *a, unsigned long n);
/** Count the number of bits used to represent the integer
@param a
The integer to count
@return The number of bits required to represent the integer
*/
int (*count_bits)(void * a);
/** Count the number of LSB bits which are zero
@param a
The integer to count
@return The number of contiguous zero LSB bits
*/
int (*count_lsb_bits)(void *a);
/** Compute a power of two
@param a The integer to store the power in
@param n The power of two you want to store (a = 2^n)
@return CRYPT_OK on success
*/
int (*twoexpt)(void *a , int n);
/* ---- radix conversions ---- */
/** read
@param
@param
@param
ascii
a
str
radix
string
The integer to store into
The string to read
The radix the integer has been represented in (2-64)
184
www.libtom.org
185
186
www.libtom.org
@param b
a
b
187
188
www.libtom.org
@param a The modulus
@param b The destination for the reduction digit
@return CRYPT_OK on success
*/
int (*montgomery_setup)(void *a, void **b);
/** get normalization value
@param a
The destination for the normalization value
@param b
The modulus
@return CRYPT_OK on success
*/
int (*montgomery_normalization)(void *a, void *b);
/** reduce a number
@param a
The number [and dest] to reduce
@param b
The modulus
@param c
The value "b" from montgomery_setup()
@return CRYPT_OK on success
*/
int (*montgomery_reduce)(void *a, void *b, void *c);
/** clean up (frees memory)
@param a
The value "b" from montgomery_setup()
@return CRYPT_OK on success
*/
void (*montgomery_deinit)(void *a);
/* ---- exponentiation ---- */
/** Modular exponentiation
@param a
The base integer
@param b
The power (can be negative) integer
@param c
The modulus integer
@param d
The destination
@return CRYPT_OK on success
*/
int (*exptmod)(void *a, void *b, void *c, void *d);
/** Primality testing
@param a
The integer to test
@param b
The destination of the result (FP_YES if prime)
189
190
*/
int (*ecc_ptdbl)(ecc_point
ecc_point
void
void
www.libtom.org
*P,
*R,
*modulus,
*mp);
191
@param key
[out] Destination of a newly created private key pair
@return CRYPT_OK if successful, upon error all allocated ram is freed
*/
int (*rsa_keygen)(prng_state *prng,
int wprng,
int size,
long e,
rsa_key *key);
/** RSA exponentiation
@param in
The octet array representing the base
@param inlen
The length of the input
@param out
The destination (to be stored in an octet array format)
@param outlen
The length of the output buffer and the resulting size
(zero padded to the size of the modulus)
@param which
PK_PUBLIC for public RSA and PK_PRIVATE for private RSA
@param key
The RSA key to use
@return CRYPT_OK on success
*/
int (*rsa_me)(const unsigned char *in,
unsigned long inlen,
unsigned char *out, unsigned long *outlen, int which,
rsa_key *key);
} ltc_math_descriptor;
14.5.1
Conventions
All bignums are accessed through an opaque void * data type. You
must internally cast the pointer if you need to access members of
your bignum structure. During the init calls a void ** will be passed
where you allocate your structure and set the pointer then initialize
the number to zero. During the deinit calls you must free the bignum
as well as the structure you allocated to place it in.
All functions except the Montgomery reductions work from left to
right with the arguments. For example, mul(a, b, c) computes c ab.
All functions (except where noted otherwise) return CRYPT OK
to signify a successful operation. All error codes must be valid LibTom-
192
www.libtom.org
14.5.2
ECC Functions
The ECC system in LibTomCrypt is based off of the NIST recommended curves over GF (p) and is used to implement EC-DSA and
EC-DH. The ECC functions work with the ecc point structure and
assume the points are stored in Jacobian projective format.
/** A point on a ECC curve, stored in Jacobian format such
that (x,y,z) => (x/z^2, y/z^3, 1) when interpreted as affine */
typedef struct {
/** The x co-ordinate */
void *x;
/** The y co-ordinate */
void *y;
/** The z co-ordinate */
void *z;
} ecc_point;
All ECC functions must use this mapping system. The only exception is when you remap all ECC callbacks which will allow you to
have more control over how the ECC math will be implemented. Out
of the box you only have three parameters per point to use (x, y, z)
however, these are just void pointers. They could point to anything
you want. The only further exception is the export functions which
expects the values to be in affine format.
Point Multiply
This will multiply the point G by the scalar k and store the result in
the point R. The value should be mapped to affine only if map is set
to one.
193
Point Addition
This will add the point P to the point Q and store it in the point R.
The mp parameter is the b value from the montgomery setup() call.
The input points may be in either affine (with z = 1) or projective
format and the output point is always projective.
Point Mapping
This will map the point P back from projective to affine. The output
point P must be of the form (x, y, 1).
Shamirs Trick
To accelerate ECDSA verification the library provides a builtin
function called ltc ecc mul2add(). This performs two point multiplications and an addition in roughly the time of one point multiplication. It is called from ecc verify hash() if an accelerator is not
present. The acclerator function must allow the points to overlap (e.g.,
A k1 A + k2 B) and must return the final point in affine format.
14.5.3
RSA Functions
194
/** The p factor of N
void *p;
/** The q factor of N
void *q;
/** The 1/q mod p CRT
void *qP;
/** The d mod (p - 1)
void *dP;
/** The d mod (q - 1)
void *dQ;
} rsa_key;
www.libtom.org
*/
*/
param */
CRT param */
CRT param */
The call reads the in buffer as an unsigned char array in big endian
format. Then it performs the exponentiation and stores the output in
big endian format to the out buffer. The output must be zero padded
(leading bytes) so that the length of the output matches the length
of the modulus (in bytes). For example, for RSA1024 the output is
always 128 bytes regardless of how small the numerical value of the
exponentiation is.
Since the function is given the entire RSA key (for private keys
only) CRT is possible as prescribed in the PKCS #1 v2.1 specification.
Index
aes desc, 18
anubis desc, 18
AR, 152
base64 decode(), 143
base64 encode(), 143
blowfish desc, 18
blowfish done(), 16
blowfish ecb decrypt(), 16
blowfish ecb encrypt(), 16
blowfish setup(), 16
BSWAP, 8
CBC Mode, 25
CBC mode, 23
cbc decrypt(), 26
cbc done(), 28
cbc encrypt(), 26
cbc getiv(), 27
cbc setiv(), 27
cbc start(), 25
CC, 152
ccm memory(), 41, 174
ccm test(), 42
CFB Mode, 25
CFB mode, 24
cfb decrypt(), 26
cfb done(), 28
cfb encrypt(), 26
cfb getiv(), 27
cfb setiv(), 27
cfb start(), 25
chc register(), 58
Cipher Decrypt, 14
Cipher Descriptor, 17
Cipher descriptor table, 18
Cipher Encrypt, 14
Cipher Hash Construction, 58
Cipher Setup, 13
Cipher Testing, 15
Ciphertext stealing, 25
CMAC, 64
CRYPT ERROR, 7
CRYPT OK, 7
CTR Mode, 25
CTR mode, 23
ctr decrypt(), 26
ctr done(), 28
ctr encrypt(), 26
ctr getiv(), 27
ctr setiv(), 27
ctr start(), 25
DATADIR, 153
der decode bit string(), 132
der decode choice(), 137
der decode ia5 string(), 134
der decode integer(), 132
195
196
der decode object identifier(), 133
der decode octet string(), 133
der decode printable string(), 135
der decode sequence(), 128
der decode sequence flexi(), 138
der decode sequence multi(), 129
der decode set(), 130
der decode short integer(), 132
der decode utctime(), 136
der decode utf8 string(), 135
der encode bit string(), 132
der encode ia5 string(), 134
der encode integer(), 132
der encode object identifier(), 133
der encode octet string(), 133
der encode printable string(), 135
der encode sequence(), 126
der encode sequence multi(), 129
der encode set(), 130
der encode setof(), 131
der encode short integer(), 132
der encode utctime(), 136
der encode utf8 string(), 135
der length bit string(), 132
der length ia5 string(), 134
der length integer(), 132
der length object identifier(), 133
der length octet string(), 133
der length printable string(), 135
der length sequence(), 128
der length short integer(), 132
der length utctime(), 136
der length utf8 string(), 135
der sequence free(), 140
des3 desc, 18
des desc, 18
DESTDIR, 153
dsa decrypt key(), 122
Index
dsa
dsa
dsa
dsa
dsa
dsa
dsa
addheader(), 35
decrypt(), 35
decrypt verify memory, 37
done(), 36
encrypt(), 35
encrypt authenticate memory,
37
eax init(), 34
eax test(), 36
ECB mode, 23
ecb decrypt(), 26
ecb done(), 28
ecb encrypt(), 26
ecb start(), 25
ECC Key Format, 107
ecc ansi x963 export(), 110
ecc ansi x963 import(), 111
ecc ansi x963 import ex(), 111
ecc decrypt key(), 113
ecc encrypt key(), 112
ecc export(), 109
ecc free(), 109
ecc import(), 110
ecc import ex(), 110
ecc make key(), 108
ecc make key ex(), 109
ecc shared secret(), 111
ecc sign hash(), 114
ecc verify hash(), 114
error to string(), 7, 9, 21
eax
eax
eax
eax
eax
eax
Index
EXTRALIBS, 154
F8 Mode, 32
f8 decrypt(), 32
f8 done(), 33
f8 encrypt(), 32
f8 getiv(), 33
f8 setiv(), 33
f8 start(), 32
f9 done(), 74
f9 file(), 75
f9 init(), 74
f9 memory(), 75, 175
f9 process(), 74
f9 test(), 75
find cipher(), 20, 21, 170
find hash(), 53
find hash oid(), 53
find prng(), 81
Fixed Point ECC, 106
FP ENTRIES, 106
FP LUT, 106
FP SIZE, 107
gcm add aad(), 45
gcm add iv(), 44
gcm done(), 45
gcm init(), 44
gcm memory(), 46, 174
gcm process(), 45
gcm reset(), 46
GMP DESC, 161
Hash descriptor table, 57
Hash Functions, 51
hash file(), 55
hash filehandle(), 55
hash memory(), 55
197
hmac
hmac
hmac
hmac
hmac
hmac
done(), 62
file(), 63
init(), 61
memory(), 62
process(), 62
test(), 63
198
LTC PTHREAD, 150
LTC SET ASN1 macro, 125
ltc utctime structure, 136
LTM DESC, 161
MAKE, 152
MECC FP, 106
Message Digest, 52
noekeon desc, 18
ocb decrypt(), 39
ocb decrypt verify memory(), 40
ocb done decrypt(), 40
ocb done encrypt(), 39
ocb encrypt(), 39
ocb init(), 38
OFB Mode, 25
OFB mode, 24
ofb decrypt(), 26
ofb done(), 28
ofb encrypt(), 26
ofb getiv(), 27
ofb setiv(), 27
ofb start(), 25
OMAC, 64
omac done(), 65
omac file(), 66
omac init(), 64
omac memory(), 66, 174
omac process(), 65
omac test(), 66
pelican done(), 70
pelican init(), 70
pelican process(), 70
PK PRIVATE, 95
PK PUBLIC, 95
PKCS #5, 140
Index
pkcs 1 oaep decode(), 92
pkcs 1 oaep encode(), 91, 97
pkcs 1 pss decode(), 93
pkcs 1 pss encode(), 92
pkcs 1 v1 5 decode(), 90
pkcs 1 v1 5 encode(), 89
pkcs 5 alg1(), 140
pkcs 5 alg2(), 141
pmac done(), 68
pmac file(), 69
pmac init(), 68
pmac memory(), 69
pmac process(), 68
pmac test(), 69
Primality Testing, 144
PRNG, 10
PRNG add entropy, 77
PRNG Descriptor, 80
PRNG done, 78
PRNG export, 78
PRNG import, 78
PRNG read, 78
PRNG ready, 77
PRNG start, 77
PRNG test, 79
Pseudo Random Number Generator, 10
rc2 desc, 18
rc5 desc, 18
rc6 desc, 18
register cipher(), 21
register hash(), 56
register prng(), 11, 81
rng get bytes(), 85
rng make prng(), 85
ROL, 9
ROL64, 9
Index
ROL64c, 9
ROLc, 9
ROR, 9
ROR64, 9
ROR64c, 9
RORc, 9
rsa decrypt key(), 97
rsa decrypt key ex(), 98
rsa encrypt key(), 96
rsa encrypt key ex(), 97
rsa export(), 9, 103
rsa exptmod(), 96
rsa free(), 95
rsa import(), 104
rsa make key(), 11, 95
rsa sign hash(), 99
rsa sign hash ex(), 99
rsa verify hash(), 100
rsa verify hash ex(), 101
saferp desc, 18
Secure RNG, 84
SET, 130
SET OF, 130
Shamirs Trick, 193
skipjack desc, 18
SSE2, 160
STORE32H, 8
STORE32L, 8
STORE64H, 8
STORE64L, 8
Symmetric Keys, 17
TFM, 107
tfm.h, 107
TFM DESC, 161
Twofish build options, 21
twofish desc, 18
199
TWOFISH SMALL, 21
TWOFISH TABLES, 21
unregister cipher(), 22
unregister hash(), 56
unregister prng(), 81
USE GMP, 161
USE LTM, 161
USE TFM, 161
variable length output, 9
XCALLOC, 157
xcbc done(), 72
xcbc file(), 73
xcbc init(), 72
xcbc memory(), 72, 174
xcbc process(), 72
xcbc test(), 73
XFREE, 157
XMALLOC, 157
XREALLOC, 157
xtea desc, 18