4
4
5
5
private import experimental.quantum.Language
6
6
private import OpenSSLOperationBase
7
+ private import experimental.quantum.OpenSSL.AvcFlow
7
8
private import experimental.quantum.OpenSSL.CtxFlow
8
9
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
9
10
private import experimental.quantum.OpenSSL.Operations.OpenSSLOperations
10
11
11
- module OpenSSLKeyGenToArgConfig implements DataFlow:: ConfigSig {
12
- predicate isSource ( DataFlow:: Node source ) {
13
- exists ( Crypto:: KeyGenerationOperationInstance keygen | keygen .getOutputKeyArtifact ( ) = source )
12
+ // TODO: verification functions
13
+ class EvpSignatureDigestInitializer extends EvpHashAlgorithmInitializer {
14
+ Expr arg ;
15
+
16
+ EvpSignatureDigestInitializer ( ) {
17
+ this .( Call ) .getTarget ( ) .getName ( ) in [ "EVP_DigestSignInit_ex" , "EVP_DigestSignInit" ] and
18
+ arg = this .( Call ) .getArgument ( 2 )
19
+ or
20
+ this .( Call ) .getTarget ( ) .getName ( ) in [ "EVP_SignInit" , "EVP_SignInit_ex" ] and
21
+ arg = this .( Call ) .getArgument ( 1 )
14
22
}
15
23
16
- predicate isSink ( DataFlow:: Node sink ) { exists ( Call c | c .getAnArgument ( ) = sink .asExpr ( ) ) }
24
+ override Expr getHashAlgorithmArg ( ) { result = arg }
25
+
26
+ override CtxPointerSource getContext ( ) { result = this .( Call ) .getArgument ( 0 ) }
17
27
}
18
28
19
- module OpenSSLKeyGenToArgFlow = TaintTracking:: Global< OpenSSLKeyGenToArgConfig > ;
29
+ class EvpSignatureKeyInitializer extends EvpKeyInitializer {
30
+ Expr arg ;
20
31
21
- // TODO: verification functions
22
- class EVP_Signature_Initializer extends EVPInitialize {
23
- EVP_Signature_Initializer ( ) {
24
- this .( Call ) .getTarget ( ) .getName ( ) in [
25
- "EVP_DigestSignInit" , "EVP_DigestSignInit_ex" , "EVP_SignInit" , "EVP_SignInit_ex" ,
26
- "EVP_PKEY_sign_init" , "EVP_PKEY_sign_init_ex" , "EVP_PKEY_sign_init_ex2" ,
27
- "EVP_PKEY_sign_message_init"
28
- ]
32
+ EvpSignatureKeyInitializer ( ) {
33
+ this .( Call ) .getTarget ( ) .getName ( ) = "EVP_DigestSignInit_ex" and
34
+ arg = this .( Call ) .getArgument ( 5 )
35
+ or
36
+ this .( Call ) .getTarget ( ) .getName ( ) = "EVP_DigestSignInit" and
37
+ arg = this .( Call ) .getArgument ( 4 )
29
38
}
30
39
31
- /**
32
- * Gets the algorithm associated with this initialization by following
33
- * where the algorithm is set through the context argument.
34
- */
35
- Expr getAlgorithmArgFromCtx ( ) {
36
- // exists(EVPPKeyAlgorithmConsumer source, DataFlow::Node sink |
37
- // result = source.getInputNode().asExpr() and
38
- // sink.asExpr() = this.getContextArg() and
39
- // OpenSSLCtxSourceToArgumentFlow::flow(source.getResultNode(), sink)
40
- // )
41
- // or
42
- result = this .getAlgorithmArgFromKey ( this .getKeyArgFromCtx ( ) )
43
- }
44
-
45
- Expr getAlgorithmArgFromKey ( Expr keyArg ) {
46
- exists ( Crypto:: KeyGenerationOperationInstance keygen |
47
- OpenSSLKeyGenToArgFlow:: flow ( keygen .getOutputKeyArtifact ( ) , DataFlow:: exprNode ( keyArg ) ) and
48
- result = keygen .( OpenSSLOperation ) .getAlgorithmArg ( )
49
- )
50
- }
40
+ override Expr getKeyArg ( ) { result = arg }
51
41
52
- /**
53
- * Gets the argument ingesting a key
54
- * by tracing the context arg back to a context creation
55
- */
56
- Expr getKeyArgFromCtx ( ) {
57
- exists ( Call contextCreationCall |
58
- ctxArgOrRetFlowsToCtxArg ( contextCreationCall , this .getContextArg ( ) ) and
59
- (
60
- contextCreationCall .getTarget ( ) .getName ( ) = "EVP_PKEY_CTX_new" and
61
- result = contextCreationCall .getArgument ( 0 )
62
- or
63
- contextCreationCall .getTarget ( ) .getName ( ) = "EVP_PKEY_CTX_new_from_pkey" and
64
- result = contextCreationCall .getArgument ( 1 )
65
- )
66
- )
67
- }
42
+ override CtxPointerSource getContext ( ) { result = this .( Call ) .getArgument ( 0 ) }
43
+ }
68
44
69
- override Expr getAlgorithmArg ( ) {
70
- // explicit algorithm as argument
71
- this .( Call ) .getTarget ( ) .getName ( ) in [ "EVP_PKEY_sign_init_ex2" , "EVP_PKEY_sign_message_init" ] and
72
- result = this .( Call ) .getArgument ( 1 )
73
- // or
74
- // // algorithm (and key) specified in the context
75
- // this.(Call).getTarget().getName() in ["EVP_PKEY_sign_init", "EVP_PKEY_sign_init_ex"] and
76
- // result = getAlgorithmArgFromCtx()
77
- // or
78
- // // algorithm specified by the key
79
- // this.(Call).getTarget().getName() in ["EVP_DigestSignInit", "EVP_DigestSignInit_ex"] and
80
- // result = getAlgorithmArgFromKey()
81
- // // NOTE: for EVP_SignInit and EVP_SignInit_ex the algorithm is not specified
82
- // // rather the algorithm is specified by the key used for signing later in a final call.
83
- }
45
+ class EvpSignaturePrimaryAlgorithmInitializer extends EvpPrimaryAlgorithmInitializer {
46
+ Expr arg ;
84
47
85
- /**
86
- * Returns the key argument if there is one.
87
- * If the key was provided via the context, we track it to the context.
88
- */
89
- override Expr getKeyArg ( ) {
90
- this .( Call ) .getTarget ( ) .getName ( ) = "EVP_DigestSignInit" and
91
- result = this .( Call ) .getArgument ( 4 )
92
- or
93
- this .( Call ) .getTarget ( ) .getName ( ) = "EVP_DigestSignInit_ex" and
94
- result = this .( Call ) .getArgument ( 5 )
48
+ EvpSignaturePrimaryAlgorithmInitializer ( ) {
49
+ // signature algorithm
50
+ this .( Call ) .getTarget ( ) .getName ( ) in [ "EVP_PKEY_sign_init_ex2" , "EVP_PKEY_sign_message_init" ] and
51
+ arg = this .( Call ) .getArgument ( 1 )
95
52
or
96
- this .( Call ) .getTarget ( ) .getName ( ) .matches ( "EVP_PKEY_%" ) and
97
- result = this .getKeyArgFromCtx ( )
53
+ // configuration through the context argument
54
+ this .( Call ) .getTarget ( ) .getName ( ) in [ "EVP_PKEY_sign_init" , "EVP_PKEY_sign_init_ex" ] and
55
+ arg = this .getContext ( )
98
56
}
99
57
100
- /**
101
- * Signing, verification or unknown.
102
- */
103
- override Crypto:: KeyOperationSubtype getKeyOperationSubtype ( ) {
104
- if this .( Call ) .getTarget ( ) .getName ( ) .toLowerCase ( ) .matches ( "%sign%" )
105
- then result instanceof Crypto:: TSignMode
106
- else
107
- if this .( Call ) .getTarget ( ) .getName ( ) .toLowerCase ( ) .matches ( "%verify%" )
108
- then result instanceof Crypto:: TVerifyMode
109
- else result instanceof Crypto:: TUnknownKeyOperationMode
110
- }
58
+ override Expr getAlgorithmArg ( ) { result = arg }
59
+
60
+ override CtxPointerSource getContext ( ) { result = this .( Call ) .getArgument ( 0 ) }
111
61
}
112
62
113
- class EVP_Signature_Update_Call extends EVPUpdate {
63
+ class EVP_Signature_Update_Call extends EvpUpdate {
114
64
EVP_Signature_Update_Call ( ) {
115
65
this .( Call ) .getTarget ( ) .getName ( ) in [
116
66
"EVP_DigestSignUpdate" , "EVP_SignUpdate" , "EVP_PKEY_sign_message_update"
@@ -121,6 +71,8 @@ class EVP_Signature_Update_Call extends EVPUpdate {
121
71
* Input is the message to sign.
122
72
*/
123
73
override Expr getInputArg ( ) { result = this .( Call ) .getArgument ( 1 ) }
74
+
75
+ override CtxPointerSource getContext ( ) { result = this .( Call ) .getArgument ( 0 ) }
124
76
}
125
77
126
78
/**
@@ -131,22 +83,37 @@ private Expr signatureOperationOutputArg(Call call) {
131
83
if call .getTarget ( ) .getName ( ) = "EVP_SignFinal_ex"
132
84
then result = call .getArgument ( 2 )
133
85
else result = call .getArgument ( 1 )
86
+ ////*******todo get rid of this predicate */
134
87
}
135
88
136
89
/**
137
90
* Base configuration for all EVP signature operations.
138
91
*/
139
- abstract class EVP_Signature_Operation extends EVPOperation , Crypto:: SignatureOperationInstance {
140
- EVP_Signature_Operation ( ) {
92
+ abstract class EvpSignatureOperation extends EvpOperation , Crypto:: SignatureOperationInstance {
93
+ EvpSignatureOperation ( ) {
141
94
this .( Call ) .getTarget ( ) .getName ( ) .matches ( "EVP_%" ) and
142
95
// NULL output argument means the call is to get the size of the signature and such call is not an operation
143
96
(
97
+ // ******TODO review logic
144
98
not exists ( signatureOperationOutputArg ( this ) .getValue ( ) )
145
99
or
146
100
signatureOperationOutputArg ( this ) .getValue ( ) != "0"
147
101
)
148
102
}
149
103
104
+ Expr getHashAlgorithmArg ( ) {
105
+ this .getInitCall ( ) .( EvpHashAlgorithmInitializer ) .getHashAlgorithmArg ( ) = result
106
+ }
107
+
108
+ override Expr getAlgorithmArg ( ) {
109
+ this .getInitCall ( ) .( EvpPrimaryAlgorithmInitializer ) .getAlgorithmArg ( ) = result
110
+ }
111
+
112
+ override Crypto:: AlgorithmValueConsumer getHashAlgorithmValueConsumer ( ) {
113
+ AvcToCallArgFlow:: flow ( result .( OpenSSLAlgorithmValueConsumer ) .getResultNode ( ) ,
114
+ DataFlow:: exprNode ( this .getHashAlgorithmArg ( ) ) )
115
+ }
116
+
150
117
/**
151
118
* Signing, verification or unknown.
152
119
*/
@@ -170,58 +137,74 @@ abstract class EVP_Signature_Operation extends EVPOperation, Crypto::SignatureOp
170
137
* Keys in explicit arguments are found by overriden methods in extending classes.
171
138
*/
172
139
override Crypto:: ConsumerInputDataFlowNode getKeyConsumer ( ) {
173
- result = DataFlow:: exprNode ( this .getInitCall ( ) .getKeyArg ( ) )
140
+ result = DataFlow:: exprNode ( this .getInitCall ( ) .( EvpKeyInitializer ) . getKeyArg ( ) )
174
141
}
175
142
176
143
override Crypto:: ArtifactOutputDataFlowNode getOutputArtifact ( ) {
177
- result = EVPOperation .super .getOutputArtifact ( )
144
+ result = EvpOperation .super .getOutputArtifact ( )
178
145
}
179
146
180
147
override Crypto:: ConsumerInputDataFlowNode getInputConsumer ( ) {
181
- result = EVPOperation .super .getInputConsumer ( )
148
+ result = EvpOperation .super .getInputConsumer ( )
182
149
}
183
150
184
151
/**
185
152
* TODO: only signing operations for now, change when verificaiton is added
186
153
*/
187
154
override Crypto:: ConsumerInputDataFlowNode getSignatureConsumer ( ) { none ( ) }
188
155
}
189
- // class EVP_Signature_Call extends EVPOperation, EVP_Signature_Operation {
190
- // EVP_Signature_Call() { this.(Call).getTarget().getName() in ["EVP_DigestSign", "EVP_PKEY_sign"] }
191
- // /**
192
- // * Output is the signature.
193
- // */
194
- // override Expr getOutputArg() { result = signatureOperationOutputArg(this) }
195
- // /**
196
- // * Input is the message to sign.
197
- // */
198
- // override Expr getInputArg() { result = this.(Call).getArgument(3) }
199
- // }
200
- // class EVP_Signature_Final_Call extends EVPFinal, EVP_Signature_Operation {
201
- // EVP_Signature_Final_Call() {
202
- // this.(Call).getTarget().getName() in [
203
- // "EVP_DigestSignFinal", "EVP_SignFinal_ex", "EVP_SignFinal", "EVP_PKEY_sign_message_final"
204
- // ]
205
- // }
206
- // override Expr getAlgorithmArg() {
207
- // none()
208
- // // // algorithm specified by the key and the key is provided in this operation
209
- // // if this.(Call).getTarget().getName() in ["EVP_SignFinal", "EVP_SignFinal_ex"]
210
- // // then result = getAlgorithmFromKey(this.getKeyConsumer().asExpr())
211
- // // else
212
- // // // or find algorithm in the initialization call
213
- // // result = EVP_Signature_Operation.super.getAlgorithmArg()
214
- // }
215
- // override Crypto::ConsumerInputDataFlowNode getKeyConsumer() {
216
- // // key provided as an argument
217
- // if this.(Call).getTarget().getName() in ["EVP_SignFinal", "EVP_SignFinal_ex"]
218
- // then result = DataFlow::exprNode(this.(Call).getArgument(3))
219
- // else
220
- // // or find key in the initialization call
221
- // result = EVP_Signature_Operation.super.getKeyConsumer()
222
- // }
223
- // /**
224
- // * Output is the signature.
225
- // */
226
- // override Expr getOutputArg() { result = signatureOperationOutputArg(this) }
227
- // }
156
+
157
+ class EVP_Signature_Call extends EvpSignatureOperation {
158
+ EVP_Signature_Call ( ) { this .( Call ) .getTarget ( ) .getName ( ) in [ "EVP_DigestSign" , "EVP_PKEY_sign" ] }
159
+
160
+ /**
161
+ * Output is the signature.
162
+ */
163
+ override Expr getOutputArg ( ) { result = signatureOperationOutputArg ( this ) }
164
+
165
+ override CtxPointerSource getContext ( ) { result = this .( Call ) .getArgument ( 0 ) }
166
+
167
+ /**
168
+ * Input is the message to sign.
169
+ */
170
+ override Expr getInputArg ( ) { result = this .( Call ) .getArgument ( 3 ) }
171
+ }
172
+
173
+ class EVP_Signature_Final_Call extends EVPFinal , EvpSignatureOperation {
174
+ EVP_Signature_Final_Call ( ) {
175
+ this .( Call ) .getTarget ( ) .getName ( ) in [
176
+ "EVP_DigestSignFinal" ,
177
+ "EVP_SignFinal_ex" ,
178
+ "EVP_SignFinal" ,
179
+ "EVP_PKEY_sign_message_final"
180
+ ]
181
+ }
182
+
183
+ override CtxPointerSource getContext ( ) { result = this .( Call ) .getArgument ( 0 ) }
184
+
185
+ //***********TODO: the algorithm arg might nto be the right type, can't use the initializer the same way if there
186
+ // are two initializers for two different algorithms */
187
+ override Expr getAlgorithmArg ( ) {
188
+ this .getInitCall ( ) .( EvpPrimaryAlgorithmInitializer ) .getAlgorithmArg ( ) = result
189
+ // // algorithm specified by the key and the key is provided in this operation
190
+ // if this.(Call).getTarget().getName() in ["EVP_SignFinal", "EVP_SignFinal_ex"]
191
+ // then result = getAlgorithmFromKey(this.getKeyConsumer().asExpr())
192
+ // else
193
+ // // or find algorithm in the initialization call
194
+ // result = EVP_Signature_Operation.super.getAlgorithmArg()
195
+ }
196
+
197
+ override Crypto:: ConsumerInputDataFlowNode getKeyConsumer ( ) {
198
+ // key provided as an argument
199
+ this .( Call ) .getTarget ( ) .getName ( ) in [ "EVP_SignFinal" , "EVP_SignFinal_ex" ] and
200
+ result = DataFlow:: exprNode ( this .( Call ) .getArgument ( 3 ) )
201
+ or
202
+ // or find key in the initialization call
203
+ result = EvpSignatureOperation .super .getKeyConsumer ( )
204
+ }
205
+
206
+ /**
207
+ * Output is the signature.
208
+ */
209
+ override Expr getOutputArg ( ) { result = signatureOperationOutputArg ( this ) }
210
+ }
0 commit comments