Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
F
Fido2Applet
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Wen Wei Li
Fido2Applet
Commits
0bd67b09
Commit
0bd67b09
authored
Jun 07, 2022
by
Josh Ji
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
code review
parent
20eb478d
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
3104 additions
and
2367 deletions
+3104
-2367
build/javacard/applet.cap
build/javacard/applet.cap
+0
-0
build/javacard/applet.exp/vku2f.jar
build/javacard/applet.exp/vku2f.jar
+0
-0
build/javacard/applet.jca
build/javacard/applet.jca
+2905
-2187
src/main/java/com/josh/vku2f/CTAP2.java
src/main/java/com/josh/vku2f/CTAP2.java
+199
-180
No files found.
build/javacard/applet.cap
View file @
0bd67b09
No preview for this file type
build/javacard/applet.exp/vku2f.jar
View file @
0bd67b09
No preview for this file type
build/javacard/applet.jca
View file @
0bd67b09
This source diff could not be displayed because it is too large. You can
view the blob
instead.
src/main/java/com/josh/vku2f/CTAP2.java
View file @
0bd67b09
...
...
@@ -31,58 +31,66 @@ import static com.josh.vku2f.ClientPINSubCommand.*;
public
class
CTAP2
extends
Applet
implements
ExtendedLength
{
private
final
CBORDecoder
cborDecoder
;
private
final
CBOREncoder
cborEncoder
;
// transient memory, clear on deselect
private
byte
[]
dataBuffer
;
private
byte
[]
scratch
;
private
byte
[]
info
;
private
final
short
[]
tempVars
;
private
final
short
[]
chainRam
;
private
final
short
[]
outChainRam
;
private
final
boolean
[]
isChaining
;
private
final
boolean
[]
isOutChaining
;
//transient memory, clear on reset
private
final
short
[]
nextAssertion
;
private
byte
[]
fidoInfo
;
private
final
CBORDecoder
cborDecoder
;
private
final
CBOREncoder
cborEncoder
;
private
final
MessageDigest
sha256MessageDigest
;
private
final
AttestationKeyPair
attestationKeyPair
;
private
boolean
personalizeComplete
;
private
CredentialArray
credentialArray
;
private
AuthenticatorMakeCredential
authenticatorMakeCredential
;
private
AuthenticatorGetAssertion
authenticatorGetAssertion
;
private
final
ClientPINCommand
clientPINCommand
;
private
StoredCredential
tempCredential
;
private
StoredCredential
[]
assertionCredentials
;
private
byte
MAX_PIN_RETRIES
=
(
byte
)
0x08
;
private
byte
MAX_UV_RETRIES
=
(
byte
)
0x08
;
private
final
ClientPINCommand
clientPINCommand
;
private
final
byte
MAX_PIN_RETRIES
=
(
byte
)
0x08
;
private
final
byte
MAX_UV_RETRIES
=
(
byte
)
0x08
;
private
byte
pinRetries
;
private
byte
uvRetries
;
// private final KeyPair ecDhKeyPair;
// private final boolean[] ecDhSet;
private
PinUvAuthProtocolOne
pinUvAuthProtocolOne
;
private
final
boolean
[]
isChaining
;
private
final
boolean
[]
isOutChaining
;
private
boolean
personalizeComplete
;
private
StoredCredential
tempCredential
;
private
StoredCredential
[]
assertionCredentials
;
// INS
public
static
final
byte
ISO_INS_GET_DATA
=
(
byte
)
0xC0
;
public
static
final
byte
FIDO2_INS_NFCCTAP_MSG
=
(
byte
)
0x10
;
public
static
final
byte
FIDO2_INS_DESELECT
=
(
byte
)
0x12
;
// FIDO Command
public
static
final
byte
FIDO2_AUTHENTICATOR_MAKE_CREDENTIAL
=
(
byte
)
0x01
;
public
static
final
byte
FIDO2_AUTHENTICATOR_GET_ASSERTION
=
(
byte
)
0x02
;
public
static
final
byte
FIDO2_AUTHENTICATOR_GET_NEXT_ASSERTION
=
(
byte
)
0x08
;
public
static
final
byte
FIDO2_AUTHENTICATOR_GET_INFO
=
(
byte
)
0x04
;
public
static
final
byte
FIDO2_AUTHENTICATOR_CLIENT_PIN
=
(
byte
)
0x06
;
public
static
final
byte
FIDO2_AUTHENTICATOR_RESET
=
(
byte
)
0x07
;
// Vendor specific - for attestation cert loading.
public
static
final
byte
FIDO2_VENDOR_ATTEST_SIGN
=
(
byte
)
0x41
;
public
static
final
byte
FIDO2_VENDOR_ATTEST_LOADCERT
=
(
byte
)
0x42
;
public
static
final
byte
FIDO2_VENDOR_PERSO_COMPLETE
=
(
byte
)
0x43
;
public
static
final
byte
FIDO2_VENDOR_ATTEST_GETPUB
=
(
byte
)
0x44
;
public
static
final
byte
FIDO2_VENDOR_GET_C
OUNT
=
(
byte
)
0x45
;
public
static
final
byte
FIDO2_VENDOR_GET_C
REDENTIAL_COUNT
=
(
byte
)
0x45
;
public
static
final
byte
FIDO2_VENDOR_ATTEST_GETCERT
=
(
byte
)
0x4A
;
public
static
final
byte
FIDO2_DESELECT
=
0x12
;
//PRLAB
public
static
final
byte
PRLAB_GET_PUKX_RX
=
(
byte
)
0x50
;
public
static
final
byte
PRLAB_GET_CX
=
(
byte
)
0x51
;
// AAGUID - Authenticator Attestation Global Unique Identifier
// this uniquely identifies the type of authenticator we have built.
...
...
@@ -129,6 +137,134 @@ public class CTAP2 extends Applet implements ExtendedLength {
}
public
static
void
install
(
byte
[]
bArray
,
short
bOffset
,
byte
bLength
)
throws
ISOException
{
short
offset
=
bOffset
;
offset
+=
(
short
)
(
bArray
[
offset
]
+
1
);
// instance
offset
+=
(
short
)
(
bArray
[
offset
]
+
1
);
// privileges
final
CTAP2
applet
=
new
CTAP2
();
try
{
applet
.
register
(
bArray
,
(
short
)
(
bOffset
+
1
),
bArray
[
bOffset
]);
}
catch
(
Exception
e
)
{
applet
.
register
();
}
}
// main entry point
public
void
process
(
APDU
apdu
)
throws
ISOException
{
byte
[]
buffer
=
apdu
.
getBuffer
();
// return FIDO2 String when selecting
if
(
selectingApplet
())
{
Util
.
arrayCopyNonAtomic
(
Utf8Strings
.
UTF8_FIDO2
,
(
short
)
0
,
buffer
,
(
short
)
0
,
(
short
)
Utf8Strings
.
UTF8_FIDO2
.
length
);
apdu
.
setOutgoingAndSend
((
short
)
0
,
(
short
)
Utf8Strings
.
UTF8_FIDO2
.
length
);
return
;
}
// Check CLA
if
(!
apdu
.
isCommandChainingCLA
()
&&
apdu
.
isISOInterindustryCLA
())
{
ISOException
.
throwIt
(
ISO7816
.
SW_CLA_NOT_SUPPORTED
);
}
JCSystem
.
requestObjectDeletion
();
switch
(
buffer
[
ISO7816
.
OFFSET_INS
])
{
case
ISO_INS_GET_DATA:
// 0xC0
if
(
isOutChaining
[
0
])
{
getData
(
apdu
);
}
else
{
ISOException
.
throwIt
(
ISO7816
.
SW_CONDITIONS_NOT_SATISFIED
);
}
break
;
case
FIDO2_INS_NFCCTAP_MSG:
// 0x10
handle
(
apdu
);
break
;
case
FIDO2_INS_DESELECT:
// 0x12
// Appears to be a reset function in the FIDO2 spec, but never referenced
// anywhere
ISOException
.
throwIt
(
ISO7816
.
SW_NO_ERROR
);
break
;
default
:
ISOException
.
throwIt
(
ISO7816
.
SW_INS_NOT_SUPPORTED
);
}
}
/**
* Handle the command chaining or extended APDU logic.
*
* Due to the FIDO2 spec requiring support for both extended APDUs and command
* chaining, we need to implement chaining here.
*
* I didn't want to pollute the logic over in the process function, and it makes
* sense to do both here.
*
* @param apdu apdu buffer
* @return length of data to be processed. 0 if command chaining is not finished.
*/
private
short
doApduIngestion
(
APDU
apdu
)
{
byte
[]
buffer
=
apdu
.
getBuffer
();
// Receive the APDU
tempVars
[
4
]
=
apdu
.
setIncomingAndReceive
();
// Get true incoming data length
tempVars
[
3
]
=
apdu
.
getIncomingLength
();
// Check if the APDU is too big, we only handle 1200 byte
if
(
tempVars
[
3
]
>
1200
)
{
returnError
(
apdu
,
CTAP2_ERR_REQUEST_TOO_LARGE
);
return
0
;
}
// Check what we need to do re APDU buffer, is it full (special case for 1 len)
// If this is a command chaining APDU, swap to that logic
if
(
isCommandChainingCLA
(
apdu
))
{
// In the chaining
if
(!
isChaining
[
0
])
{
// Must be first chaining APDU
isChaining
[
0
]
=
true
;
// Prep the variables
chainRam
[
0
]
=
0
;
}
// Copy buffer
chainRam
[
1
]
=
tempVars
[
4
];
// chainRam[0] is the current point in the buffer we start from
chainRam
[
0
]
=
Util
.
arrayCopyNonAtomic
(
buffer
,
apdu
.
getOffsetCdata
(),
dataBuffer
,
chainRam
[
0
],
chainRam
[
1
]);
return
0x00
;
}
else
if
(
isChaining
[
0
])
{
// Must be the last of the chaining - make the copy and return the length.
chainRam
[
1
]
=
tempVars
[
4
];
chainRam
[
0
]
=
Util
.
arrayCopyNonAtomic
(
buffer
,
apdu
.
getOffsetCdata
(),
dataBuffer
,
chainRam
[
0
],
chainRam
[
1
]);
isChaining
[
0
]
=
false
;
isChaining
[
1
]
=
true
;
return
chainRam
[
0
];
}
else
if
(
tempVars
[
3
]
==
0x01
)
{
dataBuffer
[
0
]
=
buffer
[
apdu
.
getOffsetCdata
()];
return
0x01
;
}
else
if
(
apdu
.
getCurrentState
()
==
APDU
.
STATE_FULL_INCOMING
)
{
// We need to do no more
// Read the entirety of the buffer into the inBuf
Util
.
arrayCopyNonAtomic
(
buffer
,
apdu
.
getOffsetCdata
(),
dataBuffer
,
(
short
)
0
,
tempVars
[
3
]);
return
tempVars
[
4
];
}
else
{
// The APDU needs a multi-stage copy
// First, copy the current data buffer in
// Get the number of bytes in the data buffer that are the Lc, vars[5] will do
tempVars
[
5
]
=
tempVars
[
4
];
// Make the copy, vars[3] is bytes remaining to get
tempVars
[
4
]
=
0
;
while
(
tempVars
[
3
]
>
0
)
{
// Copy data
tempVars
[
4
]
=
Util
.
arrayCopyNonAtomic
(
buffer
,
apdu
.
getOffsetCdata
(),
dataBuffer
,
tempVars
[
4
],
tempVars
[
5
]);
// Decrement vars[3] by the bytes copied
tempVars
[
3
]
-=
tempVars
[
5
];
// Pull more bytes
tempVars
[
5
]
=
apdu
.
receiveBytes
(
apdu
.
getOffsetCdata
());
}
// Now we're at the end, here, and the commands expect us to give them a data
// length. Turns out Le bytes aren't anywhere to be found here.
// The commands use vars[3], so vars[4] will be fine to copy to vars[3].
return
tempVars
[
4
];
}
}
public
void
handle
(
APDU
apdu
)
{
byte
[]
buffer
=
apdu
.
getBuffer
();
tempCredential
=
null
;
...
...
@@ -142,42 +278,48 @@ public class CTAP2 extends Applet implements ExtendedLength {
}
// Need to grab the CTAP command byte
switch
(
dataBuffer
[
0
])
{
case
FIDO2_AUTHENTICATOR_MAKE_CREDENTIAL:
case
FIDO2_AUTHENTICATOR_MAKE_CREDENTIAL:
//0x01
authMakeCredential
(
apdu
,
tempVars
[
3
]);
break
;
case
FIDO2_AUTHENTICATOR_GET_ASSERTION:
case
FIDO2_AUTHENTICATOR_GET_ASSERTION:
// 0x02
authGetAssertion
(
apdu
,
tempVars
[
3
]);
break
;
case
FIDO2_AUTHENTICATOR_GET_INFO:
case
FIDO2_AUTHENTICATOR_GET_INFO:
// x0x04
authGetInfo
(
apdu
);
break
;
case
FIDO2_AUTHENTICATOR_GET_NEXT_ASSERTION:
case
FIDO2_AUTHENTICATOR_CLIENT_PIN:
// 0x06
clientPin
(
apdu
,
tempVars
[
3
]);
break
;
case
FIDO2_AUTHENTICATOR_RESET:
//0x07
// Need to finish doing this, we can, I mean, but I don't like it
doReset
(
apdu
);
break
;
case
FIDO2_AUTHENTICATOR_GET_NEXT_ASSERTION:
// 0x08
authGetNextAssertion
(
apdu
,
buffer
);
break
;
case
FIDO2_VENDOR_ATTEST_SIGN:
//0x41
attestSignRaw
(
apdu
,
tempVars
[
3
]);
break
;
case
FIDO2_AUTHENTICATOR_CLIENT_PIN:
clientPin
(
apdu
,
tempVars
[
3
]);
break
;
case
FIDO2_VENDOR_ATTEST_LOADCERT:
//0x42
attestSetCert
(
apdu
,
tempVars
[
3
]);
break
;
case
FIDO2_VENDOR_PERSO_COMPLETE:
//0x43
persoComplete
(
apdu
);
perso
nalization
Complete
(
apdu
);
break
;
case
FIDO2_VENDOR_ATTEST_GETPUB:
//0x44
getAttestPublic
(
apdu
);
break
;
case
FIDO2_VENDOR_
ATTEST_GETCERT:
//0x4a
getC
er
t
(
apdu
);
case
FIDO2_VENDOR_
GET_CREDENTIAL_COUNT:
//0x45
getC
redentialCoun
t
(
apdu
);
break
;
case
FIDO2_VENDOR_GET_COUNT:
//0x45
get
Count
(
apdu
);
case
PRLAB_GET_PUKX_RX:
// 0x50
get
PuKxRx
(
apdu
);
break
;
case
FIDO2_AUTHENTICATOR_RESET:
//0x07
// Need to finish doing this, we can, I mean, but I don't like it
doReset
(
apdu
);
case
PRLAB_GET_CX:
// 0x51
getCx
(
apdu
);
break
;
case
FIDO2_VENDOR_ATTEST_GETCERT:
//0x4a
getCert
(
apdu
);
break
;
default
:
returnError
(
apdu
,
CTAP1_ERR_INVALID_COMMAND
);
...
...
@@ -185,7 +327,7 @@ public class CTAP2 extends Applet implements ExtendedLength {
}
public
void
persoComplete
(
APDU
apdu
)
{
public
void
perso
nalization
Complete
(
APDU
apdu
)
{
if
(
attestationKeyPair
.
isCertSet
()
&&
!
personalizeComplete
)
{
personalizeComplete
=
true
;
returnError
(
apdu
,
CTAP1_ERR_SUCCESS
);
...
...
@@ -212,12 +354,23 @@ public class CTAP2 extends Applet implements ExtendedLength {
}
/** get counter's value */
public
void
getCount
(
APDU
apdu
){
short
count
=
credentialArray
.
getCount
();
apdu
.
setOutgoing
();
apdu
.
setOutgoingLength
((
short
)
2
);
Util
.
setShort
(
dataBuffer
,(
short
)
0
,
count
);
apdu
.
sendBytesLong
(
dataBuffer
,(
short
)
0
,(
short
)
2
);
public
void
getCredentialCount
(
APDU
apdu
){
Util
.
setShort
(
apdu
.
getBuffer
(),
(
short
)
0x00
,
credentialArray
.
getCount
());
apdu
.
setOutgoingAndSend
((
short
)
0x00
,
(
short
)
2
);
}
/**
*
*/
private
void
getPuKxRx
(
APDU
apdu
){
}
/**
*
*/
private
void
getCx
(
APDU
apdu
){
}
/**
...
...
@@ -646,7 +799,7 @@ public class CTAP2 extends Applet implements ExtendedLength {
*/
public
void
authGetInfo
(
APDU
apdu
)
{
// Create the authenticator info if not present.
if
(
i
nfo
==
null
)
{
if
(
fidoI
nfo
==
null
)
{
// Create the authGetInfo - 0x00 is success
dataBuffer
[
0
]
=
0x00
;
cborEncoder
.
init
(
dataBuffer
,
(
short
)
1
,
(
short
)
1199
);
...
...
@@ -678,13 +831,13 @@ public class CTAP2 extends Applet implements ExtendedLength {
cborEncoder
.
encodeUInt16
((
short
)
1200
);
// Done
JCSystem
.
beginTransaction
();
i
nfo
=
new
byte
[
cborEncoder
.
getCurrentOffset
()];
Util
.
arrayCopy
(
dataBuffer
,
(
short
)
0
,
i
nfo
,
(
short
)
0
,
cborEncoder
.
getCurrentOffset
());
fidoI
nfo
=
new
byte
[
cborEncoder
.
getCurrentOffset
()];
Util
.
arrayCopy
(
dataBuffer
,
(
short
)
0
,
fidoI
nfo
,
(
short
)
0
,
cborEncoder
.
getCurrentOffset
());
JCSystem
.
commitTransaction
();
}
// Send it
Util
.
arrayCopyNonAtomic
(
info
,
(
short
)
0
,
dataBuffer
,
(
short
)
0
,
(
short
)
i
nfo
.
length
);
sendLongChaining
(
apdu
,
(
short
)
i
nfo
.
length
);
Util
.
arrayCopyNonAtomic
(
fidoInfo
,
(
short
)
0
,
dataBuffer
,
(
short
)
0
,
(
short
)
fidoI
nfo
.
length
);
sendLongChaining
(
apdu
,
(
short
)
fidoI
nfo
.
length
);
}
/**
...
...
@@ -782,88 +935,12 @@ public class CTAP2 extends Applet implements ExtendedLength {
}
// There's only so many ways to do this.
static
boolean
isCommandChainingCLA
(
APDU
apdu
)
{
public
static
boolean
isCommandChainingCLA
(
APDU
apdu
)
{
byte
[]
buf
=
apdu
.
getBuffer
();
// return true if bit4 is 1 in CLA
return
((
byte
)
(
buf
[
0
]
&
(
byte
)
0x10
)
==
(
byte
)
0x10
);
}
/**
* Handle the command chaining or extended APDU logic.
*
* Due to the FIDO2 spec requiring support for both extended APDUs and command
* chaining, we need to implement chaining here.
*
* I didn't want to pollute the logic over in the process function, and it makes
* sense to do both here.
*
* @param apdu apdu buffer
* @return length of data to be processed. 0 if command chaining is not finished.
*/
private
short
doApduIngestion
(
APDU
apdu
)
{
byte
[]
buffer
=
apdu
.
getBuffer
();
// Receive the APDU
tempVars
[
4
]
=
apdu
.
setIncomingAndReceive
();
// Get true incoming data length
tempVars
[
3
]
=
apdu
.
getIncomingLength
();
// Check if the APDU is too big, we only handle 1200 byte
if
(
tempVars
[
3
]
>
1200
)
{
returnError
(
apdu
,
CTAP2_ERR_REQUEST_TOO_LARGE
);
return
0
;
}
// Check what we need to do re APDU buffer, is it full (special case for 1 len)
// If this is a command chaining APDU, swap to that logic
if
(
isCommandChainingCLA
(
apdu
))
{
// In the chaining
if
(!
isChaining
[
0
])
{
// Must be first chaining APDU
isChaining
[
0
]
=
true
;
// Prep the variables
chainRam
[
0
]
=
0
;
}
// Copy buffer
chainRam
[
1
]
=
tempVars
[
4
];
// chainRam[0] is the current point in the buffer we start from
chainRam
[
0
]
=
Util
.
arrayCopyNonAtomic
(
buffer
,
apdu
.
getOffsetCdata
(),
dataBuffer
,
chainRam
[
0
],
chainRam
[
1
]);
return
0x00
;
}
else
if
(
isChaining
[
0
])
{
// Must be the last of the chaining - make the copy and return the length.
chainRam
[
1
]
=
tempVars
[
4
];
chainRam
[
0
]
=
Util
.
arrayCopyNonAtomic
(
buffer
,
apdu
.
getOffsetCdata
(),
dataBuffer
,
chainRam
[
0
],
chainRam
[
1
]);
isChaining
[
0
]
=
false
;
isChaining
[
1
]
=
true
;
return
chainRam
[
0
];
}
else
if
(
tempVars
[
3
]
==
0x01
)
{
dataBuffer
[
0
]
=
buffer
[
apdu
.
getOffsetCdata
()];
return
0x01
;
}
else
if
(
apdu
.
getCurrentState
()
==
APDU
.
STATE_FULL_INCOMING
)
{
// We need to do no more
// Read the entirety of the buffer into the inBuf
Util
.
arrayCopyNonAtomic
(
buffer
,
apdu
.
getOffsetCdata
(),
dataBuffer
,
(
short
)
0
,
tempVars
[
3
]);
return
tempVars
[
4
];
}
else
{
// The APDU needs a multi-stage copy
// First, copy the current data buffer in
// Get the number of bytes in the data buffer that are the Lc, vars[5] will do
tempVars
[
5
]
=
tempVars
[
4
];
// Make the copy, vars[3] is bytes remaining to get
tempVars
[
4
]
=
0
;
while
(
tempVars
[
3
]
>
0
)
{
// Copy data
tempVars
[
4
]
=
Util
.
arrayCopyNonAtomic
(
buffer
,
apdu
.
getOffsetCdata
(),
dataBuffer
,
tempVars
[
4
],
tempVars
[
5
]);
// Decrement vars[3] by the bytes copied
tempVars
[
3
]
-=
tempVars
[
5
];
// Pull more bytes
tempVars
[
5
]
=
apdu
.
receiveBytes
(
apdu
.
getOffsetCdata
());
}
// Now we're at the end, here, and the commands expect us to give them a data
// length. Turns out Le bytes aren't anywhere to be found here.
// The commands use vars[3], so vars[4] will be fine to copy to vars[3].
return
tempVars
[
4
];
}
}
/**
* Gets 256 or fewer bytes from inBuf.
*
...
...
@@ -932,68 +1009,10 @@ public class CTAP2 extends Applet implements ExtendedLength {
}
}
/**
* Checks if chaining is set for U2FApplet
*
* @return if it is chaining
*/
public
boolean
isChaining
()
{
return
isOutChaining
[
0
];
}
private
void
getCert
(
APDU
apdu
)
{
dataBuffer
[
0
]
=
0x00
;
tempVars
[
0
]
=
(
short
)
(
attestationKeyPair
.
getCert
(
dataBuffer
,
(
short
)
1
)
+
1
);
sendLongChaining
(
apdu
,
tempVars
[
0
]);
}
public
void
process
(
APDU
apdu
)
throws
ISOException
{
byte
[]
buffer
=
apdu
.
getBuffer
();
if
(
selectingApplet
())
{
Util
.
arrayCopyNonAtomic
(
Utf8Strings
.
UTF8_FIDO2
,
(
short
)
0
,
buffer
,
(
short
)
0
,
(
short
)
Utf8Strings
.
UTF8_FIDO2
.
length
);
apdu
.
setOutgoingAndSend
((
short
)
0
,
(
short
)
Utf8Strings
.
UTF8_FIDO2
.
length
);
return
;
}
if
(!
apdu
.
isCommandChainingCLA
()
&&
apdu
.
isISOInterindustryCLA
())
{
ISOException
.
throwIt
(
ISO7816
.
SW_CLA_NOT_SUPPORTED
);
}
JCSystem
.
requestObjectDeletion
();
switch
(
buffer
[
ISO7816
.
OFFSET_INS
])
{
case
ISO_INS_GET_DATA:
if
(
isChaining
())
{
getData
(
apdu
);
}
else
{
ISOException
.
throwIt
(
ISO7816
.
SW_CONDITIONS_NOT_SATISFIED
);
}
break
;
case
FIDO2_INS_NFCCTAP_MSG:
// 0x10
handle
(
apdu
);
break
;
case
FIDO2_DESELECT:
// Appears to be a reset function in the FIDO2 spec, but never referenced
// anywhere
ISOException
.
throwIt
(
ISO7816
.
SW_NO_ERROR
);
break
;
default
:
ISOException
.
throwIt
(
ISO7816
.
SW_INS_NOT_SUPPORTED
);
}
}
public
static
void
install
(
byte
[]
bArray
,
short
bOffset
,
byte
bLength
)
throws
ISOException
{
short
offset
=
bOffset
;
offset
+=
(
short
)
(
bArray
[
offset
]
+
1
);
// instance
offset
+=
(
short
)
(
bArray
[
offset
]
+
1
);
// privileges
final
CTAP2
applet
=
new
CTAP2
();
try
{
applet
.
register
(
bArray
,
(
short
)
(
bOffset
+
1
),
bArray
[
bOffset
]);
}
catch
(
Exception
e
)
{
applet
.
register
();
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment