blob: 2413f68fb64be1d5bfa09c22fbd7b03107167385 [file] [log] [blame]
// SPDX-License-Identifier: BSD-2-Clause
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
#include "tomcrypt_private.h"
#ifdef LTC_PADDING
/**
Determine the to-be-padded length.
@param length [in/out] The size of the data before/after padding
@param mode Mask of (LTC_PAD_xxx | block_length)
@return CRYPT_OK on success
*/
static int _padding_padded_length(unsigned long *length, unsigned long mode)
{
enum padding_type padding;
unsigned char pad, block_length, r, t;
LTC_ARGCHK(length != NULL);
block_length = mode & 0xff;
padding = mode & LTC_PAD_MASK;
r = *length % block_length;
switch (padding) {
case LTC_PAD_ZERO:
if (r == 0) {
t = 0;
break;
}
/* FALLTHROUGH */
case LTC_PAD_PKCS7:
case LTC_PAD_ONE_AND_ZERO:
case LTC_PAD_ZERO_ALWAYS:
t = 1;
break;
#ifdef LTC_RNG_GET_BYTES
case LTC_PAD_ISO_10126:
do {
if (rng_get_bytes(&t, sizeof(t), NULL) != sizeof(t)) {
return CRYPT_ERROR_READPRNG;
}
t %= (256 / block_length);
} while (t == 0);
break;
#endif
case LTC_PAD_ANSI_X923:
if (block_length != 16) {
return CRYPT_INVALID_ARG;
}
t = 1;
break;
default:
return CRYPT_INVALID_ARG;
}
pad = (t * block_length) - r;
if ((pad == 0) && (padding != LTC_PAD_ZERO)) {
pad = block_length;
}
*length += pad;
return CRYPT_OK;
}
/**
Add padding to data.
This pads your data.
@param data The data to depad
@param length The size of the data before padding
@param padded_length [in/out] The size of the data available/after padding
@param mode One of the LTC_PAD_xx flags
@return CRYPT_OK on success
*/
int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode)
{
unsigned long diff, l;
enum padding_type type;
int err;
LTC_ARGCHK(data != NULL);
LTC_ARGCHK(padded_length != NULL);
l = length;
if ((err = _padding_padded_length(&l, mode)) != CRYPT_OK) {
return err;
}
type = mode & LTC_PAD_MASK;
if (*padded_length < l) {
#ifdef LTC_RNG_GET_BYTES
if (type != LTC_PAD_ISO_10126) {
*padded_length = l;
} else {
*padded_length = length + 256;
}
#else
*padded_length = l;
#endif
return CRYPT_BUFFER_OVERFLOW;
}
diff = l - length;
if (diff > 255) return CRYPT_INVALID_ARG;
switch (type) {
case LTC_PAD_PKCS7:
XMEMSET(&data[length], diff, diff);
break;
#ifdef LTC_RNG_GET_BYTES
case LTC_PAD_ISO_10126:
if (rng_get_bytes(&data[length], diff-1, NULL) != diff-1) {
return CRYPT_ERROR_READPRNG;
}
data[l-1] = diff;
break;
#endif
case LTC_PAD_ANSI_X923:
XMEMSET(&data[length], 0, diff-1);
data[l-1] = diff;
break;
case LTC_PAD_ONE_AND_ZERO:
XMEMSET(&data[length + 1], 0, diff);
data[length] = 0x80;
break;
case LTC_PAD_ZERO:
case LTC_PAD_ZERO_ALWAYS:
XMEMSET(&data[length], 0, diff);
break;
default:
return CRYPT_INVALID_ARG;
}
*padded_length = l;
return CRYPT_OK;
}
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */