Compare commits

..

10 Commits

Author SHA1 Message Date
c289445f9f Ignore compiled binaries 2023-08-26 15:33:37 -05:00
8b977953a3 Use correct JC SDK 2023-08-26 15:33:02 -05:00
64eed711d0 Update ant build for sdk submodule 2023-08-26 15:31:27 -05:00
Arnaud Fontaine
75f884de5d smartpgp-cli: improve error handling in change PIN 2023-04-17 20:20:20 +02:00
Arnaud Fontaine
efdbcb6274 update github workflow 2023-04-14 16:48:50 +02:00
Arnaud Fontaine
8b1463c399 Improve PIN/PUK length testing when KDF is enabled 2023-04-12 15:32:01 +02:00
Arnaud Fontaine
faaa48c042 Remove CI/CD that rely on bin/smartpgp-cli 2022-01-10 21:14:01 +01:00
Arnaud Fontaine
e84853414f Improve CI/CD: RSA sign+decrypt and EC decrypt 2022-01-10 20:54:19 +01:00
Ryad Benadjila
0b43929a83 Add CI/CD tests using Github Actions.
The tests compile and run the applet in the jcardsim Javacard simulator.
ECDSA signature tests are performed using OpenPGPpy, other tests such as
AES are performed using the local bin/smartpgp-cli script.

TODO: add tests for RSA, asymmetric encryption, pin modifications, secure
messaging (if well supported by jcardsim), etc.
2022-01-10 16:40:35 +01:00
Arnaud Fontaine
4fbafe513b Fix possible implicit extended length usage support 2022-01-10 16:17:28 +01:00
14 changed files with 587 additions and 57 deletions

56
.github/workflows/card-status.py vendored Normal file
View File

@ -0,0 +1,56 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# OpenPGPpy : Scan devices demo
# Copyright (C) 2020 BitLogiK
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
try:
import OpenPGPpy
except ModuleNotFoundError:
# Import the OpenPGPpy from parent or current folder
# Can run demo w/o OpenPGPpy installed (from root or demo folder)
from sys import path
path.append(".")
path.append("..")
import OpenPGPpy
def main():
i = 0
displayed = 0
while True:
try:
current_card = OpenPGPpy.OpenPGPcard(reader_index=i)
print("--------------------------------------------------------")
print(f"OpenPGP card/reader : {current_card.name}")
print(f"OpenPGP version : {current_card.pgpverstr}")
print(
f"Manufacturer : {current_card.manufacturer} ({current_card.manufacturer_id})"
)
print(
f"Device serial : {current_card.serial} ({hex(current_card.serial)})"
)
displayed += 1
i += 1
except OpenPGPpy.ConnectionException as exc:
if str(exc) != "No OpenPGP applet on this reader.":
break
i += 1
if displayed == 0:
print("No OpenPGP device available")
if __name__ == "__main__":
main()

54
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,54 @@
name: smartgpg-test-applet
# Run this workflow every time a new commit pushed to your repository
on: push
jobs:
applet_tests:
runs-on: ubuntu-20.04
steps:
# Checkout repository
- name: checkout repository
uses: actions/checkout@v2
# Run actions
# Compilation tests
- name: applet tests
shell: bash
run: |
# get dependencies
echo "==== get dependencies";
sudo apt-get install -y --no-install-recommends procps autoconf automake libtool m4 pkg-config help2man make gcc ant automake autotools-dev sudo wget gnupg software-properties-common maven git pcscd libpcsclite-dev opensc;
sudo apt-get install -y python3-setuptools python3-pyscard python3-pyasn1;
pip3 install OpenPGPpy;
# get JavaCard SDKs
echo "==== get JavaCard SDKs";
git clone https://github.com/martinpaljak/oracle_javacard_sdks && mv oracle_javacard_sdks/jc303_kit/ /tmp/ && mv oracle_javacard_sdks/jc305u4_kit/ /tmp/ && rm -rf oracle_javacard_sdks;
# compile SmartPGP
echo "==== compile SmartPGP";
cat build.xml | sed 's/<cap /<cap export="SmartPGPApplet" /' > /tmp/build.xml && mv /tmp/build.xml ./;
JC_HOME=/tmp/jc303_kit/ ant;
# clone jcardsim repository, compile and install
echo "==== clone jcardsim repository, compile and install";
git clone https://github.com/licel/jcardsim;
cd jcardsim && export JC_CLASSIC_HOME=/tmp/jc305u4_kit/ && mvn initialize && mvn clean package && cd -;
# clone vsmartcard, compile and install
echo "==== clone vsmartcard, compile and install";
git clone https://github.com/frankmorgner/vsmartcard.git;
cd vsmartcard/virtualsmartcard && autoreconf --verbose --install && ./configure --sysconfdir=/etc && make && sudo make install && cd -;
# relaunch PCSC
echo "==== relaunch PCSC";
sudo killall -KILL pcscd 2> /dev/null || true;
sudo pcscd -fad 2>&1 > /tmp/log_pcsc &
sleep 2;
# launch jcardsim
echo "==== launch jcardsim";
java -cp jcardsim/target/jcardsim-3.0.5-SNAPSHOT.jar:SmartPGPApplet/smartpgp.jar com.licel.jcardsim.remote.VSmartCard .github/workflows/smartpgp.cfg 2>&1 > /tmp/log_jcardsim &
sleep 5;
# install SmartPGP
echo "==== test SmartPGP";
opensc-tool -l;
opensc-tool -s 80b800001810d276000124010304AFAF000000000000050000020F0F00;
# get card status
python3 .github/workflows/card-status.py;
# main tests
python3 .github/workflows/test_SmartPGP.py;

47
.github/workflows/reset.py vendored Normal file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# OpenPGPpy : Reset device demo
# Copyright (C) 2020 BitLogiK
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
import getpass
try:
import OpenPGPpy
except ModuleNotFoundError:
# Import the OpenPGPpy from parent or current folder
# Can run demo w/o OpenPGPpy installed (from root or demo folder)
from sys import path
path.append(".")
path.append("..")
import OpenPGPpy
def main():
mydevice = OpenPGPpy.OpenPGPcard()
print("Enter the PUK to reset the", mydevice.name)
PIN3 = "12345678" #getpass.getpass("Enter PIN3 (PUK) : ")
try:
mydevice.reset(PIN3)
except OpenPGPpy.PGPCardException as exc:
if exc.sw_code == 0x6982 or exc.sw_code == 0x6A80:
print("Error: Wrong PUK")
return
print("Reset done.")
if __name__ == "__main__":
main()

6
.github/workflows/smartpgp.cfg vendored Normal file
View File

@ -0,0 +1,6 @@
com.licel.jcardsim.card.applet.0.AID=d276000124010304AFAF000000000000
com.licel.jcardsim.card.applet.0.Class=fr.anssi.smartpgp.SmartPGPApplet
com.licel.jcardsim.card.ATR=3B80800101
com.licel.jcardsim.vsmartcard.host=localhost
com.licel.jcardsim.vsmartcard.port=35963
com.licel.jcardsim.randomdata.secure=1

372
.github/workflows/test_SmartPGP.py vendored Normal file
View File

@ -0,0 +1,372 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
from sys import path
import subprocess
import getpass
import hashlib
import tempfile
path.append(".")
import OpenPGPpy
class BadTestResult(Exception):
pass
def sha256(data):
return hashlib.sha256(data).digest()
def rsa_2048_pubkey_to_der(pubkey):
# Add ASN1 DER header
# RSA 2048
header_modulus = "30820122300d06092a864886f70d01010105000382010f003082010a0282010100"
header_exponent = "0203"
modulus = pubkey[9:265].hex()
exponent = pubkey[267:].hex()
return bytes.fromhex(header_modulus + modulus + header_exponent + exponent)
def check_rsa_2048_signature(message, signature, pubkeyd):
pubkey = rsa_2048_pubkey_to_der(pubkeyd)
fpk = tempfile.NamedTemporaryFile(delete=False)
fpk.write(pubkey)
fpk.close()
fsig = tempfile.NamedTemporaryFile(delete=False)
fsig.write(signature)
fsig.close()
verify_cmd = (
f"openssl dgst -sha256 -keyform DER -verify {fpk.name} -signature {fsig.name}"
)
sigOK = False
try:
subprocess.run(
verify_cmd, input=message, shell=True, check=True, stdout=subprocess.PIPE
)
sigOK = True
except Exception:
print("[-] ERROR in signature verification:")
print(">>> openssl is required in path to check signatures")
sigOK = False
os.remove(fpk.name)
os.remove(fsig.name)
return sigOK
def encrypt_rsa_2048(message, pubkeyd):
pubkey = rsa_2048_pubkey_to_der(pubkeyd)
fpk = tempfile.NamedTemporaryFile(delete=False)
fpk.write(pubkey)
fpk.close()
fenc = tempfile.NamedTemporaryFile(delete=False)
fenc.close()
encrypt_cmd = (
f"openssl rsautl -keyform DER -pubin -inkey {fpk.name} -pkcs -encrypt -out {fenc.name}"
)
try:
subprocess.run(
encrypt_cmd, input=message, shell=True, check=True, stdout=subprocess.PIPE
)
except Exception:
print("[-] ERROR in encrpytion")
print(">>> openssl is required in path to encrypt message")
raise
os.remove(fpk.name)
fres = open(fenc.name, 'rb')
res = fres.read()
fres.close()
os.remove(fenc.name)
return bytes.fromhex("00") + res
def test_rsa_2048_signature(token, PIN1, PIN3, repeat):
print(f"[+] == Test RSA 2048 signature ({repeat} signatures) ==")
# Verify PIN3, required for the next command
print("[+] Verify PIN3")
token.verify_pin(3, PIN3)
# Setup RSA 2048 for SIG key
print("[+] Set SIG key to RSA 2048")
token.put_data("00C1", "010800001103")
# Generate key for SIG key
print("[+] Generate SIG key")
pubkey_card = token.gen_key("B600")
# Digest message and sign
message = "Hello SmartPGP! Take that message.".encode("ascii")
header_sha256 = "3031300D060960864801650304020105000420";
hash = bytes.fromhex(header_sha256) + sha256(message)
for i in range(repeat):
print(f"[+] Test #{i + 1}")
# Verify PIN1, required for signature
token.verify_pin(1, PIN1)
print("[+] Sign SHA256 hash")
sig_card = token.sign(hash)
print("[+] Verify signature")
if not check_rsa_2048_signature(message, sig_card, pubkey_card):
print("[-] BAD signature")
raise BadTestResult
def test_rsa_2048_decrypt(token, PIN1, PIN3, repeat):
print(f"[+] == Test RSA 2048 decrypt ({repeat} deciphers) ==")
# Verify PIN3, required for the next command
print("[+] Verify PIN3")
token.verify_pin(3, PIN3)
# Setup RSA 2048 for DEC key
print("[+] Set DEC key to RSA 2048")
token.put_data("00C2", "010800001103")
# Generate key for DEC key
print("[+] Generate DEC key")
pubkey_card = token.gen_key("B800")
# Verify PIN2, required for decrypt
token.verify_pin(2, PIN1)
# Cipher message
message = "Hello SmartPGP! Take that message.".encode("ascii")
print("[+] Prepare encrypted message")
encrypted = encrypt_rsa_2048(message, pubkey_card)
for i in range(repeat):
print(f"[+] Test #{i + 1}")
print("[+] Decipher message")
decrypted = token.decipher(encrypted)
print("[+] Verify message")
if message == decrypted:
print("[+] Good deciphering")
else:
print("[-] BAD deciphering")
raise BadTestResult
def test_rsa_2048(token, PIN1, PIN3, repeat):
print("[+] === Test RSA 2048 ===")
test_rsa_2048_signature(token, PIN1, PIN3, repeat)
test_rsa_2048_decrypt(token, PIN1, PIN3, repeat)
def ec_prime256v1_pubkey_to_der(pubkey):
# Add ASN1 DER header (EC parameters)
# ECP 256 r1 header
header_hex = "3059301306072A8648CE3D020106082A8648CE3D030107034200"
return bytes.fromhex(header_hex + pubkey.hex())
def check_ec_prime256v1_signature(message, signature, pubkeyd):
pubkey = ec_prime256v1_pubkey_to_der(pubkeyd)
fpk = tempfile.NamedTemporaryFile(delete=False)
fpk.write(pubkey)
fpk.close()
fsig = tempfile.NamedTemporaryFile(delete=False)
fsig.write(signature)
fsig.close()
verify_cmd = (
f"openssl dgst -sha256 -keyform DER -verify {fpk.name} -signature {fsig.name}"
)
sigOK = False
try:
subprocess.run(
verify_cmd, input=message, shell=True, check=True, stdout=subprocess.PIPE
)
sigOK = True
except Exception:
print("[-] ERROR in signature verification")
print(">>> openssl is required in path to check signatures")
sigOK = False
os.remove(fpk.name)
os.remove(fsig.name)
return sigOK
def encrypt_ec_prime256v1(pubkeyd):
pubkey = ec_prime256v1_pubkey_to_der(pubkeyd)
fpub = tempfile.NamedTemporaryFile(delete=False)
fpub.write(pubkey)
fpub.close()
fpriv2 = tempfile.NamedTemporaryFile(delete=False)
fpriv2.close()
generate_private_cmd = (
f"openssl genpkey -outform DER -out {fpriv2.name} -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1 -pkeyopt ec_param_enc:named_curve"
)
try:
subprocess.run(
generate_private_cmd, shell=True, check=True, stdout=subprocess.PIPE
)
except Exception:
print("[-] ERROR in encrpytion")
print(">>> openssl is required in path to encrypt message")
raise
fpub2 = tempfile.NamedTemporaryFile(delete=False)
fpub2.close()
generate_pub_cmd = (
f"openssl pkey -pubout -inform DER -in {fpriv2.name} -outform DER -out {fpub2.name}"
)
try:
subprocess.run(
generate_pub_cmd, shell=True, check=True, stdout=subprocess.PIPE
)
except Exception:
print("[-] ERROR in encrpytion")
print(">>> openssl is required in path to encrypt message")
raise
fenc = tempfile.NamedTemporaryFile(delete=False)
fenc.close()
generate_ecdh_cmd = (
f"openssl pkeyutl -derive -out {fenc.name} -keyform DER -inkey {fpriv2.name} -peerform DER -peerkey {fpub.name}"
)
try:
subprocess.run(
generate_ecdh_cmd, shell=True, check=True, stdout=subprocess.PIPE
)
except Exception:
print("[-] ERROR in encrpytion")
print(">>> openssl is required in path to encrypt message")
raise
f = open(fpub2.name, 'rb')
pub2 = f.read()
pub2 = pub2[26:]
f.close()
f = open(fenc.name, 'rb')
enc = f.read()
f.close()
os.remove(fpub.name)
os.remove(fpriv2.name)
os.remove(fpub2.name)
os.remove(fenc.name)
return (bytes.fromhex("A646") + bytes.fromhex("7F4943") + bytes.fromhex("8641") + pub2, enc)
def test_ec_prime256v1_signature(token, PIN1, PIN3, repeat):
print(f"[+] == Test EC prime256v1 signature ({repeat} signatures) ==")
# Verify PIN3, required for the next command
print("[+] Verify PIN3")
token.verify_pin(3, PIN3)
# Setup EC prime256v1 for SIG key
print("[+] Set SIG key to EC prime256v1")
token.put_data("00C1", "132A8648CE3D030107")
# Generate key for SIG key
print("[+] Generate SIG key")
pubkey_card = token.gen_key("B600")
pubkey_card = pubkey_card[-65:]
# Digest message and sign
message = "Hello SmartPGP! Take that message.".encode("ascii")
hash = sha256(message)
for i in range(repeat):
print(f"[+] Test #{i + 1}")
# Verify PIN1, required for signature
token.verify_pin(1, PIN1)
print("[+] Sign SHA256 hash")
sig_card = token.sign_ec_der(hash)
print("[+] Verify signature")
if not check_ec_prime256v1_signature(message, sig_card, pubkey_card):
print("[-] BAD signature")
raise BadTestResult
def test_ec_prime256v1_decrypt(token, PIN1, PIN3, repeat):
print(f"[+] == Test EC prime256v1 decrypt ({repeat} deciphers) ==")
# Verify PIN3, required for the next command
print("[+] Verify PIN3")
token.verify_pin(3, PIN3)
# Setup EC prime256v1 for DEC key
print("[+] Set DEC key to EC prime256v1")
token.put_data("00C2", "122A8648CE3D030107")
# Generate key for DEC key
print("[+] Generate DEC key")
pubkey_card = token.gen_key("B800")
pubkey_card = pubkey_card[-65:]
# Verify PIN2, required for decrypt
token.verify_pin(2, PIN1)
print("[+] Prepare ECDH")
(encrypted, secret) = encrypt_ec_prime256v1(pubkey_card)
for i in range(repeat):
print(f"[+] Test #{i + 1}")
print("[+] Decipher (compute ECDH secret)")
decrypted = token.decipher(encrypted)
print("[+] Verify message")
if secret == decrypted:
print("[+] Good deciphering")
else:
print("[-] BAD deciphering")
raise BadTestResult
def test_ec_prime256v1(token, PIN1, PIN3, repeat):
print("[+] === Test EC prime256v1 ===")
test_ec_prime256v1_signature(token, PIN1, PIN3, repeat)
test_ec_prime256v1_decrypt(token, PIN1, PIN3, repeat)
def main(rsa, ec, repeat):
# True/False == with/without debug
token = OpenPGPpy.OpenPGPcard(False)
PIN1 = "123456"
PIN3 = "12345678"
if rsa:
test_rsa_2048(token, PIN1, PIN3, repeat)
if ec:
test_ec_prime256v1(token, PIN1, PIN3, repeat)
if __name__ == "__main__":
try:
main(rsa=True, ec=False, repeat=200)
except OpenPGPpy.openpgp_card.ConnectionException:
print(f"[-] FAILED to find OpenPGP token")
exit(1)
except OpenPGPpy.PGPCardException as exc:
if exc.sw_code != 0x9000:
print(f"[-] FAILED with: 0x{exc.sw_code:02x}")
exit(2)
except BadTestResult:
print(f"[-] FAILED test")
exit(3)

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.jar
*.cap

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "sdks"]
path = sdks
url = https://github.com/martinpaljak/oracle_javacard_sdks

View File

@ -462,17 +462,17 @@ class CardConnectionContext:
raise AdminPINFailed
####### step 3bis
if nresetting_code != None:
set_resetting_code(self.connection, nresetting_code)
(_,sw1,sw2) = set_resetting_code(self.connection, nresetting_code)
if sw1!=0x90 or sw2!=0x00:
print("set_resetting_code failed")
return
####### step 4
change_reference_data_pw1(self.connection, ascii_encode_pin(pw1), list(npw1))
(sw1,sw2) = change_reference_data_pw1(self.connection, ascii_encode_pin(pw1), list(npw1))
if sw1!=0x90 or sw2!=0x00:
print("change_reference_data_pw1 failed")
return
####### step 4bis
change_reference_data_pw3(self.connection, ascii_encode_pin(pw3), list(npw3))
(sw1,sw2) = change_reference_data_pw3(self.connection, ascii_encode_pin(pw3), list(npw3))
if sw1!=0x90 or sw2!=0x00:
print("change_reference_data_pw3 failed")
return

View File

@ -1,13 +1,18 @@
<?xml version="1.0"?>
<project name="smartpgp" default="convert" basedir=".">
<description>Ant build for SmartPGP applet</description>
<get src="https://github.com/martinpaljak/ant-javacard/releases/download/v20.03.25/ant-javacard.jar" dest="." skipexisting="true"/>
<taskdef name="javacard" classname="pro.javacard.ant.JavaCard" classpath="ant-javacard.jar"/>
<target name="convert">
<javacard>
<cap output="SmartPGPApplet.cap" sources="src" aid="d27600012401" version="1.0">
<applet class="fr.anssi.smartpgp.SmartPGPApplet" aid="d276000124010304AFAF000000000000"/>
</cap>
</javacard>
</target>
<description>Ant build for SmartPGP applet</description>
<!-- Add JC303 SDK for JCOP 3.0.1 -->
<property name="JC303" value="sdks/jc303_kit"/>
<get src="https://github.com/martinpaljak/ant-javacard/releases/download/v20.03.25/ant-javacard.jar" dest="." skipexisting="true"/>
<taskdef name="javacard" classname="pro.javacard.ant.JavaCard" classpath="ant-javacard.jar"/>
<target name="convert">
<javacard>
<cap jckit="${JC303}" output="SmartPGPApplet.cap" sources="src" aid="d27600012401" version="1.0">
<applet class="fr.anssi.smartpgp.SmartPGPApplet" aid="d276000124010304c0deedb522560000"/>
</cap>
</javacard>
</target>
</project>

View File

@ -2,15 +2,6 @@ diff --git a/src/fr/anssi/smartpgp/Constants.java b/src/fr/anssi/smartpgp/Consta
index b3c0f80..2ee1107 100644
--- a/src/fr/anssi/smartpgp/Constants.java
+++ b/src/fr/anssi/smartpgp/Constants.java
@@ -30,7 +30,7 @@ public final class Constants {
protected static final short INTERNAL_BUFFER_MAX_LENGTH =
(short)0x500;
- protected static final short APDU_MAX_LENGTH = (short)256;
+ protected static final short APDU_MAX_LENGTH = (short)0x400;
protected static final byte[] KEY_DERIVATION_FUNCTION_DEFAULT = {
(byte)0x81, (byte)0x01, (byte)0x00
@@ -149,7 +149,7 @@ public final class Constants {
(byte)0x73, /* card capabilities */
(byte)0xC0, /* 1st byte: "methods supported" see ISO 7816-4 */
@ -20,25 +11,3 @@ index b3c0f80..2ee1107 100644
(byte)0x05, /* status indicator byte : operational state */
(byte)0x90, /* SW1 */
diff --git a/src/fr/anssi/smartpgp/SmartPGPApplet.java b/src/fr/anssi/smartpgp/SmartPGPApplet.java
index c47870f..78d446d 100644
--- a/src/fr/anssi/smartpgp/SmartPGPApplet.java
+++ b/src/fr/anssi/smartpgp/SmartPGPApplet.java
@@ -25,7 +25,7 @@ import javacard.security.*;
import javacardx.apdu.*;
import javacardx.crypto.*;
-public final class SmartPGPApplet extends Applet {
+public final class SmartPGPApplet extends Applet implements ExtendedLength {
private final Persistent data;
@@ -104,7 +104,7 @@ public final class SmartPGPApplet extends Applet {
short blen = apdu.setIncomingAndReceive();
final short lc = apdu.getIncomingLength();
- final short offcdata = ISO7816.OFFSET_CDATA;
+ final short offcdata = apdu.getOffsetCdata();
short off = transients.chainingInputLength();

1
sdks Submodule

@ -0,0 +1 @@
Subproject commit e305a1a0b9bf6b9a8b0c91a9aad8d73537e7ff1b

View File

@ -27,7 +27,7 @@ public final class Constants {
protected static final short INTERNAL_BUFFER_MAX_LENGTH =
(short)0x500;
protected static final short APDU_MAX_LENGTH = (short)256;
protected static final short APDU_MAX_LENGTH = (short)0x400;
protected static final byte[] KEY_DERIVATION_FUNCTION_DEFAULT = {
(byte)0x81, (byte)0x01, (byte)0x00

View File

@ -236,8 +236,8 @@ public final class Persistent {
Common.beginTransaction(isRegistering);
user_pin_length = (byte)Constants.USER_PIN_DEFAULT.length;
user_pin.update(Constants.USER_PIN_DEFAULT, (short)0, user_pin_length);
user_pin.resetAndUnblock();
Common.commitTransaction(isRegistering);
user_pin.resetAndUnblock();
Common.beginTransaction(isRegistering);
user_puk_length = (short)0;
@ -253,8 +253,8 @@ public final class Persistent {
Common.beginTransaction(isRegistering);
admin_pin_length = (byte)Constants.ADMIN_PIN_DEFAULT.length;
admin_pin.update(Constants.ADMIN_PIN_DEFAULT, (short)0, admin_pin_length);
admin_pin.resetAndUnblock();
Common.commitTransaction(isRegistering);
admin_pin.resetAndUnblock();
isTerminated = false;
}

View File

@ -23,8 +23,9 @@ package fr.anssi.smartpgp;
import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.*;
import javacardx.apdu.ExtendedLength;
public final class SmartPGPApplet extends Applet {
public final class SmartPGPApplet extends Applet implements ExtendedLength {
private final Common common;
private final Persistent data;
@ -100,7 +101,7 @@ public final class SmartPGPApplet extends Applet {
short blen = apdu.setIncomingAndReceive();
final short lc = apdu.getIncomingLength();
final short offcdata = ISO7816.OFFSET_CDATA;
final short offcdata = apdu.getOffsetCdata();
short off = transients.chainingInputLength();
@ -766,10 +767,17 @@ public final class SmartPGPApplet extends Applet {
case (byte)0x02:
assertAdmin();
if((lc < Constants.USER_PIN_MIN_SIZE) ||
(lc > Constants.USER_PIN_MAX_SIZE)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
if(data.keyDerivationIsActive()) {
if(lc != data.keyDerivationSize()) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
} else {
if((lc < Constants.USER_PIN_MIN_SIZE) ||
(lc > Constants.USER_PIN_MAX_SIZE)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
}
transients.setUserPinMode81(false);
transients.setUserPinMode82(false);
@ -1141,10 +1149,17 @@ public final class SmartPGPApplet extends Applet {
case Constants.TAG_RESETTING_CODE:
assertAdmin();
if((lc < Constants.USER_PUK_MIN_SIZE) ||
(lc > Constants.USER_PUK_MAX_SIZE)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
if(data.keyDerivationIsActive()) {
if(lc != data.keyDerivationSize()) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
} else {
if((lc < Constants.USER_PUK_MIN_SIZE) ||
(lc > Constants.USER_PUK_MAX_SIZE)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
return;
}
}
JCSystem.beginTransaction();
data.user_puk_length = (byte)lc;