/*
* DrivingLicenseApplet - A reference implementation of the ISO18013 standards.
* Based on the passport applet code developed by the JMRTD team, see
* http://jmrtd.org
*
* Copyright (C) 2006 SoS group, Radboud University
* Copyright (C) 2009 Wojciech Mostowski, Radboud University
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
package org.isodl.applet;
import javacard.framework.ISO7816;
/**
* Generic helpers for the License.
*
* @author Cees-Bart Breunese (ceesb@cs.ru.nl)
*
*/
public class LicenseUtil implements ISO7816 {
/**
* Counts the number of set bits in a byte
*
* @param b byte to be counted
* @return 0 when number of bits in b is even
*/
static byte evenBits(byte b) {
short count = 0;
for (short i = 0; i < 8; i++) {
count += (b >>> i) & 0x1;
}
return (byte) (count % 2);
}
/**
* Calculates the xor of byte arrays in1 and in2 into out.
*
* Arrays may be the same, but regions may not overlap.
*
*
* @param in1 input array
* @param in1_o offset of input array
* @param in2 input array
* @param in2_o offset of inputarray
* @param out output array
* @param out_o offset of output array
* @param len length of xor
*/
static void xor(byte[] in1, short in1_o, byte[] in2,
short in2_o, byte[] out, short out_o, short len) {
for(short s=0; s < len; s++) {
out[(short)(out_o + s)] = (byte)(in1[(short)(in1_o + s)] ^ in2[(short)(in2_o + s)]);
}
}
/**
* Swaps two non-overlapping segments of the same length in the same byte array
* in place.
*
* @param buffer a byte array
* @param offset1 offset to first byte array
* @param offset2 offset to the second byte array
* @param len length of the segments
*/
static void swap(byte[] buffer, short offset1, short offset2, short len) {
byte byte1, byte2;
for(short i=0; i<len; i++) {
byte1 = buffer[(short)(offset1 + i)];
byte2 = buffer[(short)(offset2 + i)];
buffer[(short)(offset1 + i)] = byte2;
buffer[(short)(offset2 + i)] = byte1;
}
}
/**
* Returns the sign bit of a short as a short.
* @param a a short value
* @return the sign bit of a as a short
*/
static short sign(short a) {
return (byte)((a >>> (short)15) & 1);
}
/**
* Returns the smallest unsigned short argument.
*
* @param a a short
* @param b another short
* @return smallest unsigned value a or b.
*/
static short min(short a, short b) {
if(sign(a) == sign(b))
return (a < b ? a : b);
else if(sign(a) == 1)
return b;
else
return a;
}
/***
* Pads an input buffer with max 8 and min 1 byte padding (0x80 followed by optional zeros)
* relative to the offset and length given. Always pad with at least a 0x80 byte.
*
* See 6.2.3.1 in ISO7816-4
*
* @param buffer array to pad
* @param offset to data
* @param length of data
* @return new length, with padding, of data
*
*/
static short pad(byte[] buffer, short offset, short len) {
short padbytes = (short)(lengthWithPadding(len) - len);
for(short i=0; i<padbytes; i++) {
buffer[(short)(offset+len+i)] = (i == 0 ? (byte)0x80 : 0x00);
}
return (short)(len + padbytes);
}
static short lengthWithPadding(short inputLength) {
return (short)((((short)(inputLength + 8)) / 8) * 8);
}
/***
* Computes the actual length of a data block as byte value, without the padding.
*
* @param apdu containing data
* @param offset to data
* @param length of data
* @return new length of data, without padding
*/
static byte calcLcFromPaddedData(byte[] apdu, short offset, short length) {
for(short i=(short)(length - 1) ; i>=0; i--)
if(apdu[(short)(offset + i)] != 0)
if((apdu[(short)(offset + i)] & 0xff)!= 0x80)
// not padded
return (byte)(length & 0xff);
else
return (byte)(i & 0xff);
return 0;
}
}