@@ -205,7 +205,7 @@ module JCAModel {
205
205
*
206
206
* For example, in `Cipher.getInstance(algorithm)`, this class represents `algorithm`.
207
207
*/
208
- class CipherGetInstanceAlgorithmArg extends Crypto:: AlgorithmConsumer instanceof Expr {
208
+ class CipherGetInstanceAlgorithmArg extends Crypto:: AlgorithmValueConsumer instanceof Expr {
209
209
CipherGetInstanceCall call ;
210
210
211
211
CipherGetInstanceAlgorithmArg ( ) { this = call .getAlgorithmArg ( ) }
@@ -218,7 +218,7 @@ module JCAModel {
218
218
value = result .getValue ( )
219
219
}
220
220
221
- override Crypto:: AlgorithmElement getAKnownAlgorithmSource ( ) {
221
+ override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) {
222
222
result .( CipherStringLiteralAlgorithmInstance ) .getConsumer ( ) = this
223
223
}
224
224
}
@@ -354,15 +354,17 @@ module JCAModel {
354
354
355
355
override Crypto:: CipherOperationSubtype getCipherOperationSubtype ( ) { result = mode }
356
356
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 ( )
359
359
}
360
360
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 ( )
363
365
}
364
366
365
- override Crypto:: AlgorithmConsumer getAlgorithmConsumer ( ) { result = consumer }
367
+ override Crypto:: AlgorithmValueConsumer getAnAlgorithmValueConsumer ( ) { result = consumer }
366
368
367
369
override Crypto:: CipherOutputArtifactInstance getOutputArtifact ( ) {
368
370
result = doFinalize .getOutput ( )
@@ -493,27 +495,114 @@ module JCAModel {
493
495
}
494
496
}
495
497
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 ( ) }
498
500
499
501
override DataFlow:: Node getInputNode ( ) { result .asExpr ( ) = this }
500
502
}
501
503
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 ( ) }
504
506
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
+ }
506
547
}
507
548
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 ( ) }
510
553
511
554
override DataFlow:: Node getInputNode ( ) { result .asExpr ( ) = this }
555
+
556
+ override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) {
557
+ exists ( KnownHashAlgorithm l | l .getConsumer ( ) = this and result = l )
558
+ }
512
559
}
513
560
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 ( ) }
516
593
517
594
override DataFlow:: Node getOutputNode ( ) { result .asExpr ( ) = this }
518
595
}
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
+ }
519
608
}
0 commit comments