11import java
22import semmle.code.java.dataflow.DataFlow
3+ import semmle.code.java.dataflow.TaintTracking
34import semmle.code.java.controlflow.Dominance
45
56module JCAModel {
@@ -43,6 +44,22 @@ module JCAModel {
4344 .toUpperCase ( ) )
4445 }
4546
47+ bindingset [ kdf]
48+ predicate kdf_names ( string kdf ) {
49+ kdf .toUpperCase ( ) .matches ( [ "PBKDF2With%" , "PBEWith%" ] .toUpperCase ( ) )
50+ }
51+
52+ bindingset [ name]
53+ Crypto:: TKeyDerivationType kdf_name_to_kdf_type ( string name , string withSubstring ) {
54+ name .matches ( "PBKDF2With%" ) and
55+ result instanceof Crypto:: PBKDF2 and
56+ withSubstring = name .regexpCapture ( "PBKDF2With(.*)" , 1 )
57+ or
58+ name .matches ( "PBEWith%" ) and
59+ result instanceof Crypto:: PBES and
60+ withSubstring = name .regexpCapture ( "PBEWith(.*)" , 1 )
61+ }
62+
4663 bindingset [ name]
4764 Crypto:: THashType hash_name_to_hash_type ( string name , int digestLength ) {
4865 name = "SHA-1" and result instanceof Crypto:: SHA1 and digestLength = 160
@@ -132,7 +149,7 @@ module JCAModel {
132149 }
133150 }
134151
135- module AlgorithmStringToFetchFlow = DataFlow :: Global< AlgorithmStringToFetchConfig > ;
152+ module AlgorithmStringToFetchFlow = TaintTracking :: Global< AlgorithmStringToFetchConfig > ;
136153
137154 /**
138155 * Note: padding and a mode of operation will only exist when the padding / mode (*and its type*) are determinable.
@@ -303,7 +320,7 @@ module JCAModel {
303320
304321 CipherGetInstanceAlgorithmArg ( ) { this = call .getAlgorithmArg ( ) }
305322
306- override DataFlow :: Node getInputNode ( ) { result .asExpr ( ) = this }
323+ override Crypto :: ConsumerInputDataFlowNode getInputNode ( ) { result .asExpr ( ) = this }
307324
308325 CipherStringLiteral getOrigin ( string value ) {
309326 AlgorithmStringToFetchFlow:: flow ( DataFlow:: exprNode ( result ) ,
@@ -447,13 +464,15 @@ module JCAModel {
447464
448465 override Crypto:: CipherOperationSubtype getCipherOperationSubtype ( ) { result = mode }
449466
450- override DataFlow :: Node getNonceConsumer ( ) {
467+ override Crypto :: ConsumerInputDataFlowNode getNonceConsumer ( ) {
451468 result .asExpr ( ) = sink .getState ( ) .( InitializedCipherModeFlowState ) .getInitCall ( ) .getNonceArg ( )
452469 }
453470
454- override DataFlow:: Node getInputConsumer ( ) { result = doFinalize .getMessageArg ( ) }
471+ override Crypto:: ConsumerInputDataFlowNode getInputConsumer ( ) {
472+ result = doFinalize .getMessageArg ( )
473+ }
455474
456- override DataFlow :: Node getKeyConsumer ( ) {
475+ override Crypto :: ConsumerInputDataFlowNode getKeyConsumer ( ) {
457476 result .asExpr ( ) = sink .getState ( ) .( InitializedCipherModeFlowState ) .getInitCall ( ) .getKeyArg ( )
458477 }
459478
@@ -611,7 +630,7 @@ module JCAModel {
611630 class CipherInitCallKeyConsumer extends Crypto:: ArtifactConsumer {
612631 CipherInitCallKeyConsumer ( ) { this = any ( CipherInitCall call ) .getKeyArg ( ) }
613632
614- override DataFlow :: Node getInputNode ( ) { result .asExpr ( ) = this }
633+ override Crypto :: ConsumerInputDataFlowNode getInputNode ( ) { result .asExpr ( ) = this }
615634 }
616635
617636 class CipherOperationCallOutput extends Crypto:: CipherOutputArtifactInstance {
@@ -659,7 +678,7 @@ module JCAModel {
659678
660679 MessageDigestAlgorithmValueConsumer ( ) { this = call .getAlgorithmArg ( ) }
661680
662- override DataFlow :: Node getInputNode ( ) { result .asExpr ( ) = this }
681+ override Crypto :: ConsumerInputDataFlowNode getInputNode ( ) { result .asExpr ( ) = this }
663682
664683 override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) {
665684 exists ( KnownHashAlgorithm l | l .getConsumer ( ) = this and result = l )
@@ -719,7 +738,7 @@ module JCAModel {
719738
720739 KeyGeneratorCallAlgorithmValueConsumer ( ) { this = call .getAlgorithmArg ( ) }
721740
722- override DataFlow :: Node getInputNode ( ) { result .asExpr ( ) = this }
741+ override Crypto :: ConsumerInputDataFlowNode getInputNode ( ) { result .asExpr ( ) = this }
723742
724743 override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) {
725744 result .( CipherStringLiteralAlgorithmInstance ) .getConsumer ( ) = this
@@ -780,6 +799,10 @@ module JCAModel {
780799 Crypto:: AlgorithmInstance getAKnownAlgorithm ( ) {
781800 result = this .getAnAlgorithmValueConsumer ( ) .getAKnownAlgorithmSource ( )
782801 }
802+
803+ override Crypto:: ConsumerInputDataFlowNode getKeySizeConsumer ( ) { none ( ) }
804+
805+ override string getKeySizeFixed ( ) { none ( ) }
783806 }
784807
785808 /*
@@ -845,7 +868,9 @@ module JCAModel {
845868
846869 module MACInitCallToMACOperationFlowConfig implements DataFlow:: ConfigSig {
847870 // TODO: use flow state with one config
848- predicate isSource ( DataFlow:: Node src ) { src .asExpr ( ) instanceof MACInitCall }
871+ predicate isSource ( DataFlow:: Node src ) {
872+ exists ( MACInitCall init | src .asExpr ( ) = init .getQualifier ( ) )
873+ }
849874
850875 predicate isSink ( DataFlow:: Node sink ) {
851876 exists ( MACOperationCall call | sink .asExpr ( ) = call .( MethodCall ) .getQualifier ( ) )
@@ -884,7 +909,7 @@ module JCAModel {
884909 }
885910
886911 MACInitCall getInitCall ( ) {
887- MACInitCallToMACOperationFlow :: flow ( DataFlow:: exprNode ( this ) ,
912+ MACGetInstanceToMACOperationFlow :: flow ( DataFlow:: exprNode ( this ) ,
888913 DataFlow:: exprNode ( result .getQualifier ( ) ) )
889914 }
890915 }
@@ -897,7 +922,7 @@ module JCAModel {
897922 }
898923
899924 MACOperationCall getOperation ( ) {
900- MACInitCallToMACOperationFlow:: flow ( DataFlow:: exprNode ( this ) ,
925+ MACInitCallToMACOperationFlow:: flow ( DataFlow:: exprNode ( this . getQualifier ( ) ) ,
901926 DataFlow:: exprNode ( result .( MethodCall ) .getQualifier ( ) ) )
902927 }
903928 }
@@ -907,7 +932,7 @@ module JCAModel {
907932
908933 MACGetInstanceAlgorithmValueConsumer ( ) { this = call .getAlgorithmArg ( ) }
909934
910- override DataFlow :: Node getInputNode ( ) { result .asExpr ( ) = this }
935+ override Crypto :: ConsumerInputDataFlowNode getInputNode ( ) { result .asExpr ( ) = this }
911936
912937 override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) {
913938 exists ( KnownMACAlgorithm l | l .getConsumer ( ) = this and result = l )
@@ -933,7 +958,7 @@ module JCAModel {
933958 )
934959 }
935960
936- override DataFlow :: Node getKeyConsumer ( ) {
961+ override Crypto :: ConsumerInputDataFlowNode getKeyConsumer ( ) {
937962 exists ( MACGetInstanceCall instantiation , MACInitCall initCall |
938963 instantiation .getOperation ( ) = this and
939964 initCall .getOperation ( ) = this and
@@ -942,9 +967,195 @@ module JCAModel {
942967 )
943968 }
944969
945- override DataFlow :: Node getMessageConsumer ( ) {
970+ override Crypto :: ConsumerInputDataFlowNode getMessageConsumer ( ) {
946971 result .asExpr ( ) = super .getArgument ( 0 ) and
947972 super .getMethod ( ) .getParameterType ( 0 ) .hasName ( "byte[]" )
948973 }
949974 }
975+
976+ module SecretKeyFactoryGetInstanceToGenerateSecretFlowConfig implements DataFlow:: ConfigSig {
977+ predicate isSource ( DataFlow:: Node src ) {
978+ exists ( SecretKeyFactoryGetInstanceCall call | src .asExpr ( ) = call )
979+ }
980+
981+ predicate isSink ( DataFlow:: Node sink ) {
982+ exists ( SecretKeyFactoryGenerateSecretCall call |
983+ sink .asExpr ( ) = call .( MethodCall ) .getQualifier ( )
984+ )
985+ }
986+ }
987+
988+ module PBEKeySpecInstantiationToGenerateSecretFlowConfig implements DataFlow:: ConfigSig {
989+ predicate isSource ( DataFlow:: Node src ) {
990+ exists ( PBEKeySpecInstantiation call | src .asExpr ( ) = call )
991+ }
992+
993+ predicate isSink ( DataFlow:: Node sink ) {
994+ exists ( SecretKeyFactoryGenerateSecretCall call | sink .asExpr ( ) = call .getKeySpecArg ( ) )
995+ }
996+ }
997+
998+ module KDFAlgorithmStringToGetInstanceConfig implements DataFlow:: ConfigSig {
999+ predicate isSource ( DataFlow:: Node src ) { kdf_names ( src .asExpr ( ) .( StringLiteral ) .getValue ( ) ) }
1000+
1001+ predicate isSink ( DataFlow:: Node sink ) {
1002+ exists ( SecretKeyFactoryGetInstanceCall call | sink .asExpr ( ) = call .getAlgorithmArg ( ) )
1003+ }
1004+ }
1005+
1006+ module SecretKeyFactoryGetInstanceToGenerateSecretFlow =
1007+ DataFlow:: Global< SecretKeyFactoryGetInstanceToGenerateSecretFlowConfig > ;
1008+
1009+ module PBEKeySpecInstantiationToGenerateSecretFlow =
1010+ DataFlow:: Global< PBEKeySpecInstantiationToGenerateSecretFlowConfig > ;
1011+
1012+ module KDFAlgorithmStringToGetInstanceFlow =
1013+ DataFlow:: Global< KDFAlgorithmStringToGetInstanceConfig > ;
1014+
1015+ class PBEKeySpecInstantiation extends ClassInstanceExpr {
1016+ PBEKeySpecInstantiation ( ) {
1017+ this .getConstructedType ( ) .hasQualifiedName ( "javax.crypto.spec" , "PBEKeySpec" )
1018+ }
1019+
1020+ Expr getPasswordArg ( ) { result = this .getArgument ( 0 ) }
1021+
1022+ Expr getSaltArg ( ) { result = this .getArgument ( 1 ) }
1023+
1024+ Expr getIterationCountArg ( ) { result = this .getArgument ( 2 ) }
1025+
1026+ Expr getKeyLengthArg ( ) { result = this .getArgument ( 3 ) }
1027+ }
1028+
1029+ class SecretKeyFactoryGetInstanceCall extends MethodCall {
1030+ SecretKeyFactoryGetInstanceCall ( ) {
1031+ this .getCallee ( ) .hasQualifiedName ( "javax.crypto" , "SecretKeyFactory" , "getInstance" )
1032+ }
1033+
1034+ Expr getAlgorithmArg ( ) { result = this .getArgument ( 0 ) }
1035+
1036+ SecretKeyFactoryGenerateSecretCall getOperation ( ) {
1037+ SecretKeyFactoryGetInstanceToGenerateSecretFlow:: flow ( DataFlow:: exprNode ( this ) ,
1038+ DataFlow:: exprNode ( result .( MethodCall ) .getQualifier ( ) ) )
1039+ }
1040+ }
1041+
1042+ class KDFAlgorithmStringLiteral extends Crypto:: KeyDerivationAlgorithmInstance instanceof StringLiteral
1043+ {
1044+ SecretKeyFactoryKDFAlgorithmValueConsumer consumer ;
1045+
1046+ KDFAlgorithmStringLiteral ( ) {
1047+ kdf_names ( this .getValue ( ) ) and
1048+ KDFAlgorithmStringToGetInstanceFlow:: flow ( DataFlow:: exprNode ( this ) , consumer .getInputNode ( ) )
1049+ }
1050+
1051+ override string getRawKDFAlgorithmName ( ) { result = super .getValue ( ) }
1052+
1053+ override Crypto:: TKeyDerivationType getKDFType ( ) {
1054+ result = kdf_name_to_kdf_type ( super .getValue ( ) , _)
1055+ }
1056+
1057+ SecretKeyFactoryKDFAlgorithmValueConsumer getConsumer ( ) { result = consumer }
1058+ }
1059+
1060+ class PBKDF2AlgorithmStringLiteral extends KDFAlgorithmStringLiteral ,
1061+ Crypto:: PBKDF2AlgorithmInstance , Crypto:: HMACAlgorithmInstance , Crypto:: HashAlgorithmInstance ,
1062+ Crypto:: AlgorithmValueConsumer
1063+ {
1064+ PBKDF2AlgorithmStringLiteral ( ) { super .getKDFType ( ) instanceof Crypto:: PBKDF2 }
1065+
1066+ override Crypto:: ConsumerInputDataFlowNode getInputNode ( ) { none ( ) }
1067+
1068+ override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) { result = this }
1069+
1070+ override Crypto:: THashType getHashFamily ( ) {
1071+ result = hash_name_to_hash_type ( this .getRawHashAlgorithmName ( ) , _)
1072+ }
1073+
1074+ override int getDigestLength ( ) {
1075+ exists ( hash_name_to_hash_type ( this .getRawHashAlgorithmName ( ) , result ) )
1076+ }
1077+
1078+ override string getRawMACAlgorithmName ( ) {
1079+ result = super .getRawKDFAlgorithmName ( ) .splitAt ( "PBKDF2With" , 1 )
1080+ }
1081+
1082+ override string getRawHashAlgorithmName ( ) {
1083+ result = super .getRawKDFAlgorithmName ( ) .splitAt ( "WithHmac" , 1 )
1084+ }
1085+
1086+ override Crypto:: TMACType getMACType ( ) { result instanceof Crypto:: THMAC }
1087+
1088+ override Crypto:: AlgorithmValueConsumer getHMACAlgorithmValueConsumer ( ) { result = this }
1089+
1090+ override Crypto:: AlgorithmValueConsumer getHashAlgorithmValueConsumer ( ) { result = this }
1091+ }
1092+
1093+ class SecretKeyFactoryKDFAlgorithmValueConsumer extends Crypto:: AlgorithmValueConsumer instanceof Expr
1094+ {
1095+ SecretKeyFactoryGetInstanceCall call ;
1096+
1097+ SecretKeyFactoryKDFAlgorithmValueConsumer ( ) { this = call .getAlgorithmArg ( ) }
1098+
1099+ override Crypto:: ConsumerInputDataFlowNode getInputNode ( ) { result .asExpr ( ) = this }
1100+
1101+ override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) {
1102+ exists ( KDFAlgorithmStringLiteral l | l .getConsumer ( ) = this and result = l )
1103+ }
1104+
1105+ SecretKeyFactoryGetInstanceCall getInstantiation ( ) { result = call }
1106+ }
1107+
1108+ class SecretKeyFactoryGenerateSecretCall extends Crypto:: KeyDerivationOperationInstance instanceof MethodCall
1109+ {
1110+ SecretKeyFactoryGenerateSecretCall ( ) {
1111+ super .getCallee ( ) .hasQualifiedName ( "javax.crypto" , "SecretKeyFactory" , "generateSecret" )
1112+ }
1113+
1114+ Expr getKeySpecArg ( ) {
1115+ result = super .getArgument ( 0 ) and
1116+ super .getMethod ( ) .getParameterType ( 0 ) .hasName ( "KeySpec" )
1117+ }
1118+
1119+ PBEKeySpecInstantiation getInstantiation ( ) {
1120+ PBEKeySpecInstantiationToGenerateSecretFlow:: flow ( DataFlow:: exprNode ( result ) ,
1121+ DataFlow:: exprNode ( this .getKeySpecArg ( ) ) )
1122+ }
1123+
1124+ override Crypto:: AlgorithmValueConsumer getAnAlgorithmValueConsumer ( ) {
1125+ exists ( SecretKeyFactoryGetInstanceCall instantiation |
1126+ instantiation .getOperation ( ) = this and result = instantiation .getAlgorithmArg ( )
1127+ )
1128+ }
1129+
1130+ override Crypto:: ConsumerInputDataFlowNode getSaltConsumer ( ) {
1131+ result .asExpr ( ) = this .getInstantiation ( ) .getSaltArg ( )
1132+ }
1133+
1134+ override Crypto:: ConsumerInputDataFlowNode getInputConsumer ( ) {
1135+ result .asExpr ( ) = this .getInstantiation ( ) .getPasswordArg ( )
1136+ }
1137+
1138+ override Crypto:: ConsumerInputDataFlowNode getIterationCountConsumer ( ) {
1139+ result .asExpr ( ) = this .getInstantiation ( ) .getIterationCountArg ( )
1140+ }
1141+
1142+ override DataFlow:: Node getOutputKeyArtifact ( ) {
1143+ result .asExpr ( ) = this and
1144+ super .getMethod ( ) .getReturnType ( ) .hasName ( "SecretKey" )
1145+ }
1146+
1147+ override Crypto:: ConsumerInputDataFlowNode getOutputKeySizeConsumer ( ) {
1148+ result .asExpr ( ) = this .getInstantiation ( ) .getKeyLengthArg ( )
1149+ }
1150+
1151+ override Crypto:: ConsumerInputDataFlowNode getKeySizeConsumer ( ) {
1152+ result .asExpr ( ) = this .getInstantiation ( ) .getKeyLengthArg ( )
1153+ }
1154+
1155+ override string getKeySizeFixed ( ) { none ( ) }
1156+
1157+ override string getOutputKeySizeFixed ( ) { none ( ) }
1158+
1159+ override string getIterationCountFixed ( ) { none ( ) }
1160+ }
9501161}
0 commit comments