Encryption functions
[Cryptographic functions]

Common ciphers. More...

Defines

#define BC_AES_BLOCK   16
 Number of bytes per encrypt/decrypt block for AES.
#define BC_DES_BLOCK   8
 Number of bytes per encrypt/decrypt block for TDEA (DES).

Typedefs

typedef unsigned char BC_ARC4 [258]
 State descriptor for the ARC4 cypher.

Enumerations

enum  { BC_AES_128_KSINTS = 45, BC_AES_192_KSINTS = 53, BC_AES_256_KSINTS = 61 }
 

Size of the AES key schedule buffer, in words.

More...
enum  { BC_TDEA3_KSINTS = 25, BC_TDEA2_KSINTS = 49, BC_TDEA1_KSINTS = 73 }
 

Size of the DES/TDEA key schedule buffer, in words.

More...

Functions

void BC_AesKeySched (int *ksc, const void *key, int len)
 Prepares an AES encryption or decryption.
void BC_CipherPrepare (BC_CIPHER *cipher, const struct bc_cipher *cfunc, const struct bc_cblock *cmode, const int *sched, int *nonce)
 Initialises a block cipher.
void BC_CipherEncrypt (BC_CIPHER *state, const void *clear, void *cipher)
 Encrypts a block.
void BC_CipherDecrypt (BC_CIPHER *state, const void *cipher, void *clear)
 Decrypts a block.
unsigned BC_CipherLength (const BC_CIPHER *state)
 Returns the number of bytes processed so far.
void BC_DesKeySched (int *ksc, const void *k1, const void *k2, const void *k3)
 Generate a key schedule for a DES or TDEA encryption/decryption.
void BC_Arc4Start (BC_ARC4 crypt, const char *key, int klen)
 Initialises an ARC4 state with a given key.
void BC_Arc4Crypt (BC_ARC4 crypt, const char *in, char *out, int dlen)
 ARC4 encrytion/decryption.

Detailed Description

Common ciphers.

This sub-module implements some commonly used cipher functions. Ciphers come in two flavours, stream ciphers and block ciphers.

Stream ciphers

A stream cipher works on a stream of bytes. There is an internal state that changes after the encryption of each byte, therefore even if you feed the same data repeatedly to the cipher, you will get different results. For all intents and purposes a stream cipher is a pseudo random number generator that generates a random byte for each input byte and XOR-s that byte with the input. To decode, you generate the same random sequence and XOR it with the encrypted stream. There are versions of stream ciphers that feed back the output into the encryption process, thus a change of an input byte will change all the output bytes after that. Others do not feed back anything and thus a single input byte affects only a single output byte.

ARC4

The library provides the ARC4 stream cipher. This cipher is very fast and was very popular. It was invented by RSA and was named RC4. RSA kept the algorithm secret, but it was somehow leaked to the Internet. The name ARC4 stands for Alleged RC4. It was later demonstrated that the leaked algorithm is indeed the RC4 algorithm.
ARC4 has several weaknesses and is not considered really secure. However, you can use it to achieve reasonable security if after creating the original state from the key you use the algorithm to encrypt a certain amount of data that you discard (that is, you advance the state of the pseudo-random generator by a certain amount). As a minimum, 768 bytes should be generated and discarded but 3072 bytes is strongly suggested.

Block ciphers

Block ciphers process a fixed length of input at a time (a block). They have no internal state, therefore if you provide the same input, they will generate the same output (using the same key, that is). That is a disadvantage, because that means that repeated patterns in the cleartext will generate repeated patterns in the ciphertext and your adversary can use that to try to infer information about the nature of your message. To overcome this drawback, there are ways of using a feedback that effectively turns a block cipher into a stream cipher, although one that operates block sized chunks of the stream. Depending on how you organise the feedback, your cipher operates in a certain mode.

Common block cipher modes

With the exception of ECB, all those modes have an initial vector (or nonce) associated with them. This is a block-length size data that is usually generated random (and exchanged by public-key method) so that even if the encryption key is the same and the data is the same, the encrypted stream will still be different, thus your adversaries can not deduce that you are sending the same message or not and they can not fool you by replaying an encrypted message that they have captured earlier. In this implementation in case of the CTR mode the nonce is used to initialise the counter.

As mentioned, the CTR mode initialises the counter to the nonce and then increments it by one after each operation. The most often used CTR mode generates a the block-size number needed for each step by using the nonce smaller than the block size and use that as the more significant half of the block sized number, while the less significant half is the counter; you are not supposed to send a message that has more blocks than what you can count on this less significant half. Therefore, if that is the case, when you receive the nonce, you must place it in the more significant half of the initial vector and zero all the remaining bytes of the vector. The initial vector is always stored in big-endian byte order, that is, you store your nonce in the first n bytes of the buffer and zero the remaining block size - n bytes. An other common method is that the nonce is block sized and the block you use for a step is the arithmetic sum of the nonce and the counter; the latter is also block sized, starting with the value of 0. This of course is equivalent to initialising the counter to the nonce and just incrementing it, which is what the routine in the library does.

There's an other important issue of your message not being an exact multiple of the block size. In that case, you have to use a padding to make it so. There is no set standard on how to pad messages to multiples of block sizes, therefore the library leaves that to you. The most often, but not exclusively used method is appending 0x80 after your message and then as many 0x00 bytes as needed to make it a multiple of block size; if your original message was a multiple of the block size, you still do this, making a message one block longer. Nevertheless, the library doesn't do it for you, it's up to you (or more likely the standard that you implement) what padding scheme you use.

DES and TDEA

DES is a very old encryption standard. It is easy to implement in hardware, but it is not designed for efficient software implementation. DES uses a 56-bit key and is considered unsecure; a common PC can break DES in a fairly short time. TDEA is a standard that uses DES and makes it secure. It processes the data by running it through DES three times (encrypt, decrypt, encrypt) using two or three different DES keys. TDEA is also known as triple-DES. While TDEA is secure, it is much slower than AES. Both DES and TDEA works on 8-byte blocks.

AES

AES has been developed to counter the problems with DES. AES is secure, uses longer keys and, unlike DES, is software friendly. AES has several variants, depending on block size and key size. The library supports 16-byte blocks with 128, 192 or 256 bit (16, 24 or 32 bytes) keys.



To use the these ciphers, you need to include crypto/cipher.h.

The following table gives you a rough idea about the performance of the various functions in the library. The values represent the time, in milliseconds, that are required to perform the given function on 1KB of data. In case of the block ciphers, ECB mode is used (i.e. no pre- or postprocessing of the data). The preparation of the key schedule is not included in the time shown. The performance of these functions is significantly different depending on whether you use the ARM or the THUMB versions. If you can afford the FLASH, you should consider enabling interworking and use the ARM version of the crypto library even if you use THUMB mode otherwise. The times were measured on an LPC23xx running at 60MHz.
DES and ARC4 needs the same time to encrypt and decrypt. AES, however, is slower in decrypting. Therefore, for AES the decryption time is given separately.

Time needed to encrypt (decrypt) 1KB of data [ms]

Crypto        ARM      THUMB       ARM      THUMB
function       (encryption)         (decryption)

AES-128       3.44     5.48        5.79     7.81
AES-192       4.05     6.55        6.94     9.38
AES-256       4.66     7.61        8.06    10.95
DES           6.90    10.97
3-DES        20.22    32.40
ARC4          0.63     1.01

Enumeration Type Documentation

anonymous enum

Size of the AES key schedule buffer, in words.

Enumerator:
BC_AES_128_KSINTS 

Number of words for 128 bit keys.

BC_AES_192_KSINTS 

Number of words for 192 bit keys.

BC_AES_256_KSINTS 

Number of words for 256 bit keys.

anonymous enum

Size of the DES/TDEA key schedule buffer, in words.

Enumerator:
BC_TDEA3_KSINTS 

Number of words for TDEA3 (DES).

BC_TDEA2_KSINTS 

Number of words for TDEA2.

BC_TDEA1_KSINTS 

Number of words for TDEA1.


Function Documentation

void BC_AesKeySched ( int *  ksc,
const void *  key,
int  len 
)

Prepares an AES encryption or decryption.

This function generates the key schedule to be used when encrypting or decrypting data using the given key. After this call the key itself can be destroyed and only the key schedule must be kept. The function supports 128, 196 and 256 bit key lengths.

Parameters:
ksc Pointer to an array of 32-bit ints where the calculated key schedule will be stored. The required storage is 45, 53 or 61 words for the 128, 192 and 256 bit keys, respectively. The key schedule must not be changed but must be passed to the encrypt and decrypt routines verbatim.
key Pointer to the key. It must be 16, 24 or 32 bytes, that is 128, 196 or 256 bits long.
len The key length in bits, one of 128, 196 or 256. If the argument is not one of these numbers, then the function does nothing.
void BC_Arc4Crypt ( BC_ARC4  crypt,
const char *  in,
char *  out,
int  dlen 
)

ARC4 encrytion/decryption.

ARC4 is symmetrical, therefore you can use the same routine for encryption and decryption. The input data is pointed by in, the outgoing buffer is pointed by out. If out is NULL, then no output is generated and no input is read, but the internal state is advanced by dlen steps. If out is not NULL, but in is, then no input will be used but the output buffer will be filled with dlen number of presudorandom bytes (as if an all-0 input was encrypted). If both pointers are set, then dlen input bytes will be processed and the result will be put into the output buffer. The two pointers can point to the same area for in-place transformation but other than that special case the two areas should not overlap.

Parameters:
crypt The ARC4 state descriptor
in Pointer to the input text (clear or cipher)
out Pointer to the result text (cipher or clear)
dlen The number of bytes to process
void BC_Arc4Start ( BC_ARC4  crypt,
const char *  key,
int  klen 
)

Initialises an ARC4 state with a given key.

Parameters:
crypt Pointer to the ARC4 state descriptor
key Pointer to the encryption key
klen The length of the key in bytes, between 1 and 255. Values outside of the range will be clipped.
void BC_CipherDecrypt ( BC_CIPHER state,
const void *  cipher,
void *  clear 
)

Decrypts a block.

This function decrypts a block of data using the method and cipher function set by the BC_CipherPrepare() function. It also updates the state.

Parameters:
state A pointer to a BC_CIPHER structure that holds the state for the cipher. It must have been prepared by a call to the BC_CipherPrepare() function.
cipher Pointer to the ciphertext block. The length of the block is determined by the underlying cipher function; it is 16 bytes for AES and 8 bytes for DES/TDEA.
clear Pointer to a memory block where the cleartext will be stored. It must have the same size as the ciphertext block. It can overlap the ciphertext.
void BC_CipherEncrypt ( BC_CIPHER state,
const void *  clear,
void *  cipher 
)

Encrypts a block.

This function encrypts a block of data using the method and cipher function set by the BC_CipherPrepare() function. It also updates the state.

Parameters:
state A pointer to a BC_CIPHER structure that holds the state for the cipher. It must have been prepared by a call to the BC_CipherPrepare() function.
clear Pointer to the cleartext block. The length of the block is determined by the underlying cipher function; it is 16 bytes for AES and 8 bytes for DES/TDEA.
cipher Pointer to a memory block where the ciphertext will be stored. It must have the same size as the cleartext block. It can overlap the cleartext.
unsigned BC_CipherLength ( const BC_CIPHER state  ) 

Returns the number of bytes processed so far.

Parameters:
state A pointer to a BC_CIPHER structure that holds the state for the cipher. It must have been prepared by a call to the BC_CipherPrepare() function.
Returns:
The number of bytes processed since the cipher was initialised.
void BC_CipherPrepare ( BC_CIPHER cipher,
const struct bc_cipher *  cfunc,
const struct bc_cblock *  cmode,
const int *  sched,
int *  nonce 
)

Initialises a block cipher.

This function initialises a block cipher. The key schedule for the cipher function must have already been prepared. The initial vector, or nonce for CTR mode, also must be prepaerd before this call. The function prepares the block cipher structure with the parameters it receives.

Parameters:
cipher Pointer to the block cipher structure to initialise.
cfunc The block cipher function to use. It must be one of
BC_CIPHER_AES for AES_128, AES_192 or AES_256 or
BC_CIPHER_DES for DES, TDEA_2 or TDEA_1
cmode The chain operation of the cipher. It must be
BC_BCMODE_ECB for electronic codebook mode,
BC_BCMODE_CBC for cipher block chaining mode,
BC_BCMODE_CFB for cipher feedback mode,
BC_BCMODE_OFB for output feedback mode or
BC_BCMODE_CTR for counter mode.
sched The key schedule for the underlying block cipher function. For BC_CIPHER_AES it must have been prepared by a call to BC_AesKeySched() and for BC_CIPHER_DES by a call to BC_DesKeySched(). While the cipher is active, the key schedule must not be changed.
nonce The initial vector or nonce. It must be a pointer to as many bytes as the block size of the cipher function, that is, 16 bytes for AES and 8 bytes for DES. This memory location is changed by the encrypt and decrypt calls and should not be modified between calls. Furthermore, for CTR mode it is treated as a 16 or 8 byte long integer, stored in big-endian format, and incremented by 1 after every encryption or decryption. The only operation mode that does not use this parameter is ECB, in that case this memory will never be referenced and the pointer passed in this parameter will be ignored.
void BC_DesKeySched ( int *  ksc,
const void *  k1,
const void *  k2,
const void *  k3 
)

Generate a key schedule for a DES or TDEA encryption/decryption.

This function receives 1, 2 or 3 64-bit DES key(s) and fills the key schedule array with the subkeys needed to perform the DES calculations. The actual DES key is only 56 bit long, but the standard declares that it should be stored in 64 bits. In each byte the LSB should be an odd parity bit for the remaining 7 bits. This function does not check the key parity bits, it just discards them silently.

Parameters:
ksc A pointer to an integer array where the key schedule will be stored. The size of the array depends on the number of keys provided, namely 25, 49 or 73 ints for 1, 2 or 3 keys, respecively.
k1 A pointer to an 8 byte array where the key is stored. This pointer must not be NULL. This key will be used in DES mode or as K1 in TDEA mode. Note that DES mode is identical to TDEA mode 3 (where K1=K2=K3).
k2 A pointer to an 8 byte array for the second key. If this pointer is NULL, then the key schedule will be prepared for DES and it has to be 25 integers long. If the pointer is not NULL, then the key schedule will be prepared for TDEA mode and this will be K2.
k3 A pointer to an 8 byte array for the third key. If the k2 argument was NULL, then this parameter is ignored. Otherwise, if this parameter is NULL, then TDEA-2 mode is prepared, that is, K3=K1 and the key schedule array must be 49 integers long. If the pointer is not NULL, the TDEA-1 mode is prepared and this will be K3. In that case the key schedule buffer must be 73 integers long.
Note:
It is assumed that you don't do key schedule often. Normally, you do it once and use the generated schedule for encrypting or decrypting large amounts of data. Therefore, to save space, the key scheduling algoritm is implemented in a slow but small way, while in the actual encryption code space is traded in for execution speed.
Generated on Fri Aug 13 12:02:25 2010 by  doxygen 1.6.3