Kann die Nullstellung des Speichers durch Xoring von Daten mit sich selbst in C optimiert werden?

Grant Sanders

Manchmal müssen wir aus Sicherheitsgründen den Speicher auf Null setzen, um einen unbeabsichtigten Zugriff auf vertrauliche Daten zu verhindern, beispielsweise um einen Schlüssel nach dem Verschlüsseln einiger Daten sicher zu löschen. Die meisten Leute schlagen vor, zufällige Daten in ein Array zu schreiben, das die vertraulichen Informationen enthält, da dies von einem Compiler nicht optimiert werden kann. Es versteht sich von selbst, dass die naive Verwendung von Funktionen wie memsetdurch einen optimierenden Compiler aufgrund der Als-ob-Regel optimiert werden kann, wenn es sich um die letzte Operation handelt, die an den Daten ausgeführt wird, bevor sie den Gültigkeitsbereich verlassen. Das Abrufen und Schreiben von zufälligen Daten ist jedoch langsam, und ich habe möglicherweise eine Lösung gefunden. Ich möchte eine Expertenmeinung, bevor ich sie im Produktionscode bereitstelle.

Wenn Sie irgendetwas mit sich selbst verknüpfen, ergibt sich aufgrund der Natur des Bedieners immer ein Wert von Null, und es ist sehr schnell. Das Durchlaufen eines Speicherblocks und das Xoring mit sich selbst scheint eine sehr effektive Lösung für das Problem der Nullung zu sein, aber ich befürchte, dass er durch einen ausreichend guten optimierenden Compiler wegoptimiert werden könnte. Es ist plattformübergreifend und portabel und erfordert keine Verwendung der Standardbibliothek, außer für die Verwendung des size_tDatentyps. Ich habe eine Referenzimplementierung dessen beigefügt, was ich unten meine. Darin habe ich eine aufgerufene Funktion, nukedie einen Zeiger data_to_zeround iterativ xors sizeBytes mit sich nimmt.

void nuke (void *data_to_zero, size_t size)
{
    size_t i;

    for (i = 0; i < size; i++) {
        ((unsigned char*)data_to_zero)[i] ^= ((unsigned char*)data_to_zero)[i];
    }
}

Diese Implementierung ist ziemlich langsam, aber wesentlich schneller als das Erfassen und Schreiben ausreichend zufälliger Daten data. Nach der Optimierung ist es schneller als die memsetImplementierungen, auf die ich sowieso zugreifen kann, was überraschend ist.

Ich habe Assembly noch nicht gelernt, aber die Assembly-Ausgabe nach der Optimierung mit GCC und Clang auf O2- und O3-Ebene eines 64-Bit-x86-Prozessors enthält die xorlAnweisung irgendwo im Code, manchmal zweimal. Das zeigt mir, dass die Speicherung tatsächlich stattfindet, aber ich möchte, dass jemand, der weiß, wovon er spricht, dies bestätigt.

Ist das eine praktikable Lösung?

Himbeer Chekurov

Der richtige Weg, dies zu tun, besteht darin, die memset_s()Funktion aufzurufen . Es verwendet das flüchtige Typqualifikationsmerkmal, um den Compiler darüber zu informieren, dass der Aufruf der Funktion memset_s () nicht optimiert werden sollte.

Leider ist diese Lösung aufgrund der Art des flüchtigen Typs, der vor allen Arten von Optimierungen schützt, möglicherweise nicht so effizient wie möglich. Sie kann den Compiler daran hindern, die optimalen Montageanweisungen zu verwenden, und kann zu weniger effizientem Code führen. Ein weiteres Problem memset_s()ist, dass es in C11 eingeführt wurde.

Wenn Sie nicht verwenden können memset_s(), müssen Sie eine der folgenden Methoden in Betracht ziehen:

  1. Eine andere Lösung kann darin bestehen, den Speicher zu "berühren", indem Sie wie folgt nach dem memset () auf den Speicher zugreifen *(volatile char*)pwd= *(volatile char*)pwd. Das Problem bei dieser Lösung ist, dass sie möglicherweise nicht für alle Implementierungen funktioniert.
  2. schreibe deine eigene Version von memset_s()(BEISPIEL 1). Das Problem dabei ist, dass es auch immer noch nicht garantiert funktioniert - Der C-Standard besagt, dass Zugriffe auf flüchtige Objekte Teil des unveränderlichen beobachtbaren Verhaltens sind -, sagt jedoch nichts über Zugriffe über lvalue-Ausdrücke mit flüchtigen Typen aus
  3. Meines Wissens ist der beste Weg, einen flüchtigen Funktionszeiger zu verwenden (BEISPIEL 2)

Als Fazit - was auch immer Sie wählen, es wird dringend empfohlen, immer den resultierenden Assemdbly-Code zu überprüfen, um sicherzustellen, dass der Speicher tatsächlich gelöscht wird und keiner der Speicheraufrufe optimiert wird.

BEISPIEL 1.

static void secure_memzero(void * p, size_t len)
{ 
    volatile uint8_t * _p = p;

    while (len--) *_p++ = 0;
}

BEISPIEL 2.

static void * (* const volatile memset_ptr)(void *, int, size_t) = memset;

static void secure_memzero(void * p, size_t len)
{

    (memset_ptr)(p, 0, len);
}

void
dosomethingsensitive(void)
{
    uint8_t key[32];

    ...

    /* Zero sensitive information. */
    secure_memzero(key, sizeof(key));
}

Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.

Bei Verstößen wenden Sie sich bitte [email protected] Löschen.

bearbeiten am
0

Lass mich ein paar Worte sagen

0Kommentare
LoginNach der Teilnahme an der Überprüfung

Verwandte Artikel

Wie kann die Speicherung von NSAttributedString in Swift mithilfe von Daten und Codierbarkeit optimiert werden?

Wie kann die Standardgröße des von Python bereitgestellten Speichers auf eine Variable verringert werden?

Wie kann die Erstellungszeit des Webpacks mit dem Tool prefetchPlugin & analyse optimiert werden?

Wie kann ich mit vue js überprüfen, wann sich Daten in einer Komponente von selbst ändern?

Kann MSVC mit Codegen für die Verbindungszeit in C und C ++ optimiert werden?

Wie kann ein Teil von SVG mit CSS auf sich selbst gedreht werden?

Wie kann die Leistung beim Schreiben von Objekten optimiert werden?

Wie kann die Leistung von QGraphicsView optimiert werden?

Wie kann die Bereinigung von Twitter-Texten optimiert werden?

Wie kann die Listenleistung von JetPack Compose optimiert werden?

Wie kann das Erhalten von Durchschnittswerten des Arrays optimiert werden?

Wie kann die Renderleistung mit React optimiert werden?

Wie kann die Histogrammstatistik mit Neon-Intrinsics optimiert werden?

Wie kann die Speichernutzung des PHP-Prozesses optimiert werden?

Eigenschaft '0' von undefined kann nicht gelesen werden, selbst wenn die Daten geholt und an die Komponente übergeben werden

C ++ Calculator kann 0 nicht durch sich selbst teilen

Wie kann verhindert werden, dass sich die Datei selbst überschreibt?

Das Aktualisieren des Mobx-Speichers, der innerhalb von self beobachtet werden kann, führt zu 'Die Eigenschaft von <observable> von undefined kann nicht gelesen werden'.

Wie kann die Summe der Werte aus dem Array mit dem genauen Wert aus dem Array von Objekten optimiert werden?

Aktualisieren des Objekts in C# mit Daten, die von JSInterop stammen, werden nicht erneut gerendert

Reduzierung der sich überschneidenden Anzahl von Bussen, die in gerader Linie von einer Stadt zu einer anderen Haltestelle fahren, und kann mein derzeitiger Ansatz optimiert werden?

Python kann die gebundene Methode nicht mit sich selbst vergleichen

Das Laden von JDBC ResultSet in Array durch GoogleScript ist sehr langsam / wie kann es optimiert werden?

Mit Visual Studio 2017 kann ein Referenzelement im Konstruktor mit sich selbst initialisiert werden. Ist es wirklich legal C ++?

GCC Optimiert eine if-Klausel, die nicht optimiert werden kann

Warum unterscheiden sich Daten, die aus dem Ergebnis von toString () erstellt wurden, von sich selbst?

Speichern von Daten mithilfe des lokalen Speichers

Wie kann die Ventilsimulationslogik optimiert werden?

Erweiterung, mit der Wrapper, die sich selbst ausgeben, als Selbst eingegeben werden