Christmas is coming soon! To thank for the support from all our dear customers, Christmas promotional activity is going on in JavaCardOS online store. For more activities details, please check this post.

MAC Algorithm

Algorithm School

Moderator: UNKNwYSHSA

tay00000
Posts: 123
Joined: Tue Sep 27, 2016 10:58 am
Points :1600
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 :3027
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 2 guests

JavaCard OS : Disclaimer