Skip to content

Commit 192bb7f

Browse files
committed
Added support for block cipher modes
1 parent 2eecda3 commit 192bb7f

File tree

4 files changed

+664
-66
lines changed

4 files changed

+664
-66
lines changed

java/ql/lib/experimental/quantum/BouncyCastle/AlgorithmInstances.qll

Lines changed: 189 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class EllipticCurveStringLiteralInstance extends Crypto::EllipticCurveInstance i
1414
override string getRawEllipticCurveName() { result = super.getValue() }
1515

1616
EllipticCurveAlgorithmValueConsumer getConsumer() {
17-
result = EllipticCurveStringLiteralToConsumer::getConsumerFromLiteral(this, _, _)
17+
result = EllipticCurveStringLiteralToConsumerFlow::getConsumerFromLiteral(this, _, _)
1818
}
1919

2020
override Crypto::TEllipticCurveType getEllipticCurveType() {
@@ -69,25 +69,19 @@ abstract class SignatureAlgorithmInstance extends Crypto::KeyOperationAlgorithmI
6969
}
7070

7171
override string getRawAlgorithmName() {
72-
typeNameToRawAlgorithmName(super.getConstructedType().getName(), result)
72+
typeNameToRawAlgorithmNameMapping(super.getConstructedType().getName(), result)
7373
}
7474

75-
/**
76-
* Used for data flow from elliptic curve string literals to the algorithm
77-
* instance.
78-
*/
75+
// Used for data flow from elliptic curve string literals to the algorithm
7976
DataFlow::Node getParametersInput() { none() }
8077

81-
/**
82-
* Used for data flow from elliptic curve string literals to the algorithm
83-
* instance.
84-
*/
78+
// Used for data flow from elliptic curve string literals to the algorithm
8579
DataFlow::Node getEllipticCurveInput() { none() }
8680
}
8781

8882
/**
89-
* Represents an elliptic curve signature algorithm where both the signature
90-
* algorithm and elliptic curve are implicitly defined by the underlying type.
83+
* An elliptic curve signature algorithm where both the signature algorithm and
84+
* elliptic curve are implicitly defined by the underlying type.
9185
*/
9286
abstract class KnownEllipticCurveSignatureAlgorithmInstance extends KnownEllipticCurveInstance,
9387
SignatureAlgorithmInstance
@@ -107,7 +101,7 @@ class DsaSignatureAlgorithmInstance extends SignatureAlgorithmInstance instanceo
107101
}
108102

109103
override string getRawAlgorithmName() {
110-
typeNameToRawAlgorithmName(super.getConstructedType().getName(), result)
104+
typeNameToRawAlgorithmNameMapping(super.getConstructedType().getName(), result)
111105
}
112106
}
113107

@@ -122,7 +116,7 @@ class Ed25519SignatureAlgorithmInstance extends KnownEllipticCurveSignatureAlgor
122116
}
123117

124118
override string getRawAlgorithmName() {
125-
typeNameToRawAlgorithmName(super.getConstructedType().getName(), result)
119+
typeNameToRawAlgorithmNameMapping(super.getConstructedType().getName(), result)
126120
}
127121

128122
override string getRawEllipticCurveName() { result = "Curve25519" }
@@ -139,7 +133,7 @@ class Ed448SignatureAlgorithmInstance extends KnownEllipticCurveSignatureAlgorit
139133
}
140134

141135
override string getRawAlgorithmName() {
142-
typeNameToRawAlgorithmName(super.getConstructedType().getName(), result)
136+
typeNameToRawAlgorithmNameMapping(super.getConstructedType().getName(), result)
143137
}
144138

145139
override string getRawEllipticCurveName() { result = "Curve448" }
@@ -163,7 +157,7 @@ class EcdsaSignatureAlgorithmInstance extends SignatureAlgorithmInstance instanc
163157
}
164158

165159
override string getRawAlgorithmName() {
166-
typeNameToRawAlgorithmName(super.getConstructedType().getName(), result)
160+
typeNameToRawAlgorithmNameMapping(super.getConstructedType().getName(), result)
167161
}
168162

169163
override Crypto::KeyOpAlg::Algorithm getAlgorithmType() {
@@ -184,7 +178,7 @@ class StatefulSignatureAlgorithmInstance extends SignatureAlgorithmInstance inst
184178
}
185179

186180
override string getRawAlgorithmName() {
187-
typeNameToRawAlgorithmName(super.getConstructedType().getName(), result)
181+
typeNameToRawAlgorithmNameMapping(super.getConstructedType().getName(), result)
188182
}
189183

190184
override Crypto::KeyOpAlg::Algorithm getAlgorithmType() {
@@ -218,19 +212,15 @@ abstract class KeyGenerationAlgorithmInstance extends Crypto::KeyOperationAlgori
218212
}
219213

220214
override string getRawAlgorithmName() {
221-
typeNameToRawAlgorithmName(super.getConstructedType().getName(), result)
215+
typeNameToRawAlgorithmNameMapping(super.getConstructedType().getName(), result)
222216
}
223217

224-
/**
225-
* Used for data flow from elliptic curve string literals to the algorithm
226-
* instance.
227-
*/
218+
// Used for data flow from elliptic curve string literals to the algorithm
219+
// instance.
228220
DataFlow::Node getParametersInput() { none() }
229221

230-
/**
231-
* Used for data flow from elliptic curve string literals to the algorithm
232-
* instance.
233-
*/
222+
// Used for data flow from elliptic curve string literals to the algorithm
223+
// instance.
234224
DataFlow::Node getEllipticCurveInput() { none() }
235225
}
236226

@@ -320,7 +310,7 @@ class StatefulSignatureKeyGenerationAlgorithmInstance extends KeyGenerationAlgor
320310
}
321311

322312
override string getRawAlgorithmName() {
323-
typeNameToRawAlgorithmName(super.getConstructedType().getName(), result)
313+
typeNameToRawAlgorithmNameMapping(super.getConstructedType().getName(), result)
324314
}
325315

326316
override Crypto::KeyOpAlg::Algorithm getAlgorithmType() {
@@ -332,11 +322,103 @@ class StatefulSignatureKeyGenerationAlgorithmInstance extends KeyGenerationAlgor
332322
}
333323
}
334324

325+
/**
326+
* A block cipher used in a mode of operation. The algorithm is implicitly
327+
* defined by the type.
328+
*/
329+
class BlockCipherAlgorithmInstance extends Crypto::KeyOperationAlgorithmInstance instanceof ClassInstanceExpr
330+
{
331+
// We track the block cipher mode here to ensure that going from the block
332+
// cipher instance to the block cipher mode instance and back always yields
333+
// the same instance.
334+
//
335+
// Since the block cipher algorithm instance is always resolved using data
336+
// flow from the block cipher mode, we don't loose any information by
337+
// requiring that this flow exists.
338+
BlockCipherModeAlgorithmInstance mode;
339+
340+
BlockCipherAlgorithmInstance() {
341+
super.getConstructedType() instanceof Modes::BlockCipher and
342+
mode = BlockCipherToBlockCipherModeFlow::getBlockCipherModeFromBlockCipher(this, _, _)
343+
}
344+
345+
override Crypto::KeyOpAlg::Algorithm getAlgorithmType() {
346+
if blockCipherNameToAlgorithmMapping(this.getRawAlgorithmName(), _)
347+
then blockCipherNameToAlgorithmMapping(this.getRawAlgorithmName(), result)
348+
else result = Crypto::KeyOpAlg::TSymmetricCipher(Crypto::KeyOpAlg::OtherSymmetricCipherType())
349+
}
350+
351+
// TODO: Implement this.
352+
override int getKeySizeFixed() { none() }
353+
354+
override string getRawAlgorithmName() {
355+
typeNameToRawAlgorithmNameMapping(super.getType().getName(), result)
356+
}
357+
358+
override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { result = mode }
359+
360+
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() {
361+
result = BlockCipherToPaddingModeFlow::getPaddingModeFromBlockCipher(this)
362+
}
363+
364+
override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() { none() }
365+
366+
// Gets a consumer of this block cipher algorithm instance.
367+
Crypto::AlgorithmValueConsumer getConsumer() { result = mode.getBlockCipherArg() }
368+
}
369+
370+
/**
371+
* A block cipher mode instance.
372+
*/
373+
class BlockCipherModeAlgorithmInstance extends Crypto::ModeOfOperationAlgorithmInstance,
374+
BlockCipherModeAlgorithmValueConsumer instanceof ClassInstanceExpr
375+
{
376+
BlockCipherModeAlgorithmInstance() {
377+
super.getConstructedType() instanceof Modes::UnpaddedBlockCipherMode
378+
}
379+
380+
override string getRawModeAlgorithmName() {
381+
result = super.getConstructedType().getName().splitAt("BlockCipher", 0)
382+
}
383+
384+
override Crypto::TBlockCipherModeOfOperationType getModeType() {
385+
if modeNameToModeTypeMapping(this.getRawModeAlgorithmName(), _)
386+
then modeNameToModeTypeMapping(this.getRawModeAlgorithmName(), result)
387+
else result = Crypto::OtherMode()
388+
}
389+
390+
Expr getBlockCipherArg() {
391+
exists(Expr arg |
392+
arg = super.getAnArgument() and
393+
arg.getType() instanceof Modes::BlockCipher and
394+
result = arg
395+
)
396+
}
397+
398+
Crypto::AlgorithmValueConsumer getConsumer() { result = this }
399+
}
400+
401+
/**
402+
* A padding mode instance implicitly determined by the constructor.
403+
*/
404+
class PaddingAlgorithmInstance extends Crypto::PaddingAlgorithmInstance instanceof ClassInstanceExpr
405+
{
406+
PaddingAlgorithmInstance() { super.getConstructedType() instanceof Modes::PaddingMode }
407+
408+
override Crypto::TPaddingType getPaddingType() {
409+
paddingNameToTypeMapping(this.getRawPaddingAlgorithmName(), result)
410+
}
411+
412+
override string getRawPaddingAlgorithmName() {
413+
result = super.getConstructedType().getName().splitAt("Padding", 0)
414+
}
415+
}
416+
335417
/**
336418
* Private predicates mapping type names to raw names, key sizes and algorithms.
337419
*/
338420
bindingset[typeName]
339-
private predicate typeNameToRawAlgorithmName(string typeName, string algorithmName) {
421+
private predicate typeNameToRawAlgorithmNameMapping(string typeName, string algorithmName) {
340422
// Ed25519, Ed25519ph, and Ed25519ctx key generators and signers
341423
typeName.matches("Ed25519%") and
342424
algorithmName = "Ed25519"
@@ -356,6 +438,66 @@ private predicate typeNameToRawAlgorithmName(string typeName, string algorithmNa
356438
// HSS
357439
typeName.matches("HSS%") and
358440
algorithmName = "HSS"
441+
or
442+
typeName.matches("AES%") and
443+
algorithmName = "AES"
444+
or
445+
typeName.matches("Aria%") and
446+
algorithmName = "Aria"
447+
or
448+
typeName.matches("Blowfish%") and
449+
algorithmName = "Blowfish"
450+
or
451+
typeName.matches("DES%") and
452+
algorithmName = "DES"
453+
or
454+
typeName.matches("TripleDES%") and
455+
algorithmName = "TripleDES"
456+
}
457+
458+
private predicate modeNameToModeTypeMapping(
459+
string modeName, Crypto::TBlockCipherModeOfOperationType modeType
460+
) {
461+
modeName = "CBC" and
462+
modeType = Crypto::CBC()
463+
or
464+
modeName = "CCM" and
465+
modeType = Crypto::CCM()
466+
or
467+
modeName = "CFB" and
468+
modeType = Crypto::CFB()
469+
or
470+
modeName = "CTR" and
471+
modeType = Crypto::CTR()
472+
or
473+
modeName = "ECB" and
474+
modeType = Crypto::ECB()
475+
or
476+
modeName = "GCM" and
477+
modeType = Crypto::GCM()
478+
or
479+
modeName = "OCB" and
480+
modeType = Crypto::OCB()
481+
or
482+
modeName = "OFB" and
483+
modeType = Crypto::OFB()
484+
or
485+
modeName = "XTS" and
486+
modeType = Crypto::XTS()
487+
}
488+
489+
private predicate paddingNameToTypeMapping(string paddingName, Crypto::TPaddingType paddingType) {
490+
paddingName = "NoPadding" and
491+
paddingType = Crypto::NoPadding()
492+
or
493+
paddingName = "PKCS7" and
494+
paddingType = Crypto::PKCS7()
495+
or
496+
paddingName = "ISO10126" and
497+
paddingType = Crypto::OtherPadding()
498+
or
499+
paddingName = "ZeroByte" and
500+
paddingType = Crypto::OtherPadding()
359501
}
360502

361503
private predicate signatureNameToKeySizeAndAlgorithmMapping(
@@ -381,3 +523,22 @@ private predicate generatorNameToKeySizeAndAlgorithmMapping(
381523
keySize = 448 and
382524
algorithm = Crypto::KeyOpAlg::TSignature(Crypto::KeyOpAlg::Ed448())
383525
}
526+
527+
private predicate blockCipherNameToAlgorithmMapping(
528+
string name, Crypto::KeyOpAlg::Algorithm algorithm
529+
) {
530+
name = "AES" and
531+
algorithm = Crypto::KeyOpAlg::TSymmetricCipher(Crypto::KeyOpAlg::AES())
532+
or
533+
name = "Aria" and
534+
algorithm = Crypto::KeyOpAlg::TSymmetricCipher(Crypto::KeyOpAlg::ARIA())
535+
or
536+
name = "Blowfish" and
537+
algorithm = Crypto::KeyOpAlg::TSymmetricCipher(Crypto::KeyOpAlg::BLOWFISH())
538+
or
539+
name = "DES" and
540+
algorithm = Crypto::KeyOpAlg::TSymmetricCipher(Crypto::KeyOpAlg::DES())
541+
or
542+
name = "TripleDES" and
543+
algorithm = Crypto::KeyOpAlg::TSymmetricCipher(Crypto::KeyOpAlg::TripleDES())
544+
}
Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import java
22
import AlgorithmInstances
33

4-
abstract class HashAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { }
5-
6-
abstract class CipherAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { }
7-
84
abstract class EllipticCurveAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer { }
95

6+
/**
7+
* An AVC for an elliptic curve algorithm where the algorithm is defined by an
8+
* elliptic curve string literal.
9+
*/
1010
class EllipticCurveStringLiteralArg extends EllipticCurveAlgorithmValueConsumer instanceof Expr {
1111
EllipticCurveStringLiteralArg() {
1212
this = any(Params::ParametersInstantiation params).getAlgorithmArg()
@@ -20,8 +20,8 @@ class EllipticCurveStringLiteralArg extends EllipticCurveAlgorithmValueConsumer
2020
}
2121

2222
/**
23-
* The AVC for a signature algorithm where the algorithm is implicitly defined
24-
* by the constructor.
23+
* An AVC for a signature algorithm where the algorithm is implicitly defined by
24+
* the constructor.
2525
*/
2626
abstract class SignatureAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer {
2727
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result = this }
@@ -30,11 +30,40 @@ abstract class SignatureAlgorithmValueConsumer extends Crypto::AlgorithmValueCon
3030
}
3131

3232
/**
33-
* The AVC for a key generation algorithm where the algorithm is implicitly
33+
* An AVC for a key generation algorithm where the algorithm is implicitly
3434
* defined by the constructor.
3535
*/
3636
abstract class KeyGenerationAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer {
3737
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result = this }
3838

3939
override Crypto::ConsumerInputDataFlowNode getInputNode() { none() }
4040
}
41+
42+
/**
43+
* A block cipher argument passed to an block cipher mode constructor.
44+
*/
45+
class BlockCipherAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer instanceof Expr {
46+
BlockCipherAlgorithmValueConsumer() {
47+
this = any(BlockCipherModeAlgorithmInstance mode).getBlockCipherArg()
48+
}
49+
50+
override Crypto::ConsumerInputDataFlowNode getInputNode() { result.asExpr() = this }
51+
52+
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
53+
result.(BlockCipherAlgorithmInstance).getConsumer() = this
54+
}
55+
}
56+
57+
/**
58+
* An AVC for a block cipher mode implicitly defined by the constructor.
59+
*/
60+
abstract class BlockCipherModeAlgorithmValueConsumer extends Crypto::AlgorithmValueConsumer instanceof ClassInstanceExpr
61+
{
62+
BlockCipherModeAlgorithmValueConsumer() {
63+
this.getType() instanceof Modes::UnpaddedBlockCipherMode
64+
}
65+
66+
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() { result = this }
67+
68+
override Crypto::ConsumerInputDataFlowNode getInputNode() { none() }
69+
}

0 commit comments

Comments
 (0)