44
55private import experimental.quantum.Language
66private import OpenSSLOperationBase
7+ private import experimental.quantum.OpenSSL.AvcFlow
78private import experimental.quantum.OpenSSL.CtxFlow
89private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
910private import experimental.quantum.OpenSSL.Operations.OpenSSLOperations
1011
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 )
1422 }
1523
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 ) }
1727}
1828
19- module OpenSSLKeyGenToArgFlow = TaintTracking:: Global< OpenSSLKeyGenToArgConfig > ;
29+ class EvpSignatureKeyInitializer extends EvpKeyInitializer {
30+ Expr arg ;
2031
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 )
2938 }
3039
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 }
5141
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+ }
6844
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 ;
8447
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 )
9552 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 ( )
9856 }
9957
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 ) }
11161}
11262
113- class EVP_Signature_Update_Call extends EVPUpdate {
63+ class EVP_Signature_Update_Call extends EvpUpdate {
11464 EVP_Signature_Update_Call ( ) {
11565 this .( Call ) .getTarget ( ) .getName ( ) in [
11666 "EVP_DigestSignUpdate" , "EVP_SignUpdate" , "EVP_PKEY_sign_message_update"
@@ -121,6 +71,8 @@ class EVP_Signature_Update_Call extends EVPUpdate {
12171 * Input is the message to sign.
12272 */
12373 override Expr getInputArg ( ) { result = this .( Call ) .getArgument ( 1 ) }
74+
75+ override CtxPointerSource getContext ( ) { result = this .( Call ) .getArgument ( 0 ) }
12476}
12577
12678/**
@@ -131,22 +83,37 @@ private Expr signatureOperationOutputArg(Call call) {
13183 if call .getTarget ( ) .getName ( ) = "EVP_SignFinal_ex"
13284 then result = call .getArgument ( 2 )
13385 else result = call .getArgument ( 1 )
86+ ////*******todo get rid of this predicate */
13487}
13588
13689/**
13790 * Base configuration for all EVP signature operations.
13891 */
139- abstract class EVP_Signature_Operation extends EVPOperation , Crypto:: SignatureOperationInstance {
140- EVP_Signature_Operation ( ) {
92+ abstract class EvpSignatureOperation extends EvpOperation , Crypto:: SignatureOperationInstance {
93+ EvpSignatureOperation ( ) {
14194 this .( Call ) .getTarget ( ) .getName ( ) .matches ( "EVP_%" ) and
14295 // NULL output argument means the call is to get the size of the signature and such call is not an operation
14396 (
97+ // ******TODO review logic
14498 not exists ( signatureOperationOutputArg ( this ) .getValue ( ) )
14599 or
146100 signatureOperationOutputArg ( this ) .getValue ( ) != "0"
147101 )
148102 }
149103
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+
150117 /**
151118 * Signing, verification or unknown.
152119 */
@@ -170,58 +137,74 @@ abstract class EVP_Signature_Operation extends EVPOperation, Crypto::SignatureOp
170137 * Keys in explicit arguments are found by overriden methods in extending classes.
171138 */
172139 override Crypto:: ConsumerInputDataFlowNode getKeyConsumer ( ) {
173- result = DataFlow:: exprNode ( this .getInitCall ( ) .getKeyArg ( ) )
140+ result = DataFlow:: exprNode ( this .getInitCall ( ) .( EvpKeyInitializer ) . getKeyArg ( ) )
174141 }
175142
176143 override Crypto:: ArtifactOutputDataFlowNode getOutputArtifact ( ) {
177- result = EVPOperation .super .getOutputArtifact ( )
144+ result = EvpOperation .super .getOutputArtifact ( )
178145 }
179146
180147 override Crypto:: ConsumerInputDataFlowNode getInputConsumer ( ) {
181- result = EVPOperation .super .getInputConsumer ( )
148+ result = EvpOperation .super .getInputConsumer ( )
182149 }
183150
184151 /**
185152 * TODO: only signing operations for now, change when verificaiton is added
186153 */
187154 override Crypto:: ConsumerInputDataFlowNode getSignatureConsumer ( ) { none ( ) }
188155}
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