mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-17 12:48:41 +00:00
Fix UB in serpent ##crypto (#17899)
This commit is contained in:
parent
651398d6af
commit
6119a784e8
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user