The API for Skinny-C provides CTR mode for bulk encryption of arbitrarily-sized data blocks. The first step is to initialize the CTR control structure with the key. For this example we will use a 256-bit key with Skinny128:
The skinny128_ctr_init() function chooses the best CTR mode implementation for your platform at runtime. For example, the AVX2 backend will be used if your CPU supports AVX2 and the library was compiled with AVX2 support enabled.
The next step is to set the counter value for the current data block. Counter values are typically formed by combining a packet sequence number with an offset into the packet. It is very important that the counter values be different from one packet to the next.
The following is an example of setting the initial counter value based on a 32-bit packet sequence number:
The bytes at the end of the counter value will be incremented each time CTR mode needs a new 128-bit block of encrypted data. In this example there are 12 bytes available for incrementing.
If your application processes large amounts of data, then there is a risk that the sequence number might roll around. If this is the case, then you should use a 64-bit sequence number, or abort the connection when the sequence number rolls around, or both.
Encryption of packets is accomplished as follows:
The first two parameters are the output buffer for the ciphertext and the input buffer for the plaintext. In this example we are encrypting the data in-place within the same buffer but they can be different.
To encrypt the next packet, increment the sequence number and then call skinny128_ctr_set_counter() and skinny128_ctr_encrypt() again.
In CTR mode, decryption and encryption are identical operations, so there is no "decrypt" function in the CTR API. Use skinny128_ctr_encrypt().
Once you have finished encrypting all packets, you should clean up the CTR control structure to free any dyanmically-allocated memory that was allocated by skinny128_ctr_init():
SKINNY is a tweakable block cipher, so it is possible to encrypt packets with CTR mode in a slightly different way. Instead of passing the sequence number in as part of the counter block, the sequence number can be provided as a per-packet tweak.
This is definitely useful when encrypting packets with Skinny64 or Mantis as the 64-bit counter value is not large enough to contain both a 64-bit sequence number and a packet offset.
As before, we start by initializing the 128-bit key and the CTR control structure with Skinny64:
For each packet, the sequence number is provided as the tweak and the counter value is reset to all-zeroes:
Packet encryption is similar to before:
Finally, clean up when the session ends:
The API for Skinny-C provides ECB encryption on a block-by-block basis. The first step is to initialize the key schedule using the key. For this example we will use a 256-bit key with Skinny128:
Each block of the plaintext is then encrypted as follows:
To decrypt a ciphertext back to the original plaintext:
The API for Skinny-C provides an alternative ECB interface that encrypts multiple blocks in parallel on platforms that have SIMD instruction support. This can be useful for implementing block cipher modes like OCB that operate on blocks in parallel.
To perform parallel encryption, we start by initializing the parallel ECB context and then set the key:
The skinny128_parallel_ecb_init() function chooses the best parallel ECB implementation for your platform at runtime. For example, the AVX2 backend will be used if your CPU supports AVX2 and the library was compiled with AVX2 support enabled.
Encryption of eight blocks at a time is accomplished as follows (decryption is similar):
The first two parameters are the output buffer for the ciphertext and the input buffer for the plaintext. In this example we are encrypting the data in-place within the same buffer but they can be different.
The amount of parallelism is dependent upon the specific back end implementation. The best parallel block size (in bytes) is given by ecb.parallel_size
. This can be used to tune the parallel block size at runtime.
Once you have finished encrypting or decrypting data, you should clean up the parallel ECB control structure to free any dyanmically-allocated memory that was allocated by skinny128_parallel_ecb_init():