Transports: Use constant time method for HMAC verification

This commit is contained in:
zzz
2014-05-07 14:47:15 +00:00
parent fb9a4eb87a
commit a014918c0d
2 changed files with 23 additions and 3 deletions

View File

@ -109,7 +109,7 @@ public class HMACGenerator {
mac.doFinal(rv, 0); mac.doFinal(rv, 0);
release(mac); release(mac);
boolean eq = DataHelper.eq(rv, 0, origMAC, origMACOffset, origMACLength); boolean eq = DataHelper.eqCT(rv, 0, origMAC, origMACOffset, origMACLength);
releaseTmp(rv); releaseTmp(rv);
return eq; return eq;
} }

View File

@ -983,6 +983,8 @@ public class DataHelper {
* This treats (null == null) as true, (null == (!null)) as false, * This treats (null == null) as true, (null == (!null)) as false,
* and unequal length arrays as false. * and unequal length arrays as false.
* *
* Variable time.
*
* @return Arrays.equals(lhs, rhs) * @return Arrays.equals(lhs, rhs)
*/ */
public final static boolean eq(byte lhs[], byte rhs[]) { public final static boolean eq(byte lhs[], byte rhs[]) {
@ -1018,11 +1020,12 @@ public class DataHelper {
/** /**
* Unlike eq(byte[], byte[]), this returns false if either lhs or rhs is null. * Unlike eq(byte[], byte[]), this returns false if either lhs or rhs is null.
* @throws AIOOBE if either array isn't long enough * Variable time.
*
* @throws ArrayIndexOutOfBoundsException if either array isn't long enough
*/ */
public final static boolean eq(byte lhs[], int offsetLeft, byte rhs[], int offsetRight, int length) { public final static boolean eq(byte lhs[], int offsetLeft, byte rhs[], int offsetRight, int length) {
if ( (lhs == null) || (rhs == null) ) return false; if ( (lhs == null) || (rhs == null) ) return false;
if (length <= 0) return true;
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
if (lhs[offsetLeft + i] != rhs[offsetRight + i]) if (lhs[offsetLeft + i] != rhs[offsetRight + i])
return false; return false;
@ -1030,10 +1033,27 @@ public class DataHelper {
return true; return true;
} }
/**
* Unlike eq(), this throws NPE if either lhs or rhs is null.
* Constant time.
*
* @throws NullPointerException if lhs or rhs is null
* @throws ArrayIndexOutOfBoundsException if either array isn't long enough
* @since 0.9.13
*/
public final static boolean eqCT(byte lhs[], int offsetLeft, byte rhs[], int offsetRight, int length) {
int r = 0;
for (int i = 0; i < length; i++) {
r |= lhs[offsetLeft + i] ^ rhs[offsetRight + i];
}
return r == 0;
}
/** /**
* Big endian compare, treats bytes as unsigned. * Big endian compare, treats bytes as unsigned.
* Shorter arg is lesser. * Shorter arg is lesser.
* Args may be null, null is less than non-null. * Args may be null, null is less than non-null.
* Variable time.
*/ */
public final static int compareTo(byte lhs[], byte rhs[]) { public final static int compareTo(byte lhs[], byte rhs[]) {
if ((rhs == null) && (lhs == null)) return 0; if ((rhs == null) && (lhs == null)) return 0;