diff --git a/java/ql/lib/experimental/Quantum/JCA.qll b/java/ql/lib/experimental/Quantum/JCA.qll index 4a9082bf91c2..2bce7fa68438 100644 --- a/java/ql/lib/experimental/Quantum/JCA.qll +++ b/java/ql/lib/experimental/Quantum/JCA.qll @@ -6,6 +6,10 @@ import semmle.code.java.controlflow.Dominance module JCAModel { import Language + abstract class JCAAlgorithmInstance extends Crypto::AlgorithmInstance { + abstract Crypto::AlgorithmValueConsumer getConsumer(); + } + // TODO: Verify that the PBEWith% case works correctly bindingset[algo] predicate cipher_names(string algo) { @@ -49,6 +53,9 @@ module JCAModel { kdf.toUpperCase().matches(["PBKDF2With%", "PBEWith%"].toUpperCase()) } + bindingset[name] + predicate elliptic_curve_names(string name) { Crypto::isEllipticCurveAlgorithmName(name) } + bindingset[name] Crypto::TKeyDerivationType kdf_name_to_kdf_type(string name, string withSubstring) { name.matches("PBKDF2With%") and @@ -110,6 +117,12 @@ module JCAModel { string getPadding() { result = this.getValue().splitAt("/", 2) } } + class EllipticCurveStringLiteral extends StringLiteral { + EllipticCurveStringLiteral() { elliptic_curve_names(this.getValue()) } + + string getStandardEllipticCurveName() { result = this.getValue() } + } + class CipherGetInstanceCall extends Call { CipherGetInstanceCall() { this.getCallee().hasQualifiedName("javax.crypto", "Cipher", "getInstance") @@ -139,9 +152,9 @@ module JCAModel { } /** - * Data-flow configuration modelling flow from a cipher string literal to a `CipherGetInstanceCall` argument. + * Data-flow configuration modelling flow from a cipher string literal to a value consumer argument. */ - private module AlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + private module CipherAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CipherStringLiteral } predicate isSink(DataFlow::Node sink) { @@ -149,7 +162,22 @@ module JCAModel { } } - module AlgorithmStringToFetchFlow = TaintTracking::Global; + module CipherAlgorithmStringToFetchFlow = + TaintTracking::Global; + + /** + * Data-flow configuration modelling flow from a cipher string literal to a value consumer argument. + */ + private module EllipticCurveAlgorithmStringToFetchConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof EllipticCurveStringLiteral } + + predicate isSink(DataFlow::Node sink) { + exists(Crypto::AlgorithmValueConsumer consumer | sink = consumer.getInputNode()) + } + } + + module EllipticCurveAlgorithmStringToFetchFlow = + TaintTracking::Global; /** * Note: padding and a mode of operation will only exist when the padding / mode (*and its type*) are determinable. @@ -160,8 +188,8 @@ module JCAModel { * * TODO: Model the case of relying on a provider default, but alert on it as a bad practice. */ - class CipherStringLiteralPaddingAlgorithmInstance extends CipherStringLiteralAlgorithmInstance, - Crypto::PaddingAlgorithmInstance instanceof CipherStringLiteral + class CipherStringLiteralPaddingAlgorithmInstance extends JCAAlgorithmInstance, + CipherStringLiteralAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof CipherStringLiteral { CipherStringLiteralPaddingAlgorithmInstance() { exists(super.getPadding()) } // TODO: provider defaults @@ -183,8 +211,8 @@ module JCAModel { } } - class CipherStringLiteralModeAlgorithmInstance extends CipherStringLiteralPaddingAlgorithmInstance, - Crypto::ModeOfOperationAlgorithmInstance instanceof CipherStringLiteral + class CipherStringLiteralModeAlgorithmInstance extends JCAAlgorithmInstance, + CipherStringLiteralPaddingAlgorithmInstance, Crypto::ModeOfOperationAlgorithmInstance instanceof CipherStringLiteral { CipherStringLiteralModeAlgorithmInstance() { exists(super.getMode()) } // TODO: provider defaults @@ -216,15 +244,141 @@ module JCAModel { } } - class CipherStringLiteralAlgorithmInstance extends Crypto::CipherAlgorithmInstance instanceof CipherStringLiteral + class KeyGeneratorGetInstanceCall extends MethodCall { + KeyGeneratorGetInstanceCall() { + this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "getInstance") + or + this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "getInstance") + } + + Expr getAlgorithmArg() { result = super.getArgument(0) } + } + + // For general elliptic curves, getInstance("EC") is used + // and java.security.spec.ECGenParameterSpec("") is what sets the specific curve. + // The result of ECGenParameterSpec is passed to KeyPairGenerator.initialize + // If the curve is not specified, the default is used. + // We would trace the use of this inside a KeyPairGenerator.initialize + class ECGenParameterSpecCall extends ClassInstanceExpr { + ECGenParameterSpecCall() { + this.(ClassInstanceExpr) + .getConstructedType() + .hasQualifiedName("java.security.spec", "ECGenParameterSpec") + } + + Expr getAlgorithmArg() { result = super.getArgument(0) } + + KeyPairGeneratorInitializeCall getInitializeConsumerCall() { + exists(DataFlow::Node sink | + ECGenParameterSpecCallToInitializeFlow::flow(DataFlow::exprNode(this), sink) and + result.getAnArgument() = sink.asExpr() + ) + } + } + + abstract class KeyGenAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { + // abstract predicate flowsToKeyGenerateCallQualifier(KeyGeneratorGenerateCall sink); + abstract DataFlow::Node getResultNode(); + } + + class KeyPairGeneratorInitializeCall extends MethodCall { + KeyPairGeneratorInitializeCall() { + this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "initialize") + } + + Expr getKeyArg() { + result = this.getArgument(0) and + result.getType() instanceof IntegralType + } + } + + private module ECGenParameterSpecCallToInitializeConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ECGenParameterSpecCall } + + predicate isSink(DataFlow::Node sink) { + exists(KeyPairGeneratorInitializeCall c | c.getAnArgument() = sink.asExpr()) + } + } + + module ECGenParameterSpecCallToInitializeFlow = + DataFlow::Global; + + class ECGenParameterSpecAlgorithmValueConsumer extends KeyGenAlgorithmValueConsumer { + ECGenParameterSpecCall call; + + ECGenParameterSpecAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } + + override DataFlow::Node getResultNode() { + // Traversing to the initialilzer directly and calling this the 'result' + // to simplify the trace. In theory you would trace from the call + // through the initializer, but we already have a trace to the initializer + // so using this instead of altering/creating data flow configs. + call.getInitializeConsumerCall().getQualifier() = result.asExpr() + } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + result.(JCAAlgorithmInstance).getConsumer() = this + } + } + + class KeyGeneratorGetInstanceAlgorithmValueConsumer extends KeyGenAlgorithmValueConsumer { + KeyGeneratorGetInstanceCall call; + + KeyGeneratorGetInstanceAlgorithmValueConsumer() { this = call.getAlgorithmArg() } + + override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } + + override DataFlow::Node getResultNode() { result.asExpr() = call } + + override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { + // The source is any instance whose consumer is this + result.(JCAAlgorithmInstance).getConsumer() = this + } + } + + class EllipticCurveStringLiteralAlgorithmInstance extends JCAAlgorithmInstance, + Crypto::EllipticCurveAlgorithmInstance instanceof StringLiteral + { + Crypto::AlgorithmValueConsumer consumer; + + EllipticCurveStringLiteralAlgorithmInstance() { + // Trace a known elliptic curve algorithm string literal to a key gen consumer + EllipticCurveAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), + consumer.getInputNode()) + } + + override Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } + + override string getRawEllipticCurveAlgorithmName() { result = super.getValue() } + + override string getStandardCurveName() { result = this.getRawEllipticCurveAlgorithmName() } + + override Crypto::TEllipticCurveType getEllipticCurveFamily() { + Crypto::isEllipticCurveAlgorithm(this.getRawEllipticCurveAlgorithmName(), _, result) + } + + override string getKeySize() { + exists(int keySize | + Crypto::isEllipticCurveAlgorithm(this.getRawEllipticCurveAlgorithmName(), keySize, _) and + result = keySize.toString() + ) + } + } + + class CipherStringLiteralAlgorithmInstance extends JCAAlgorithmInstance, + Crypto::CipherAlgorithmInstance instanceof CipherStringLiteral { + // NOTE: this consumer is generic, but cipher algorithms can be consumed + // by getInstance as well as key generation Crypto::AlgorithmValueConsumer consumer; CipherStringLiteralAlgorithmInstance() { - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) + CipherAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) } - Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } + override Crypto::AlgorithmValueConsumer getConsumer() { result = consumer } override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { result = this // TODO: provider defaults @@ -302,8 +456,8 @@ module JCAModel { override int getDigestLength() { exists(hash_name_to_hash_type(hashName, result)) } } - class OAEPPaddingAlgorithmInstance extends Crypto::OAEPPaddingAlgorithmInstance, - CipherStringLiteralPaddingAlgorithmInstance + class OAEPPaddingAlgorithmInstance extends JCAAlgorithmInstance, + Crypto::OAEPPaddingAlgorithmInstance, CipherStringLiteralPaddingAlgorithmInstance { override Crypto::HashAlgorithmInstance getOAEPEncodingHashAlgorithm() { result = this } @@ -323,7 +477,7 @@ module JCAModel { override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } CipherStringLiteral getOrigin(string value) { - AlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), + CipherAlgorithmStringToFetchFlow::flow(DataFlow::exprNode(result), DataFlow::exprNode(this.(Expr).getAChildExpr*())) and value = result.getValue() } @@ -651,7 +805,8 @@ module JCAModel { module KnownHashAlgorithmLiteralToMessageDigestFlow = DataFlow::Global; - class KnownHashAlgorithm extends Crypto::HashAlgorithmInstance instanceof StringLiteral { + class KnownHashAlgorithm extends JCAAlgorithmInstance, Crypto::HashAlgorithmInstance instanceof StringLiteral + { MessageDigestAlgorithmValueConsumer consumer; KnownHashAlgorithm() { @@ -660,7 +815,7 @@ module JCAModel { consumer.getInputNode()) } - MessageDigestAlgorithmValueConsumer getConsumer() { result = consumer } + override MessageDigestAlgorithmValueConsumer getConsumer() { result = consumer } override string getRawHashAlgorithmName() { result = this.(StringLiteral).getValue() } @@ -733,22 +888,10 @@ module JCAModel { } } - class KeyGeneratorCallAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { - KeyGeneratorGetInstanceCall call; - - KeyGeneratorCallAlgorithmValueConsumer() { this = call.getAlgorithmArg() } - - override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this } - - override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { - result.(CipherStringLiteralAlgorithmInstance).getConsumer() = this - } - } - // flow from instance created by getInstance to generateKey - module KeyGeneratorGetInstanceToGenerateConfig implements DataFlow::ConfigSig { + module KeyGeneratorAlgValueConsumerToGenerateConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { - exists(KeyGeneratorGetInstanceCall call | src.asExpr() = call) + exists(KeyGenAlgorithmValueConsumer consumer | consumer.getResultNode() = src) } predicate isSink(DataFlow::Node sink) { @@ -756,23 +899,8 @@ module JCAModel { } } - module KeyGeneratorGetInstanceToGenerateFlow = - DataFlow::Global; - - class KeyGeneratorGetInstanceCall extends MethodCall { - KeyGeneratorGetInstanceCall() { - this.getCallee().hasQualifiedName("javax.crypto", "KeyGenerator", "getInstance") - or - this.getCallee().hasQualifiedName("java.security", "KeyPairGenerator", "getInstance") - } - - Expr getAlgorithmArg() { result = super.getArgument(0) } - - predicate flowsToKeyGenerateCallQualifier(KeyGeneratorGenerateCall sink) { - KeyGeneratorGetInstanceToGenerateFlow::flow(DataFlow::exprNode(this), - DataFlow::exprNode(sink.(MethodCall).getQualifier())) - } - } + module KeyGeneratorAlgValueConsumerToGenerateFlow = + DataFlow::Global; class KeyGeneratorGenerateCall extends Crypto::KeyGenerationOperationInstance instanceof MethodCall { @@ -791,8 +919,10 @@ module JCAModel { override Crypto::KeyArtifactType getOutputKeyType() { result = type } override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() { - exists(KeyGeneratorGetInstanceCall getInstance | - getInstance.flowsToKeyGenerateCallQualifier(this) and result = getInstance.getAlgorithmArg() + exists(KeyGenAlgorithmValueConsumer consumer | + KeyGeneratorAlgValueConsumerToGenerateFlow::flow(consumer.getResultNode(), + DataFlow::exprNode(this.(Call).getQualifier())) and + result = consumer ) } @@ -879,7 +1009,8 @@ module JCAModel { module MACInitCallToMACOperationFlow = DataFlow::Global; - class KnownMACAlgorithm extends Crypto::MACAlgorithmInstance instanceof StringLiteral { + class KnownMACAlgorithm extends JCAAlgorithmInstance, Crypto::MACAlgorithmInstance instanceof StringLiteral + { MACGetInstanceAlgorithmValueConsumer consumer; KnownMACAlgorithm() { @@ -887,7 +1018,7 @@ module JCAModel { MACKnownAlgorithmToConsumerFlow::flow(DataFlow::exprNode(this), consumer.getInputNode()) } - MACGetInstanceAlgorithmValueConsumer getConsumer() { result = consumer } + override MACGetInstanceAlgorithmValueConsumer getConsumer() { result = consumer } override string getRawMACAlgorithmName() { result = super.getValue() } @@ -1039,7 +1170,8 @@ module JCAModel { } } - class KDFAlgorithmStringLiteral extends Crypto::KeyDerivationAlgorithmInstance instanceof StringLiteral + class KDFAlgorithmStringLiteral extends JCAAlgorithmInstance, + Crypto::KeyDerivationAlgorithmInstance instanceof StringLiteral { SecretKeyFactoryKDFAlgorithmValueConsumer consumer; @@ -1054,10 +1186,10 @@ module JCAModel { result = kdf_name_to_kdf_type(super.getValue(), _) } - SecretKeyFactoryKDFAlgorithmValueConsumer getConsumer() { result = consumer } + override SecretKeyFactoryKDFAlgorithmValueConsumer getConsumer() { result = consumer } } - class PBKDF2AlgorithmStringLiteral extends KDFAlgorithmStringLiteral, + class PBKDF2AlgorithmStringLiteral extends JCAAlgorithmInstance, KDFAlgorithmStringLiteral, Crypto::PBKDF2AlgorithmInstance, Crypto::HMACAlgorithmInstance, Crypto::HashAlgorithmInstance, Crypto::AlgorithmValueConsumer { @@ -1158,4 +1290,5 @@ module JCAModel { override string getIterationCountFixed() { none() } } + // TODO: flow the GCGenParametersSpecCall to an init, and the init to the operations } diff --git a/java/ql/lib/experimental/Quantum/Language.qll b/java/ql/lib/experimental/Quantum/Language.qll index 9e27fedf7faf..8027ef33df7b 100644 --- a/java/ql/lib/experimental/Quantum/Language.qll +++ b/java/ql/lib/experimental/Quantum/Language.qll @@ -95,6 +95,14 @@ class GenericRemoteDataSource extends Crypto::GenericRemoteDataSource { } class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceof Literal { + ConstantDataSource() { + // TODO: this is an API specific workaround for JCA, as 'EC' is a constant that may be used + // where typical algorithms are specified, but EC specifically means set up a + // default curve container, that will later be specified explicitly (or if not a default) + // curve is used. + this = any(Literal l | l.getValue() != "EC") + } + override DataFlow::Node getOutputNode() { result.asExpr() = this } override predicate flowsTo(Crypto::FlowAwareElement other) { diff --git a/shared/cryptography/codeql/cryptography/Model.qll b/shared/cryptography/codeql/cryptography/Model.qll index 33c75c556ef3..09f67f156c2a 100644 --- a/shared/cryptography/codeql/cryptography/Model.qll +++ b/shared/cryptography/codeql/cryptography/Model.qll @@ -626,7 +626,30 @@ module CryptographyBase Input> { abstract class KeyEncapsulationAlgorithmInstance extends AlgorithmInstance { } - abstract class EllipticCurveAlgorithmInstance extends AlgorithmInstance { } + abstract class EllipticCurveAlgorithmInstance extends AlgorithmInstance { + /** + * Gets the isolated name as it appears in source + * + * This name should not be parsed or formatted beyond isolating the raw name if necessary. + */ + abstract string getRawEllipticCurveAlgorithmName(); + + /** + * The 'standard' curve name, e.g., "P-256" or "secp256r1". + * meaning the full name of the curve, including the family, key size, and other + * typical parameters found on the name. In many cases this will + * be equivalent to `getRawEllipticCurveAlgorithmName()`, but not always + * (e.g., if the curve is specified through a raw NID). + * In cases like an NID, we want the standardized name so users can quickly + * understand what the curve is, while also parsing out the family and key size + * separately. + */ + abstract string getStandardCurveName(); + + abstract TEllipticCurveType getEllipticCurveFamily(); + + abstract string getKeySize(); + } abstract class HashOperationInstance extends OperationInstance { abstract DigestArtifactInstance getDigestArtifact(); @@ -787,6 +810,9 @@ module CryptographyBase Input> { final private class KeyDerivationAlgorithmInstanceOrValueConsumer = AlgorithmInstanceOrValueConsumer::Union; + final private class EllipticCurveAlgorithmInstanceOrValueConsumer = + AlgorithmInstanceOrValueConsumer::Union; + private newtype TNode = // Artifacts (data that is not an operation or algorithm, e.g., a key) TDigest(DigestArtifactInstance e) or @@ -806,7 +832,7 @@ module CryptographyBase Input> { TKeyCreationOperation(KeyCreationOperationInstance e) or // Algorithms (e.g., SHA-256, AES) TCipherAlgorithm(CipherAlgorithmInstanceOrValueConsumer e) or - TEllipticCurveAlgorithm(EllipticCurveAlgorithmInstance e) or + TEllipticCurveAlgorithm(EllipticCurveAlgorithmInstanceOrValueConsumer e) or THashAlgorithm(HashAlgorithmInstanceOrValueConsumer e) or TKeyDerivationAlgorithm(KeyDerivationAlgorithmInstanceOrValueConsumer e) or TKeyEncapsulationAlgorithm(KeyEncapsulationAlgorithmInstance e) or @@ -2062,39 +2088,133 @@ module CryptographyBase Input> { ES() or OtherEllipticCurveType() - abstract class EllipticCurve extends AlgorithmNode, TEllipticCurveAlgorithm { - abstract string getKeySize(Location location); + private predicate isBrainpoolCurve(string curveName, int keySize) { + // ALL BRAINPOOL CURVES + keySize in [160, 192, 224, 256, 320, 384, 512] and + ( + curveName = "BRAINPOOLP" + keySize.toString() + "R1" + or + curveName = "BRAINPOOLP" + keySize.toString() + "T1" + ) + } + + private predicate isSecCurve(string curveName, int keySize) { + // ALL SEC CURVES + keySize in [112, 113, 128, 131, 160, 163, 192, 193, 224, 233, 239, 256, 283, 384, 409, 521, 571] and + exists(string suff | suff in ["R1", "R2", "K1"] | + curveName = "SECT" + keySize.toString() + suff or + curveName = "SECP" + keySize.toString() + suff + ) + } + + private predicate isC2Curve(string curveName, int keySize) { + // ALL C2 CURVES + keySize in [163, 176, 191, 208, 239, 272, 304, 359, 368, 431] and + exists(string pre, string suff | + pre in ["PNB", "ONB", "TNB"] and suff in ["V1", "V2", "V3", "V4", "V5", "W1", "R1"] + | + curveName = "C2" + pre + keySize.toString() + suff + ) + } + + private predicate isPrimeCurve(string curveName, int keySize) { + // ALL PRIME CURVES + keySize in [192, 239, 256] and + exists(string suff | suff in ["V1", "V2", "V3"] | + curveName = "PRIME" + keySize.toString() + suff + ) + } + + private predicate isNumsCurve(string curveName, int keySize) { + // ALL NUMS CURVES + keySize in [256, 384, 512] and + exists(string suff | suff in ["T1"] | curveName = "NUMSP" + keySize.toString() + suff) + } + + bindingset[curveName] + predicate isEllipticCurveAlgorithmName(string curveName) { + isEllipticCurveAlgorithm(curveName, _, _) + } + + /** + * Holds if `name` corresponds to a known elliptic curve. + */ + bindingset[rawName] + predicate isEllipticCurveAlgorithm(string rawName, int keySize, TEllipticCurveType curveFamily) { + exists(string curveName | curveName = rawName.toUpperCase() | + isSecCurve(curveName, keySize) and curveFamily = SEC() + or + isBrainpoolCurve(curveName, keySize) and curveFamily = BRAINPOOL() + or + isC2Curve(curveName, keySize) and curveFamily = C2() + or + isPrimeCurve(curveName, keySize) and curveFamily = PRIME() + or + isNumsCurve(curveName, keySize) and curveFamily = NUMS() + or + curveName = "ES256" and keySize = 256 and curveFamily = ES() + or + curveName = "CURVE25519" and keySize = 255 and curveFamily = CURVE25519() + or + curveName = "X25519" and keySize = 255 and curveFamily = CURVE25519() + or + curveName = "ED25519" and keySize = 255 and curveFamily = CURVE25519() + or + curveName = "CURVE448" and keySize = 448 and curveFamily = CURVE448() + or + curveName = "ED448" and keySize = 448 and curveFamily = CURVE448() + or + curveName = "X448" and keySize = 448 and curveFamily = CURVE448() + or + curveName = "SM2" and keySize in [256, 512] and curveFamily = SM2() + ) + } + + final class EllipticCurveNode extends AlgorithmNode, TEllipticCurveAlgorithm { + EllipticCurveAlgorithmInstanceOrValueConsumer instance; + + EllipticCurveNode() { this = TEllipticCurveAlgorithm(instance) } - abstract TEllipticCurveType getCurveFamily(); + override string getInternalType() { result = "EllipticCurveAlgorithm" } + + final override string getRawAlgorithmName() { + result = instance.asAlg().getRawEllipticCurveAlgorithmName() + } + + // NICK QUESTION: do I repeat the key size and curve family predicates here as wrappers of the instance? + override LocatableElement asElement() { result = instance } + + TEllipticCurveType getEllipticCurveFamily() { + result = instance.asAlg().getEllipticCurveFamily() + } override predicate properties(string key, string value, Location location) { super.properties(key, value, location) or - // [KNOWN_OR_UNKNOWN] + // [ONLY_KNOWN] key = "KeySize" and - if exists(this.getKeySize(location)) - then value = this.getKeySize(location) - else ( - value instanceof UnknownPropertyValue and location instanceof UnknownLocation - ) - // other properties, like field type are possible, but not modeled until considered necessary + value = instance.asAlg().getKeySize() and + location = this.getLocation() + or + key = "StdCurveName" and + value = instance.asAlg().getStandardCurveName().toUpperCase() and + location = this.getLocation() } override string getAlgorithmName() { result = this.getRawAlgorithmName().toUpperCase() } - - /** - * Mandating that for Elliptic Curves specifically, users are responsible - * for providing as the 'raw' name, the official name of the algorithm. - * - * Casing doesn't matter, we will enforce further naming restrictions on - * `getAlgorithmName` by default. - * - * Rationale: elliptic curve names can have a lot of variation in their components - * (e.g., "secp256r1" vs "P-256"), trying to produce generalized set of properties - * is possible to capture all cases, but such modeling is likely not necessary. - * if all properties need to be captured, we can reassess how names are generated. - */ - abstract override string getRawAlgorithmName(); + // /** + // * Mandating that for Elliptic Curves specifically, users are responsible + // * for providing as the 'raw' name, the official name of the algorithm. + // * + // * Casing doesn't matter, we will enforce further naming restrictions on + // * `getAlgorithmName` by default. + // * + // * Rationale: elliptic curve names can have a lot of variation in their components + // * (e.g., "secp256r1" vs "P-256"), trying to produce generalized set of properties + // * is possible to capture all cases, but such modeling is likely not necessary. + // * if all properties need to be captured, we can reassess how names are generated. + // */ + // abstract override string getRawAlgorithmName(); } abstract class KEMAlgorithm extends TKeyEncapsulationAlgorithm, AlgorithmNode {