MAC Algorithm
Posted: Wed Mar 01, 2017 5:58 am
I would like to suggest @JavaCardOS to launch MAC algorithms for command MACs (DES-MAC, AES-MAC, HMAC).
For the HMAC codes, here is my source code contribution below.
For the HMAC codes, here is my source code contribution below.
Code: Select all
import javacard.framework.ISOException;
import javacard.framework.Util;
import javacard.security.MessageDigest;
/**
* HMAC Class. Supports any supported HMAC-SHA1 and HMAC-SHA2 classes that the
* card supports.
*
* @author Tay
*/
public class HMACSHA {
private static final byte IPAD = (byte) 0x36;
private static final byte OPAD = (byte) 0x5c;
private static short outSize = 20;
private static short blockSize = 64;
/**
* HMAC algo from RFC-2104. Setup the blocksize of the algo. Default
* SHA-1.
*
* @param hash MessageDigest hash class
* @param hKey Byte array containing HMAC Key
* @param hKeyOff Byte array of HMAC key to offset
* @param hKeyLen Length of HMAC Key which can be any length
* @param msg Message buffer
* @param mOff Message buffer offset
* @param mLen Message length
* @param ipad IPAD buffer - Please assign an empty buffer with the same blockSize length as that of the target hash
* @param offIPad Offset from which the IPAD buffer would be used
* @param opad OPAD buffer - Please assign an empty buffer with the same blockSize length as that of the target hash
* @param offOPad Offset from which the IPAD buffer would be used
* @param secB Secret Key calculation buffer - Please assign an empty buffer with the same blockSize length as that of the target hash
* @param offSecB Offset from which the Secret Key calculation buffer would be used
* @param oMsg Output message buffer
* @param outOff Output message buffer offest
*/
public static void process(MessageDigest hash, byte[] hKey, short hKeyOff,
short hKeyLen, byte[] msg, short mOff, short mLen, byte[] ipad,
short offIPad, byte[] opad, short offOPad, byte[] secB,
short OffSecB, byte[] oMsg, short outOff) {
// Decide the output size from the resulting HMAC and blockSize per hash type for the HMAC
if (hash.getAlgorithm() == MessageDigest.ALG_SHA) {
outSize = (short) 20; // SHA-1
blockSize = (short) 64;
} else if (hash.getAlgorithm() == MessageDigest.ALG_SHA_256) {
outSize = (short) 32; // SHA-256
blockSize = (short) 64;
} else if (hash.getAlgorithm() == MessageDigest.ALG_SHA_384) {
outSize = (short) 48; // SHA-384
blockSize = (short) 128;
} else if (hash.getAlgorithm() == MessageDigest.ALG_SHA_512) {
outSize = (short) 64; // SHA-512
blockSize = (short) 128;
}
// For code hygiene, always zeroize the IPAD, OPAD and SECB buffer otherwise the results will turn "dirty"
Util.arrayFillNonAtomic(ipad, offIPad, blockSize, (byte) 0x00);
Util.arrayFillNonAtomic(opad, offIPad, blockSize, (byte) 0x00);
Util.arrayFillNonAtomic(secB, offIPad, blockSize, (byte) 0x00);
// Block size == key size. Derive secret key.
if (hKeyLen > blockSize) {
hash.reset();
hash.doFinal(hKey, hKeyOff, hKeyLen, secB, OffSecB);
} else {
Util.arrayCopyNonAtomic(hKey, hKeyOff, secB, OffSecB, hKeyLen);
}
try {
// Setup IPAD & OPAD secrets while using first byte of the outMsg array via outOffset
oMsg[outOff] = (byte) 0x00;
for (; (oMsg[outOff] & 0xFF) < blockSize;) {
ipad[(short) ((oMsg[outOff] & 0xFF) + offIPad)] = (byte) (secB[(short) ((oMsg[outOff] & 0xFF) + OffSecB)] ^ IPAD);
opad[(short) ((oMsg[outOff] & 0xFF) + offOPad)] = (byte) (secB[(short) ((oMsg[outOff] & 0xFF) + OffSecB)] ^ OPAD);
oMsg[outOff] = (byte) ((oMsg[outOff] & 0xFF) + 1);
}
oMsg[outOff] = (byte) 0x00;
} catch (ArrayIndexOutOfBoundsException e) {
ISOException.throwIt((short) 0xFC03);
}
// hash(i_key_pad ∥ message)
hash.reset();
hash.update(ipad, offIPad, blockSize);
hash.doFinal(msg, mOff, mLen, oMsg, outOff);
//hash(o_key_pad ∥ i_pad-hashed)
hash.reset();
hash.update(opad, offOPad, blockSize);
hash.doFinal(oMsg, outOff, outSize, oMsg, outOff);
}
}