Skip to content

Commit

Permalink
NeoPGPApplet: implement GetChallenge
Browse files Browse the repository at this point in the history
Implement the GetChallange instruction to return random data. The
maximum size is 128 byte because that will fit into every APDU buffer.

Signed-off-by: Michael Walle <[email protected]>
  • Loading branch information
mwalle committed Apr 14, 2024
1 parent 27d42a5 commit 11e958b
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ outside of an object constructor and all objects are created during the
- [x] Support for RSA keys
- [x] Support for ECC keys
- [x] KDF support
- [x] Get Challenge command support
- [ ] AES encryption/decryption
- [ ] Per signature request PIN verification
- [ ] Private DOs
- [ ] Get Challenge command support
- [ ] SmartPGPs secure messaging

## Build it yourself
Expand Down
30 changes: 27 additions & 3 deletions src/cc/walle/neopgp/NeoPGPApplet.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.RandomData;
import javacardx.apdu.ExtendedLength;

public class NeoPGPApplet extends Applet implements ExtendedLength {
Expand Down Expand Up @@ -225,6 +226,9 @@ public class NeoPGPApplet extends Applet implements ExtendedLength {
private static final byte USER_PIN_MODE_NORMAL = (byte)0;
private static final byte USER_PIN_MODE_CDS = (byte)1;
private byte[] tmpBuffer = null;
RandomData random;

public static final short GET_CHALLENGE_MAX_LENGTH = (short)0x80;

private NeoPGPApplet(byte[] buf, short off, short len) {
if (len >= (short)2)
Expand Down Expand Up @@ -261,6 +265,7 @@ private NeoPGPApplet(byte[] buf, short off, short len) {
caFingerprints[i] = new NeoFixedByteArray(FINGERPRINT_LENGTH);
digitalSignatureCounter = new byte[3];
createTmpBuffer();
random = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
}

private void createTmpBuffer() {
Expand Down Expand Up @@ -477,7 +482,7 @@ public void process(APDU apdu) {
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
break;
case INS_GET_CHALLENGE:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
processGetChallenge(apdu);
break;
case INS_TERMINATE_DF:
processTerminateDF(apdu);
Expand Down Expand Up @@ -580,7 +585,7 @@ private short getExtendedCapabilities(byte[] buf, short off) {
/* exteded capabilites */
buf[off++] =
(byte)(0 << 7) | /* SM supported */
(byte)(0 << 6) | /* GET_CHALLENGE supported */
(byte)(1 << 6) | /* GET_CHALLENGE supported */
(byte)(1 << 5) | /* Key import supported */
(byte)(0 << 4) | /* PW status changeable */
(byte)(0 << 3) | /* Private use DOs supported */
Expand All @@ -592,7 +597,7 @@ private short getExtendedCapabilities(byte[] buf, short off) {
buf[off++] = (byte)0x00;

/* Max length for GET CHALLENGE */
off = Util.setShort(buf, off, (short)0);
off = Util.setShort(buf, off, GET_CHALLENGE_MAX_LENGTH);

/* Max length of cardholder certificates */
off = Util.setShort(buf, off, (short)0);
Expand Down Expand Up @@ -1336,4 +1341,23 @@ private void processImportKey(APDU apdu) throws ISOException {
}
JCSystem.commitTransaction();
}

private void processGetChallenge(APDU apdu) throws ISOException {
byte[] buf = apdu.getBuffer();
byte p1 = buf[ISO7816.OFFSET_P1];
byte p2 = buf[ISO7816.OFFSET_P2];
short le;

if (p1 != 0 || p2 != 0)
ISOException.throwIt(ISO7816.SW_WRONG_P1P2);

le = apdu.setOutgoing();
if (le > GET_CHALLENGE_MAX_LENGTH)
le = GET_CHALLENGE_MAX_LENGTH;

random.generateData(buf, (short)0, le);

apdu.setOutgoingLength(le);
apdu.sendBytesLong(buf, (short)0, le);
}
}
26 changes: 26 additions & 0 deletions test/cc/walle/neopgp/GetChallengeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-or-later
package cc.walle.neopgp;

import org.junit.Test;

public class GetChallengeTest extends JcardsimTestCase {
@Test public void getChallenge() {
assertResponseLength(16 , "0084000010");
}

@Test public void getChallengeMaxLength() {
assertResponseLength(128 , "0084000080");
}

@Test public void getChallengeOversize() {
assertResponseLength(128 , "0084000081");
}

@Test public void getChallengeOversizeZero() {
assertResponseLength(128 , "0084000000");
}

@Test public void getChallengeOversizeExtendedLength() {
assertResponseLength(128 , "00840000001000");
}
}
6 changes: 6 additions & 0 deletions test/cc/walle/neopgp/JcardsimTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,10 @@ public void assertResponseData(String expected, String command) {
assertEquals(ISO7816.SW_NO_ERROR & 0xffff, res.getSW());
assertEquals(expected, ByteUtil.hexString(res.getData()));
}

public void assertResponseLength(int expected, String command) {
ResponseAPDU res = transmit(command);
assertEquals(ISO7816.SW_NO_ERROR & 0xffff, res.getSW());
assertEquals(expected, res.getData().length);
}
}

0 comments on commit 11e958b

Please sign in to comment.