152 lines
3.5 KiB
C
152 lines
3.5 KiB
C
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
|
|
/* SPDX-License-Identifier: Unlicense */
|
|
#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 s_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:
|
|
case LTC_PAD_SSH:
|
|
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 l, n;
|
|
enum padding_type type;
|
|
int err;
|
|
unsigned char diff, pad;
|
|
|
|
LTC_ARGCHK(data != NULL);
|
|
LTC_ARGCHK(padded_length != NULL);
|
|
|
|
l = length;
|
|
if ((err = s_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;
|
|
}
|
|
|
|
if (l - length > 255) return CRYPT_INVALID_ARG;
|
|
diff = (unsigned char)(l - length);
|
|
|
|
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-1u, NULL) != diff-1u) {
|
|
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_SSH:
|
|
pad = 0x1;
|
|
for (n = length; n < l; ++n) {
|
|
data[n] = pad++;
|
|
}
|
|
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
|