Skip to content

Commit 354effe

Browse files
committed
Crypto: Missing hash algorithms for HMAC operations in jca.
1 parent c01c060 commit 354effe

File tree

4 files changed

+322
-156
lines changed

4 files changed

+322
-156
lines changed

java/ql/lib/experimental/quantum/JCA.qll

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ module JCAModel {
2020

2121
abstract class SignatureAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { }
2222

23+
abstract class MacAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { }
24+
2325
// TODO: Verify that the PBEWith% case works correctly
2426
bindingset[algo]
2527
predicate cipher_names(string algo) {
@@ -85,7 +87,7 @@ module JCAModel {
8587
name.toUpperCase()
8688
.matches([
8789
"HMAC%", "AESCMAC", "DESCMAC", "GMAC", "Poly1305", "SipHash", "BLAKE2BMAC",
88-
"HMACRIPEMD160"
90+
"HMACRIPEMD160", "%CMAC"
8991
].toUpperCase())
9092
}
9193

@@ -128,6 +130,10 @@ module JCAModel {
128130
result instanceof Crypto::SHA2 and
129131
digestLength = name.replaceAll("-", "").splitAt("SHA", 1).toInt()
130132
or
133+
name in ["SHA-512/224", "SHA-512/256", "SHA512/224", "SHA512/256"] and
134+
result instanceof Crypto::SHA2 and
135+
digestLength = name.replaceAll("-", "").splitAt("SHA-512/", 1).toInt()
136+
or
131137
name in ["SHA3-224", "SHA3-256", "SHA3-384", "SHA3-512", "SHA3256", "SHA3384", "SHA3512"] and
132138
result instanceof Crypto::SHA3 and
133139
digestLength = name.replaceAll("-", "").splitAt("SHA3", 1).toInt()
@@ -1580,7 +1586,7 @@ module JCAModel {
15801586
if super.getValue().toUpperCase().matches("HMAC%")
15811587
then result = KeyOpAlg::TMac(KeyOpAlg::HMAC())
15821588
else
1583-
if super.getValue().toUpperCase().matches("CMAC%")
1589+
if super.getValue().toUpperCase().matches("%CMAC%")
15841590
then result = KeyOpAlg::TMac(KeyOpAlg::CMAC())
15851591
else result = KeyOpAlg::TMac(KeyOpAlg::OtherMacAlgorithmType())
15861592
}
@@ -1600,6 +1606,54 @@ module JCAModel {
16001606
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() }
16011607
}
16021608

1609+
class KnownHmacAlgorithmInstance extends Crypto::HmacAlgorithmInstance instanceof KnownMacAlgorithm
1610+
{
1611+
override Crypto::AlgorithmValueConsumer getHashAlgorithmValueConsumer() {
1612+
result = this.(KnownMacAlgorithm).getConsumer()
1613+
}
1614+
1615+
override int getKeySizeFixed() {
1616+
// already defined by parent key operation algorithm, but extending an instance
1617+
// still requires we override this method
1618+
result = super.getKeySizeFixed()
1619+
}
1620+
1621+
override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() {
1622+
// already defined by parent key operation algorithm, but extending an instance
1623+
// still requires we override this method
1624+
result = super.getKeySizeConsumer()
1625+
}
1626+
1627+
override string getRawAlgorithmName() {
1628+
// already defined by parent key operation algorithm, but extending an instance
1629+
// still requires we override this method
1630+
result = super.getRawAlgorithmName()
1631+
}
1632+
1633+
override Crypto::KeyOpAlg::AlgorithmType getAlgorithmType() {
1634+
result = KeyOpAlg::TMac(KeyOpAlg::HMAC())
1635+
}
1636+
}
1637+
1638+
class KnownMacHashAlgorithm extends Crypto::HashAlgorithmInstance instanceof KnownMacAlgorithm,
1639+
JavaConstant
1640+
{
1641+
Crypto::THashType hashType;
1642+
int digestLength;
1643+
1644+
KnownMacHashAlgorithm() {
1645+
super.getValue().toUpperCase().matches("HMAC%") and
1646+
hashType =
1647+
hash_name_to_type_known(super.getValue().toUpperCase().splitAt("HMAC", 1), digestLength)
1648+
}
1649+
1650+
override string getRawHashAlgorithmName() { result = super.getValue() }
1651+
1652+
override Crypto::THashType getHashType() { result = hashType }
1653+
1654+
override int getFixedDigestLength() { result = digestLength }
1655+
}
1656+
16031657
class MacGetInstanceCall extends MethodCall {
16041658
MacGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "Mac", "getInstance") }
16051659

@@ -1629,7 +1683,9 @@ module JCAModel {
16291683
}
16301684
}
16311685

1632-
class MacGetInstanceAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer {
1686+
class MacGetInstanceAlgorithmValueConsumer extends MacAlgorithmValueConsumer,
1687+
HashAlgorithmValueConsumer
1688+
{
16331689
MacGetInstanceAlgorithmValueConsumer() { this = any(MacGetInstanceCall c).getAlgorithmArg() }
16341690

16351691
override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this }
@@ -1696,9 +1752,18 @@ module JCAModel {
16961752
MacFlowAnalysisImpl::getAnIntermediateUseFromFinalUse(this, _, _).getOutput()
16971753
}
16981754

1699-
override Crypto::AlgorithmValueConsumer getHashAlgorithmValueConsumer() { none() }
1755+
override Crypto::AlgorithmValueConsumer getHashAlgorithmValueConsumer() {
1756+
result = this.getInstantiationCall().getAlgorithmArg()
1757+
}
17001758

1701-
override predicate hasHashAlgorithmConsumer() { none() }
1759+
override predicate hasHashAlgorithmConsumer() {
1760+
// TODO: do we consider that these operations have no hash and that it is only associated to the mac algorithm node?
1761+
// in JCA that seems to be correct, but would removing the hash consumer here break things generally?
1762+
this.getHashAlgorithmValueConsumer()
1763+
.getAKnownAlgorithmSource()
1764+
.(Crypto::KeyOperationAlgorithmInstance)
1765+
.getAlgorithmType() = KeyOpAlg::TMac(KeyOpAlg::HMAC())
1766+
}
17021767

17031768
override Crypto::KeyOperationSubtype getKeyOperationSubtype() {
17041769
result instanceof Crypto::TMacMode

0 commit comments

Comments
 (0)