Our Online Store have the new products: RFID antenna board. Currently it can work with JC10M24R and JCOP4 card chips.
Compared with normal cards, the antenna board module has a smaller size and fixed holes, which is easy to integrate in the IOT(Internet Of Things) project.

MAC Algorithm

Algorithm School

Moderator: UNKNwYSHSA

tay00000
Posts: 161
Joined: Tue Sep 27, 2016 10:58 am
Points :2324
Contact:

MAC Algorithm

Post by 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: 630
Joined: Thu May 21, 2015 4:05 am
Points :3053
Contact:

Re: MAC Algorithm

Post by 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

Post Reply Previous topicNext topic

Who is online

Users browsing this forum: No registered users and 20 guests

JavaCard OS : Disclaimer