Fix UB in serpent ##crypto (#17899)

This commit is contained in:
Liumeo 2020-11-09 23:36:16 -05:00 committed by GitHub
parent 651398d6af
commit 6119a784e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 49 deletions

View File

@ -9,7 +9,7 @@ static bool serpent_set_key(RCrypto *cry, const ut8 *key, int keylen, int mode,
if ((keylen != 128 / 8) && (keylen != 192 / 8) && (keylen != 256 / 8)) {
return false;
}
st.key_size = keylen*8;
st.key_size = keylen * 8;
eprintf ("key_size: %d\n", st.key_size);
memcpy (st.key, key, keylen);
cry->dir = direction;
@ -33,16 +33,16 @@ static bool update(RCrypto *cry, const ut8 *buf, int len) {
const int blocks = size / BLOCK_SIZE;
int i, j;
ut8 *const obuf = calloc (4, size/4);
ut8 *const obuf = calloc (4, size / 4);
if (!obuf) {
return false;
}
ut32 *const ibuf = calloc (4, size/4);
ut32 *const ibuf = calloc (4, size / 4);
if (!ibuf) {
free (obuf);
return false;
}
ut32 *const tmp = calloc (4, size/4);
ut32 *const tmp = calloc (4, size / 4);
if (!tmp) {
free (obuf);
free (ibuf);
@ -50,34 +50,37 @@ static bool update(RCrypto *cry, const ut8 *buf, int len) {
}
// Construct ut32 blocks from byte stream
for (j = 0; j < size/4; j++) {
ibuf[j] = r_read_le32(&buf[4*j]);
for (j = 0; j < len / 4; j++) {
ibuf[j] = r_read_le32 (buf + 4 * j);
}
if (len & 0x3) {
ut8 tail[4] = {0}; // Zero padding
memcpy (tail, buf + (len & ~0x3), len & 0x3);
ibuf[len / 4] = r_read_le32 (tail);
}
// Zero padding.
if (cry->dir == 0) {
for (i = 0; i < blocks; i++) {
// delta in number of ut32
const int delta = (BLOCK_SIZE * i)/4;
const int delta = (BLOCK_SIZE * i) / 4;
serpent_encrypt (&st, ibuf + delta, tmp + delta);
}
} else if (cry->dir > 0) {
for (i = 0; i < blocks; i++) {
// delta in number of ut32
const int delta = (BLOCK_SIZE * i)/4;
const int delta = (BLOCK_SIZE * i) / 4;
serpent_decrypt (&st, ibuf + delta, tmp + delta);
}
}
// Construct ut32 blocks from byte stream
int k;
for (j = 0; j < size/4; j++) {
k = 4*j;
for (j = 0; j < size / 4; j++) {
k = 4 * j;
obuf[k] = tmp[j] & 0xff;
obuf[k+1] = (tmp[j] >> 8) & 0xff;
obuf[k+2] = (tmp[j] >> 16) & 0xff;
obuf[k+3] = (tmp[j] >> 24) & 0xff;
obuf[k + 1] = (tmp[j] >> 8) & 0xff;
obuf[k + 2] = (tmp[j] >> 16) & 0xff;
obuf[k + 3] = (tmp[j] >> 24) & 0xff;
}
r_crypto_append (cry, obuf, size);

View File

@ -74,49 +74,49 @@ static inline ut8 get_bit(int i, ut32 input) {
void apply_IP(ut32 in[DW_BY_BLOCK], ut32 out[DW_BY_BLOCK]) {
int index;
int i;
for (i = 0; i < DW_BY_BLOCK*32; i++) {
for (i = 0; i < DW_BY_BLOCK * 32; i++) {
index = IPTable[i];
out[i/32] ^= (-(ut32)get_bit (index%32, in[index/32]) ^ out[i/32])
& (1 << i);
out[i / 32] ^= (-(ut32)get_bit (index % 32, in[index / 32]) ^ out[i / 32])
& (1 << (i & 0x1f));
}
}
void apply_FP(ut32 in[DW_BY_BLOCK], ut32 out[DW_BY_BLOCK]) {
int index;
int i;
for (i = 0; i < DW_BY_BLOCK*32; i++) {
for (i = 0; i < DW_BY_BLOCK * 32; i++) {
index = FPTable[i];
out[i/32] ^= (-(ut32)get_bit (index%32, in[index/32]) ^ out[i/32])
& (1 << i);
out[i / 32] ^= (-(ut32)get_bit (index % 32, in[index / 32]) ^ out[i / 32])
& (1 << (i & 0x1f));
}
}
void serpent_keyschedule(struct serpent_state st,
ut32 subkeys[NB_SUBKEYS*DW_BY_BLOCK]) {
ut32 subkeys[NB_SUBKEYS * DW_BY_BLOCK]) {
if ((st.key_size != 128) && (st.key_size != 192)
&& (st.key_size != 256)) {
eprintf ("Invalid key size");
exit (1);
}
ut32 tmpkeys[DW_BY_BLOCK*NB_SUBKEYS+DW_BY_USERKEY] = {0};
ut32 tmpkeys[DW_BY_BLOCK * NB_SUBKEYS + DW_BY_USERKEY] = {0};
const ut32 phi = 0x9e3779b9;
int si;
ut8 in, out;
int i, j, l;
for (i = 0; i < st.key_size/32; i++) {
for (i = 0; i < st.key_size / 32; i++) {
tmpkeys[i] = st.key[i];
}
// Padding key
if (st.key_size != 256) {
tmpkeys[st.key_size/32] = 1;
tmpkeys[st.key_size / 32] = 1;
}
for (i=DW_BY_USERKEY; i < NB_SUBKEYS*DW_BY_BLOCK+DW_BY_USERKEY; i++) {
tmpkeys[i] = tmpkeys[i-8] ^ tmpkeys[i-5] ^ tmpkeys[i-3] ^ tmpkeys[i-1]
^ phi ^ (i-8);
for (i = DW_BY_USERKEY; i < NB_SUBKEYS * DW_BY_BLOCK + DW_BY_USERKEY; i++) {
tmpkeys[i] = tmpkeys[i - 8] ^ tmpkeys[i - 5] ^ tmpkeys[i - 3] ^ tmpkeys[i - 1]
^ phi ^ (i - 8);
rotl (tmpkeys + i, 11);
}
@ -126,24 +126,24 @@ void serpent_keyschedule(struct serpent_state st,
// Iterates over all nibbles of the subkey i
for (j = 0; j < NIBBLES_BY_SUBKEY; j++) {
in = get_bit (j, tmpkeys[0+DW_BY_BLOCK*i+DW_BY_USERKEY])
| get_bit (j, tmpkeys[1+DW_BY_BLOCK*i+DW_BY_USERKEY]) << 1
| get_bit (j, tmpkeys[2+DW_BY_BLOCK*i+DW_BY_USERKEY]) << 2
| get_bit (j, tmpkeys[3+DW_BY_BLOCK*i+DW_BY_USERKEY]) << 3;
in = get_bit (j, tmpkeys[0 + DW_BY_BLOCK * i + DW_BY_USERKEY])
| get_bit (j, tmpkeys[1 + DW_BY_BLOCK * i + DW_BY_USERKEY]) << 1
| get_bit (j, tmpkeys[2 + DW_BY_BLOCK * i + DW_BY_USERKEY]) << 2
| get_bit (j, tmpkeys[3 + DW_BY_BLOCK * i + DW_BY_USERKEY]) << 3;
out = apply_sbox (si, in);
for (l = 0; l < DW_BY_BLOCK; l++) {
subkeys[l+DW_BY_BLOCK*i] |= get_bit (l, (ut32)out) << j;
subkeys[l + DW_BY_BLOCK * i] |= get_bit (l, (ut32)out) << j;
}
}
}
// Apply IP on every subkey
for (i = 0; i < NB_SUBKEYS; i++) {
apply_IP (&subkeys[i*DW_BY_BLOCK],
&tmpkeys[DW_BY_USERKEY + i*DW_BY_BLOCK]);
apply_IP (&subkeys[i * DW_BY_BLOCK],
&tmpkeys[DW_BY_USERKEY + i * DW_BY_BLOCK]);
}
memcpy (subkeys, tmpkeys + DW_BY_USERKEY, 132*sizeof(ut32));
memcpy (subkeys, tmpkeys + DW_BY_USERKEY, 132 * sizeof(ut32));
}
void apply_xor(ut32 block[DW_BY_BLOCK], ut32 subkey[DW_BY_BLOCK]) {
@ -159,11 +159,11 @@ void apply_permut(ut32 block[DW_BY_BLOCK]) {
rotl (tmp_block + 0, 13);
rotl (tmp_block + 2, 3);
tmp_block[1] ^= tmp_block[0] ^ tmp_block[2];
tmp_block[3] ^= tmp_block[2] ^ (tmp_block[0]<<3);
tmp_block[3] ^= tmp_block[2] ^ (tmp_block[0] << 3);
rotl (tmp_block + 1, 1);
rotl (tmp_block + 3, 7);
tmp_block[0] ^= tmp_block[1] ^ tmp_block[3];
tmp_block[2] ^= tmp_block[3] ^ (tmp_block[1]<<7);
tmp_block[2] ^= tmp_block[3] ^ (tmp_block[1] << 7);
rotl (tmp_block + 0, 5);
rotl (tmp_block + 2, 22);
apply_IP (tmp_block, block);
@ -174,11 +174,11 @@ void apply_permut_inv(ut32 block[DW_BY_BLOCK]) {
apply_FP (block, tmp_block);
rotr (tmp_block + 0, 5);
rotr (tmp_block + 2, 22);
tmp_block[2] ^= tmp_block[3] ^ (tmp_block[1]<<7);
tmp_block[2] ^= tmp_block[3] ^ (tmp_block[1] << 7);
tmp_block[0] ^= tmp_block[1] ^ tmp_block[3];
rotr (tmp_block + 3, 7);
rotr (tmp_block + 1, 1);
tmp_block[3] ^= tmp_block[2] ^ (tmp_block[0]<<3);
tmp_block[3] ^= tmp_block[2] ^ (tmp_block[0] << 3);
tmp_block[1] ^= tmp_block[0] ^ tmp_block[2];
rotr (tmp_block + 2, 3);
rotr (tmp_block + 0, 13);
@ -189,18 +189,18 @@ void apply_round(int round, ut32 block[DW_BY_BLOCK],
ut32 subkeys[DW_BY_BLOCK*NB_SUBKEYS]) {
int i, j;
apply_xor (block, subkeys + 4*round);
apply_xor (block, subkeys + 4 * round);
for (i = 0; i < DW_BY_BLOCK; i++) {
ut32 res = 0;
for (j = 0; j < 8; j++) {
res |= apply_sbox (round%8, (block[i] >> 4*j) & 0xf) << 4*j;
res |= apply_sbox (round % 8, (block[i] >> 4 * j) & 0xf) << 4 * j;
}
block[i] = res;
}
if (round == NB_ROUNDS - 1) {
apply_xor (block, subkeys + 4*(round+1));
apply_xor (block, subkeys + 4 * (round + 1));
} else {
apply_permut (block);
}
@ -209,7 +209,7 @@ void apply_round(int round, ut32 block[DW_BY_BLOCK],
void apply_round_inv(int round, ut32 block[DW_BY_BLOCK],
ut32 subkeys[DW_BY_BLOCK*NB_SUBKEYS]) {
if (round == NB_ROUNDS - 1) {
apply_xor (block, subkeys + 4*(round+1));
apply_xor (block, subkeys + 4 * (round + 1));
} else {
apply_permut_inv (block);
}
@ -220,18 +220,18 @@ void apply_round_inv(int round, ut32 block[DW_BY_BLOCK],
for (i = 0; i < DW_BY_BLOCK; i++) {
res = 0;
for (j = 0; j < 8; j++) {
res |= apply_sbox_inv (round%8, (block[i] >> 4*j) & 0xf) << 4*j;
res |= apply_sbox_inv (round%8, (block[i] >> 4 * j) & 0xf) << 4 * j;
}
block[i] = res;
}
apply_xor (block, subkeys + 4*round);
apply_xor (block, subkeys + 4 * round);
}
void serpent_encrypt(struct serpent_state *st, ut32 in[DW_BY_BLOCK],
ut32 out[DW_BY_BLOCK]) {
int i;
ut32 subkeys[DW_BY_BLOCK*NB_SUBKEYS] = {0};
ut32 subkeys[DW_BY_BLOCK * NB_SUBKEYS] = {0};
ut32 tmp_block[DW_BY_BLOCK] = {0};
serpent_keyschedule (*st, subkeys);
@ -248,7 +248,7 @@ void serpent_encrypt(struct serpent_state *st, ut32 in[DW_BY_BLOCK],
void serpent_decrypt(struct serpent_state *st, ut32 in[DW_BY_BLOCK],
ut32 out[DW_BY_BLOCK]) {
int i;
ut32 subkeys[DW_BY_BLOCK*NB_SUBKEYS] = {0};
ut32 subkeys[DW_BY_BLOCK * NB_SUBKEYS] = {0};
ut32 tmp_block[DW_BY_BLOCK] = {0};
serpent_keyschedule (*st, subkeys);

View File

@ -35,6 +35,6 @@ void serpent_decrypt(struct serpent_state *st, ut32 in[DW_BY_BLOCK], ut32 out[DW
* all the subkeys needed for the encryptio/dcryption with serpent.
*/
void serpent_keyschedule(struct serpent_state st,
ut32 subkeys[NB_SUBKEYS*DW_BY_BLOCK]);
ut32 subkeys[NB_SUBKEYS * DW_BY_BLOCK]);
#endif

View File

@ -932,6 +932,14 @@ EXPECT=<<EOF
EOF
RUN
NAME=rahash2 -E serpent-ecb zero padding
FILE=-
CMDS=!rahash2 -E serpent-ecb -S "1032547698badcfe1032547698badcfe1032547698badcfe1032547698badcfe" -x "101231" | rax2 -S
EXPECT=<<EOF
417dfc518e8146ea81b089731b56fefa
EOF
RUN
NAME=rahash2 -a fletcher8 -s hello-world
FILE=-
CMDS=!rahash2 -a fletcher8 -s hello-world