@@ -205,7 +205,7 @@ module JCAModel {
205205 *
206206 * For example, in `Cipher.getInstance(algorithm)`, this class represents `algorithm`.
207207 */
208- class CipherGetInstanceAlgorithmArg extends Crypto:: AlgorithmConsumer instanceof Expr {
208+ class CipherGetInstanceAlgorithmArg extends Crypto:: AlgorithmValueConsumer instanceof Expr {
209209 CipherGetInstanceCall call ;
210210
211211 CipherGetInstanceAlgorithmArg ( ) { this = call .getAlgorithmArg ( ) }
@@ -218,7 +218,7 @@ module JCAModel {
218218 value = result .getValue ( )
219219 }
220220
221- override Crypto:: AlgorithmElement getAKnownAlgorithmSource ( ) {
221+ override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) {
222222 result .( CipherStringLiteralAlgorithmInstance ) .getConsumer ( ) = this
223223 }
224224 }
@@ -354,15 +354,17 @@ module JCAModel {
354354
355355 override Crypto:: CipherOperationSubtype getCipherOperationSubtype ( ) { result = mode }
356356
357- override Crypto :: NonceArtifactConsumer getNonceConsumer ( ) {
358- result = sink .getState ( ) .( InitializedCipherModeFlowState ) .getInitCall ( ) .getNonceArg ( )
357+ override DataFlow :: Node getNonceConsumer ( ) {
358+ result . asExpr ( ) = sink .getState ( ) .( InitializedCipherModeFlowState ) .getInitCall ( ) .getNonceArg ( )
359359 }
360360
361- override Crypto:: CipherInputConsumer getInputConsumer ( ) {
362- result = doFinalize .getMessageArg ( ) .asExpr ( )
361+ override DataFlow:: Node getInputConsumer ( ) { result = doFinalize .getMessageArg ( ) }
362+
363+ override DataFlow:: Node getKeyConsumer ( ) {
364+ result .asExpr ( ) = sink .getState ( ) .( InitializedCipherModeFlowState ) .getInitCall ( ) .getKeyArg ( )
363365 }
364366
365- override Crypto:: AlgorithmConsumer getAlgorithmConsumer ( ) { result = consumer }
367+ override Crypto:: AlgorithmValueConsumer getAnAlgorithmValueConsumer ( ) { result = consumer }
366368
367369 override Crypto:: CipherOutputArtifactInstance getOutputArtifact ( ) {
368370 result = doFinalize .getOutput ( )
@@ -493,27 +495,114 @@ module JCAModel {
493495 }
494496 }
495497
496- class CipherInitCallNonceArgConsumer extends Crypto:: NonceArtifactConsumer instanceof Expr {
497- CipherInitCallNonceArgConsumer ( ) { this = any ( CipherInitCall call ) .getNonceArg ( ) }
498+ class CipherInitCallKeyConsumer extends Crypto:: ArtifactConsumer {
499+ CipherInitCallKeyConsumer ( ) { this = any ( CipherInitCall call ) .getKeyArg ( ) }
498500
499501 override DataFlow:: Node getInputNode ( ) { result .asExpr ( ) = this }
500502 }
501503
502- class CipherInitCallKeyConsumer extends Crypto :: ArtifactConsumer {
503- CipherInitCallKeyConsumer ( ) { this = any ( CipherInitCall call ) .getKeyArg ( ) }
504+ class CipherOperationCallOutput extends CipherOutputArtifact {
505+ CipherOperationCallOutput ( ) { this = any ( CipherOperationCall call ) .getOutput ( ) }
504506
505- override DataFlow:: Node getInputNode ( ) { result .asExpr ( ) = this }
507+ override DataFlow:: Node getOutputNode ( ) { result .asExpr ( ) = this }
508+ }
509+
510+ bindingset [ hash]
511+ predicate hash_names ( string hash ) {
512+ hash .toUpperCase ( )
513+ .matches ( [
514+ "SHA-1" , "SHA-256" , "SHA-384" , "SHA-512" , "SHA3-224" , "SHA3-256" , "SHA3-384" ,
515+ "SHA3-512" , "BLAKE2b" , "BLAKE2s"
516+ ] .toUpperCase ( ) )
517+ }
518+
519+ // flow config from a known hash algorithm literal to MessageDigest.getInstance
520+ module KnownHashAlgorithmLiteralToMessageDigestConfig implements DataFlow:: ConfigSig {
521+ predicate isSource ( DataFlow:: Node src ) { hash_names ( src .asExpr ( ) .( StringLiteral ) .getValue ( ) ) }
522+
523+ predicate isSink ( DataFlow:: Node sink ) {
524+ exists ( MessageDigestGetInstanceCall call | sink .asExpr ( ) = call .getAlgorithmArg ( ) )
525+ }
526+ }
527+
528+ module KnownHashAlgorithmLiteralToMessageDigestFlow =
529+ DataFlow:: Global< KnownHashAlgorithmLiteralToMessageDigestConfig > ;
530+
531+ class KnownHashAlgorithm extends Crypto:: HashAlgorithmInstance instanceof StringLiteral {
532+ MessageDigestAlgorithmValueConsumer consumer ;
533+
534+ KnownHashAlgorithm ( ) {
535+ hash_names ( this .getValue ( ) ) and
536+ KnownHashAlgorithmLiteralToMessageDigestFlow:: flow ( DataFlow:: exprNode ( this ) ,
537+ consumer .getInputNode ( ) )
538+ }
539+
540+ MessageDigestAlgorithmValueConsumer getConsumer ( ) { result = consumer }
541+
542+ override string getRawAlgorithmName ( ) { result = this .( StringLiteral ) .getValue ( ) }
543+
544+ override Crypto:: THashType getHashFamily ( ) {
545+ result = Crypto:: OtherHashType ( ) // TODO
546+ }
506547 }
507548
508- class CipherMessageInputConsumer extends Crypto:: CipherInputConsumer {
509- CipherMessageInputConsumer ( ) { this = any ( CipherOperationCall call ) .getMessageArg ( ) .asExpr ( ) }
549+ class MessageDigestAlgorithmValueConsumer extends Crypto:: AlgorithmValueConsumer {
550+ MessageDigestGetInstanceCall call ;
551+
552+ MessageDigestAlgorithmValueConsumer ( ) { this = call .getAlgorithmArg ( ) }
510553
511554 override DataFlow:: Node getInputNode ( ) { result .asExpr ( ) = this }
555+
556+ override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) {
557+ exists ( KnownHashAlgorithm l | l .getConsumer ( ) = this and result = l )
558+ }
512559 }
513560
514- class CipherOperationCallOutput extends CipherOutputArtifact {
515- CipherOperationCallOutput ( ) { this = any ( CipherOperationCall call ) .getOutput ( ) }
561+ class MessageDigestGetInstanceCall extends MethodCall {
562+ MessageDigestGetInstanceCall ( ) {
563+ this .getCallee ( ) .hasQualifiedName ( "java.security" , "MessageDigest" , "getInstance" )
564+ }
565+
566+ Expr getAlgorithmArg ( ) { result = this .getArgument ( 0 ) }
567+
568+ DigestHashOperation getDigestCall ( ) {
569+ DigestGetInstanceToDigestFlow:: flow ( DataFlow:: exprNode ( this ) ,
570+ DataFlow:: exprNode ( result .( DigestCall ) .getQualifier ( ) ) )
571+ }
572+ }
573+
574+ class DigestCall extends MethodCall {
575+ DigestCall ( ) { this .getCallee ( ) .hasQualifiedName ( "java.security" , "MessageDigest" , "digest" ) }
576+
577+ Expr getDigestArtifactOutput ( ) { result = this }
578+ }
579+
580+ // flow config from MessageDigest.getInstance to MessageDigest.digest
581+ module DigestGetInstanceToDigestConfig implements DataFlow:: ConfigSig {
582+ predicate isSource ( DataFlow:: Node src ) { src .asExpr ( ) instanceof MessageDigestGetInstanceCall }
583+
584+ predicate isSink ( DataFlow:: Node sink ) {
585+ exists ( DigestCall c | c .getQualifier ( ) = sink .asExpr ( ) )
586+ }
587+ }
588+
589+ module DigestGetInstanceToDigestFlow = DataFlow:: Global< DigestGetInstanceToDigestConfig > ;
590+
591+ class DigestArtifact extends DigestArtifactInstance {
592+ DigestArtifact ( ) { this = any ( DigestCall call ) .getDigestArtifactOutput ( ) }
516593
517594 override DataFlow:: Node getOutputNode ( ) { result .asExpr ( ) = this }
518595 }
596+
597+ class DigestHashOperation extends Crypto:: HashOperationInstance instanceof DigestCall {
598+ override Crypto:: DigestArtifactInstance getDigestArtifact ( ) {
599+ result = this .( DigestCall ) .getDigestArtifactOutput ( )
600+ }
601+
602+ override Crypto:: AlgorithmValueConsumer getAnAlgorithmValueConsumer ( ) {
603+ exists ( MessageDigestGetInstanceCall call |
604+ call .getDigestCall ( ) = this and result = call .getAlgorithmArg ( )
605+ )
606+ }
607+ }
519608}
0 commit comments