// SmartCard Applet
// Authors: Robert Relyea <rrelyea@redhat.com>
// Package: CardEdgeApplet
// Description: CardEdge implementation with JavaCard
//
// BEGIN LICENSE BLOCK
// Copyright (C) 2006 Red Hat, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. The name of the author may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// Changes to this license can be made only by the copyright author with
// explicit written consent.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Alternatively, the contents of this file may be used under the terms of
// the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
// case the provisions of the LGPL are applicable instead of those above. If
// you wish to allow use of your version of this file only under the terms
// of the LGPL, and not to allow others to use your version of this file
// under the terms of the BSD license, indicate your decision by deleting
// the provisions above and replace them with the notice and other
// provisions required by the LGPL. If you do not delete the provisions
// above, a recipient may use your version of this file under the terms of
// either the BSD license or the LGPL.
//
// 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 St, Fifth Floor, Boston, MA 02110-1301 USA
// END LICENSE_BLOCK
package com.redhat.ckey.applet;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
import javacard.framework.Util;
/**
* ASN1 parser Class
*
* <p>This Simplistic ASN.1 parser does not interpret tags, it simply finds
* elements based on where their fields are supposed to wind up at. </p>
*
*
* Object fields:
* <pre>
* short[] newSize; // way to get around java's restrictions on pass by ref.
* byte[] data
* </pre>
*
* @author Robert Relyea
* @version 0.0.1
*
*/
public class ASN1
{
public static final short SW_BAD_DER_DATA = (short)0x9cd0;
private final short NEXT = 0;
private final short SIZE = 1;
private final short END = 2;
private short[] params;
public ASN1()
{
params=JCSystem.makeTransientShortArray((short)3,
JCSystem.CLEAR_ON_DESELECT);
}
public short GetEnd()
{
return params[END];
}
public short GetSize()
{
return params[SIZE];
}
public short GetNext()
{
return params[NEXT];
}
public byte GetTag(byte buf[], short offset, short end)
{
if (end <= offset) {
ISOException.throwIt(SW_BAD_DER_DATA);
}
return buf[offset];
}
public short Unwrap(byte buf[], short offset, short end, short dbg)
{
byte tag;
byte len;
short length = 0;
if (end < (short)(offset+2)) {
ISOException.throwIt(SW_BAD_DER_DATA);
}
tag = buf[offset++];
if (tag == 0) {
ISOException.throwIt(SW_BAD_DER_DATA);
}
len = buf[offset++];
length = Util.makeShort((byte)0,len);
if ((len & 0x80) != 0) {
short count = Util.makeShort((byte)0,(byte)(len & 0x7f));
if (end < (short)(offset+count)) {
ISOException.throwIt(SW_BAD_DER_DATA);
}
if (count > 2) {
ISOException.throwIt(SW_BAD_DER_DATA);
}
length = 0;
while (count-- > 0) {
length = (short)((length << 8)
| Util.makeShort((byte)0,buf[offset++]));
}
}
params[SIZE] = length;
params[NEXT] = ((short)(offset+length));
params[END] = ((short)(offset+length));
return offset;
}
public short Skip(byte buf[], short offset, short end, short dbg)
{
Unwrap(buf,offset,end,dbg);
return params[NEXT];
}
public short UnwrapBitString(byte buf[], short offset, short end, short dbg)
{
if (buf[offset] != 0) {
ISOException.throwIt(SW_BAD_DER_DATA);
}
if (end < (short)(offset+1)) {
ISOException.throwIt(SW_BAD_DER_DATA);
}
params[SIZE]--;
return (short)(offset+1);
}
public short Signed2Unsigned(byte buf[], short offset, short end, short dbg)
{
short startOffset = offset;
short startSize=params[SIZE];
for (; offset < end && buf[offset] == 0 ; offset++){
params[SIZE]--;
}
if (offset >= end) {
ISOException.throwIt(SW_BAD_DER_DATA);
}
return offset;
}
}