KeyEncoding: more constant time

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2018-05-30 23:16:41 +02:00
parent ba4672b422
commit e664a05d4b

View File

@ -62,11 +62,10 @@ public final class KeyEncoding {
final byte[] key = new byte[KEY_LENGTH]; final byte[] key = new byte[KEY_LENGTH];
if (input.length != KEY_LENGTH_BASE64 || input[KEY_LENGTH_BASE64 - 1] != '=') if (input.length != KEY_LENGTH_BASE64 || input[KEY_LENGTH_BASE64 - 1] != '=')
throw new IllegalArgumentException(KEY_LENGTH_BASE64_EXCEPTION_MESSAGE); throw new IllegalArgumentException(KEY_LENGTH_BASE64_EXCEPTION_MESSAGE);
int i; int i, ret = 0;
for (i = 0; i < KEY_LENGTH / 3; ++i) { for (i = 0; i < KEY_LENGTH / 3; ++i) {
final int val = decodeBase64(input, i * 4); final int val = decodeBase64(input, i * 4);
if (val < 0) ret |= val >>> 31;
throw new IllegalArgumentException(KEY_LENGTH_BASE64_EXCEPTION_MESSAGE);
key[i * 3] = (byte) ((val >>> 16) & 0xff); key[i * 3] = (byte) ((val >>> 16) & 0xff);
key[i * 3 + 1] = (byte) ((val >>> 8) & 0xff); key[i * 3 + 1] = (byte) ((val >>> 8) & 0xff);
key[i * 3 + 2] = (byte) (val & 0xff); key[i * 3 + 2] = (byte) (val & 0xff);
@ -78,10 +77,12 @@ public final class KeyEncoding {
'A', 'A',
}; };
final int val = decodeBase64(endSegment, 0); final int val = decodeBase64(endSegment, 0);
if (val < 0 || (val & 0xff) != 0) ret |= (val >>> 31) | (val & 0xff);
throw new IllegalArgumentException(KEY_LENGTH_BASE64_EXCEPTION_MESSAGE);
key[i * 3] = (byte) ((val >>> 16) & 0xff); key[i * 3] = (byte) ((val >>> 16) & 0xff);
key[i * 3 + 1] = (byte) ((val >>> 8) & 0xff); key[i * 3 + 1] = (byte) ((val >>> 8) & 0xff);
if (ret != 0)
throw new IllegalArgumentException(KEY_LENGTH_BASE64_EXCEPTION_MESSAGE);
return key; return key;
} }
@ -90,25 +91,31 @@ public final class KeyEncoding {
final byte[] key = new byte[KEY_LENGTH]; final byte[] key = new byte[KEY_LENGTH];
if (input.length != KEY_LENGTH_HEX) if (input.length != KEY_LENGTH_HEX)
throw new IllegalArgumentException(KEY_LENGTH_HEX_EXCEPTION_MESSAGE); throw new IllegalArgumentException(KEY_LENGTH_HEX_EXCEPTION_MESSAGE);
int ret = 0;
int c_acc = 0; for (int i = 0; i < KEY_LENGTH_HEX; i += 2) {
int state = 0; int c, c_num, c_num0, c_alpha, c_alpha0, c_val, c_acc;
for (int i = 0; i < KEY_LENGTH_HEX; ++i) { c = input[i];
final int c = input[i]; c_num = c ^ 48;
final int c_num = c ^ 48; c_num0 = ((c_num - 10) >>> 8) & 0xff;
final int c_num0 = (c_num - 10) >> 8; c_alpha = (c & ~32) - 55;
final int c_alpha = (c & ~32) - 55; c_alpha0 = (((c_alpha - 10) ^ (c_alpha - 16)) >>> 8) & 0xff;
final int c_alpha0 = ((c_alpha - 10) ^ (c_alpha - 16)) >> 8; ret |= ((c_num0 | c_alpha0) - 1) >>> 8;
if ((c_num0 | c_alpha0) == 0) c_val = (c_num0 & c_num) | (c_alpha0 & c_alpha);
throw new IllegalArgumentException(KEY_LENGTH_HEX_EXCEPTION_MESSAGE); c_acc = c_val * 16;
final int c_val = (c_num0 & c_num) | (c_alpha0 & c_alpha);
if (state == 0) c = input[i + 1];
c_acc = c_val * 16; c_num = c ^ 48;
else c_num0 = ((c_num - 10) >>> 8) & 0xff;
key[i / 2] = (byte) (c_acc | c_val); c_alpha = (c & ~32) - 55;
state = ~state; c_alpha0 = (((c_alpha - 10) ^ (c_alpha - 16)) >>> 8) & 0xff;
ret |= ((c_num0 | c_alpha0) - 1) >>> 8;
c_val = (c_num0 & c_num) | (c_alpha0 & c_alpha);
key[i / 2] = (byte) (c_acc | c_val);
} }
if (ret != 0)
throw new IllegalArgumentException(KEY_LENGTH_HEX_EXCEPTION_MESSAGE);
return key; return key;
} }