wolfSSL Manual

Chapter 10: wolfCrypt (formerly CTaoCrypt) Usage Reference



wolfCrypt is the cryptography library primarily used by wolfSSL. It is optimized for speed, small footprint, and portability. wolfSSL interchange with other cryptography libraries as required.


Types used in the examples:


typedef unsigned char byte;

typedef unsigned int  word32;



10.1 Hash Functions



10.1.1 MD4


NOTE:  MD4 is outdated and considered broken. Please consider using a different hashing function if possible.


To use MD4 include the MD4 header "wolfssl/ctaocrypt/md4.h". The structure to use is Md4, which is a typedef. Before using, the hash initialization must be done with the InitMd4() call. Use Md4Update() to update the hash and Md4Final() to retrieve the final hash


byte md4sum[MD4_DIGEST_SIZE];

byte buffer[1024];      

// fill buffer with data to hash


Md4 md4;

InitMd4(&md4);


Md4Update(&md4, buffer, sizeof(buffer));  // can be called again and again

Md4Final(&md4, md4sum);         


md4sum now contains the digest of the hashed data in buffer.



10.1.2 MD5


To use MD5 include the MD5 header "wolfssl/ctaocrypt/md5.h". The structure to use is Md5, which is a typedef. Before using, the hash initialization must be done with the InitMd5() call. Use Md5Update() to update the hash and Md5Final() to retrieve the final hash


byte md5sum[MD5_DIGEST_SIZE];

byte buffer[1024];      

// fill buffer with data to hash


Md5 md5;

InitMd5(&md5);


Md5Update(&md5, buffer, sizeof(buffer));  // can be called again and again

Md5Final(&md5, md5sum);         


md5sum now contains the digest of the hashed data in buffer.



10.1.3 SHA / SHA-256 / SHA-384 / SHA-512


To use SHA include the SHA header "wolfssl/ctaocrypt/sha.h". The structure to use is Sha, which is a typedef. Before using, the hash initialization must be done with the InitSha() call. Use ShaUpdate() to update the hash and ShaFinal() to retrieve the final hash:


byte shaSum[SHA_DIGEST_SIZE];

byte buffer[1024];      

// fill buffer with data to hash


Sha sha;

InitSha(&sha);


ShaUpdate(&sha, buffer, sizeof(buffer));  // can be called again and again

ShaFinal(&sha, shaSum);


shaSum now contains the digest of the hashed data in buffer.


To use either SHA-256 or SHA-512, follow the same steps as shown above, but use either the “wolfssl/ctaocrypt/sha256.h” or “wolfssl/ctaocrypt/sha512.h”.  The SHA-256 and SHA-512 functions are named similarly to the SHA functions.  


For SHA-256, the functions InitSha256(), Sha256Update(), and Sha256Final() will be used with the structure Sha256.


For SHA-512, the functions InitSha512(), Sha512Update(), and Sha512Final() will be used with the structure Sha512.



10.1.4 RIPEMD-160


To use RIPEMD-160, include the header "wolfssl/ctaocrypt/ripemd.h". The structure to use is RipeMd, which is a typedef. Before using, the hash initialization must be done with the InitRipeMd() call. Use RipeMdUpdate() to update the hash and RipeMdFinal() to retrieve the final hash


byte ripeMdSum[RIPEMD_DIGEST_SIZE];

byte buffer[1024];      

// fill buffer with data to hash


RipeMd ripemd;

InitRipeMd(&ripemd);


RipeMdUpdate(&ripemd, buffer, sizeof(buffer));  // can be called again and again

RipeMdFinal(&ripemd, ripeMdSum);         


ripeMdSum now contains the digest of the hashed data in buffer.



10.2 Keyed Hash Functions



10.2.1 HMAC


wolfCrypt currently provides HMAC for message digest needs. The structure Hmac is found in the header "wolfssl/ctaocrypt/hmac.h". HMAC initialization is done with HmacSetKey().  3 different types are supported with HMAC; MD5, SHA, and SHA-256. Here's an example with SHA-256.


Hmac    hmac;

bytekey[24];    // fill key with keying material

bytebuferr[2048];   // fill buffer with data to digest

bytehmacDigest[SHA256_DIGEST_SIZE];


HmacSetKey(&hmac, SHA256, key, sizeof(key));

HmacUpdate(&hmac, buffer, sizeof(buffer));

HmacFinal(&hmac, hmacDigest);


hmacDigest now contains the digest of the hashed data in buffer.



10.2.2 GMAC


wolfCrypt also provides GMAC for message digest needs. The structure Gmac is found in the header "wolfssl/ctaocrypt/aes.h", as it is an application AES-GCM. GMAC initialization is done with GmacSetKey().


Gmac    gmac;

bytekey[16];    // fill key with keying material

byte iv[12];// fill iv with an initialization vector

bytebuffer[2048];   // fill buffer with data to digest

bytegmacDigest[16];


GmacSetKey(&gmac, key, sizeof(key));

GmacUpdate(&hmac, iv, sizeof(iv), buffer, sizeof(buffer),

    gmacDigest, sizeof(gmacDigest));


gmacDigest now contains the digest of the hashed data in buffer.



10.2.3 Poly1305


wolfCrypt also provides Poly1305 for message digest needs. The structure Poly1305 is found in the header "wolfssl/wolfcrypt/poly1305.h". Poly1305 initialization is done with Poly1305SetKey(). The process of setting a key in Poly1305 should be done again, with a new key, when next using Poly1305 after Poly1305Final() has been called.


Poly1305    pmac;

bytekey[32];    // fill key with keying material

bytebuffer[2048];   // fill buffer with data to digest

bytepmacDigest[16];


Poly1305SetKey(&pmac, key, sizeof(key));

Poly1305Update(&pmac, buffer, sizeof(buffer));

Poly1305Final(&pmac, pmacDigest);


pmacDigest now contains the digest of the hashed data in buffer.



10.3 Block Ciphers



10.3.1 AES


wolfCrypt provides support for AES with key sizes of 16 bytes (128 bits), 24 bytes (192 bits), or 32 bytes (256 bits). CBC mode is supported for encryption/decryption and is provided through AesCbcEncrypt() and AesCbcDecrypt(). Please include the header "wolfssl/ctaocrypt/aes.h"  to use AES. AES has a block size of 16 bytes and the IV should also be 16 bytes. Function usage is usually as follows:


Aes enc;

Aes dec;


const byte key[] = {  // some 24 byte key };

const byte iv[] = { // some 16 byte iv };


byte plain[32];   // an increment of 16, fill with data

byte cipher[32];


// encrypt

AesSetKey(&enc, key, sizeof(key), iv, AES_ENCRYPTION);

AesCbcEncrypt(&enc, cipher, plain, sizeof(plain));


cipher now contains the cipher text from the plain text.


// decrypt

AesSetKey(&dec, key, sizeof(key), iv, AES_DECRYPTION);

AesCbcDecrypt(&dec, plain, cipher, sizeof(cipher));


plain now contains the original plaintext from the cipher text.



10.3.2 DES and 3DES


wolfCrypt provides support for DES and 3DES (Des3 since 3 is an invalid leading C identifier). To use these include the header "wolfssl/ctaocrypt/des.h". The structures you can use are Des and Des3. Initialization is done through Des_SetKey() or Des3_SetKey(). CBC encryption/decryption is provided through Des_CbcEnrypt() / Des_CbcDecrypt() and Des3_CbcEncrypt() / Des3_CbcDecrypt(). Des has a key size of 8 bytes (24 for 3DES) and the block size is 8 bytes, so only pass increments of 8 bytes to encrypt/decrypt functions. If your data isn't in a block size increment you'll need to add padding to make sure it is. Each SetKey() also takes an IV (an initialization vector that is the same size as the key size). Usage is usually like the following:


Des3 enc;

Des3 dec;


const byte key[] = {  // some 24 byte key };

const byte iv[] = { // some 24 byte iv };


byte plain[24];   // an increment of 8, fill with data

byte cipher[24];


// encrypt

Des3_SetKey(&enc, key, iv, DES_ENCRYPTION);

Des3_CbcEncrypt(&enc, cipher, plain, sizeof(plain));


cipher now contains the cipher text from the plain text.


// decrypt

Des3_SetKey(&dec, key, iv, DES_DECRYPTION);

Des3_CbcDecrypt(&dec, plain, cipher, sizeof(cipher));


plain now contains the original plaintext from the cipher text.



10.3.3 Camellia


wolfCrypt provides support for the Camellia block cipher. To use Camellia include the header "wolfssl/wolfcrypt/camellia.h". The structure you can use is called Camellia. Initialization is done through CamelliaSetKey(). CBC encryption/decryption is provided through CamelliaCbcEnrypt() and CamelliaCbcDecrypt() while direct encryption/decryption is provided through CamelliaEncryptDirect() and CamelliaDecryptDirect().


For usage examples please see the camellia_test() function in <wolfssl_root>/wolfcrypt/test/test.c.

 


10.4 Stream Ciphers



10.4.1 ARC4


The most common stream cipher used on the Internet is ARC4. wolfCrypt supports it through the header "wolfssl/ctaocrypt/arc4.h".  Usage is simpler than block ciphers because there is no block size and the key length can be any length. The following is a typical usage of ARC4.


Arc4 enc;

Arc4 dec;


const byte key[] = {  // some key any length};


byte plain[27];   // no size restriction, fill with data

byte cipher[27];


// encrypt

Arc4SetKey(&enc, key, sizeof(key));

Arc4Process(&enc, cipher, plain, sizeof(plain));


cipher now contains the cipher text from the plain text.


// decrypt

Arc4SetKey(&dec, key, sizeof(key));

Arc4Process(&dec, plain, cipher, sizeof(cipher));


plain now contains the original plaintext from the cipher text.



10.4.2 RABBIT


A newer stream cipher gaining popularity is RABBIT. This stream cipher can be used through wolfCrypt by including the header "wolfssl/ctaocrypt/rabbit.h". RABBIT is very fast compared to ARC4, but has key constraints of 16 bytes (128 bits) and an optional IV of 8 bytes (64 bits). Otherwise usage is exactly like ARC4:


Rabbit enc;

Rabbit dec;


const byte key[] = {  // some key 16 bytes};

const byte iv[] = { // some iv 8 bytes };


byte plain[27];   // no size restriction, fill with data

byte cipher[27];


// encrypt

RabbitSetKey(&enc, key, iv);  // iv can be a NULL pointer

RabbitProcess(&enc, cipher, plain, sizeof(plain));


cipher now contains the cipher text from the plain text.


// decrypt

RabbitSetKey(&dec, key, iv);

RabbitProcess(&dec, plain, cipher, sizeof(cipher));


plain now contains the original plaintext from the cipher text.



10.4.3 HC-128


Another stream cipher in current use is HC-128, which is even faster than RABBIT (about 5 times faster than ARC4).  To use it with wolfCrypt, please include the header "wolfssl/ctaocrypt/hc128.h". HC-128 also uses 16 bytes keys (128 bits) but uses 16 bytes vs (128 bits) unlike RABBIT.


HC128 enc;

HC128 dec;


const byte key[] = {  // some key 16 bytes};

const byte iv[] = { // some iv 16 bytes };


byte plain[37];   // no size restriction, fill with data

byte cipher[37];


// encrypt

Hc128_SetKey(&enc, key, iv);  // iv can be a NULL pointer

Hc128_Process(&enc, cipher, plain, sizeof(plain));


cipher now contains the cipher text from the plain text.


// decrypt

Hc128_SetKey(&dec, key, iv);

Hc128_Process(&dec, plain, cipher, sizeof(cipher));


plain now contains the original plaintext from the cipher text.


10.4.4 ChaCha


ChaCha with 20 rounds is slightly faster than ARC4 while maintaining a high level of security.  To use it with wolfCrypt, please include the header "wolfssl/wolfcrypt/chacha.h". ChaCha typically uses 32 byte keys (256 bit) but can also use 16 byte keys (128 bits).


CHACHA enc;

CHACHA dec;


const byte key[] = {  // some key 32 bytes};

const byte iv[]  = {  // some iv 12 bytes };


byte plain[37];   // no size restriction, fill with data

byte cipher[37];


// encrypt

Chacha_SetKey(&enc, key, keySz);

Chacha_SetIV(&enc, iv, counter); //counter is the start block

//counter is usually set as 0

Chacha_Process(&enc, cipher, plain, sizeof(plain));


cipher now contains the cipher text from the plain text.


// decrypt

Chacha_SetKey(&enc, key, keySz);

Chacha_SetIV(&enc, iv, counter);

Chacha_Process(&enc, plain, cipher, sizeof(cipher));


plain now contains the original plaintext from the cipher text.


Chacha_SetKey only needs to be set once but for each packet of information sent Chacha_SetIV must be called with a new iv (nonce). Counter is set as an argument to allow for partially decrypting/encrypting information by starting at a different block when performing the encrypt/decrypt process, but in most cases is set to 0. ChaCha should not be used without a mac algorithm ie Poly1305 , hmac.



10.5 Public Key Cryptography



10.5.1 RSA


wolfCrypt provides support for RSA through the header "wolfssl/ctaocrypt/rsa.h". There are two types of RSA keys, public and private. A public key allows anyone to encrypt something that only the holder of the private key can decrypt. It also allows the private key holder to sign something and anyone with a public key can verify that only the private key holder actually signed it. Usage is usually like the following:


RsaKey rsaPublicKey;


byte publicKeyBuffer[]  = { // holds the raw data from the key, maybe from a file

                               like RsaPublicKey.der };

word32 idx = 0;             //  where to start reading into the buffer


RsaPublicKeyDecode(publicKeyBuffer, &idx, &rsaPublicKey, sizeof(publicKeyBuffer));


byte in[] = { // plain text to encrypt };

byte out[128];

RNG rng;


InitRng(&rng);


word32 outLen = RsaPublicEncrypt(in, sizeof(in), out, sizeof(out), &rsaPublicKey, &rng);


Now ‘out’ holds the cipher text from the plain text ‘in’. RsaPublicEncrypt() will return the length in bytes written to out or a negative number in case of an error. RsaPublicEncrypt() needs a RNG (Random Number Generator) for the padding used by the encryptor and it must be initialized before it can be used. To make sure that the output buffer is large enough to pass you can first call RsaEncryptSize() which will return the number of bytes that a successful call to RsaPublicEnrypt() will write.


In the event of an error, a negative return from RsaPublicEnrypt(), or RsaPublicKeyDecode() for that matter, you can call wolfCryptErrorString() to get a string describing the error that occurred.


void CTaoCryptErrorString(int error, char* buffer);


Make sure that buffer is at least MAX_ERROR_SZ bytes (80).


Now to decrypt out:


RsaKey rsaPrivateKey;


byte privateKeyBuffer[] = { // hold the raw data from the key, maybe from a file

                               like RsaPrivateKey.der };

word32 idx = 0;             //  where to start reading into the buffer


RsaPrivateKeyDecode(privateKeyBuffer, &idx, &rsaPrivateKey, sizeof(privateKeyBuffer));


byte plain[128];


word32 plainSz = RsaPrivateDecrypt(out, outLen, plain, sizeof(plain), &rsaPrivateKey);


Now plain will hold plainSz bytes or an error code. For complete examples of each type in wolfCrypt please see the file wolfcrypt/test/test.c.  Note that the RsaPrivateKeyDecode function only accepts keys in raw DER format.



10.5.2 DH (Diffie-Hellman)


wolfCrypt provides support for Diffie-Hellman through the header "wolfssl/ctaocrypt/dh.h".  The Diffie-Hellman key exchange algorithm allows two parties to establish a shared secret key.  Usage is usually similar to the following example, where sideA and sideB designate the two parties.


In the following example, dhPublicKey contains the Diffie-Hellman public parameters.  privA holds the generated private key for sideA, pubA holds the generated public key for sideA, and agreeA holds the mutual key that both sides have agreed on.


DhKey     dhPublicKey;

word32    idx = 0;  // where to start reading into the publicKeyBuffer

word32    pubASz, pubBSz, agreeASz;

byte tmp[1024];

RNG  rng;


byte privA[128];

byte pubA[128];

byte agreeA[128];


InitDhKey(&dhPublicKey);


byte publicKeyBuffer[] = { // holds the raw data from the public key parameters, maybe from a file like dh1024.der }


DhKeyDecode(tmp, &idx, &dhPublicKey, publicKeyBuffer);


InitRng(&rng);  // Initialize random number generator


DhGenerateKeyPair() will generate a public and private DH key based on the initial public parameters in dhPublicKey.


DhGenerateKeyPair(&dhPublicKey, &rng, privA, &privASz, pubA, &pubASz);


After sideB sends their public key (pubB) to sideA, sideA can then generate the mutually-agreed key(agreeA) using the DhAgree() function.


DhAgree(&dhPublicKey, agreeA, &agreeASz, privA, privASz, pubB, pubBSz);


Now, agreeA holds sideA’s mutually-generated key (of size agreeASz bytes).  The same process will have been done on sideB.


For a complete example of Diffie-Hellman in wolfCrypt, see the file wolfcrypt/test/test.c.



10.5.3 EDH (Ephemeral Diffie-Hellman)


A wolfSSL server can do Ephemeral Diffie-Hellman.  No build changes are needed to add this feature, though an application will have to register the ephemeral group parameters on the server side to enable the EDH cipher suites.  A new API can be used to do this:


int wolfSSL_SetTmpDH(CYASSL* ssl, unsigned char* p,int pSz,unsigned char* g,int gSz);


The example server and echoserver use this function from SetDH().



10.5.4 DSA (Digital Signature Algorithm)


wolfCrypt provides support for DSA and DSS through the header "wolfssl/ctaocrypt/dsa.h".  DSA allows for the creation of a digital signature based on a given data hash.  DSA uses the SHA hash algorithm to generate a hash of a block of data, then signs that hash using the signer’s private key.  Standard usage is similar to the following.  


We first declare our DSA key structure (key), initialize our initial message (message) to be signed, and initialize our DSA key buffer (dsaKeyBuffer).


DsaKey key;

byte   message[] = { // message data to sign }

byte   dsaKeyBuffer[] = { // holds the raw data from the DSA key, maybe from a file

                           like dsa512.der }


We then declare our SHA structure (sha), random number generator (rng), array to store our SHA hash (hash), array to store our signature (signature), idx (to mark where to start reading in our dsaKeyBuffer), and an int (answer) to hold our return value after verification.


Sha  sha;

RNG  rng;

byte  hash[SHA_DIGEST_SIZE];

byte  signature[40];

word32 idx = 0;

int  answer;


Set up and create the SHA hash.  For more information on wolfCrypt’s SHA algorithm, see section 10.1.3. The SHA hash of “message” is stored in the variable “hash”.


InitSha(&sha);

ShaUpdate(&sha, message, sizeof(message));

ShaFinal(&sha, hash);


Initialize the DSA key structure, populate the structure key value, and initialize the random number generator (rng).


InitDsaKey(&key);

DsaPrivateKeyDecode(dsaKeyBuffer, &idx, &key, sizeof(dsaKeyBuffer));


InitRng(&rng);


The DsaSign() function creates a signature (signature) using the DSA private key, hash value, and random number generator.


DsaSign(hash, signature, &key, &rng);


To verify the signature, use DsaVerify(). If verification is successful, answer will be equal to “1”. Once finished, free the DSA key structure using FreeDsaKey().


DsaVerify(hash, signature, &key, &answer);

FreeDsaKey(&key);

Docs -> wolfSSL Manual

Questions? +1 (425) 245-8247