11import java
22
3+ module Params {
4+ import Language
5+ import BouncyCastle.FlowAnalysis
6+ import BouncyCastle.AlgorithmInstances
7+
8+ /**
9+ * A model of the `Parameters` class in Bouncy Castle.
10+ */
11+ class Parameters extends RefType {
12+ Parameters ( ) {
13+ // Matches `org.bouncycastle.crypto.params`, `org.bouncycastle.asn1.x9`, etc.
14+ this .getPackage ( ) .getName ( ) .matches ( "org.bouncycastle.%" ) and
15+ this .getName ( ) .matches ( "%Parameters" )
16+ }
17+ }
18+
19+ class KeyParameters extends Parameters {
20+ KeyParameters ( ) {
21+ this .getPackage ( ) .getName ( ) = "org.bouncycastle.crypto.params" and
22+ this .getName ( ) .matches ( "%KeyParameters" )
23+ }
24+ }
25+
26+ /**
27+ * Any call that returns a BouncyCastle parameters object. This type is used
28+ * to model data flow to resolve algorithm instances like elliptic curves.
29+ *
30+ * Examples:
31+ * ```
32+ * curveParams = SECNamedCurves.getByName(...);
33+ * domainParams = new ECDomainParameters(...);
34+ * ```
35+ */
36+ class ParametersInstantiation extends Call {
37+ ParametersInstantiation ( ) {
38+ // Class instantiations
39+ this .( ConstructorCall )
40+ .getConstructedType ( )
41+ .getPackage ( )
42+ .getName ( )
43+ .matches ( "org.bouncycastle.%" ) and
44+ this .( ConstructorCall ) .getConstructedType ( ) instanceof Parameters
45+ or
46+ // (Static) factory methods
47+ this .( MethodCall )
48+ .getCallee ( )
49+ .getDeclaringType ( )
50+ .getPackage ( )
51+ .getName ( )
52+ .matches ( "org.bouncycastle.%" ) and
53+ this .( MethodCall ) .getType ( ) instanceof Parameters
54+ }
55+
56+ // Can be overridden by subclasses which take a key size argument.
57+ Expr getKeySizeArg ( ) { none ( ) }
58+
59+ Crypto:: ConsumerInputDataFlowNode getAKeySizeConsumer ( ) {
60+ result .asExpr ( ) = this .getKeySizeArg ( )
61+ }
62+
63+ // Can be overridden by subclasses which take an algorithm argument.
64+ Expr getAlgorithmArg ( ) { none ( ) }
65+
66+ Crypto:: AlgorithmValueConsumer getAnAlgorithmValueConsumer ( ) {
67+ result .getInputNode ( ) .asExpr ( ) = this .getAlgorithmArg ( )
68+ }
69+
70+ Expr getAParametersArg ( ) {
71+ result = this .getAnArgument ( ) and
72+ result .getType ( ) instanceof Parameters
73+ }
74+
75+ Crypto:: ConsumerInputDataFlowNode getAParametersConsumer ( ) {
76+ result .asExpr ( ) = this .getAParametersArg ( )
77+ }
78+ }
79+
80+ class X9ECParametersInstantiation extends ParametersInstantiation {
81+ X9ECParametersInstantiation ( ) { this .( Expr ) .getType ( ) .getName ( ) = "X9ECParameters" }
82+
83+ override Expr getAlgorithmArg ( ) { result = this .getArgument ( 0 ) }
84+ }
85+
86+ class EllipticCurveStringLiteralArg extends EllipticCurveAlgorithmValueConsumer instanceof Expr {
87+ ParametersInstantiation params ;
88+
89+ EllipticCurveStringLiteralArg ( ) { this = params .getAlgorithmArg ( ) }
90+
91+ override Crypto:: ConsumerInputDataFlowNode getInputNode ( ) { result .asExpr ( ) = this }
92+
93+ override Crypto:: AlgorithmInstance getAKnownAlgorithmSource ( ) {
94+ result .( EllipticCurveStringLiteralInstance ) .getConsumer ( ) = this
95+ }
96+ }
97+ }
98+
399/**
4100 * Models for the signature algorithms defined by the `org.bouncycastle.crypto.signers` package.
5101 */
@@ -26,6 +122,40 @@ module Signers {
26122 MethodCall getAMethodCall ( string name ) {
27123 result .getCallee ( ) .hasQualifiedName ( this .getPackage ( ) .getName ( ) , this .getName ( ) , name )
28124 }
125+
126+ // Overridden by subclasses to provide the message argument.
127+ Expr getMessageArg ( MethodCall call ) {
128+ call .getCallee ( ) .getName ( ) = "update" and
129+ result = call .getArgument ( 0 )
130+ }
131+
132+ // Overridden by subclasses to provide the signature argument.
133+ Expr getSignatureArg ( MethodCall call ) {
134+ call .getCallee ( ) .getName ( ) = "verifySignature" and
135+ result = call .getArgument ( 0 )
136+ }
137+
138+ // Overridden by subclasses to provide the signature output.
139+ Expr getSignatureOutput ( MethodCall call ) {
140+ call .getCallee ( ) .getName ( ) = "generateSignature" and
141+ result = call
142+ }
143+ }
144+
145+ class ECDSASigner extends Signer {
146+ ECDSASigner ( ) { this .getName ( ) .matches ( "ECDSA%" ) }
147+
148+ override Expr getMessageArg ( MethodCall call ) {
149+ // For ECDSA the message is passed directly to `generateSignature()`.
150+ call .getCallee ( ) .getName ( ) .matches ( [ "generateSignature" , "verifySignature" ] ) and
151+ result = call .getArgument ( 0 )
152+ }
153+
154+ override Expr getSignatureArg ( MethodCall call ) {
155+ // For ECDSA, r and s are passed to `verifySignature()` as separate arguments.
156+ call .getCallee ( ) .getName ( ) = "verifySignature" and
157+ result = call .getArgument ( [ 1 , 2 ] )
158+ }
29159 }
30160
31161 /**
@@ -45,7 +175,17 @@ module Signers {
45175
46176 Expr getForSigningArg ( ) { result = this .getArgument ( 0 ) }
47177
48- Expr getKeyArg ( ) { result = this .getArgument ( 1 ) }
178+ Expr getKeyArg ( ) {
179+ this .getParameterArg ( ) .getType ( ) instanceof Params:: KeyParameters and
180+ result = this .getParameterArg ( )
181+ }
182+
183+ // The second argument is used to provide parameters (like the key) to the signer.
184+ Expr getParameterArg ( ) { result = this .getArgument ( 1 ) }
185+
186+ Crypto:: ConsumerInputDataFlowNode getAParametersConsumer ( ) {
187+ result .asExpr ( ) = this .getParameterArg ( )
188+ }
49189
50190 // TODO: Support dataflow for the operation sub-type.
51191 Crypto:: KeyOperationSubtype getKeyOperationSubtype ( ) {
@@ -68,36 +208,48 @@ module Signers {
68208 * verify the signature, respectively.
69209 */
70210 private class SignerUseCall extends MethodCall {
71- SignerUseCall ( ) { this = any ( Signer signer ) .getAUseCall ( ) }
211+ Signer signer ;
212+
213+ SignerUseCall ( ) { this = signer .getAUseCall ( ) }
72214
73215 predicate isIntermediate ( ) { this .getCallee ( ) .getName ( ) = "update" }
74216
75- Expr getInput ( ) { result = this . getArgument ( 0 ) }
217+ Expr getMessageInput ( ) { result = signer . getMessageArg ( this ) }
76218
77- Expr getOutput ( ) { result = this }
219+ Expr getSignatureInput ( ) { result = signer .getSignatureArg ( this ) }
220+
221+ Expr getSignatureOutput ( ) { result = signer .getSignatureOutput ( this ) }
78222 }
79223
80224 /**
81225 * Instantiate the flow analysis module for the `Signer` class.
82226 */
83- private module FlowAnalysis =
227+ private module SignerFlow =
84228 NewToInitToUseFlowAnalysis< SignerNewCall , SignerInitCall , SignerUseCall > ;
85229
86230 /**
87231 * A signing operation instance is a call to either `update()`, `generateSignature()`,
88232 * or `verifySignature()` on a `Signer` instance.
89233 */
90- class SignatureOperationInstance extends Crypto:: KeyOperationInstance instanceof SignerUseCall {
234+ class SignatureOperationInstance extends Crypto:: SignatureOperationInstance instanceof SignerUseCall
235+ {
91236 SignatureOperationInstance ( ) { not this .isIntermediate ( ) }
92237
93238 override Crypto:: AlgorithmValueConsumer getAnAlgorithmValueConsumer ( ) {
94- result = FlowAnalysis:: getNewFromUse ( this , _, _)
239+ result = this .getParameters ( ) .getAnAlgorithmValueConsumer ( )
240+ or
241+ result = SignerFlow:: getNewFromUse ( this , _, _)
95242 }
96243
97244 override Crypto:: KeyOperationSubtype getKeyOperationSubtype ( ) {
98- if FlowAnalysis:: hasInit ( this )
99- then result = this .getInitCall ( ) .getKeyOperationSubtype ( )
100- else result = Crypto:: TUnknownKeyOperationMode ( )
245+ // This is less expensive and more robust than resolving the subtype using
246+ // dataflow from the `forSigning` argument to `init()`.
247+ if super .getMethod ( ) .getName ( ) = "generateSignature"
248+ then result = Crypto:: TSignMode ( )
249+ else
250+ if super .getMethod ( ) .getName ( ) = "verifySignature"
251+ then result = Crypto:: TVerifyMode ( )
252+ else result = Crypto:: TUnknownKeyOperationMode ( )
101253 }
102254
103255 override Crypto:: ConsumerInputDataFlowNode getKeyConsumer ( ) {
@@ -107,18 +259,36 @@ module Signers {
107259 override Crypto:: ConsumerInputDataFlowNode getNonceConsumer ( ) { none ( ) }
108260
109261 override Crypto:: ConsumerInputDataFlowNode getInputConsumer ( ) {
110- result .asExpr ( ) = this .getAnUpdateCall ( ) .getInput ( )
262+ // Inputs to signers with streaming APIs
263+ result .asExpr ( ) = this .getAnUpdateCall ( ) .getMessageInput ( )
264+ or
265+ // Inputs to signers with one shot APIs
266+ result .asExpr ( ) = super .getMessageInput ( )
267+ }
268+
269+ override Crypto:: ConsumerInputDataFlowNode getSignatureArtifactConsumer ( ) {
270+ result .asExpr ( ) = super .getSignatureInput ( )
111271 }
112272
113273 override Crypto:: ArtifactOutputDataFlowNode getOutputArtifact ( ) {
114- this . getKeyOperationSubtype ( ) = Crypto :: TSignMode ( ) and
115- result .asExpr ( ) = super .getOutput ( )
274+ // Signature output
275+ result .asExpr ( ) = super .getSignatureOutput ( )
116276 }
117277
118- SignerInitCall getInitCall ( ) { result = FlowAnalysis :: getInitFromUse ( this , _, _) }
278+ SignerInitCall getInitCall ( ) { result = SignerFlow :: getInitFromUse ( this , _, _) }
119279
120280 SignerUseCall getAnUpdateCall ( ) {
121- result = FlowAnalysis:: getAnIntermediateUseFromFinalUse ( this , _, _)
281+ result = SignerFlow:: getAnIntermediateUseFromFinalUse ( this , _, _)
282+ }
283+
284+ Crypto:: KeyArtifactOutputInstance getKey ( ) { result .flowsTo ( this .getInitCall ( ) .getKeyArg ( ) ) }
285+
286+ Generators:: KeyGenerationOperationInstance getKeyGenerationOperationInstance ( ) {
287+ result .getKeyArtifactOutputInstance ( ) = this .getKey ( )
288+ }
289+
290+ Params:: ParametersInstantiation getParameters ( ) {
291+ result = this .getKeyGenerationOperationInstance ( ) .getParameters ( )
122292 }
123293 }
124294}
@@ -194,6 +364,11 @@ module Generators {
194364 // TODO: We may need to model this using the `parameters` argument passed to
195365 // the `init()` method.
196366 Crypto:: ConsumerInputDataFlowNode getKeySizeConsumer ( ) { none ( ) }
367+
368+ // The `KeyGenerationParameters` argument used to configure the key generator.
369+ Crypto:: ConsumerInputDataFlowNode getAParametersConsumer ( ) {
370+ result .asExpr ( ) = this .getArgument ( 0 )
371+ }
197372 }
198373
199374 /**
@@ -216,6 +391,14 @@ module Generators {
216391 private module KeyGeneratorFlow =
217392 NewToInitToUseFlowAnalysis< KeyGeneratorNewCall , KeyGeneratorInitCall , KeyGeneratorUseCall > ;
218393
394+ private module ParametersFlow =
395+ ParametersToInitFlowAnalysis< Params:: ParametersInstantiation , KeyGeneratorInitCall > ;
396+
397+ Params:: ParametersInstantiation getParametersFromInit ( KeyGeneratorInitCall init ) {
398+ result = ParametersFlow:: getParametersFromInit ( init , _, _) and
399+ result instanceof Params:: X9ECParametersInstantiation
400+ }
401+
219402 /**
220403 * A key generation operation instance is a call to `generateKey()` or
221404 * `generateKeyPair()` on a key generator defined under
@@ -224,6 +407,10 @@ module Generators {
224407 class KeyGenerationOperationInstance extends Crypto:: KeyGenerationOperationInstance instanceof KeyGeneratorUseCall
225408 {
226409 override Crypto:: AlgorithmValueConsumer getAnAlgorithmValueConsumer ( ) {
410+ // The algorithm value consumer flows through a parameters argument to `init()`
411+ result = this .getParameters ( ) .getAnAlgorithmValueConsumer ( )
412+ or
413+ // The algorithm is implicit in the key generator type
227414 result = KeyGeneratorFlow:: getNewFromUse ( this , _, _)
228415 }
229416
@@ -240,17 +427,12 @@ module Generators {
240427 override Crypto:: ConsumerInputDataFlowNode getKeySizeConsumer ( ) {
241428 result = KeyGeneratorFlow:: getInitFromUse ( this , _, _) .getKeySizeConsumer ( )
242429 }
243- }
244- }
245430
246- /**
247- * Models for cryptographic parameters defined by the `org.bouncycastle.crypto.params` package.
248- */
249- module Parameters {
250- class KeyGenerationParameters extends RefType {
251- KeyGenerationParameters ( ) {
252- this .getPackage ( ) .getName ( ) = "org.bouncycastle.crypto.params" and
253- this .getName ( ) .matches ( "%KeyGenerationParameters" )
431+ Params:: ParametersInstantiation getParameters ( ) {
432+ exists ( KeyGeneratorInitCall init |
433+ init = KeyGeneratorFlow:: getInitFromUse ( this , _, _) and
434+ result = ParametersFlow:: getParametersFromInit ( init , _, _)
435+ )
254436 }
255437 }
256438}
0 commit comments