Skip to content

Commit dc5da82

Browse files
committed
Compat touchups: non-static vars, commit largeBlob, MDS, attCert
1 parent 70f242c commit dc5da82

File tree

3 files changed

+45
-39
lines changed

3 files changed

+45
-39
lines changed

install_attestation_cert.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import secrets
1212

1313
from cryptography.hazmat.primitives.asymmetric import ec
14+
from cryptography.hazmat.primitives._serialization import Encoding, PrivateFormat, NoEncryption
15+
from cryptography.hazmat.primitives.serialization import load_der_private_key
1416

1517
from python_tests.ctap.ctap_test import BasicAttestationTestCase
1618

@@ -27,7 +29,7 @@
2729
help='CA certificate, expressed as base64-encoded DER')
2830
parser.add_argument('--ca-private-key',
2931
default=None,
30-
help='CA private key, expressed as a hex string')
32+
help='CA private key, expressed as base64-encoded unencrypted PKCS8 DER')
3133
parser.add_argument('--org',
3234
default='ACME',
3335
help='Organization name to use for certificates')
@@ -51,17 +53,25 @@
5153
tc = BasicAttestationTestCase()
5254
if args.ca_private_key is None:
5355
ca_privkey_and_cert = tc.get_ca_cert(org=args.org)
56+
privkey_bytes = ca_privkey_and_cert[0].private_bytes(
57+
encoding=Encoding.DER,
58+
format=PrivateFormat.PKCS8,
59+
encryption_algorithm=NoEncryption()
60+
)
61+
print(f"Generated CA private key: {base64.b64encode(privkey_bytes)}")
62+
print(f"Generated CA cert: {base64.b64encode(ca_privkey_and_cert[1])}")
5463
else:
55-
ca_privkey_and_cert = bytes.fromhex(args.ca_private_key), base64.b64decode(args.ca_cert_bytes)
56-
private_key = ec.generate_private_key(ec.SECP256R1())
64+
privkey = load_der_private_key(data=base64.b64decode(args.ca_private_key), password=None)
65+
ca_privkey_and_cert = privkey, base64.b64decode(args.ca_cert_bytes)
66+
67+
print(f"Using AAGUID: {aaguid.hex()}")
5768

69+
private_key = ec.generate_private_key(ec.SECP256R1())
5870
cert_bytes = tc.get_x509_certs(private_key, name=args.name, ca_privkey_and_cert=ca_privkey_and_cert,
5971
org=args.org, country=args.country)
60-
print(f"Using AAGUID: {aaguid.hex()}")
61-
print(f"Using CA certificate: {base64.b64encode(cert_bytes[-1])}")
6272

6373
at_bytes = tc.assemble_cbor_from_attestation_certs(private_key=private_key,
64-
cert_bytes=cert_bytes,
74+
cert_bytes=cert_bytes[:-1],
6575
aaguid=aaguid)
6676

6777
devices = list(CtapPcscDevice.list_devices())

mds.json

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"legalHeader": "https://fidoalliance.org/metadata/metadata-statement-legal-header/",
33
"description": "FIDO2 Javacard Applet",
4-
"aaguid": "00000000-0000-0000-0000-000000000000",
4+
"aaguid": "b6a13d01-7826-af82-1b05-2b53adba1b4e",
5+
"icon": "data:image/png;base64,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",
56
"alternativeDescriptions": {
67
},
78
"protocolFamily": "fido2",
@@ -13,53 +14,47 @@
1314
],
1415
"authenticationAlgorithms": ["secp256r1_ecdsa_sha256_raw"],
1516
"publicKeyAlgAndEncodings": ["cose"],
16-
"attestationTypes": ["basic_surrogate"],
17+
"attestationTypes": ["basic_full"],
1718
"userVerificationDetails": [
1819
[
1920
{"userVerificationMethod": "none"}
2021
],
2122
[{
22-
"userVerificationMethod": "passcode_external",
23-
"caDesc": {
24-
"base": 10,
25-
"minLength": 4
26-
}
23+
"userVerificationMethod": "passcode_external"
2724
}]
2825
],
2926
"keyProtection": ["hardware", "secure_element"],
3027
"matcherProtection": ["on_chip"],
3128
"cryptoStrength": 128,
3229
"attachmentHint": ["nfc"],
3330
"tcDisplay": [],
34-
"attestationRootCertificates": [
35-
36-
],
31+
"attestationRootCertificates": ["MIIBPjCB5qADAgECAhRGVRN2Qi4Y97Q3vK0l5YB8CqNbVTAKBggqhkjOPQQDAjAgMQ0wCwYDVQQKDARBQ01FMQ8wDQYDVQQDDAZBdXRoQ0EwHhcNMjMwOTE1MTYwNDE0WhcNMzMwOTEzMTYwNDE0WjAgMQ0wCwYDVQQKDARBQ01FMQ8wDQYDVQQDDAZBdXRoQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATyn3WzUaMddA5MqLqf27YTS2izCw+HTX+vTUeImQkg9bPB67t4SswTEgT/VAQq7WgjGFRw0mk2Pu3nAf98wAjfMAoGCCqGSM49BAMCA0cAMEQCIESrgGpvqhNKAsHqZVWUYZxQRcss3nGwnFg827aZamMCAiA1vQUO0f5VAzLRccQK7/otfRBha/5wNUyK8QyF8pQcgA=="],
3732
"authenticatorGetInfo": {
38-
"versions": [ "FIDO_2_0", "FIDO_2_1", "FIDO_2_1_PRE", "U2F_V2" ],
39-
"extensions": [ "uvm", "credBlob", "credProtect", "hmac-secret", "largeBlobKey" ],
40-
"aaguid": "00000000000000000000000000000000",
41-
"options": {
33+
"versions": [ "FIDO_2_0", "FIDO_2_1", "FIDO_2_1_PRE", "U2F_V2" ],
34+
"extensions": [ "uvm", "credBlob", "credProtect", "hmac-secret", "largeBlobKey", "minPinLength" ],
35+
"aaguid": "b6a13d017826af821b052b53adba1b4e",
36+
"algorithms": [ { "alg": -7, "type": "public-key" } ],
37+
"options": {
4238
"rk": true,
4339
"clientPin": false,
40+
"up": false,
4441
"alwaysUv": false,
4542
"credMgmt": true,
4643
"authnrCfg": true,
4744
"largeBlobs": true,
4845
"makeCredUvNotRqd": true,
4946
"pinUvAuthToken": true,
50-
"setMinPINLength": true
51-
},
52-
"algorithms": [{"alg": -7, "type": "public-key"}],
53-
"maxMsgSize": 1024,
54-
"maxCredBlobLength": 32,
55-
"pinUvAuthProtocols": [2, 1],
56-
"maxCredentialCountInList": 10,
57-
"maxCredentialIdLength": 64,
58-
"maxSerializedLargeBlobArray": 1024,
59-
"firmwareVersion": 1,
60-
"remainingDiscoverableCredentials": 100,
61-
"minPINLength": 4,
62-
"maxRPIDsForSetMinPINLength": 2,
63-
"uvModality": 512
47+
"setMinPINLength": true
48+
},
49+
"maxCredBlobLength": 32,
50+
"pinUvAuthProtocols": [2, 1],
51+
"maxCredentialCountInList": 10,
52+
"maxCredentialIdLength": 64,
53+
"firmwareVersion": 1,
54+
"remainingDiscoverableCredentials": 100,
55+
"minPINLength": 4,
56+
"maxSerializedLargeBlobArray": 1024,
57+
"maxRPIDsForSetMinPINLength": 2,
58+
"uvModality": 512
6459
}
6560
}

src/main/java/us/q3q/fido2/FIDO2Applet.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -241,15 +241,15 @@ public final class FIDO2Applet extends Applet implements ExtendedLength {
241241
/**
242242
* random IV for authenticator private wrapping with highSecurityWrappingKey
243243
*/
244-
private static byte[] highSecurityWrappingIV;
244+
private final byte[] highSecurityWrappingIV;
245245
/**
246246
* random IV for authenticator private wrapping with lowSecurityWrappingKey
247247
*/
248-
private static byte[] lowSecurityWrappingIV;
248+
private final byte[] lowSecurityWrappingIV;
249249
/**
250250
* random IV for authenticator private wrapping of NON discoverable credentials
251251
*/
252-
private static byte[] externalCredentialIV;
252+
private final byte[] externalCredentialIV;
253253
/**
254254
* first half random data, second half the HMAC of that using the wrapping key:
255255
* used for checking if a potential wrapping key is the correct one
@@ -357,7 +357,7 @@ public final class FIDO2Applet extends Applet implements ExtendedLength {
357357
/**
358358
* Length of the currently stored large-blob array
359359
*/
360-
private static short largeBlobStoreFill;
360+
private short largeBlobStoreFill;
361361

362362
/**
363363
* Unique identifier ID - set on loading an attestation,
@@ -3925,6 +3925,7 @@ private void handleLargeBlobSet(APDU apdu, byte[] buffer, short incomingDataOffs
39253925
try {
39263926
largeBlobStoreIndex = newBlobStoreIndex;
39273927
largeBlobStoreFill = totalLength;
3928+
ok = true;
39283929
} finally {
39293930
if (ok) {
39303931
JCSystem.commitTransaction();
@@ -5389,7 +5390,6 @@ private void authenticatorReset(APDU apdu) {
53895390

53905391
final short pinIdx = pinRetryCounter.prepareIndex();
53915392
final byte tempBlobStoreIndex = (byte)(largeBlobStoreIndex == 0 ? 1 : 0);
5392-
final byte realBlobStoreIndex = largeBlobStoreIndex;
53935393

53945394
// Empty the large blob store OUTside the main transaction, since it's non-precious and double buffered
53955395
final byte[] inactiveLargeBlobStore = getInactiveLargeBlobStore();
@@ -5411,6 +5411,7 @@ private void authenticatorReset(APDU apdu) {
54115411
JCSystem.abortTransaction();
54125412
}
54135413
}
5414+
// active is now inactive
54145415
Util.arrayFillNonAtomic(activeLargeBlobStore, (short) 0,
54155416
(short) activeLargeBlobStore.length, (byte) 0x00);
54165417
Util.arrayCopyNonAtomic(CannedCBOR.INITIAL_LARGE_BLOB_ARRAY, (short) 0,

0 commit comments

Comments
 (0)