blob: fee692224eb65884e64b20d26dff5b3a133ac218 [file] [log] [blame]
/*
* Copyright(C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.javacard.keymaster;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.Util;
/**
* KMMap represents an array of a KMType key and a KMType value. Map is the sequence of pairs. Each
* pair is one or more sub-types of KMType. The KMMap instance maps to the CBOR type map. KMMap is a
* KMType and it further extends the value field in TLV_HEADER as MAP_HEADER struct{ short
* subType;short length;} followed by a sequence of pairs. Each pair contains a key and a value as
* short pointers to KMType instances.
*/
public class KMMap extends KMType {
public static final short ANY_MAP_LENGTH = 0x1000;
private static final byte MAP_HEADER_SIZE = 4;
private static KMMap prototype;
private KMMap() {}
private static KMMap proto(short ptr) {
if (prototype == null) {
prototype = new KMMap();
}
instanceTable[KM_MAP_OFFSET] = ptr;
return prototype;
}
public static short exp() {
short ptr = instance(MAP_TYPE, (short) MAP_HEADER_SIZE);
Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), (short) 0);
Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2), ANY_MAP_LENGTH);
return ptr;
}
public static short instance(short length) {
short ptr = KMType.instance(MAP_TYPE, (short) (MAP_HEADER_SIZE + (length * 4)));
Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), (short) 0);
Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2), length);
return ptr;
}
public static short instance(short length, byte type) {
short ptr = instance(length);
Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), type);
return ptr;
}
public static KMMap cast(short ptr) {
if (heap[ptr] != MAP_TYPE) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}
return proto(ptr);
}
public void add(short index, short keyPtr, short valPtr) {
short len = length();
if (index >= len) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
short keyIndex =
(short)
(instanceTable[KM_MAP_OFFSET]
+ TLV_HEADER_SIZE
+ MAP_HEADER_SIZE
+ (short) (index * 4));
Util.setShort(heap, keyIndex, keyPtr);
Util.setShort(heap, (short) (keyIndex + 2), valPtr);
}
public short getKey(short index) {
short len = length();
if (index >= len) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
return Util.getShort(
heap,
(short)
(instanceTable[KM_MAP_OFFSET]
+ TLV_HEADER_SIZE
+ MAP_HEADER_SIZE
+ (short) (index * 4)));
}
public short getKeyValue(short index) {
short len = length();
if (index >= len) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
return Util.getShort(
heap,
(short)
(instanceTable[KM_MAP_OFFSET]
+ TLV_HEADER_SIZE
+ MAP_HEADER_SIZE
+ (short) (index * 4 + 2)));
}
public void swap(short index1, short index2) {
short len = length();
if (index1 >= len || index2 >= len) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
// Swap keys
short indexPtr1 =
Util.getShort(
heap,
(short)
(instanceTable[KM_MAP_OFFSET]
+ TLV_HEADER_SIZE
+ MAP_HEADER_SIZE
+ (short) (index1 * 4)));
short indexPtr2 =
Util.getShort(
heap,
(short)
(instanceTable[KM_MAP_OFFSET]
+ TLV_HEADER_SIZE
+ MAP_HEADER_SIZE
+ (short) (index2 * 4)));
Util.setShort(
heap,
(short)
(instanceTable[KM_MAP_OFFSET]
+ TLV_HEADER_SIZE
+ MAP_HEADER_SIZE
+ (short) (index1 * 4)),
indexPtr2);
Util.setShort(
heap,
(short)
(instanceTable[KM_MAP_OFFSET]
+ TLV_HEADER_SIZE
+ MAP_HEADER_SIZE
+ (short) (index2 * 4)),
indexPtr1);
// Swap Values
indexPtr1 =
Util.getShort(
heap,
(short)
(instanceTable[KM_MAP_OFFSET]
+ TLV_HEADER_SIZE
+ MAP_HEADER_SIZE
+ (short) (index1 * 4 + 2)));
indexPtr2 =
Util.getShort(
heap,
(short)
(instanceTable[KM_MAP_OFFSET]
+ TLV_HEADER_SIZE
+ MAP_HEADER_SIZE
+ (short) (index2 * 4 + 2)));
Util.setShort(
heap,
(short)
(instanceTable[KM_MAP_OFFSET]
+ TLV_HEADER_SIZE
+ MAP_HEADER_SIZE
+ (short) (index1 * 4 + 2)),
indexPtr2);
Util.setShort(
heap,
(short)
(instanceTable[KM_MAP_OFFSET]
+ TLV_HEADER_SIZE
+ MAP_HEADER_SIZE
+ (short) (index2 * 4 + 2)),
indexPtr1);
}
public void canonicalize() {
KMCoseMap.canonicalize(instanceTable[KM_MAP_OFFSET], length());
}
public short getStartOff() {
return (short) (instanceTable[KM_MAP_OFFSET] + TLV_HEADER_SIZE + MAP_HEADER_SIZE);
}
public short length() {
return Util.getShort(heap, (short) (instanceTable[KM_MAP_OFFSET] + TLV_HEADER_SIZE + 2));
}
public byte[] getBuffer() {
return heap;
}
}