|
| 1 | +import cpp |
| 2 | +private import experimental.quantum.Language |
| 3 | +private import experimental.quantum.OpenSSL.LibraryDetector |
| 4 | +private import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants |
| 5 | +private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase |
| 6 | +private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances |
| 7 | + |
| 8 | +abstract class PKeyValueConsumer extends OpenSSLAlgorithmValueConsumer { } |
| 9 | + |
| 10 | +class EVPPKeyAlgorithmConsumer extends PKeyValueConsumer { |
| 11 | + DataFlow::Node valueArgNode; |
| 12 | + DataFlow::Node resultNode; |
| 13 | + |
| 14 | + EVPPKeyAlgorithmConsumer() { |
| 15 | + resultNode.asExpr() = this.(Call) and // in all cases the result is the return |
| 16 | + isPossibleOpenSSLFunction(this.(Call).getTarget()) and |
| 17 | + ( |
| 18 | + // NOTE: some of these consumers are themselves key gen operations, |
| 19 | + // in these cases, the operation will be created separately for the same function. |
| 20 | + this.(Call).getTarget().getName() in [ |
| 21 | + "EVP_PKEY_CTX_new_id", "EVP_PKEY_new_raw_private_key", "EVP_PKEY_new_raw_public_key", |
| 22 | + "EVP_PKEY_new_mac_key" |
| 23 | + ] and |
| 24 | + valueArgNode.asExpr() = this.(Call).getArgument(0) |
| 25 | + or |
| 26 | + this.(Call).getTarget().getName() in [ |
| 27 | + "EVP_PKEY_CTX_new_from_name", "EVP_PKEY_new_raw_private_key_ex", |
| 28 | + "EVP_PKEY_new_raw_public_key_ex", "EVP_PKEY_CTX_ctrl", "EVP_PKEY_CTX_set_group_name" |
| 29 | + ] and |
| 30 | + valueArgNode.asExpr() = this.(Call).getArgument(1) |
| 31 | + or |
| 32 | + // argInd 2 is 'type' which can be RSA, or EC |
| 33 | + // if RSA argInd 3 is the key size, else if EC argInd 3 is the curve name |
| 34 | + // In all other cases there is no argInd 3, and argInd 2 is the algorithm. |
| 35 | + // Since this is a key gen operation, handling the key size should be handled |
| 36 | + // when the operation is again modeled as a key gen operation. |
| 37 | + this.(Call).getTarget().getName() = "EVP_PKEY_Q_keygen" and |
| 38 | + ( |
| 39 | + // Elliptic curve case |
| 40 | + // If the argInd 3 is a derived type (pointer or array) then assume it is a curve name |
| 41 | + if this.(Call).getArgument(3).getType().getUnderlyingType() instanceof DerivedType |
| 42 | + then valueArgNode.asExpr() = this.(Call).getArgument(3) |
| 43 | + else |
| 44 | + // All other cases |
| 45 | + valueArgNode.asExpr() = this.(Call).getArgument(2) |
| 46 | + ) |
| 47 | + ) |
| 48 | + } |
| 49 | + |
| 50 | + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { |
| 51 | + exists(OpenSSLAlgorithmInstance i | i.getAVC() = this and result = i) |
| 52 | + } |
| 53 | + |
| 54 | + override DataFlow::Node getResultNode() { result = resultNode } |
| 55 | + |
| 56 | + override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode } |
| 57 | +} |
0 commit comments