Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
5f355c7
Add first sample JCA encryption model
knewbury01 Feb 4, 2025
86e51da
Improve JCA aes alg model, add test
knewbury01 Feb 5, 2025
efcf7ea
Add broken crypto query
knewbury01 Feb 5, 2025
2e12bb5
Merge branch 'nic/crypto-test' into knewbury01/JCA-sample
knewbury01 Feb 6, 2025
60d931a
Update progress on JCA
knewbury01 Feb 7, 2025
6005437
Update JCA model with flow to call as AESuse and format JCA model
knewbury01 Feb 10, 2025
9c8ade7
Merge branch 'nic/crypto-test' into knewbury01/JCA-sample
knewbury01 Feb 10, 2025
59208bd
Update JCA model to use shared lib
knewbury01 Feb 10, 2025
1a12fb3
Update JCA model, refactor modes
knewbury01 Feb 10, 2025
4d44755
Refactor Model and CBOM print queries
nicolaswill Feb 11, 2025
874e3b5
Modify model to use newtypes, expand modeling
nicolaswill Feb 12, 2025
b777a22
Expand model and specialize newtype relations
nicolaswill Feb 14, 2025
df01fa7
Expand model and JCA modeling
nicolaswill Feb 16, 2025
8707e4d
Continue Artifact data-flow WIP
nicolaswill Feb 18, 2025
3871c6a
Adding support for encryption operation detection.
bdrodes Feb 18, 2025
9ee4a7a
Adding a sketch for a CipherOperation concept to model encryption/dec…
bdrodes Feb 20, 2025
83dc5b9
Fixing type bug
bdrodes Feb 20, 2025
011ed3f
Simplifying additional flow step logic.
bdrodes Feb 20, 2025
9ac9252
Adding a todo
bdrodes Feb 20, 2025
86cab46
Misc. updates to support all JCA cipher operations, including wrap, u…
bdrodes Feb 21, 2025
2b0b927
Add Nonce association to Operation, update graph
nicolaswill Feb 24, 2025
eb91ecf
Add generic artifact data-flow
nicolaswill Feb 25, 2025
f55f27b
Expand handling of generic artifact sources
nicolaswill Feb 25, 2025
04f4683
Rewrite handling of known unknowns and data-flow
nicolaswill Feb 27, 2025
ef0614a
Restore removed node location output
nicolaswill Feb 27, 2025
0354afc
Make ArtifactConsumers instances of some Artifacts
nicolaswill Feb 27, 2025
cf33cf7
Add input and output nodes and fix cross product
nicolaswill Feb 28, 2025
627790f
Clean up consumer and instance interfaces
nicolaswill Mar 3, 2025
076f531
Proof-of-concept query for InsecureOrUnknownNonceAtOperation
bdrodes Mar 3, 2025
14cb2bb
Updates to insecure or unknown nonce at operation.
bdrodes Mar 3, 2025
2ee1681
Adding a proof-of-concept PossibleReusedNonce query.
bdrodes Mar 3, 2025
8865d89
Removing old ReusedNonce query.
bdrodes Mar 3, 2025
cce5f24
Initial OpenSSL modeling work.
bdrodes Mar 4, 2025
de3ff45
Misc updates for OpenSSL modeling to trace algorithm literals to know…
bdrodes Mar 5, 2025
6083df2
Completed tying algorithm instances to consumers. Now the model shoul…
bdrodes Mar 5, 2025
b9bd199
Regression fixes for JCA
bdrodes Mar 6, 2025
32d29ff
Changed casing on TCipherType, Added some initial fixes for hash supp…
bdrodes Mar 7, 2025
cf72fde
Fixing cross product in getPropertyAsGraphString (parameter `root` no…
bdrodes Mar 7, 2025
47affa0
Restore location output for nodes
nicolaswill Mar 7, 2025
bac0a63
Initial hash models for openssl.
bdrodes Mar 7, 2025
64241ca
Merge branch 'brodes/cipher_operation' of https://github.com/nicolasw…
bdrodes Mar 7, 2025
d99812a
Adding GOSTHash to THashType.
bdrodes Mar 10, 2025
3316d61
Ctx flow comments.
bdrodes Mar 10, 2025
6a4659f
Updating known constants for OpenSSL to handle direct algorithm gette…
bdrodes Mar 10, 2025
bd07b8a
Making getter flow through 'copy' more general (copy can appear in an…
bdrodes Mar 10, 2025
4518086
Getting rid of commented out code.
bdrodes Mar 10, 2025
0672027
Tracing new notion of known getters, which now includes direct getter…
bdrodes Mar 10, 2025
73368ea
Adding hashes to openssl library import
bdrodes Mar 10, 2025
fe52351
Stubbing out hash operation node, borrowing from cipher operaiton node
bdrodes Mar 10, 2025
036035b
Adding modeling for OpenSSL random number generation.
bdrodes Mar 10, 2025
c83cb53
Adding an instantiation of the additional flow step class to automati…
bdrodes Mar 10, 2025
f72efa6
Uncommenting out generic dataflow
bdrodes Mar 10, 2025
ae574f7
Resolving hash and cipher types for openssl not using literals but Kn…
bdrodes Mar 11, 2025
f69b057
Updating OpenSSLKnownAlgorithmConstants.qll (a few bugs) and also enf…
bdrodes Mar 11, 2025
085e8d4
Hash nodes have instances.
bdrodes Mar 11, 2025
44b1e92
commenting out hash size for now, TODO
bdrodes Mar 11, 2025
7757279
Adding a KDF algorithm getter.
bdrodes Mar 11, 2025
d988afd
Adding an EVP_AASYM_CIPHER_fetch getter.
bdrodes Mar 11, 2025
a9458ba
Formatting, removing dead comments,
bdrodes Mar 11, 2025
c98e6d7
Adding a stub EVP_CIpher_Operation for EVP_PKEY, this probably should…
bdrodes Mar 11, 2025
71eae39
Adding missing block modes.
bdrodes Mar 11, 2025
8a7671d
Adding block mode models to openssl.
bdrodes Mar 11, 2025
95607c5
Refactor instances and consumers + add JCA hashes
nicolaswill Mar 18, 2025
63aaebb
.
bdrodes Mar 19, 2025
d18dac0
Add JCA key (generation) modelling
nicolaswill Mar 20, 2025
b695641
Add signature to cipher operation
bdrodes Mar 20, 2025
9278a41
Merge branch 'brodes/cipher_operation' of https://github.com/nicolasw…
bdrodes Mar 20, 2025
fb7c003
Add initial MAC support for JCA, refactor hashes
nicolaswill Mar 22, 2025
e9c3e14
Merge branch 'brodes/cipher_operation' of https://github.com/nicolasw…
nicolaswill Mar 22, 2025
9cd0340
Remove rankdir=LR; from DOT output
nicolaswill Mar 26, 2025
bec69ca
Refactor consumer and generic source model
nicolaswill Mar 26, 2025
ac96649
Misc. modifications to support elliptic curves and hooking them up to…
bdrodes Apr 1, 2025
5050758
Refactor output artifact type
nicolaswill Apr 2, 2025
66a6029
Merge branch 'brodes/cipher_operation' into brodes/elliptic_curves
bdrodes Apr 2, 2025
697c9f0
Elliptic curve AVCs are incorrect, but I'm not sure how to fix them g…
bdrodes Apr 4, 2025
69429a3
Merge pull request #9 from nicolaswill/brodes/elliptic_curves
bdrodes Apr 4, 2025
a2fe19a
Initial progress on key agreement.
bdrodes Apr 4, 2025
b9d0abd
Move CipherOperation into KeyOperation, refactor
nicolaswill Apr 9, 2025
1958c19
Reimplement EC, MAC, key creation logic + consumer
nicolaswill Apr 16, 2025
28ccc83
Adding a means to distinguish asymmetric algorithms.
bdrodes Apr 28, 2025
fdd09a4
Adding a new means for determining if there is nonce reuse.
bdrodes Apr 28, 2025
7b7ed61
Adding an asymmetric algorithm slice.
bdrodes Apr 28, 2025
1fd7643
Adding example slicing queries.
bdrodes Apr 28, 2025
5a8bffa
Removing old asymmetric algorithm slice
bdrodes Apr 28, 2025
ce3eabf
Updating model to support slicing.
bdrodes Apr 28, 2025
219476c
Adding KDF iteration count inventory filters.
bdrodes Apr 28, 2025
ac3675b
Typo fix
bdrodes Apr 28, 2025
ac798f2
Cipher Algorithm Slices
bdrodes Apr 28, 2025
7f24a25
Add modelling for JCA key gen cipher algorithm
nicolaswill Apr 30, 2025
9c87ad8
Merge branch 'brodes/key_agreement' of https://github.com/nicolaswill…
nicolaswill Apr 30, 2025
dd2f53f
Merge pull request #10 from nicolaswill/brodes/key_agreement
nicolaswill Apr 30, 2025
2b1b90c
Merge pull request #4 from nicolaswill/brodes/cipher_operation
nicolaswill Apr 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 110 additions & 1 deletion cpp/ql/lib/experimental/Quantum/Language.qll
Original file line number Diff line number Diff line change
@@ -1,12 +1,121 @@
private import codeql.cryptography.Model
import semmle.code.cpp.ir.IR
import semmle.code.cpp.security.FlowSources as FlowSources
private import cpp as Lang

module CryptoInput implements InputSig<Lang::Location> {
class DataFlowNode = DataFlow::Node;

class LocatableElement = Lang::Locatable;

class UnknownLocation = Lang::UnknownDefaultLocation;

LocatableElement dfn_to_element(DataFlow::Node node) {
result = node.asExpr() or
result = node.asParameter() or
result = node.asVariable()
}
}

module Crypto = CryptographyBase<Lang::Location, CryptoInput>;

import OpenSSL
/**
* Artifact output to node input configuration
*/
abstract class AdditionalFlowInputStep extends DataFlow::Node {
abstract DataFlow::Node getOutput();

final DataFlow::Node getInput() { result = this }
}

/**
* Generic data source to node input configuration
*/
module GenericDataSourceUniversalFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source = any(Crypto::GenericDataSourceInstance i).getOutputNode()
}

predicate isSink(DataFlow::Node sink) {
sink = any(Crypto::FlowAwareElement other).getInputNode()
}

predicate isBarrierOut(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getInputNode()
}

predicate isBarrierIn(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getOutputNode()
}

predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.(AdditionalFlowInputStep).getOutput() = node2
}
}

// // // TODO: I think this will be inefficient, no?
// // class ConstantDataSource extends Crypto::GenericConstantOrAllocationSource instanceof Literal {
// // override DataFlow::Node getOutputNode() {
// // result.asExpr() = this
// // }
// // override predicate flowsTo(Crypto::FlowAwareElement other) {
// // // TODO: separate config to avoid blowing up data-flow analysis
// // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode())
// // }
// // override string getAdditionalDescription() { result = this.toString() }
// // }
// /**
// * Definitions of various generic data sources
// */
// // final class DefaultFlowSource = SourceNode;
// // final class DefaultRemoteFlowSource = RemoteFlowSource;
// // class GenericLocalDataSource extends Crypto::GenericLocalDataSource {
// // GenericLocalDataSource() {
// // any(DefaultFlowSource src | not src instanceof DefaultRemoteFlowSource).asExpr() = this
// // }
// // override DataFlow::Node getOutputNode() { result.asExpr() = this }
// // override predicate flowsTo(Crypto::FlowAwareElement other) {
// // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode())
// // }
// // override string getAdditionalDescription() { result = this.toString() }
// // }
// // class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource {
// // GenericRemoteDataSource() { any(DefaultRemoteFlowSource src).asExpr() = this }
// // override DataFlow::Node getOutputNode() { result.asExpr() = this }
// // override predicate flowsTo(Crypto::FlowAwareElement other) {
// // GenericDataSourceUniversalFlow::flow(this.getOutputNode(), other.getInputNode())
// // }
// // override string getAdditionalDescription() { result = this.toString() }
// // }
// module GenericDataSourceUniversalFlow = DataFlow::Global<GenericDataSourceUniversalFlowConfig>;
module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source = any(Crypto::ArtifactInstance artifact).getOutputNode()
}

predicate isSink(DataFlow::Node sink) {
sink = any(Crypto::FlowAwareElement other).getInputNode()
}

predicate isBarrierOut(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getInputNode()
}

predicate isBarrierIn(DataFlow::Node node) {
node = any(Crypto::FlowAwareElement element).getOutputNode()
}

predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.(AdditionalFlowInputStep).getOutput() = node2
}
}

module ArtifactUniversalFlow = DataFlow::Global<ArtifactUniversalFlowConfig>;

abstract class CipherOutputArtifact extends Crypto::KeyOperationOutputArtifactInstance {
override predicate flowsTo(Crypto::FlowAwareElement other) {
ArtifactUniversalFlow::flow(this.getOutputNode(), other.getInputNode())
}
}

import OpenSSL.OpenSSL
102 changes: 0 additions & 102 deletions cpp/ql/lib/experimental/Quantum/OpenSSL.qll

This file was deleted.

97 changes: 97 additions & 0 deletions cpp/ql/lib/experimental/Quantum/OpenSSL/CtxFlow.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* In OpenSSL, flow between 'context' parameters is often used to
* store state/config of how an operation will eventually be performed.
* Tracing algorithms and configurations to operations therefore
* requires tracing context parameters for many OpenSSL apis.
*
* This library provides a dataflow analysis to track context parameters
* between any two functions accepting openssl context parameters.
* The dataflow takes into consideration flowing through duplication and copy calls
* as well as flow through flow killers (free/reset calls).
*
* TODO: we may need to revisit 'free' as a dataflow killer, depending on how
* we want to model use after frees.
*
* This library also provides classes to represent context Types and relevant
* arguments/expressions.
*/

import semmle.code.cpp.dataflow.new.DataFlow

class CTXType extends Type {
CTXType() {
// TODO: should we limit this to an openssl path?
this.getUnspecifiedType().stripType().getName().matches("evp_%ctx_%st")
}
}

class CTXPointerExpr extends Expr {
CTXPointerExpr() {
this.getType() instanceof CTXType and
this.getType() instanceof PointerType
}
}

class CTXPointerArgument extends CTXPointerExpr {
CTXPointerArgument() { exists(Call c | c.getAnArgument() = this) }

Call getCall() { result.getAnArgument() = this }
}

class CTXClearCall extends Call {
CTXClearCall() {
this.getTarget().getName().toLowerCase().matches(["%free%", "%reset%"]) and
this.getAnArgument() instanceof CTXPointerArgument
}
}

class CTXCopyOutArgCall extends Call {
CTXCopyOutArgCall() {
this.getTarget().getName().toLowerCase().matches(["%copy%"]) and
this.getAnArgument() instanceof CTXPointerArgument
}
}

class CTXCopyReturnCall extends Call {
CTXCopyReturnCall() {
this.getTarget().getName().toLowerCase().matches(["%dup%"]) and
this.getAnArgument() instanceof CTXPointerArgument and
this instanceof CTXPointerExpr
}
}

module OpenSSLCTXArgumentFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CTXPointerArgument }

predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof CTXPointerArgument }

predicate isBarrier(DataFlow::Node node) {
exists(CTXClearCall c | c.getAnArgument() = node.asExpr())
}

predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(CTXCopyOutArgCall c |
c.getAnArgument() = node1.asExpr() and
c.getAnArgument() = node2.asExpr() and
node1.asExpr() != node2.asExpr() and
node2.asExpr().getType() instanceof CTXType
)
or
exists(CTXCopyReturnCall c |
c.getAnArgument() = node1.asExpr() and
c = node2.asExpr() and
node1.asExpr() != node2.asExpr() and
node2.asExpr().getType() instanceof CTXType
)
}
}

module OpenSSLCTXArgumentFlow = DataFlow::Global<OpenSSLCTXArgumentFlowConfig>;

predicate ctxFlowsTo(CTXPointerArgument source, CTXPointerArgument sink) {
exists(DataFlow::Node a, DataFlow::Node b |
OpenSSLCTXArgumentFlow::flow(a, b) and
a.asExpr() = source and
b.asExpr() = sink
)
}
25 changes: 25 additions & 0 deletions cpp/ql/lib/experimental/Quantum/OpenSSL/EVPCipherConsumers.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import EVPCipherInitializer
import EVPCipherOperation
import EVPCipherAlgorithmSource

class EVP_Cipher_Initializer_Algorithm_Consumer extends Crypto::AlgorithmConsumer instanceof EVPCipherInitializerAlgorithmArgument
{
override DataFlow::Node getInputNode() { result.asExpr() = this }

override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
result.(KnownOpenSSLCipherConstantAlgorithmInstance).getConsumer() = this
}
}

// //TODO: need a key consumer
// class EVP_Initializer_Key_Consumer extends Crypto::KeyConsumer instanceof EVP_Cipher_Inititalizer isntanceof InitializerKeyArgument{
// }
class EVP_Cipher_Initializer_IV_Consumer extends Crypto::NonceArtifactConsumer instanceof EVPCipherInitializerIVArgument
{
override DataFlow::Node getInputNode() { result.asExpr() = this }
}

class EVP_Cipher_Input_Consumer extends Crypto::CipherInputConsumer instanceof EVPCipherInputArgument
{
override DataFlow::Node getInputNode() { result.asExpr() = this }
}
Loading