Compare commits

..

24 Commits

Author SHA1 Message Date
7a87360a4a Add codefactor to dictionary 2023-10-07 23:21:28 -05:00
459e16b8f0 Add Codefactor badge 2023-10-07 23:20:49 -05:00
37c5ed9540 fix typo 2023-10-06 20:31:54 -05:00
653e968ee2 Document constants 2023-10-06 20:31:21 -05:00
69b5c1a9bc Add a warning about ROCA 2023-10-06 20:01:36 -05:00
55c1a5edb3 Add a comment 2023-10-05 19:15:05 -05:00
27f845187f Add a comment 2023-10-05 19:14:50 -05:00
dd1b18e5cb Add words to spell check dictionary 2023-10-05 19:14:30 -05:00
cc7f455e83 Reset card serial to 00000000 2023-10-04 19:19:10 -05:00
943f922668 Reset command chaining + extended length to 0x80
Turns out that this does not work on the omni-ring, despite documention saying it should
2023-10-04 16:30:40 -05:00
52c4efd5f5 Hide venv and compiled python 2023-10-04 16:29:27 -05:00
0b77c33d97 Add a warning about ROCA 2023-10-04 15:30:08 -05:00
819f4b736b update comment 2023-10-04 14:25:48 -05:00
141cf85eb7 Restructure README 2023-10-04 14:25:34 -05:00
e9584d79b8 Reduce internal buffer size by 330 bytes
This sets the value to hold only rsa 2048 length (949) + 1 bytes
2023-10-04 13:47:21 -05:00
604de144c6 Choose better values for internal buffer max size
2048: 0x3B0 -> 0x3B6 (was actually 6 bytes too small)
3072: 0x570 -> 0x50F (was 61 bytes larger than necessary)
4096: 0x730 -> 0x66D (was 195 bytes larger than necessary)
2023-10-04 13:38:28 -05:00
1724975b08 Remove AUTHORS file
since we're preserving git history and copyright headers
2023-10-04 12:39:31 -05:00
41c367371f Rename License file 2023-10-04 12:33:16 -05:00
6925c1a366 update license headers to correct git repo 2023-10-04 12:21:18 -05:00
5168bb86d8 Enable Extended Length command chaining by default 2023-10-04 12:14:38 -05:00
d70ca4b185 Remove factory reset patch
We do want the card to reset if the pin gets brute forced
2023-10-04 12:02:11 -05:00
f14a76b2ae Remove demo videos 2023-10-04 11:45:24 -05:00
f9593b4b41 Update Applet Class path 2023-10-04 11:45:05 -05:00
c59f9618ba update readme 2023-08-26 16:02:53 -05:00
28 changed files with 178 additions and 187 deletions

View File

@@ -3,6 +3,7 @@
# OpenPGPpy : Scan devices demo
# Copyright (C) 2020 BitLogiK
# Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
#
# 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

View File

@@ -3,6 +3,7 @@
# OpenPGPpy : Reset device demo
# Copyright (C) 2020 BitLogiK
# Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
#
# 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

View File

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

2
.gitignore vendored
View File

@@ -1,2 +1,4 @@
*.jar
*.cap
*/.venv/*
*.pyc

18
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,18 @@
{
"license.author": "Code Fox <SmartPGP@c0de.dev>",
"license.extension": ".txt",
"license.default": "GPL-2.0",
"license.filename": "LICENSE",
"license.year": "auto",
"cSpell.words": [
"APDU",
"apdubuf",
"CodeFactor",
"Infineon",
"minlen",
"nopad",
"offcdata",
"pkcs",
"smartpgp"
]
}

View File

@@ -1,6 +0,0 @@
Maintainer: Arnaud Fontaine
Contributors:
- Arnaud Fontaine
- Pierre Chifflier (bin/*)

View File

@@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
Copyright (C) <YEAR> <YOUR NAME> (<YOUR EMAIL ADDRESS>)
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

168
README.md
View File

@@ -1,159 +1,131 @@
# SmartPGP applet
[![CodeFactor](https://www.codefactor.io/repository/github/c0de-fox/smartpgp/badge)](https://www.codefactor.io/repository/github/c0de-fox/smartpgp)
SmartPGP is a free and open source implementation of the [OpenPGP card
3.4 specification](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.pdf) in JavaCard.
## Features
The following features are implemented at the applet level, but some
of them depend on underlying hardware support and available
(non-)volatile memory resources:
- RSA (>= 2048 bits modulus, 17 bits exponent) for signature,
encryption and authentication;
- RSA (>= 2048 bits modulus, 17 bits exponent) for signature, encryption and authentication
- On-board key generation and external private key import
- PIN codes (user, admin and resetting code) up to 127 characters each
- Certificate up to 1 kB (DER encoded) for each key
- Login, URL, and private DOs up to 256 bytes
- Command and response chaining
- AES 128/256 bits deciphering primitive
- On-board key generation and external private key import;
## Warnings
- PIN codes (user, admin and resetting code) up to 127 characters;
### ROCA
- Certificate up to 1 kB (DER encoded) for each key;
[Infineon SLE78](https://www.infineon.com/cms/en/product/security-smart-card-solutions/security-controllers/contactless-and-dual-interface-security-controllers/) chips are vulnerable to [ROCA](https://crocs.fi.muni.cz/public/papers/rsa_ccs17).
This attack is only relevant if you used on-device key generation. It allows an adversary to obtain your private key, using only your public key.
- Login, URL, and private DOs up to 256 bytes;
- Command and response chaining;
- AES 128/256 bits deciphering primitive;
There isn't much that can be done to rectify this, other than generating the private RSA keys off of your device and importing them. [Other work arounds](https://crocs.fi.muni.cz/public/papers/rsa_ccs17#detection_tools_mitigation_and_workarounds). (Using the [OpenCrypto JCMathLib](https://github.com/OpenCryptoProject/JCMathLib) to handle the cryptographic functions may work too)
Use [this tool](https://github.com/crocs-muni/roca#install-with-pip) to determine if your public keys are vulnerable.
## Default values
The SmartPGP applet is configured with the following default values:
- Admin PIN is 12345678;
- Admin PIN is 12345678
- User PIN is 123456
- No PUK (a.k.a. resetting code) is defined
- RSA 2048 bits for PGP keys
- User PIN is 123456;
These values can be changed by modifying the [Constants](src/dev/c0de/smartpgp/Constants.java) class.
- No PUK (a.k.a. resetting code) is defined;
After the applet has been installed, the [smartpgp-cli](bin/smartpgp-cli) utility
will be able to change the above values.
- RSA 2048 bits for PGP keys;
_Note: These settings are restored if you factory reset the applet._
These values can be changed by modifying default values in the code
(see the [Constants](src/fr/anssi/smartpgp/Constants.java)
class).
__Note: If you change algorithm attributes, the key and corresponding certificate will be erased.__
When the applet is installed, one can use the `smartpgp-cli` utility
given in the `bin` directory to change these values. Keep in mind that
when you change the algorithm attributes of a PGP key, the key and the
corresponding certificate are
erased. Also note that hard coded default values will be restored upon
a factory reset.
## Build and Install instructions
### Prerequisites
# Application support
- A Java compiler (No higher than OpenJDK 11 or equivalent)
- A device compliant with JavaCard 3.0.1 (or above) with enough available resources
- Applet: ~23 KiB of non-volatile (eeprom/flash) memory
- Persistant Data: ~10 KiB of non-volatile (eeprom/flash) memory
- Transient Data: ~2 KiB of volatile (RAM) memory
Tokens following the OpenPGP card 3.4 specification are not yet fully
supported by most PGP applications.
<!-- - The [pyscard](https://pypi.org/project/pyscard/) and [pyasn1](https://pypi.org/project/pyasn1/)
Python libraries for `smartcard-cli`. -->
## GnuPG
### Importing RSA keys above 2048 bits
OpenPGP card 3.x is supported by [GnuPG](https://www.gnupg.org/)
starting from version 2.1.16.
The internal buffer that stores keys is configured with a default value that is only large enough for RSA 2048 bit keys.
## OpenKeychain
If your card is able to handle larger RSA key bit-lengths (3072 or 4096), and you want to import those keys, you will need to increase the buffer size.
OpenPGP card 3.x is supported by [OpenKeychain](https://www.openkeychain.org/)
starting from version 4.2.
This can be accomplished by modifying `Constants.INTERNAL_BUFFER_MAX_LENGTH` in [Constants.java](src/dev/c0de/smartpgp/Constants.java)
#### RSA 2048 bit keys
# Content of the repository
When produced by OpenPGP, these keys are 949 Bytes in length.
`Constants.INTERNAL_BUFFER_MAX_LENGTH` may not be smaller than `(short)0x3b6` (decimal: 950)
The repository contains several directories:
#### RSA 3072 bit keys
- `bin` contains a Python library and command line tool called
`smartpgp-cli` to interact with an OpenPGP card 3.x;
- `src` contains the JavaCard source code of the SmartPGP applet;
When produced by OpenPGP, these keys are 1294 Bytes in length.
`Constants.INTERNAL_BUFFER_MAX_LENGTH` may not be smaller than `(short)0x50f` (decimal: 1295)
- `videos` contains sample videos demonstrating smartcard interactions
with OpenKeychain and K9 mail on Android Nexus 5.
#### RSA 4096 bit keys
When produced by OpenPGP, these keys are 1644 Bytes in length.
`Constants.INTERNAL_BUFFER_MAX_LENGTH` may not be smaller than `(short)0x66d` (decimal: 1645)
### Reducing flash and/or RAM consumption
# Build and installation instructions
When the applet is installed, all data structures will be allocated
to their maximum size. This is a standard practice for JavaCard applets
to ensure that there will not be a memory allocation failure at runtime.
A consequence of this is that, if you configure a large rsa key and
use a small key, that extra space can not be used for anything else.
## Prerequisites
- JavaCard Development Kit 3.0.1 (or above) from
[Oracle website](http://www.oracle.com/technetwork/java/embedded/javacard/downloads/index.html);
- A device compliant with JavaCard 3.0.1 (or above) with enough
available resources to hold the code (approximately 23 kB of
non-volatile memory), persistent data (approximately 10 kB of
non-volatile memory) and volatile data (approximately 2 kB of RAM).
- The [pyscard](https://pypi.org/project/pyscard/) and [pyasn1](https://pypi.org/project/pyasn1/)
Python libraries for `smartcard-cli`.
## Importing RSA keys above 2048 bits (3072 or 4096 bits)
The size of the internal buffer is set by default to a value that
permits to import RSA 2048 bits. If your card is able to deal with RSA
keys of 3072 or 4096 bits and you want to be able to import such keys,
then you need to adjust the size of this buffer:
- for RSA 2048 bits, `Constants.INTERNAL_BUFFER_MAX_LENGTH` must be at
least `(short)0x3b0`;
- for RSA 3072 bits, `Constants.INTERNAL_BUFFER_MAX_LENGTH` must be at
least `(short)0x570`;
- for RSA 4096 bits, `Constants.INTERNAL_BUFFER_MAX_LENGTH` must be at
least `(short)0x730`.
## Reducing flash and/or RAM consumption
The applet allocates all its data structures to their maximal size
at installation to avoid as much as possible runtime errors caused by
memory allocation failure. If your device does not have enough flash
and/or RAM available, or if you plan not to use some features
(e.g. stored certificates), you can adjust the applet to reduce its
resource consumption by tweaking the following variables:
If your device does not have enough flash memory and/or RAM, or you plan
to not use some features (eg. on-device certificates), you can modify
the following variables in [Constants.java](src/dev/c0de/smartpgp/Constants.java)
- `Constants.INTERNAL_BUFFER_MAX_LENGTH`: the size in bytes of the
internal RAM buffer used for input/output chaining. Chaining is
especially used in case of long commands and responses such as those
involved in private key import and certificate import/export;
- `Constants.EXTENDED_CAPABILITIES`, bytes 5 and 6: the maximal size
in bytes of a certificate associated to a key. Following the OpenPGP
card specification, a certificate can be stored for each of the
three keys.
- `Constants.EXTENDED_CAPABILITIES`, bytes 5 and 6: the maximum size
in bytes of a certificate associated to a key. The default is 1152 Bytes.
A certificate can be stored for each of the three keys.
### Building the CAP file
## Building the CAP file
- Set path to the JavaCard Development Kit:
`export JC_HOME="your/path/to/javacardkit"`
- (Optional) Edit the `build.xml` file and replace the `0xAF:0xAF`
bytes in the `APPLET_AID` with your own manufacturer identifier (see
section 4.2.1 of OpenPGP card specification). Alternatively, set the
- (Optional) Edit the `build.xml` file and replace the `APPLET_AID`
with your a unique value. Alternatively, set the
right AID instance bytes during applet installation.
Generate the AID using [this tool](https://c0de.dev/c0de/SmartPGP-AID-Generator)
- Execute `ant` with no parameter will produce the CAP file in
`SmartPGPApplet.cap`.
- Execute `ant` to build `SmartPGPApplet.cap`
## Installing the CAP file
### Installing the CAP file
The CAP file installation depends on your device, so you have to refer
to the instructions given by your device manufacturer. Most open cards
relying on Global Platform with default keys are supported by
[GlobalPlatformPro](https://github.com/martinpaljak/GlobalPlatformPro).
Be careful to use a valid AID according to the OpenPGP card
specification (see section 4.2.1) for each card (`-create <AID>` with
GlobalPlatformPro)
You must use a valid, unique AID that matches the OpenPGP card specification (see section 4.2.1)
for each card (`-create <AID>` with GlobalPlatformPro)
Example Installation commands:
- `gp --install SmartPGPApplet.cap --default`
- `gp --install SmartPGPApplet.cap --create <AID>`

View File

@@ -1,8 +1,9 @@
#!/usr/bin/env python3
# SmartPGP : JavaCard implementation of OpenPGP card v3 specification
# https://github.com/ANSSI-FR/SmartPGP
# https://c0de.dev/c0de/SmartPGP
# Copyright (C) 2016 ANSSI
# Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@@ -1,6 +1,7 @@
# SmartPGP : JavaCard implementation of OpenPGP card v3 specification
# https://github.com/ANSSI-FR/SmartPGP
# https://c0de.dev/c0de/SmartPGP
# Copyright (C) 2016 ANSSI
# Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@@ -1,7 +1,8 @@
# SmartPGP : JavaCard implementation of OpenPGP card v3 specification
# https://github.com/ANSSI-FR/SmartPGP
# https://c0de.dev/c0de/SmartPGP
# Copyright (C) 2016 ANSSI
# Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License

View File

@@ -11,7 +11,7 @@
<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"/>
<applet class="dev.c0de.smartpgp.SmartPGPApplet" aid="d276000124010304c0de000000000000"/>
</cap>
</javacard>
</target>

View File

@@ -1,17 +0,0 @@
diff --git a/src/fr/anssi/smartpgp/SmartPGPApplet.java b/src/fr/anssi/smartpgp/SmartPGPApplet.java
index c47870f..87162fb 100644
--- a/src/fr/anssi/smartpgp/SmartPGPApplet.java
+++ b/src/fr/anssi/smartpgp/SmartPGPApplet.java
@@ -1329,10 +1329,12 @@ public final class SmartPGPApplet extends Applet {
return;
}
+/*
if(data.admin_pin.getTriesRemaining() <= 0) {
data.isTerminated = true;
return;
}
+*/
assertAdmin();

View File

@@ -1,13 +0,0 @@
diff --git a/src/fr/anssi/smartpgp/Constants.java b/src/fr/anssi/smartpgp/Constants.java
index b3c0f80..2ee1107 100644
--- a/src/fr/anssi/smartpgp/Constants.java
+++ b/src/fr/anssi/smartpgp/Constants.java
@@ -149,7 +149,7 @@ public final class Constants {
(byte)0x73, /* card capabilities */
(byte)0xC0, /* 1st byte: "methods supported" see ISO 7816-4 */
(byte)0x01, /* 2nd byte: "data coding byte" idem */
- (byte)0x80, /* 3rd byte: command chaining (not extended length by default as all readers do not support them...) */
+ (byte)0xC0, /* 3rd byte: command chaining + extended length */
(byte)0x05, /* status indicator byte : operational state */
(byte)0x90, /* SW1 */

View File

@@ -1,7 +1,8 @@
/*
SmartPGP : JavaCard implementation of OpenPGP card v3 specification
https://github.com/ANSSI-FR/SmartPGP
https://c0de.dev/c0de/SmartPGP
Copyright (C) 2016 ANSSI
Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -18,7 +19,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package fr.anssi.smartpgp;
package dev.c0de.smartpgp;
import javacard.framework.*;
import javacard.security.*;
@@ -31,9 +32,11 @@ public final class Common {
protected final RandomData random;
protected Common() {
/* Get an instance of cryptography Ciphers */
cipher_aes_cbc_nopad = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
cipher_rsa_pkcs1 = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
/* Get an instance of the Secure Random Number Generator */
random = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
}
@@ -157,8 +160,8 @@ public final class Common {
}
}
protected static final short writeAlgorithmInformation(final byte key_tag,
final byte[] buf, short off) {
protected static final short writeAlgorithmInformation(final byte key_tag, final byte[] buf, short off) {
for(short m = 2; m <= 4; ++m) {
for(byte form = Constants.RSA_IMPORT_SUPPORTS_FORMAT_1 ? 1 : 3; form <= 3; form += 2) {
buf[off++] = key_tag;

View File

@@ -1,7 +1,8 @@
/*
SmartPGP : JavaCard implementation of OpenPGP card v3 specification
https://github.com/ANSSI-FR/SmartPGP
https://c0de.dev/c0de/SmartPGP
Copyright (C) 2016 ANSSI
Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -18,51 +19,57 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package fr.anssi.smartpgp;
package dev.c0de.smartpgp;
import javacard.framework.*;
public final class Constants {
protected static final short INTERNAL_BUFFER_MAX_LENGTH =
(short)0x500;
/* 0x3b6 for rsa 2048; 0x50f for rsa 3072; 0x66d for rsa 4096 */
protected static final short INTERNAL_BUFFER_MAX_LENGTH = (short)0x3b6; // Max size of key in bytes
protected static final short APDU_MAX_LENGTH = (short)0x400;
/* See section 4.3.2 of the specification; Default is NONE; Standard UTF-8 PWs*/
protected static final byte[] KEY_DERIVATION_FUNCTION_DEFAULT = {
(byte)0x81, (byte)0x01, (byte)0x00
};
protected static final byte USER_PIN_RETRY_COUNT = 3;
protected static final byte USER_PIN_MIN_SIZE = 0x06;
protected static final byte USER_PIN_MAX_SIZE = 0x7f; /* max is 0x7f because PIN format 2 */
protected static final byte USER_PIN_RETRY_COUNT = 3; /* Card gets locked after this many incorrect attempts */
protected static final byte USER_PIN_MIN_SIZE = 0x06; /* 6 chars is minimum as defined by spec */
protected static final byte USER_PIN_MAX_SIZE = 0x7f; /* 127 chars is maximum as defined by spec */
/* UTF-8 bytes for the default user pin: 123456 is the value defined by the specification */
protected static final byte[] USER_PIN_DEFAULT = {
(byte)0x31, (byte)0x32, (byte)0x33, (byte)0x34,
(byte)0x35, (byte)0x36
};
/* Is the USER_PIN required for signing actions; default: true */
protected static final boolean USER_PIN_DEFAULT_FORCE_VERIFY_SIGNATURE = true;
protected static final byte USER_PUK_RETRY_COUNT = 3;
protected static final byte USER_PUK_MIN_SIZE = 0x08;
protected static final byte USER_PUK_MAX_SIZE = 0x7f; /* max is 0x7f because PIN format 2 */
protected static final byte USER_PUK_RETRY_COUNT = 3; /* */
protected static final byte USER_PUK_MIN_SIZE = 0x08; /* 8 chars is minimum as defined by spec */
protected static final byte USER_PUK_MAX_SIZE = 0x7f; /* 127 chars is maximum as defined by spec */
protected static final byte ADMIN_PIN_RETRY_COUNT = 3;
protected static final byte ADMIN_PIN_MIN_SIZE = 0x08;
protected static final byte ADMIN_PIN_MAX_SIZE = 0x7f; /* max is 0x7f because PIN format 2 */
protected static final byte ADMIN_PIN_RETRY_COUNT = 3; /* Card gets reset after this many failed attempts */
protected static final byte ADMIN_PIN_MIN_SIZE = 0x08; /* 8 chars is minimum as defined by spec */
protected static final byte ADMIN_PIN_MAX_SIZE = 0x7f; /* 127 chars is maximum as defined by spec */
protected static final byte[] ADMIN_PIN_DEFAULT = {
(byte)0x31, (byte)0x32, (byte)0x33, (byte)0x34,
(byte)0x35, (byte)0x36, (byte)0x37, (byte)0x38
};
protected static final byte FINGERPRINT_SIZE = 20;
protected static final byte GENERATION_DATE_SIZE = 4;
protected static final byte FINGERPRINT_SIZE = 20; /* size of each fingerprint in bytes */
protected static final byte GENERATION_DATE_SIZE = 4; /* number of bytes to store the date+time */
protected static final byte NAME_MAX_LENGTH = 39;
protected static final byte LANG_MIN_LENGTH = 2;
protected static final byte LANG_MAX_LENGTH = 8;
protected static final byte[] LANG_DEFAULT = { (byte)0x65, (byte)0x6e };
protected static final byte NAME_MAX_LENGTH = 39; /* max number of chars in cardholder name */
protected static final byte LANG_MIN_LENGTH = 2; /* 2 char language codes */
protected static final byte LANG_MAX_LENGTH = 8; /* spec allows up to 4 languages */
protected static final byte[] LANG_DEFAULT = { (byte)0x65, (byte)0x6e }; /* utf-8: EN */
/* Unsure if the following bytes and shorts actually need to be in card memory */
protected static final byte SEX_NOT_KNOWN = (byte)0x30;
protected static final byte SEX_MALE = (byte)0x31;
@@ -107,6 +114,8 @@ public final class Constants {
protected static final short TAG_KEY_DERIVATION_FUNCTION = (short)0x00f9;
protected static final short TAG_ALGORITHM_INFORMATION = (short)0x00fa;
/* The bytes and shorts below appear to be needed */
protected static final byte CRT_TAG_AUTHENTICATION_KEY = (byte)0xa4;
protected static final byte CRT_TAG_SIGNATURE_KEY = (byte)0xb6;
protected static final byte CRT_TAG_DECRYPTION_KEY = (byte)0xb8;
@@ -148,7 +157,10 @@ public final class Constants {
(byte)0x73, /* card capabilities */
(byte)0xC0, /* 1st byte: "methods supported" see ISO 7816-4 */
(byte)0x01, /* 2nd byte: "data coding byte" idem */
(byte)0x80, /* 3rd byte: command chaining (not extended length by default as all readers do not support them...) */
/* 3rd byte: command chaining + extended length; Set to 0xC0 if
extended length is supported by card and reader */
(byte)0x80,
(byte)0x05, /* status indicator byte : operational state */
(byte)0x90, /* SW1 */
@@ -165,9 +177,9 @@ public final class Constants {
0x02 | /* support PSO:DEC/ENC AES */
0x01), /* support KDF-DO */
(byte)0x00, /* SM 0x01 = 128 bits, 0x02 = 256 bits, 0x03 = SCP11b */
(byte)0x00, (byte)0x20, /* max length get challenge */
(byte)0x04, (byte)0x80, /* max length of carholder certificate */
(byte)0x00, (byte)0xff, /* max length of special DOs (private, login, url, KDF-DO) */
(byte)0x00, (byte)0x20, /* max length of get challenge response in bytes (decimal: 32) */
(byte)0x04, (byte)0x80, /* max length of cardholder certificate in bytes (decimal: 1152) */
(byte)0x00, (byte)0xff, /* max length of special DOs (private, login, url, KDF-DO) in bytes (decimal: 255) */
(byte)0x00, /* PIN format 2 is not supported */
(byte)0x00 /* MSE not supported */
};
@@ -213,6 +225,7 @@ public final class Constants {
protected static final byte ALGORITHM_ATTRIBUTES_MIN_LENGTH = 6;
protected static final byte ALGORITHM_ATTRIBUTES_MAX_LENGTH = 13;
/* FIXME: Can I modify these to get safer private key generation? */
protected static final byte[] ALGORITHM_ATTRIBUTES_DEFAULT = {
(byte)0x01, /* RSA */
(byte)0x08, (byte)0x00, /* 2048 bits modulus */

View File

@@ -1,7 +1,8 @@
/*
SmartPGP : JavaCard implementation of OpenPGP card v3 specification
https://github.com/ANSSI-FR/SmartPGP
https://c0de.dev/c0de/SmartPGP
Copyright (C) 2016 ANSSI
Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -18,7 +19,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package fr.anssi.smartpgp;
package dev.c0de.smartpgp;
import javacard.framework.*;

View File

@@ -1,7 +1,8 @@
/*
SmartPGP : JavaCard implementation of OpenPGP card v3 specification
https://github.com/ANSSI-FR/SmartPGP
https://c0de.dev/c0de/SmartPGP
Copyright (C) 2016 ANSSI
Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -18,7 +19,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package fr.anssi.smartpgp;
package dev.c0de.smartpgp;
import javacard.framework.*;
import javacard.security.*;
@@ -178,6 +179,14 @@ public final class PGPKey {
return Util.getShort(attributes, (short)3);
}
/*
* !!! WARNING !!! - Read this if your JavaCard is Infineon SLE78
* The API called by this function is flawed and vulnerable to ROCA.
* Malicious actors are able to determine the private key using ONLY the public key.
*
* It's HIGHLY recommended that you do NOT use this API; Instead, you
* should generate your private key off-device, then import it later
*/
private final KeyPair generateRSA() {
final PrivateKey priv = (PrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_CRT_PRIVATE, rsaModulusBitSize(), false);
final RSAPublicKey pub = (RSAPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, rsaModulusBitSize(), false);

View File

@@ -1,7 +1,8 @@
/*
SmartPGP : JavaCard implementation of OpenPGP card v3 specification
https://github.com/ANSSI-FR/SmartPGP
https://c0de.dev/c0de/SmartPGP
Copyright (C) 2016 ANSSI
Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -18,7 +19,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package fr.anssi.smartpgp;
package dev.c0de.smartpgp;
import javacard.framework.*;
import javacard.security.*;
@@ -86,8 +87,7 @@ public final class Persistent {
protected final OwnerPIN admin_pin; /* PW3 */
protected byte admin_pin_length;
/* Called at Applet Install time; Reserve memory of persistent data objects */
protected Persistent() {
login = new byte[Constants.specialDoMaxLength()];
login_length = 0;

View File

@@ -1,7 +1,8 @@
/*
SmartPGP : JavaCard implementation of OpenPGP card v3 specification
https://github.com/ANSSI-FR/SmartPGP
https://c0de.dev/c0de/SmartPGP
Copyright (C) 2016 ANSSI
Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -18,7 +19,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package fr.anssi.smartpgp;
package dev.c0de.smartpgp;
import javacard.framework.*;
import javacard.security.*;
@@ -38,11 +39,13 @@ public final class SmartPGPApplet extends Applet implements ExtendedLength {
transients = new Transients();
}
/* Called on applet install */
public static final void install(byte[] buf, short off, byte len) {
// Reserve memory immediately
new SmartPGPApplet().register(buf, (short)(off + 1), buf[off]);
}
private final PGPKey currentTagOccurenceToKey() {
private final PGPKey currentTagOccurrenceToKey() {
switch(transients.currentTagOccurrence()) {
case 0:
return data.pgp_keys[Persistent.PGP_KEYS_OFFSET_AUT];
@@ -420,7 +423,7 @@ public final class SmartPGPApplet extends Applet implements ExtendedLength {
break;
case Constants.TAG_CARDHOLDER_CERTIFICATE:
k = currentTagOccurenceToKey();
k = currentTagOccurrenceToKey();
if(k == null) {
ISOException.throwIt(Constants.SW_REFERENCE_DATA_NOT_FOUND);
@@ -470,7 +473,7 @@ public final class SmartPGPApplet extends Applet implements ExtendedLength {
return 0;
}
final PGPKey k = currentTagOccurenceToKey();
final PGPKey k = currentTagOccurrenceToKey();
if(k == null) {
ISOException.throwIt(Constants.SW_REFERENCE_DATA_NOT_FOUND);
@@ -1062,7 +1065,7 @@ public final class SmartPGPApplet extends Applet implements ExtendedLength {
case Constants.TAG_CARDHOLDER_CERTIFICATE:
assertAdmin();
k = currentTagOccurenceToKey();
k = currentTagOccurrenceToKey();
if(k == null) {
ISOException.throwIt(Constants.SW_REFERENCE_DATA_NOT_FOUND);
return;

View File

@@ -1,7 +1,8 @@
/*
SmartPGP : JavaCard implementation of OpenPGP card v3 specification
https://github.com/ANSSI-FR/SmartPGP
https://c0de.dev/c0de/SmartPGP
Copyright (C) 2016 ANSSI
Copyright (C) 2023 Code Fox <SmartPGP@c0de.dev>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -18,7 +19,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package fr.anssi.smartpgp;
package dev.c0de.smartpgp;
import javacard.framework.*;

View File

@@ -6,7 +6,7 @@
<target name="convert">
<javacard>
<cap output="TestApplet.cap" sources="src" aid="aaaaaaaaaaaa" version="1.0">
<applet class="fr.anssi.smartpgp.TestApplet" aid="aaaaaaaaaaaa00000000000000000000"/>
<applet class="dev.c0de.smartpgp.TestApplet" aid="aaaaaaaaaaaa00000000000000000000"/>
</cap>
</javacard>
</target>

View File

@@ -1,4 +1,4 @@
package fr.anssi.smartpgp;
package dev.c0de.smartpgp;
public final class Data {

View File

@@ -1,4 +1,4 @@
package fr.anssi.smartpgp;
package dev.c0de.smartpgp;
public final class ECConstants {

View File

@@ -1,4 +1,4 @@
package fr.anssi.smartpgp;
package dev.c0de.smartpgp;
import javacard.framework.*;

Binary file not shown.

Binary file not shown.

Binary file not shown.