Padding
Some cryptographic primitives, such as AES ciphers in block cipher modes of operation, often require that the input data size be a multiple of the primitive's block size. Because the size of some data (e.g., plaintext) can be variable, padding can be added to meet the primitive's size requirements.
Padding also defends against plaintext length attacks by hiding the length of the plaintext.
Padding is only required when an algorithm uses a block cipher mode of operation and its input is not a multiple of the cipher block size. Padding is optional if the input size is already a multiple of the block size.
The qcrypto cipher algorithm APIs can provide automatic padding; otherwise, the caller has to provide any padding the algorithm requires.
The supported padding algorithms described here are ones that are reversible, which means that there is no ambiguity when the ciphertext is decrypted and unpadded into the plaintext. If there is an error in the padding removal, the plaintext is corrupted and shouldn't be trusted.
Both PKCS7 and ISO7816 padding add an extra block to the input data even if the input data is a multiple of the block size.
The cryptography industry is moving away from block ciphers and padding towards stream ciphers, which work on input of any length and don't require padding.
PKCS7 padding
The PKCS7 padding mode adds whole bytes to the end of input data until it is equal to a multiple of the blocksize. The padding byte value is the number of bytes that need to be added to reach the blocksize multiple.
PKCS7 padding supports blocksizes of up to 255 bytes.
See the library reference for detailed descriptions of the following functions:
ISO7816 padding
The ISO.2FIEC_7816-4 padding mode adds a byte of value 0x80 followed by as many 0x00 bytes as are required to make the data equal to a multiple of the blocksize.See the library reference for detailed descriptions of the following functions:
Padding examples
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <qcrypto/qcrypto.h>
#include <qcrypto/qcrypto_error.h>
int main(void)
{
int ret;
int pad_result = 1;
int unpad_result = 1;
size_t blocksize = 16;
const uint8_t inbuf[] = {0xab, 0xab};
const size_t insize = sizeof(inbuf);
const uint8_t *in_bin = inbuf;
size_t insize_cmp = insize;
const uint8_t outbuf[] = {
0xab, 0xab, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
0x0e, 0x0e, 0x0e, 0x0e
};
const size_t outsize = sizeof(outbuf);
size_t outsize_cmp = outsize;
uint8_t out_cmpbuf[outsize];
uint8_t *out_cmp = out_cmpbuf;
/* Initialize the Qcrypto Library */
ret = qcrypto_init(QCRYPTO_INIT_LAZY, NULL);
if (ret != QCRYPTO_R_EOK) {
fprintf(stderr, "qcryto_init() failed (%d:%s)\n", ret, qcrypto_strerror(ret));
goto done;
}
/* Padding pkcs7 pad */
ret = qcrypto_padding_pkcs7_pad(in_bin, insize, out_cmp, &outsize_cmp, blocksize);
if (ret != QCRYPTO_R_EOK) {
fprintf(stderr, "qcrypto_padding_pkcs7_pad() failed (%d:%s)\n", ret, qcrypto_strerror(ret));
goto done;
}
/* Compare pad length */
if (outsize_cmp != outsize) {
fprintf(stderr, "Computed pad length failed to match with expected pad length\n");
goto done;
}
/* Compare pad results */
pad_result = memcmp(out_cmp, outbuf, outsize);
if (pad_result == 0) {
printf("Computed pad matches with expected pad\n");
} else {
fprintf(stderr, "Computed pad failed to match with expected pad\n");
goto done;
}
/* Padding pkcs7 unpad */
insize_cmp = outsize;
ret = qcrypto_padding_pkcs7_unpad(out_cmp, &insize_cmp);
if (ret != QCRYPTO_R_EOK) {
fprintf(stderr, "qcrypto_padding_pkcs7_unpad() failed (%d:%s)\n", ret, qcrypto_strerror(ret));
goto done;
}
/* Compare unpad length */
if (insize_cmp != insize) {
fprintf(stderr, "Computed unpad length failed to match with expected unpad length\n");
goto done;
}
/* Compare unpad results */
unpad_result = memcmp(out_cmp, inbuf, insize_cmp);
if (unpad_result == 0) {
printf("Computed unpad matches with expected unpad\n");
} else {
fprintf(stderr, "Computed unpad failed to match with expected unpad\n");
goto done;
}
goto done;
done:
/* Uninitialize the Qcrypto Library */
qcrypto_uninit();
return ret;
}