use of org.openecard.sal.protocol.genericcryptography.apdu.PSODecipher in project open-ecard by ecsec.
the class DecipherStep method perform.
@Override
public DecipherResponse perform(Decipher request, Map<String, Object> internalData) {
DecipherResponse response = WSHelper.makeResponse(DecipherResponse.class, WSHelper.makeResultOK());
try {
ConnectionHandleType connectionHandle = SALUtils.getConnectionHandle(request);
String didName = SALUtils.getDIDName(request);
byte[] applicationID = connectionHandle.getCardApplication();
CardStateEntry cardStateEntry = SALUtils.getCardStateEntry(internalData, connectionHandle);
Assert.securityConditionDID(cardStateEntry, applicationID, didName, CryptographicServiceActionName.DECIPHER);
DIDStructureType didStructure = SALUtils.getDIDStructure(request, didName, cardStateEntry, connectionHandle);
CryptoMarkerType cryptoMarker = new CryptoMarkerType(didStructure.getDIDMarker());
byte[] keyReference = cryptoMarker.getCryptoKeyInfo().getKeyRef().getKeyRef();
byte[] algorithmIdentifier = cryptoMarker.getAlgorithmInfo().getCardAlgRef();
byte[] slotHandle = connectionHandle.getSlotHandle();
// See eGK specification, part 1, version 2.2.0, section 15.9.6.
if (didStructure.getDIDScope().equals(DIDScopeType.LOCAL)) {
keyReference[0] = (byte) (0x80 | keyReference[0]);
}
TLV tagKeyReference = new TLV();
tagKeyReference.setTagNumWithClass(0x84);
tagKeyReference.setValue(keyReference);
TLV tagAlgorithmIdentifier = new TLV();
tagAlgorithmIdentifier.setTagNumWithClass(0x80);
tagAlgorithmIdentifier.setValue(algorithmIdentifier);
byte[] mseData = ByteUtils.concatenate(tagKeyReference.toBER(), tagAlgorithmIdentifier.toBER());
CardCommandAPDU apdu = new ManageSecurityEnvironment((byte) 0x41, ManageSecurityEnvironment.CT, mseData);
apdu.transmit(dispatcher, slotHandle);
byte[] ciphertext = request.getCipherText();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BigInteger bitKeySize = cryptoMarker.getCryptoKeyInfo().getKeySize();
int blocksize = bitKeySize.divide(new BigInteger("8")).intValue();
// check if the ciphertext length is divisible by the blocksize without rest
if ((ciphertext.length % blocksize) != 0) {
return WSHelper.makeResponse(DecipherResponse.class, WSHelper.makeResultError(ECardConstants.Minor.App.INCORRECT_PARM, "The length of the ciphertext should be a multiple of the blocksize."));
}
// decrypt the ciphertext block for block
for (int offset = 0; offset < ciphertext.length; offset += blocksize) {
byte[] ciphertextblock = ByteUtils.copy(ciphertext, offset, blocksize);
apdu = new PSODecipher(ByteUtils.concatenate(PADDING_INDICATOR_BYTE, ciphertextblock), (byte) blocksize);
CardResponseAPDU responseAPDU = apdu.transmit(dispatcher, slotHandle);
baos.write(responseAPDU.getData());
}
response.setPlainText(baos.toByteArray());
} catch (ECardException e) {
response.setResult(e.getResult());
} catch (Exception e) {
logger.error(e.getMessage(), e);
response.setResult(WSHelper.makeResult(e));
}
return response;
}
Aggregations