Announce two new product: SmartCard Reader Rockey200 and USB2.0 Extension Cable

ROCKEY 200 is a handy and portable USB Smart Card reader that can perform read/write operations on any ISO 7816-1/2/3/4 smart cards which are compatible with protocol T=0 and T=1.

USB2.0 Extension Cable With high speed USB 2.0 devices such as USB token ,USB Card Reader and so on.

Come to try it now!

MAC Algorithm

Algorithm School

Moderator: UNKNwYSHSA

tay00000
Posts: 112
Joined: Tue Sep 27, 2016 10:58 am
Points: 1478
Contact:

MAC Algorithm

Postby tay00000 » 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.

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);

    }
}


User avatar
UNKNwYSHSA
Posts: 628
Joined: Thu May 21, 2015 4:05 am
Points: 2979
Contact:

Re: MAC Algorithm

Postby UNKNwYSHSA » Fri Mar 03, 2017 10:21 pm

The implementation of algorithms in specifications like GlobalPlatform/EMV/... is better. For example:
Requirement:
GlobalPlatform SCP authenticate algorithm.
Implementation:
Input: GP static Key, card challenge, ...
Output: Host cryptogram, command MAC, ...
Note:
The source code for this function can be found from GlobalPlatformPro (Java)/GPShell (C/C++)/pyGlobalPlatform(Python)/...
sense and simplicity


Return to “Algorithm School”

Who is online

Users browsing this forum: No registered users and 1 guest

JavaCard OS : Disclaimer