From 5cb7bed7f82b9907901529ec3f5ede37ad18cfe1 Mon Sep 17 00:00:00 2001 From: "avinash.hedage" Date: Tue, 21 Jun 2022 06:34:17 +0000 Subject: [PATCH] handled aes des no pad zero input --- .../javacard/keymaster/KMKeymasterApplet.java | 22 +++++++++++++++++-- .../javacard/keymaster/KMOperationState.java | 13 +++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index e10e8220..c3339420 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -1776,7 +1776,19 @@ private void finishAesDesOperation(KMOperationState op){ KMByteBlob.cast(data[OUTPUT_DATA]).getStartOff()); } catch (CryptoException e) { if (e.getReason() == CryptoException.ILLEGAL_USE) { - KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + // As per VTS, zero length input on AES/DES with PADDING_NONE Should return a zero length + // output. But JavaCard fails with CryptoException.ILLEGAL_USE if no input data is + // provided via update() method. So ignore this exception in case if all below conditions + // are satisfied and simply return empty output. + // 1. padding mode is PADDING_NONE. + // 2. No input message is processed in update(). + // 3. Zero length input data is passed in finish operation. + if ((op.getPadding() == KMType.PADDING_NONE) && + !op.isInputMsgProcessed() && (KMByteBlob.cast(data[INPUT_DATA]).length() == 0)) { + len = 0; + } else { + KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + } } } KMByteBlob.cast(data[OUTPUT_DATA]).setLength(len); @@ -2136,7 +2148,13 @@ private void processUpdateOperationCmd(APDU apdu) { } catch (CryptoException e) { KMException.throwIt(KMError.INVALID_TAG); } - + if (KMByteBlob.cast(data[INPUT_DATA]).length() > 0) { + // This flag is used to denote that an input data of length > 0 is received and processed + // successfully in update command. This flag is later used in the finish operation + // to handle a particular use case, where a zero length input data on AES/DES algorithm + // with PADDING_NONE should return a zero length output with OK response. + op.setProcessedInputMsg(true); + } // Adjust the Output data if it is not equal to input data. // This happens in case of JCardSim provider. KMByteBlob.cast(data[OUTPUT_DATA]).setLength(len); diff --git a/Applet/src/com/android/javacard/keymaster/KMOperationState.java b/Applet/src/com/android/javacard/keymaster/KMOperationState.java index a6ed2280..8c9bb545 100644 --- a/Applet/src/com/android/javacard/keymaster/KMOperationState.java +++ b/Applet/src/com/android/javacard/keymaster/KMOperationState.java @@ -56,6 +56,7 @@ public class KMOperationState { private static final short SECURE_USER_ID_REQD = 2; private static final short AUTH_TIMEOUT_VALIDATED = 4; private static final short AES_GCM_UPDATE_ALLOWED = 8; + private static final byte PROCESSED_INPUT_MSG = 16; // Max user secure ids. private static final byte MAX_SECURE_USER_IDS = 5; @@ -122,6 +123,10 @@ public void setPurpose(short purpose) { data[PURPOSE] = purpose; } + public boolean isInputMsgProcessed() { + return (data[FLAGS] & PROCESSED_INPUT_MSG) != 0; + } + public void setOperation(KMOperation op) { operations[OPERATION] = op; } @@ -150,6 +155,14 @@ public void setAuthTime(byte[] timeBuf, short start) { Util.arrayCopyNonAtomic(timeBuf, start, authTime, (short) 0, AUTH_TIME_SIZE); } + public void setProcessedInputMsg(boolean flag) { + if (flag) { + data[FLAGS] = (byte) (data[FLAGS] | PROCESSED_INPUT_MSG); + } else { + data[FLAGS] = (byte) (data[FLAGS] & (~PROCESSED_INPUT_MSG)); + } + } + public void setOneTimeAuthReqd(boolean flag) { if (flag) { data[FLAGS] = (short) (data[FLAGS] | SECURE_USER_ID_REQD);