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
Josh Ji
Fido2Applet
Commits
3a6bee2d
Commit
3a6bee2d
authored
Nov 06, 2023
by
Josh Ji
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
hkdf_chain finished
parent
97229b46
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
67 additions
and
15 deletions
+67
-15
build.gradle
build.gradle
+1
-1
src/main/java/com/josh/vku2f/CTAP2.java
src/main/java/com/josh/vku2f/CTAP2.java
+5
-3
src/main/java/com/josh/vku2f/HKDF.java
src/main/java/com/josh/vku2f/HKDF.java
+1
-1
src/main/java/com/josh/vku2f/HMAC.java
src/main/java/com/josh/vku2f/HMAC.java
+8
-1
src/main/java/com/josh/vku2f/IDSecret.java
src/main/java/com/josh/vku2f/IDSecret.java
+52
-9
No files found.
build.gradle
View file @
3a6bee2d
...
@@ -25,7 +25,7 @@ repositories {
...
@@ -25,7 +25,7 @@ repositories {
final
def
jcdk_dir
=
'sdks/jc305u3_kit'
final
def
jcdk_dir
=
'sdks/jc305u3_kit'
javacard
{
javacard
{
config
{
config
{
debugGpPro
true
//
debugGpPro true
jckit
jcdk_dir
jckit
jcdk_dir
cap
{
cap
{
packageName
'com.josh.vku2f'
packageName
'com.josh.vku2f'
...
...
src/main/java/com/josh/vku2f/CTAP2.java
View file @
3a6bee2d
...
@@ -114,9 +114,9 @@ public class CTAP2 extends Applet implements ExtendedLength {
...
@@ -114,9 +114,9 @@ public class CTAP2 extends Applet implements ExtendedLength {
// 1210 bytes of a transient buffer for read-in and out
// 1210 bytes of a transient buffer for read-in and out
// We advertise 1200 bytes supported, but 10 bytes for protocol nonsense
// We advertise 1200 bytes supported, but 10 bytes for protocol nonsense
try
{
try
{
dataBuffer
=
JCSystem
.
makeTransientByteArray
((
short
)
1
5
10
,
JCSystem
.
CLEAR_ON_DESELECT
);
dataBuffer
=
JCSystem
.
makeTransientByteArray
((
short
)
1
2
10
,
JCSystem
.
CLEAR_ON_DESELECT
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
dataBuffer
=
new
byte
[
1
5
10
];
dataBuffer
=
new
byte
[
1
2
10
];
}
}
try
{
try
{
scratch
=
JCSystem
.
makeTransientByteArray
((
short
)
512
,
JCSystem
.
CLEAR_ON_DESELECT
);
scratch
=
JCSystem
.
makeTransientByteArray
((
short
)
512
,
JCSystem
.
CLEAR_ON_DESELECT
);
...
@@ -477,6 +477,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
...
@@ -477,6 +477,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
KeyAgreement
keyAgreement
=
KeyAgreement
.
getInstance
(
KeyAgreement
.
ALG_EC_SVDP_DH
,
false
);
KeyAgreement
keyAgreement
=
KeyAgreement
.
getInstance
(
KeyAgreement
.
ALG_EC_SVDP_DH
,
false
);
keyAgreement
.
init
(
attestationKeyPair
.
getPrivate
());
keyAgreement
.
init
(
attestationKeyPair
.
getPrivate
());
keyAgreement
.
generateSecret
(
idSecret
.
puK_idp
,
(
short
)
0
,
(
short
)
65
,
idSecret
.
sharedSecret
,
(
short
)
0
);
keyAgreement
.
generateSecret
(
idSecret
.
puK_idp
,
(
short
)
0
,
(
short
)
65
,
idSecret
.
sharedSecret
,
(
short
)
0
);
sha256MessageDigest
.
doFinal
(
idSecret
.
sharedSecret
,
(
short
)
0
,(
short
)
idSecret
.
sharedSecret
.
length
,
idSecret
.
hashedSharedSecret
,(
short
)
0
);
idSecret
.
initHKDFChain
();
idSecret
.
initHKDFChain
();
...
@@ -674,8 +676,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
...
@@ -674,8 +676,8 @@ public class CTAP2 extends Applet implements ExtendedLength {
cborEncoder
.
startArray
((
short
)
4
);
cborEncoder
.
startArray
((
short
)
4
);
cborEncoder
.
encodeByteString
(
idSecret
.
nonce
,
(
short
)
0
,
(
short
)
idSecret
.
nonce
.
length
);
cborEncoder
.
encodeByteString
(
idSecret
.
nonce
,
(
short
)
0
,
(
short
)
idSecret
.
nonce
.
length
);
cborEncoder
.
encodeByteString
(
idSecret
.
idHash
,
(
short
)
0
,
(
short
)
idSecret
.
idHash
.
length
);
cborEncoder
.
encodeByteString
(
idSecret
.
idHash
,
(
short
)
0
,
(
short
)
idSecret
.
idHash
.
length
);
cborEncoder
.
encodeByteString
(
idSecret
.
counterE
,
(
short
)
0
,
(
short
)
idSecret
.
counter
.
length
);
cborEncoder
.
encodeByteString
(
idSecret
.
hmacValue
,
(
short
)
0
,
(
short
)
idSecret
.
hmacValue
.
length
);
cborEncoder
.
encodeByteString
(
idSecret
.
hmacValue
,
(
short
)
0
,
(
short
)
idSecret
.
hmacValue
.
length
);
cborEncoder
.
encodeByteString
(
idSecret
.
counter
,
(
short
)
0
,
(
short
)
idSecret
.
counter
.
length
);
}
}
// We're actually done, send this out
// We're actually done, send this out
...
...
src/main/java/com/josh/vku2f/HKDF.java
View file @
3a6bee2d
...
@@ -8,7 +8,7 @@ public class HKDF
...
@@ -8,7 +8,7 @@ public class HKDF
private
byte
[]
counter
=
new
byte
[
1
];
// for expand()
private
byte
[]
counter
=
new
byte
[
1
];
// for expand()
private
byte
[]
temp
;
private
byte
[]
temp
;
public
HKDF
(){
public
HKDF
(){
hmac
=
new
HMAC
();
hmac
=
HMAC
.
getInstance
();
temp
=
JCSystem
.
makeTransientByteArray
((
short
)
32
,
JCSystem
.
CLEAR_ON_RESET
);
temp
=
JCSystem
.
makeTransientByteArray
((
short
)
32
,
JCSystem
.
CLEAR_ON_RESET
);
}
}
public
void
extract
(
byte
[]
salt
,
byte
[]
ikm
,
byte
[]
output
,
short
offset
){
public
void
extract
(
byte
[]
salt
,
byte
[]
ikm
,
byte
[]
output
,
short
offset
){
...
...
src/main/java/com/josh/vku2f/HMAC.java
View file @
3a6bee2d
...
@@ -13,8 +13,15 @@ public class HMAC
...
@@ -13,8 +13,15 @@ public class HMAC
private
MessageDigest
sha256
=
MessageDigest
.
getInstance
(
MessageDigest
.
ALG_SHA_256
,
false
);
private
MessageDigest
sha256
=
MessageDigest
.
getInstance
(
MessageDigest
.
ALG_SHA_256
,
false
);
private
byte
[]
ikeypad
;
private
byte
[]
ikeypad
;
private
byte
[]
okeypad
;
private
byte
[]
okeypad
;
private
static
HMAC
hmac
;
public
HMAC
(){
public
static
HMAC
getInstance
(){
if
(
hmac
==
null
)
{
hmac
=
new
HMAC
();
}
return
hmac
;
}
private
HMAC
(){
key
=
new
byte
[
BLOCK_SIZE
];
key
=
new
byte
[
BLOCK_SIZE
];
ikeypad
=
new
byte
[
BLOCK_SIZE
];
ikeypad
=
new
byte
[
BLOCK_SIZE
];
okeypad
=
new
byte
[
BLOCK_SIZE
];
okeypad
=
new
byte
[
BLOCK_SIZE
];
...
...
src/main/java/com/josh/vku2f/IDSecret.java
View file @
3a6bee2d
...
@@ -18,16 +18,19 @@ public class IDSecret {
...
@@ -18,16 +18,19 @@ public class IDSecret {
public
final
byte
[]
hashedSharedSecret
=
new
byte
[
32
];
public
final
byte
[]
hashedSharedSecret
=
new
byte
[
32
];
public
final
byte
[]
HKDF_CHAIN_IV
=
new
byte
[
32
];
public
final
byte
[]
HKDF_CHAIN_IV
=
new
byte
[
32
];
public
final
byte
[]
nonce
=
new
byte
[
32
];
public
final
byte
[]
nonce
=
new
byte
[
32
];
public
final
byte
[]
nonce1
=
new
byte
[
32
];
public
final
byte
[]
idHash
=
new
byte
[
32
];
public
final
byte
[]
idHash
=
new
byte
[
32
];
public
final
byte
[]
idHash1
=
new
byte
[
32
];
public
final
byte
[]
counter
=
new
byte
[
4
];
// for hkdfChain
public
final
byte
[]
counter
=
new
byte
[
4
];
// for hkdfChain
public
final
byte
[]
counterE
=
new
byte
[
4
];
// for hkdfChain
public
final
byte
[]
hmacValue
=
new
byte
[
32
];
public
final
byte
[]
hmacValue
=
new
byte
[
32
];
public
final
byte
[]
hmacKey
=
new
byte
[
32
];
public
final
byte
[]
hmacKey
=
new
byte
[
32
];
public
final
short
OKM_LENGTH
=
(
short
)
32
;
public
final
short
OKM_LENGTH
=
(
short
)
32
;
public
final
MessageDigest
sha256
;
public
final
MessageDigest
sha256
;
public
HKDFChain
hkdfChain
;
public
HKDFChain
hkdfChain
;
public
final
HMAC
hmac
=
new
HMAC
();
public
final
HMAC
hmac
=
HMAC
.
getInstance
();
public
final
CBOREncoder
encoder
=
new
CBOREncoder
();
public
final
CBOREncoder
encoder
=
new
CBOREncoder
();
public
final
byte
[]
temp
=
JCSystem
.
makeTransientByteArray
((
short
)
32
,
JCSystem
.
CLEAR_ON_DESELECT
);
public
final
byte
[]
temp
=
JCSystem
.
makeTransientByteArray
((
short
)
64
,
JCSystem
.
CLEAR_ON_DESELECT
);
public
IDSecret
(){
public
IDSecret
(){
id
=
new
DomString
(
Utf8Strings
.
UTF8_NULL
,
(
short
)
Utf8Strings
.
UTF8_NULL
.
length
);
id
=
new
DomString
(
Utf8Strings
.
UTF8_NULL
,
(
short
)
Utf8Strings
.
UTF8_NULL
.
length
);
...
@@ -41,12 +44,16 @@ public class IDSecret {
...
@@ -41,12 +44,16 @@ public class IDSecret {
}
}
public
void
PIVInfoNext
(){
public
void
PIVInfoNext
(){
Random
.
getInstance
().
nextBytes
(
nonce
,
(
short
)
0
,
(
short
)
nonce
.
length
);
Random
.
getInstance
().
nextBytes
(
nonce
,
(
short
)
0
,
(
short
)
nonce
.
length
);
// n
sha256
.
doFinal
(
id
.
str
,
(
short
)
0
,
id
.
len
,
temp
,
(
short
)
0
);
sha256
.
doFinal
(
id
.
str
,
(
short
)
0
,
id
.
len
,
temp
,
(
short
)
0
);
// H(ID)
sha256
.
update
(
temp
,
(
short
)
0
,
(
short
)
temp
.
length
);
sha256
.
doFinal
(
nonce
,
(
short
)
0
,
(
short
)
nonce
.
length
,
temp
,
(
short
)
32
);
// H(n)
sha256
.
doFinal
(
nonce
,
(
short
)
0
,
(
short
)
nonce
.
length
,
idHash
,
(
short
)
0
);
sha256
.
doFinal
(
temp
,
(
short
)
0
,
(
short
)
temp
.
length
,
idHash
,
(
short
)
0
);
// H(H(ID)||H(n))
hkdfChain
.
next
(
hmacKey
,
(
short
)
0
);
hkdfChain
.
next
(
hmacKey
,
(
short
)
0
);
plusOne
(
counter
);
plusOne
(
counter
);
// C += 1
plusOne
(
nonce
,
nonce1
);
// n += 1
sha256
.
doFinal
(
nonce1
,
(
short
)
0
,
(
short
)
nonce1
.
length
,
temp
,
(
short
)
32
);
// H(n+1)
sha256
.
doFinal
(
temp
,
(
short
)
0
,
(
short
)
temp
.
length
,
temp
,
(
short
)
0
);
// H(H(ID)||H(n+1))
xor
(
counter
,
temp
,
counterE
);
// XOR(counter, H(n+1))
hmac
.
setKey
(
hmacKey
);
hmac
.
setKey
(
hmacKey
);
hmac
.
update
(
idHash
);
hmac
.
update
(
idHash
);
hmac
.
doFinal
(
hmacValue
,
(
short
)
0
);
hmac
.
doFinal
(
hmacValue
,
(
short
)
0
);
...
@@ -57,18 +64,43 @@ public class IDSecret {
...
@@ -57,18 +64,43 @@ public class IDSecret {
* return data length
* return data length
*/
*/
public
short
dump
(
byte
[]
apduBuffer
,
byte
[]
dataBuffer
,
CBOREncoder
encoder
){
public
short
dump
(
byte
[]
apduBuffer
,
byte
[]
dataBuffer
,
CBOREncoder
encoder
){
PIVInfoNext
();
//
PIVInfoNext();
encoder
.
init
(
dataBuffer
,
(
short
)
0
,
(
short
)
1200
);
encoder
.
init
(
dataBuffer
,
(
short
)
0
,
(
short
)
1200
);
encoder
.
startArray
((
short
)
9
);
encoder
.
startMap
((
short
)
11
);
encoder
.
encodeTextString
(
new
byte
[]{
'i'
,
'd'
},
(
short
)
0
,
(
short
)
2
);
encoder
.
encodeTextString
(
id
.
str
,(
short
)
0
,
id
.
len
);
encoder
.
encodeTextString
(
id
.
str
,(
short
)
0
,
id
.
len
);
encoder
.
encodeTextString
(
new
byte
[]{
'n'
},
(
short
)
0
,
(
short
)
1
);
encoder
.
encodeByteString
(
nonce
,(
short
)
0
,
(
short
)
nonce
.
length
);
encoder
.
encodeByteString
(
nonce
,(
short
)
0
,
(
short
)
nonce
.
length
);
encoder
.
encodeTextString
(
new
byte
[]{
'i'
,
'd'
,
'h'
},
(
short
)
0
,
(
short
)
3
);
encoder
.
encodeByteString
(
idHash
,(
short
)
0
,
(
short
)
idHash
.
length
);
encoder
.
encodeByteString
(
idHash
,(
short
)
0
,
(
short
)
idHash
.
length
);
encoder
.
encodeTextString
(
new
byte
[]{
'i'
,
'v'
},
(
short
)
0
,
(
short
)
2
);
encoder
.
encodeByteString
(
HKDF_CHAIN_IV
,(
short
)
0
,
(
short
)
HKDF_CHAIN_IV
.
length
);
encoder
.
encodeByteString
(
HKDF_CHAIN_IV
,(
short
)
0
,
(
short
)
HKDF_CHAIN_IV
.
length
);
encoder
.
encodeTextString
(
new
byte
[]{
'p'
,
'k'
},
(
short
)
0
,
(
short
)
2
);
encoder
.
encodeByteString
(
puK_idp
,(
short
)
0
,
(
short
)
puK_idp
.
length
);
encoder
.
encodeByteString
(
puK_idp
,(
short
)
0
,
(
short
)
puK_idp
.
length
);
encoder
.
encodeTextString
(
new
byte
[]{
's'
,
'k'
},
(
short
)
0
,
(
short
)
2
);
encoder
.
encodeByteString
(
sharedSecret
,(
short
)
0
,
(
short
)
sharedSecret
.
length
);
encoder
.
encodeByteString
(
sharedSecret
,(
short
)
0
,
(
short
)
sharedSecret
.
length
);
encoder
.
encodeTextString
(
new
byte
[]{
's'
,
'k'
,
'h'
},
(
short
)
0
,
(
short
)
3
);
encoder
.
encodeByteString
(
hashedSharedSecret
,(
short
)
0
,
(
short
)
hashedSharedSecret
.
length
);
encoder
.
encodeByteString
(
hashedSharedSecret
,(
short
)
0
,
(
short
)
hashedSharedSecret
.
length
);
encoder
.
encodeTextString
(
new
byte
[]{
'c'
},
(
short
)
0
,
(
short
)
1
);
encoder
.
encodeByteString
(
counter
,(
short
)
0
,
(
short
)
counter
.
length
);
encoder
.
encodeByteString
(
counter
,(
short
)
0
,
(
short
)
counter
.
length
);
encoder
.
encodeTextString
(
new
byte
[]{
'c'
,
'E'
},
(
short
)
0
,
(
short
)
2
);
encoder
.
encodeByteString
(
counterE
,(
short
)
0
,
(
short
)
counter
.
length
);
encoder
.
encodeTextString
(
new
byte
[]{
'h'
,
'k'
,
'e'
,
'y'
,},
(
short
)
0
,
(
short
)
4
);
encoder
.
encodeByteString
(
hmacKey
,(
short
)
0
,
(
short
)
hmacKey
.
length
);
encoder
.
encodeTextString
(
new
byte
[]{
'h'
,
'm'
,
'a'
,
'c'
,},
(
short
)
0
,
(
short
)
4
);
encoder
.
encodeByteString
(
hmacValue
,(
short
)
0
,
(
short
)
hmacValue
.
length
);
encoder
.
encodeByteString
(
hmacValue
,(
short
)
0
,
(
short
)
hmacValue
.
length
);
return
encoder
.
getCurrentOffset
();
return
encoder
.
getCurrentOffset
();
}
}
...
@@ -93,6 +125,17 @@ public class IDSecret {
...
@@ -93,6 +125,17 @@ public class IDSecret {
}
}
}
}
public
void
plusOne
(
byte
[]
input
,
byte
[]
output
){
Util
.
arrayCopy
(
input
,
(
short
)
0
,
output
,
(
short
)
0
,
(
short
)
input
.
length
);
plusOne
(
output
);
}
public
void
xor
(
byte
[]
a
,
byte
[]
b
,
byte
[]
output
){
for
(
short
i
=
0
;
i
<
a
.
length
;
i
++){
output
[
i
]
=
(
byte
)(
a
[
i
]
^
b
[
i
]);
}
}
private
void
testSharedObjects
(
byte
[]
apduBuffer
){
private
void
testSharedObjects
(
byte
[]
apduBuffer
){
/*
/*
byte[] aid = new byte[]{(byte)0xa0,(byte)0x00,(byte)0x00,(byte)0x02,(byte)0x47,(byte)0x10,(byte)0x01};
byte[] aid = new byte[]{(byte)0xa0,(byte)0x00,(byte)0x00,(byte)0x02,(byte)0x47,(byte)0x10,(byte)0x01};
...
...
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