
Automatisiertes differentielles Fuzzing-Tool für kryptografische Software, das Implementierungsfehler, Compliance-Verstöße und Seitenkanal-Leaks durch intelligentes, parallelisiertes Testen über mehrere Sprachen und Plattformen hinweg erkennt.
CDF ist ein Werkzeug zum automatischen Testen der Korrektheit und Sicherheit von kryptographischer Software. CDF kann Implementierungsfehler, Compliance-Verstöße, Seitenkanal-Leaks usw. erkennen.
CDF implementiert eine Kombination von Unit-Tests mit "Differential Fuzzing", einem Ansatz, der das Verhalten verschiedener Implementierungen derselben Primitive vergleicht, wenn sie mit Grenzfällen und Werten gefüttert werden, die die Codeabdeckung maximieren.
Im Gegensatz zu allgemeinen Fuzzern und Testsoftware ist CDF:
Intelligent: CDF weiß, welche Art von Algorithmus es testet und passt sich an die getesteten Funktionen an.
Schnell: CDF testet nur das, was getestet werden muss, und parallelisiert seine Tests so weit wie möglich.
Polyvalent: CDF ist nicht auf eine bestimmte Sprache oder API festgelegt, sondern unterstützt beliebige ausführbare Programme oder Skripte.
Portabel: CDF läuft auf jeder Unix- oder Windows-Plattform, da es in Go ohne plattformspezifische Abhängigkeiten geschrieben ist.
Der Zweck von CDF ist es, Entwicklern und Sicherheitsforschern ein effizienteres Testwerkzeug zur Verfügung zu stellen, das effektiver ist als Testvektoren und billiger als manuelle Überprüfung formaler Verifikation.
CDF wurde erstmals auf der Black Hat USA 2017 vorgestellt. Sie können die Folien unserer Präsentation einsehen, die allgemeine Informationen über die Beweggründe und das Design von CDF enthalten.
CDF ist in Go codiert, die aktuelle Version wurde mit Go 1.8 entwickelt. Es hat keine Abhängigkeiten außerhalb der Standardbibliothek von Go.
Wir stellen jedoch Beispielprogramme zum Testen mit CDF zur Verfügung, die in C, Python, C++, Java und Go geschrieben sind und spezifische Kryptobibliotheken zum Ausführen benötigen. Derzeit erforderliche Bibliotheken sind:
make wird die cdf-Binärdatei erstellen.
Eine Reihe von Beispielprogrammen sind unter example verfügbar: make examples-all erstellt alle Beispiele, während make examples-go nur die Go-Beispiele erstellt.
make test führt Unit-Tests (von CDF) aus.
Für den Anfang können Sie sich die Verwendungsinformationen ansehen, indem Sie cdf -h ausführen.
Sie können dann ein Beispiel wie das rsaenc Interface gegen die RSA-OAEP-Go- und CryptoPP-Beispiele testen. Betrachten Sie CryptoPP als Referenz, können Sie die Go-Implementierung testen mit:
cdf rsaenc /examples/oaep_rsa2048_go /examples/oaep_rsa2048_cryptopp
Dieser Befehl führt verschiedene Tests durch, die für das rsaenc-Interface spezifisch sind.
In diesem Beispiel sollte CDF sich über die maximale Größe des öffentlichen Exponenten beschweren, die die Go-Implementierung unterstützt: Wenn wir ihren Code überprüfen, sehen wir, dass der öffentliche Exponent als normale Ganzzahl gespeichert wird, während er in CryptoPP (und den meisten anderen Implementierungen) als große Ganzzahl gespeichert wird. Dies ist jedoch absichtlich so und wird wahrscheinlich nicht geändert.
Parameter sind in config.json definiert. Die meisten Parameter sind selbsterklärend. Möglicherweise möchten Sie andere private Schlüssel für rsaenc und ecdsa setzen (diese Interfaces werden mit festen Schlüsseln getestet, obwohl einige Schlüsselparameter, wie die Exponenten, in einigen Tests geändert werden).
Der Parameter seed ermöglicht es Ihnen, den Seed zu ändern, der in den pseudozufälligen Generatoren von CDF verwendet wird. (Das getestete Programm könnte jedoch einen anderen PRNG verwenden, wie die OAEP-Beispiele.) Der Parameter concurrency legt die Anzahl der gleichzeitigen Goroutinen fest, die CDF beim Forken der Programme erzeugen soll. Beachten Sie, dass es am besten ist, diese Zahl unter der tatsächlichen Anzahl der Kerne zu halten. Der Parameter verboseLog schreibt, wenn auf true gesetzt, alle Ein- und Ausgaben der Programme, auch für die erfolgreichen Tests, in eine Datei log.txt.
Um Ihre Software mit CDF zu testen, müssen Sie ein Programm erstellen, das Eingaben liest und Ausgaben gemäß den CDF-Schnittstellen schreibt und das intern das getestete Programm aufruft. CDF-Schnittstellen sind Abstraktionen einer Kryptofunktionalität, um Black-Box-Tests beliebiger Implementierungen zu ermöglichen.
Wenn Sie beispielsweise das ECDSA-Signaturschema implementiert haben, sollte Ihr Programm der ecdsa Schnittstelle entsprechen und als Eingaben 4 oder 5 Argumente entgegennehmen, um eine Nachricht zu signieren oder eine Signatur zu verifizieren. Diese Argumente sind die öffentliche X-Koordinate, die öffentliche Y-Koordinate, die private große Ganzzahl D und die Nachricht, die Sie signieren möchten. Dann sollte es nur die großen Ganzzahlen R und S jeweils in einer neuen Zeile ausgeben. Oder, um eine Nachricht zu verifizieren, sollte es X, Y, R, S und die Nachricht akzeptieren und dann nur True oder False ausgeben. Die Spezifikationen der Schnittstellen sind unten detailliert.
Unsere Beispiele für Schnittstellenimplementierungen helfen Ihnen, eigene zu erstellen.
Die Fehlerbehandlung ist dem getesteten Programm überlassen, aber um aussagekräftige Fehler in CDF zu erhalten, ist es am besten, bei Fehlern zu beenden, einen Fehlercode zurückzugeben und eine Fehlermeldung auszugeben.
Das Schnittstellenprogramm kann in jeder Sprache geschrieben werden, es muss nur eine ausführbare Datei sein, die einer CDF-Schnittstelle entspricht. Ein Schnittstellenprogramm wird typischerweise in derselben Sprache wie das getestete Programm geschrieben, aber das ist nicht zwingend erforderlich (es kann ein Wrapper in einer anderen Sprache sein, z.B. für Java-Programme).
CDF unterstützt derzeit die folgenden Schnittstellen, wobei Parameter als hexadezimale ASCII-Strings kodiert sind, sofern nicht anders beschrieben:
Die dsa-Schnittstelle testet Implementierungen des Digital Signature Algorithm (DSA). Sie muss die Signatur- und Verifikationsoperationen unterstützen:
| Operation | Eingabe | Ausgabe |
|---|---|---|
| Signatur | p q g y x m | r s |
| Verifikation | p q g y r s m | Wahrheitswert |
Hier sind p, q, g DSA-Parameter, y ein öffentlicher Schlüssel, x ein privater Schlüssel, m eine Nachricht, r und s bilden die Signatur, die durch eine neue Zeile getrennt zurückgegeben werden muss. Der Wahrheitswert, entweder "true" oder "false", wird als String dargestellt.
Die dsa-Schnittstelle unterstützt einen optionalen Test: der -h erlaubt es, den Hashing-Prozess zu umgehen und direkt den zu signierenden Hashwert bereitzustellen. Dies ermöglicht CDF, weitere Tests durchzuführen, wie z.B. die Überprüfung auf Überläufe oder Hash-Trunkierung.
Die ecdsa-Schnittstelle testet Implementierungen des Elliptic Curve Digital Signature Algorithm (ECDSA). Sie muss die Signatur- und Verifikationsoperationen unterstützen:
| Operation | Eingabe | Ausgabe |
|---|---|---|
| Signatur | x y d m | r s |
| Verifikation | x y r s m | Wahrheitswert |