@@ -18,6 +18,8 @@ module JCAModel {
1818
1919 abstract class KeyAgreementAlgorithmValueConsumer extends Crypto:: AlgorithmValueConsumer { }
2020
21+ abstract class SignatureAlgorithmValueConsumer extends Crypto:: AlgorithmValueConsumer { }
22+
2123 // TODO: Verify that the PBEWith% case works correctly
2224 bindingset [ algo]
2325 predicate cipher_names ( string algo ) {
@@ -100,6 +102,12 @@ module JCAModel {
100102 ] .toUpperCase ( ) )
101103 }
102104
105+ bindingset [ name]
106+ predicate signature_names ( string name ) {
107+ name .toUpperCase ( ) .splitAt ( "with" .toUpperCase ( ) , 1 ) .matches ( [ "RSA" , "ECDSA" , "DSA" ] )
108+ // note RSASSA-PSS is RSA with PSS where the digest is set through PSSParameterSpec
109+ }
110+
103111 bindingset [ name]
104112 predicate key_agreement_names ( string name ) {
105113 name .toUpperCase ( ) .matches ( [ "DH" , "EDH" , "ECDH" , "X25519" , "X448" ] .toUpperCase ( ) )
@@ -217,6 +225,25 @@ module JCAModel {
217225 name .toUpperCase ( ) in [ "ECDH" , "X25519" , "X448" ]
218226 }
219227
228+ bindingset [ name]
229+ predicate signature_name_to_type_known ( Crypto:: KeyOpAlg:: TAlgorithm type , string name ) {
230+ name .toUpperCase ( ) .splitAt ( "with" .toUpperCase ( ) , 1 ) = "RSA" and
231+ type = KeyOpAlg:: TAsymmetricCipher ( KeyOpAlg:: RSA ( ) )
232+ or
233+ name .toUpperCase ( ) .splitAt ( "with" .toUpperCase ( ) , 1 ) = "ECDSA" and
234+ type = KeyOpAlg:: TSignature ( KeyOpAlg:: ECDSA ( ) )
235+ or
236+ name .toUpperCase ( ) .splitAt ( "with" .toUpperCase ( ) , 1 ) = "DSA" and
237+ type = KeyOpAlg:: TSignature ( KeyOpAlg:: DSA ( ) )
238+ or
239+ name .toUpperCase ( ) .matches ( "RSASSA-PSS" ) and type = KeyOpAlg:: TAsymmetricCipher ( KeyOpAlg:: RSA ( ) )
240+ }
241+
242+ bindingset [ name]
243+ Crypto:: HashType signature_name_to_hash_type_known ( string name , int digestLength ) {
244+ result = hash_name_to_type_known ( name .splitAt ( "with" , 0 ) , digestLength )
245+ }
246+
220247 /**
221248 * A `StringLiteral` in the `"ALG/MODE/PADDING"` or `"ALG"` format
222249 */
@@ -345,7 +372,7 @@ module JCAModel {
345372 override KeyOpAlg:: AlgorithmType getAlgorithmType ( ) {
346373 if cipher_name_to_type_known ( _, super .getAlgorithmName ( ) )
347374 then cipher_name_to_type_known ( result , super .getAlgorithmName ( ) )
348- else result instanceof KeyOpAlg:: TUnknownKeyOperationAlgorithmType
375+ else result instanceof KeyOpAlg:: TOtherKeyOperationAlgorithmType
349376 }
350377
351378 override int getKeySizeFixed ( ) {
@@ -1639,6 +1666,196 @@ module JCAModel {
16391666 override Crypto:: ConsumerInputDataFlowNode getNonceConsumer ( ) { none ( ) }
16401667 }
16411668
1669+ /**
1670+ * Signatures
1671+ */
1672+ module SignatureKnownAlgorithmToConsumerConfig implements DataFlow:: ConfigSig {
1673+ predicate isSource ( DataFlow:: Node src ) { src .asExpr ( ) instanceof SignatureStringLiteral }
1674+
1675+ predicate isSink ( DataFlow:: Node sink ) {
1676+ sink = any ( SignatureAlgorithmValueConsumer call ) .getInputNode ( )
1677+ }
1678+ }
1679+
1680+ module SignatureKnownAlgorithmToConsumerFlow =
1681+ TaintTracking:: Global< SignatureKnownAlgorithmToConsumerConfig > ;
1682+
1683+ class SignatureGetInstanceCall extends MethodCall {
1684+ SignatureGetInstanceCall ( ) {
1685+ this .getCallee ( ) .hasQualifiedName ( "java.security" , "Signature" , "getInstance" )
1686+ }
1687+
1688+ Expr getAlgorithmArg ( ) { result = this .getArgument ( 0 ) }
1689+ }
1690+
1691+ class SignatureGetInstanceAlgorithmValueConsumer extends SignatureAlgorithmValueConsumer instanceof Expr
1692+ {
1693+ SignatureGetInstanceAlgorithmValueConsumer ( ) {
1694+ this = any ( SignatureGetInstanceCall c ) .getAlgorithmArg ( )
1695+ }
1696+
1697+ override Crypto:: ConsumerInputDataFlowNode getInputNode ( ) { result .asExpr ( ) = this }
1698+
1699+ override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) {
1700+ result .( SignatureStringLiteralAlgorithmInstance ) .getConsumer ( ) = this
1701+ }
1702+ }
1703+
1704+ class SignatureStringLiteral extends StringLiteral {
1705+ SignatureStringLiteral ( ) { signature_names ( this .getValue ( ) ) }
1706+ }
1707+
1708+ class SignatureStringLiteralAlgorithmInstance extends Crypto:: KeyOperationAlgorithmInstance instanceof SignatureStringLiteral
1709+ {
1710+ SignatureAlgorithmValueConsumer consumer ;
1711+
1712+ SignatureStringLiteralAlgorithmInstance ( ) {
1713+ SignatureKnownAlgorithmToConsumerFlow:: flow ( DataFlow:: exprNode ( this ) , consumer .getInputNode ( ) )
1714+ }
1715+
1716+ SignatureAlgorithmValueConsumer getConsumer ( ) { result = consumer }
1717+
1718+ override string getRawAlgorithmName ( ) { result = super .getValue ( ) }
1719+
1720+ override Crypto:: KeyOpAlg:: AlgorithmType getAlgorithmType ( ) {
1721+ if signature_name_to_type_known ( _, super .getValue ( ) )
1722+ then signature_name_to_type_known ( result , super .getValue ( ) )
1723+ else result = Crypto:: KeyOpAlg:: TOtherKeyOperationAlgorithmType ( )
1724+ }
1725+
1726+ override Crypto:: ConsumerInputDataFlowNode getKeySizeConsumer ( ) {
1727+ // TODO: trace to any key size initializer?
1728+ none ( )
1729+ }
1730+
1731+ override int getKeySizeFixed ( ) {
1732+ // TODO: are there known fixed key sizes to consider?
1733+ none ( )
1734+ }
1735+
1736+ override Crypto:: ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm ( ) { none ( ) }
1737+
1738+ override Crypto:: PaddingAlgorithmInstance getPaddingAlgorithm ( ) { none ( ) }
1739+ }
1740+
1741+ class SignatureHashAlgorithmInstance extends Crypto:: HashAlgorithmInstance instanceof SignatureStringLiteralAlgorithmInstance
1742+ {
1743+ Crypto:: THashType hashType ;
1744+ int digestLength ;
1745+
1746+ SignatureHashAlgorithmInstance ( ) {
1747+ hashType = signature_name_to_hash_type_known ( this .( StringLiteral ) .getValue ( ) , digestLength )
1748+ }
1749+
1750+ override string getRawHashAlgorithmName ( ) { result = this .( StringLiteral ) .getValue ( ) }
1751+
1752+ override Crypto:: THashType getHashFamily ( ) { result = hashType }
1753+
1754+ override int getFixedDigestLength ( ) { result = digestLength }
1755+ }
1756+
1757+ class SignatureInitCall extends MethodCall {
1758+ SignatureInitCall ( ) {
1759+ this .getCallee ( ) .hasQualifiedName ( "java.security" , "Signature" , [ "initSign" , "initVerify" ] )
1760+ }
1761+
1762+ Expr getKeyArg ( ) {
1763+ result = this .getArgument ( 0 )
1764+ // TODO: verify can take in a certificate too?
1765+ }
1766+ }
1767+
1768+ private class SignatureOperationCall extends MethodCall {
1769+ SignatureOperationCall ( ) {
1770+ this .getMethod ( ) .hasQualifiedName ( "java.security" , "Signature" , [ "update" , "sign" , "verify" ] )
1771+ }
1772+
1773+ predicate isIntermediate ( ) { super .getMethod ( ) .getName ( ) = "update" }
1774+
1775+ Expr getMsgInput ( ) { result = this .getArgument ( 0 ) and this .getMethod ( ) .getName ( ) = "update" }
1776+
1777+ Expr getSignatureOutput ( ) {
1778+ // no args, the signature is returned
1779+ result = this and this .getMethod ( ) .getName ( ) = "sign" and not exists ( this .getArgument ( 0 ) )
1780+ or
1781+ // with args, the signature is written to the arg
1782+ result = this .getArgument ( 0 ) and this .getMethod ( ) .getName ( ) = "sign"
1783+ }
1784+
1785+ Expr getSignatureInput ( ) {
1786+ result = this .getArgument ( 0 ) and this .getMethod ( ) .getName ( ) = "verify"
1787+ }
1788+
1789+ Crypto:: KeyOperationSubtype getSubtype ( ) {
1790+ result instanceof Crypto:: TSignMode and this .getMethod ( ) .getName ( ) = "sign"
1791+ or
1792+ result instanceof Crypto:: TVerifyMode and this .getMethod ( ) .getName ( ) = "verify"
1793+ }
1794+ }
1795+
1796+ class SignatureOperationinstance extends Crypto:: SignatureOperationInstance instanceof SignatureOperationCall
1797+ {
1798+ SignatureOperationinstance ( ) {
1799+ // exclude update (only include sign and verify)
1800+ not super .isIntermediate ( )
1801+ }
1802+
1803+ SignatureGetInstanceCall getInstantiationCall ( ) {
1804+ result = SignatureFlowAnalysisImpl:: getInstantiationFromUse ( this , _, _)
1805+ }
1806+
1807+ SignatureInitCall getInitCall ( ) {
1808+ result = SignatureFlowAnalysisImpl:: getInitFromUse ( this , _, _)
1809+ }
1810+
1811+ override Crypto:: ConsumerInputDataFlowNode getInputConsumer ( ) {
1812+ result .asExpr ( ) = super .getMsgInput ( ) or
1813+ result .asExpr ( ) =
1814+ SignatureFlowAnalysisImpl:: getAnIntermediateUseFromFinalUse ( this , _, _) .getMsgInput ( )
1815+ }
1816+
1817+ override Crypto:: ConsumerInputDataFlowNode getKeyConsumer ( ) {
1818+ result .asExpr ( ) = this .getInitCall ( ) .getKeyArg ( )
1819+ }
1820+
1821+ override Crypto:: AlgorithmValueConsumer getAnAlgorithmValueConsumer ( ) {
1822+ result = this .getInstantiationCall ( ) .getAlgorithmArg ( )
1823+ }
1824+
1825+ override Crypto:: ArtifactOutputDataFlowNode getOutputArtifact ( ) {
1826+ result .asExpr ( ) = super .getSignatureOutput ( ) or
1827+ result .asExpr ( ) =
1828+ SignatureFlowAnalysisImpl:: getAnIntermediateUseFromFinalUse ( this , _, _) .getSignatureOutput ( )
1829+ }
1830+
1831+ override Crypto:: AlgorithmValueConsumer getHashAlgorithmValueConsumer ( ) {
1832+ // TODO: RSASSA-PSS literal sets hashes differently, through a ParameterSpec
1833+ result = this .getInstantiationCall ( ) .getAlgorithmArg ( )
1834+ }
1835+
1836+ override predicate hasHashAlgorithmConsumer ( ) {
1837+ // All jca signature algorithms specify a hash unless explicitly set as "NONEwith..."
1838+ exists ( SignatureStringLiteralAlgorithmInstance i |
1839+ i .getConsumer ( ) = this .getAnAlgorithmValueConsumer ( ) and
1840+ not i .getRawAlgorithmName ( ) .toUpperCase ( ) .matches ( "NONEwith%" .toUpperCase ( ) )
1841+ )
1842+ }
1843+
1844+ override Crypto:: KeyOperationSubtype getKeyOperationSubtype ( ) { result = super .getSubtype ( ) }
1845+
1846+ override Crypto:: ConsumerInputDataFlowNode getNonceConsumer ( ) { none ( ) }
1847+
1848+ override Crypto:: ConsumerInputDataFlowNode getSignatureConsumer ( ) {
1849+ result .asExpr ( ) = super .getSignatureInput ( ) or
1850+ result .asExpr ( ) =
1851+ SignatureFlowAnalysisImpl:: getAnIntermediateUseFromFinalUse ( this , _, _) .getSignatureInput ( )
1852+ }
1853+ }
1854+
1855+ module SignatureFlowAnalysisImpl =
1856+ GetInstanceInitUseFlowAnalysis< SignatureGetInstanceCall , SignatureInitCall ,
1857+ SignatureOperationCall > ;
1858+
16421859 /*
16431860 * Elliptic Curves (EC)
16441861 */
0 commit comments