PeterPawn / YourFritz

dynamic package management for AVM routers
GNU General Public License v2.0
225 stars 63 forks source link

signimage: new and enhanced version #12

Open PeterPawn opened 6 years ago

PeterPawn commented 6 years ago
PeterPawn commented 6 years ago

In a first step, I've added a workaround to the old version of image signing script to circumvent the MD5 computation failure from "firmwarecfg stream", if the signature starts at the "wrong" offset.

fda77 commented 2 years ago

After 3 years still urgent? ;-) I noticed images signed with signimage are smaller than original file, eg 13 blocks but expected 2

Minor/optional feature requests for https://github.com/Freetz-NG/freetz-ng/blob/master/fwmod#L2108

PeterPawn commented 2 years ago

Jetzt gehe ich mal zu Deutsch zurück, damit es keine weiteren Mißverständnisse geben kann.

Deine Änderungen an Freetz-NG sind ja jetzt gerade erst ein paar Stunden alt - ich sehe noch nicht so ganz, wo das am Ende landen soll (die Kommentare der Commits sorgen auch nicht für weitere Erhellung).

Wenn Du tatsächlich dem Benutzer die Wahl lassen willst, womit er sein Image signieren lassen will, dann warte bitte noch etwas. Ich bin gerade an umfangreichen Änderungen für die Dateien in signimage am Arbeiten - erste Änderungen sind alle im Branch signimage zu finden und es werden sich definitiv auch einige Dinge bei den Dateinamen und Environment-Variablen ändern. Ich habe gerade mal die letzten Änderungen von heute morgen noch auf GitHub geschoben (lagen bisher nur lokal auf meinen zwei eigenen Git-Servern) - da ist aber noch nichts in Stein gemeißelt.

Der Teil mit dem Signieren ist zwar jetzt praktisch fertig (und sollte dank POSIX-Kompatibilität sowohl mit bash in der Freetz-Toolchain als auch mit der ash auf der FRITZ!Box funktionieren, auch ohne daß man den SheBang erst ändert), aber es fehlen noch die zwei Skripte für das Generieren des eigenen Keys und das Prüfen der Signaturen.


Deine "feature requests" verstehe ich so nicht ... kannst Du das bitte noch einmal klarer schreiben (gerne auch in Deutsch)? Was soll "read private key without temporary file" sein? Der private Schlüssel sollte doch irgendwo im Home-Verzeichnis des Benutzers landen bzw. sogar als kleines Paket (zumindest in Freetz) bereitgestellt werden, das man sichern und wieder einspielen kann - ansonsten hat man (spätestens wenn man mit VMs arbeitet und da dann mal wieder ein neues Image auf dem Markt ist, das man verwenden will) früher oder später ja ein "Duuuscheinander" bei den RSA-Keys.

Ich wüßte gar nicht, wo man da eine temporäre Datei brauchen sollte. Und beim Image-Signieren braucht man nun mal die Ausgabe in eine andere Datei - theoretisch wäre zwar auch ein "in-place"-Signieren möglich, aber eben nur dann, wenn das Image per se genug freie Blöcke am Ende enthält oder bereits ein Signatur-Member enthalten ist, den man überschreiben könnte. Außer du meintest eigentlich auch beim Signieren ein "--append" an die Ausgangsdatei - da gibt es aber schon ein paar Hürden.


Genau das mit dem "genug Platz" wird aber selbst bei der Verwendung von GNU-tar zum Packen des neuen Images (vor dem Signieren) nicht immer der Fall sein - wenn dabei eine Datei herauskommt, die im letzten 10K-Block (immer unter der Annahme, daß stets volle 10K-Blöcke ausgegeben werden, wobei das tar-Kommando gleichzeitig sicherstellt, daß die vom Standard geforderten 2 EoA-Blöcke vorhanden sind) genau 18 (logische) Records hat, dann reichen die zwei leeren dahinter noch aus, damit es keinen weiteren Block in der signierten Datei braucht:

peh@vidar:/tmp> mkdir sigtest
peh@vidar:/tmp> cd sigtest/
peh@vidar:/tmp/sigtest> mkdir var
peh@vidar:/tmp/sigtest> for i in $(seq 35); do mkdir var/subdir$i; done
peh@vidar:/tmp/sigtest> tar --format=gnu -c -f 36-blocks.tar ./var
peh@vidar:/tmp/sigtest> wc -c 36-blocks.tar
20480 36-blocks.tar
peh@vidar:/tmp/sigtest> dd if=/dev/zero bs=512 count=1 2>/dev/null | tr '\000' '\377' > var/dummy
peh@vidar:/tmp/sigtest> tar --format=gnu --append -f 36-blocks.tar var/dummy
peh@vidar:/tmp/sigtest> wc -c 36-blocks.tar
20480 36-blocks.tar
peh@vidar:/tmp/sigtest> od -A x -t x1z 36-blocks.tar | tail -n 33
004600 2e 2f 76 61 72 2f 73 75 62 64 69 72 33 35 2f 00  >./var/subdir35/.<
004610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004660 00 00 00 00 30 30 30 30 37 35 35 00 30 30 30 31  >....0000755.0001<
004670 37 35 30 00 30 30 30 30 31 34 34 00 30 30 30 30  >750.0000144.0000<
004680 30 30 30 30 30 30 30 00 31 34 31 35 31 32 33 36  >0000000.14151236<
004690 30 36 35 00 30 31 32 31 34 31 00 20 35 00 00 00  >065.012141. 5...<
0046a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004700 00 75 73 74 61 72 20 20 00 70 65 68 00 00 00 00  >.ustar  .peh....<
004710 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
004720 00 00 00 00 00 00 00 00 00 75 73 65 72 73 00 00  >.........users..<
004730 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004800 76 61 72 2f 64 75 6d 6d 79 00 00 00 00 00 00 00  >var/dummy.......<
004810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004860 00 00 00 00 30 30 30 30 36 34 34 00 30 30 30 31  >....0000644.0001<
004870 37 35 30 00 30 30 30 30 31 34 34 00 30 30 30 30  >750.0000144.0000<
004880 30 30 30 31 30 30 30 00 31 34 31 35 31 32 34 31  >0001000.14151241<
004890 35 35 35 00 30 31 31 34 31 31 00 20 30 00 00 00  >555.011411. 0...<
0048a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004900 00 75 73 74 61 72 20 20 00 70 65 68 00 00 00 00  >.ustar  .peh....<
004910 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
004920 00 00 00 00 00 00 00 00 00 75 73 65 72 73 00 00  >.........users..<
004930 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  >................<
*
004c00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
005000
peh@vidar:/tmp/sigtest> tar --format=gnu -c -f 38-blocks.tar ./var
peh@vidar:/tmp/sigtest> wc -c 38-blocks.tar
20480 38-blocks.tar
peh@vidar:/tmp/sigtest> tar --format=gnu --append -f 38-blocks.tar var/dummy
peh@vidar:/tmp/sigtest> wc -c 38-blocks.tar
30720 38-blocks.tar
peh@vidar:/tmp/sigtest> od -A x -t x1z 38-blocks.tar | tail -n 35
004800 2e 2f 76 61 72 2f 64 75 6d 6d 79 00 00 00 00 00  >./var/dummy.....<
004810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004860 00 00 00 00 30 30 30 30 36 34 34 00 30 30 30 31  >....0000644.0001<
004870 37 35 30 00 30 30 30 30 31 34 34 00 30 30 30 30  >750.0000144.0000<
004880 30 30 30 31 30 30 30 00 31 34 31 35 31 32 34 30  >0001000.14151240<
004890 36 30 31 00 30 31 31 35 33 35 00 20 30 00 00 00  >601.011535. 0...<
0048a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004900 00 75 73 74 61 72 20 20 00 70 65 68 00 00 00 00  >.ustar  .peh....<
004910 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
004920 00 00 00 00 00 00 00 00 00 75 73 65 72 73 00 00  >.........users..<
004930 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004a00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  >................<
*
004c00 76 61 72 2f 64 75 6d 6d 79 00 00 00 00 00 00 00  >var/dummy.......<
004c10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004c60 00 00 00 00 30 30 30 30 36 34 34 00 30 30 30 31  >....0000644.0001<
004c70 37 35 30 00 30 30 30 30 31 34 34 00 30 30 30 30  >750.0000144.0000<
004c80 30 30 30 31 30 30 30 00 31 34 31 35 31 32 34 30  >0001000.14151240<
004c90 36 30 31 00 30 31 31 34 30 30 00 20 30 00 00 00  >601.011400. 0...<
004ca0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004d00 00 75 73 74 61 72 20 20 00 70 65 68 00 00 00 00  >.ustar  .peh....<
004d10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
004d20 00 00 00 00 00 00 00 00 00 75 73 65 72 73 00 00  >.........users..<
004d30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004e00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  >................<
*
005000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
007800
peh@vidar:/tmp/sigtest>

Beim ersten Mal sind es 36 Verzeichnisse (1x ./var + 35x var/subdirXX) a 512 Byte = 18432 Byte gesamt, mit 4 freien 512-Byte-Records im letzten 10-KB-Block. Wie zu erwarten, braucht es dafür exakt 2x 10 KB (die ersten 10 KB sind nur Füllstoff, damit es wenigstens zwei Blöcke werden) und am Ende sind noch 4 Records frei (von 0x4800 bis 0x5000). Fügt man jetzt eine weitere Datei hinzu (anstelle der Signatur-Datei, der Platzbedarf ist aber derselbe: 512 Byte für den Header und 512 Byte für die Daten), landet die in den Bytes von 0x4800 bis 0x4C00 und es bleiben immer noch zwei leere Blöcke am Ende über -> das TAR-File wächst durch das tar --append NICHT in seiner Größe.

Beim zweiten Mal sind es dann schon per se 38 Blöcke (es sind die Daten für die var/dummy dazugekommen) und damit nur noch zwei leere Blöcke nach dem (ersten) Packen. Fügt man jetzt noch einmal eine kleine Datei hinzu (hier noch einmal die oben schon erzeugte var/dummy, aber die Signatur-Datei benötigt immer noch denselben Platz wie dieses Beispiel), gibt es eben keine leeren Blöcke mehr am Ende der Datei (wie beim 7530-Image 07.29 für die 7530 zu sehen bei AVM) und das tar --append fügt einem weiteren (kompletten 10-KB-)Block hinzu, womit die Datei dann 30 KB groß wird und vermutlich (aber das habe ich tatsächlich noch nicht getestet) von der AVM-Firmware als "fehlerhaft signiert" eingestuft werden dürfte.

Denn wenn AVM in diesem Falle eine Datei als "gültig" ansieht, die OHNE diese 20 weiteren leeren (512-Byte-)Records daherkommt, dann kann das eigentlich für die Datei MIT dem zusätzlichen 10-KB-Block nicht auch noch gelten - der signierte Hash kann sich nur auf eine der beiden Dateigrößen stützen und damit sollte auch nur eine der beiden als gültig signiert akzeptiert werden.

Daß die AVM-Variante (ohne zwingende EoA-Blöcke) von der AVM-Firmware verstanden wird, ist bereits geklärt (7530 07.29-Image) - bleibt die Frage, was sie zur anderen Variante sagt (und alles andere als ein "rc=210" wäre dann schon ein sehr absonderlicher Fall). Verweigert sie da aber die Zustimmung, gibt es auch bei der Methode mit OpenSSL und tar --append mindestens einen Fall, wo es Probleme gibt. Eigentlich sogar auch wieder zwei, weil auch die Variante mit 37 Records (die liegt ja zwischen den bisher gezeigten mit 36 und 38) schon zu einem weiteren 10 KB-Block beim tar --append führt, weil im Block davor nur noch Platz für einen einzelnen EoA-Block wäre (von 0x4E00 bis 0x5000):

peh@vidar:/tmp/sigtest> mkdir var/subdir36
peh@vidar:/tmp/sigtest> ls -1 var | wc -l
36
peh@vidar:/tmp/sigtest> tar --format=gnu -c -f 37-blocks.tar ./var
peh@vidar:/tmp/sigtest> wc -c 37-blocks.tar
20480 37-blocks.tar
peh@vidar:/tmp/sigtest> dd if=/dev/zero bs=512 count=1 2>/dev/null | tr '\000' '\377' > var/dummy
peh@vidar:/tmp/sigtest> tar --format=gnu --append -f 37-blocks.tar var/dummy
peh@vidar:/tmp/sigtest> wc -c 37-blocks.tar
30720 37-blocks.tar
peh@vidar:/tmp/sigtest> od -A x -t x1z 37-blocks.tar | tail -n 33
004800 2e 2f 76 61 72 2f 73 75 62 64 69 72 33 36 2f 00  >./var/subdir36/.<
004810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004860 00 00 00 00 30 30 30 30 37 35 35 00 30 30 30 31  >....0000755.0001<
004870 37 35 30 00 30 30 30 30 31 34 34 00 30 30 30 30  >750.0000144.0000<
004880 30 30 30 30 30 30 30 00 31 34 31 35 31 32 34 37  >0000000.14151247<
004890 34 32 31 00 30 31 32 31 34 30 00 20 35 00 00 00  >421.012140. 5...<
0048a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004900 00 75 73 74 61 72 20 20 00 70 65 68 00 00 00 00  >.ustar  .peh....<
004910 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
004920 00 00 00 00 00 00 00 00 00 75 73 65 72 73 00 00  >.........users..<
004930 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004a00 76 61 72 2f 64 75 6d 6d 79 00 00 00 00 00 00 00  >var/dummy.......<
004a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004a60 00 00 00 00 30 30 30 30 36 34 34 00 30 30 30 31  >....0000644.0001<
004a70 37 35 30 00 30 30 30 30 31 34 34 00 30 30 30 30  >750.0000144.0000<
004a80 30 30 30 31 30 30 30 00 31 34 31 35 31 32 34 37  >0001000.14151247<
004a90 35 32 30 00 30 31 31 34 30 37 00 20 30 00 00 00  >520.011407. 0...<
004aa0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004b00 00 75 73 74 61 72 20 20 00 70 65 68 00 00 00 00  >.ustar  .peh....<
004b10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
004b20 00 00 00 00 00 00 00 00 00 75 73 65 72 73 00 00  >.........users..<
004b30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
004c00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  >................<
*
004e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  >................<
*
007800
peh@vidar:/tmp/sigtest>

Soviel zu dem, was ich bisher im Bezug auf die Frage, ob das Signieren mit tar --append automatisch auch immer Ergebnisse bringt, die AVM problemlos verifizieren kann, zusammengetragen habe (mehr als Demo meiner Überlegungen, denn als ernsthafte Beschäftigung mit dem Thema) - man müßte dann halt diese Grenzfälle mal auf der Box mit der AVM-Firmware prüfen lassen.

Wenn das tatsächlich so sein sollte, daß AVM den leeren 10 KB-Block hinter der Signatur (den es so bei AVM eben nicht gibt) ignoriert und ihn NICHT in die Hash-Berechnung mit einfließen läßt (es ist ja anzunehmen, daß AVM da Block für Block liest und dann immer entscheidet, ob der den MD5-Status aktualisieren soll oder nicht), sondern den Inhalt des letzten Blocks ignoriert (weil beim Auftauchen der Signatur-Datei im TAR-Stream bereits die abschließende Berechnung (MD5_Final()) erfolgt), dann wäre das wieder eine fette Lücke, zumindest dann, wenn da auch anderes als leere Blöcke unberücksichtig bliebe beim Hashen.

Aber wie gesagt - das müßte man erst mal testen ...


Jedenfalls sehe ich schon aufgrund der o.a. Problematik, daß so ein File auch mal größer werden kann beim Signieren (und es garantiert auch immer größer wird, wenn man es mit busybox tar gepackt hat, weil das eben nur die notwendigen Daten ausgibt und den "Blockfaktor" gar nicht kennt:

peh@vidar:/tmp/sigtest> rm var/dummy
peh@vidar:/tmp/sigtest> busybox tar -c -f bb-36-blocks.tar ./var
peh@vidar:/tmp/sigtest> wc -c bb-36-blocks.tar
19456 bb-36-blocks.tar
peh@vidar:/tmp/sigtest>

), nicht so richtig, wie man da generell ein "in-place"-Signieren machen sollte und als "Sonderfall", wo man erst noch aufwändig prüfen muß, ob der freie Platz für so ein Signieren an Ort und Stelle auch reicht, ist mir das eigentlich erst mal zu "künstlich" als Bedarf. In Freetz-NG solltest Du immer genug Platz für eine zweite Kopie haben und selbst auf der Box habe ich bisher eigentlich nie an DIESER Stelle Probleme bekommen.

Zumal ja eigentlich die Ausgabe-Datei am Ende diejenige ist, die dann auch irgendwohin übertragen werden muß/soll (am besten auf die Box) und da kann man die dann auch gleich am Ziel irgendwie ablegen. Die unsignierte Eingabedatei ist dann halt die überflüssige - die muß man dann eben so schnell es geht entsorgen, wenn es um den belegten Platz geht. Ein Signieren im Rahmen einer Pipe (wo also das Signieren die Eingabedatei nur einmal als Stream lesen kann - es sei denn, man speichert sie doch noch irgendwo und liest diese Kopie dann mehrfach) ist mit meiner Methode nicht möglich - schon für die ganzen Prüfungen (um die Anwender vor den Folgen des Nichtlesens von Anleitungen u.ä. zu bewahren) muß die Eingabedatei mehrfach verarbeitet werden.

Das wäre das, was ich unter Deinem ersten "Wunsch" verstehen würde - m.E. nur schlecht (sicher!) umzusetzen und da ist es mir dann eigentlich auch wieder lieber, wenn meine Skript-Dateien gar nicht erst in den Verdacht geraten können, sie wären am Verstümmeln und/oder Verschwinden einer Datei schuld, weil sie die Eingabedatei "angefaßt" haben. Die Fälle, wann da nun genug Platz für eine Signatur ist und wann die Datei "verlängert" werden müßte (zumindest wenn man korrekte EoA-Records haben möchte), sind mir auch zu komplex - es ist ja nicht zwingend gesagt, daß die Eingabedatei unbedingt auch --blocking-factor=20 verwenden muß (beim GNU-tar) und beim BB-tar ginge es dann auch generell nicht, wie ich oben gezeigt habe, weil das nur die notwendigen Daten schreibt.

Zwar wird eigentlich schon mittels dd geschrieben und man müßte nur noch das Positionieren an die richtige Stelle der "Eingabedatei" davor setzen (anstelle des Kopierens von der Eingabedatei nach STDOUT: https://github.com/PeterPawn/YourFritz/blob/a276313a047cc7096eb1241da5f103dd4322e37c/signimage/yf_sign#L640) und dabei STDOUT auf STDIN dieses dd-Prozesses umleiten, aber das ist mir irgendwie doch zu heiß (zumindest im Moment) - ich würde erst mal sehen wollen, wie sich das mit dem Ersetzen einer vorhandenen Signatur letztlich macht. Wenn das halbwegs sauber läuft (auch "in the wild") und damit dann auch mehrfache Signier-Versuche funktionieren (denn die "unsignierte Eingabedatei" wäre nach einem "in-place"-Signieren ja nicht mehr vorhanden), dann denke ich darüber noch einmal nach.

Mit dem zweiten Punkt kann ich aber gar nichts anfangen - da verstehe ich nur Bahnhof, weil ich gar keine Vorstellung habe, wo da der Key irgendetwas mit einer temporären Datei zu tun haben sollte (s.o.).

PeterPawn commented 2 years ago

Und nebenbei: Dringend war das tatsächlich mal, als das hier erstellt wurde - aber der gefundene Workaround: https://github.com/PeterPawn/YourFritz/issues/12#issuecomment-418233368 hatte das dann schon in der Zeitspanne, die man als "urgent" ansehen würde, entschärfen können. Ganz so schlimm, wie das auf den ersten Blick aussieht, ist es also auch nicht - wirklich "urgent" war nur der vierte Punkt im ersten Beitrag und der war dann relativ zeitnah auch erledigt. Da hätte ich vermutlich das "urgent" dann auch gleich löschen sollen - so hole ich es jetzt eben nach. :sunglasses:

fda77 commented 2 years ago

Deutsch ist mir lieber und einfacher. Das war wohl schlechtes Timing dass ich das genau jetzt eingebaut hab, naja. Hab schon gesehen dass das Script bald einen anderen Namen hat. Shebang hatte ich nicht geändert - lief auch so. Weshalb er13 das ändert und wo es da Probleme gab weiss ich nicht Man kann jetzt für sign/verify je auswählen welche Methode man verwenden möchte - falls eine mal nicht mehr funktionieren sollte ^^

in-place signing

wo man erst noch aufwändig prüfen muß, ob der freie Platz für so ein Signieren an Ort und Stelle auch reicht, ist mir das eigentlich erst mal zu "künstlich" als Bedarf.

Jo, muss nicht sein, wäre halt ganz praktisch wenn der Output nicht in eine Datei umgeleitet werden müsste und diese dann über das Original verschoben werden müsste.

Zumal ja eigentlich die Ausgabe-Datei am Ende diejenige ist, die dann auch irgendwohin übertragen werden muß/soll (am besten auf die Box) und da kann man die dann auch gleich am Ziel irgendwie ablegen

Beim signieren durch fwmod liegt die Datei schon in images/ und könnte geflasht werden. Die Signierung kann man im menuconfig auch deaktivieren, dann wird das ganze einfach übersprungen

read private [and pub] key without temporary file from command line

1) beim Prüfen Freetz hat die pub-keys nicht als 100 Dateien sondern in der .config als Variable: https://github.com/Freetz-NG/freetz-ng/blob/master/config/avm/signature.in. Praktischer wäre es den Key zu übergeben statt eine temporäre Datei zu erstellen

2) beim Signieren In Freetz liegt die Datei in .signature/prv. Trotz FREETZ_IMAGE_SIGNING_PREFIX kann diese nicht direkt verwendet werden, da dieser Variable immer noch ein .key (oder so ähnlich) angehängt wird. Ich lege dafür jedes mal einen temporären Link an. Übigens wäre es ganz nett falls die Keydatei nicht existiert in der Fehlermeldung angezeigt wird wo gesucht wurde! Ich hab mir mit "sh -x" beholfen, steht aber auch bestimmt irgendwo in der README

das TAR-File wächst durch das tar --append NICHT in seiner Größe.

Ja, das hab ich auch festgestellt, ng (freetz/) weiss ich nicht) gibt die Größen vorher und nachher an

PeterPawn commented 2 years ago

Praktischer wäre es den Key zu übergeben statt eine temporäre Datei zu erstellen

Da redest Du offenbar dann aber vom (künftigen) yf_check_signature - da sollte das als alternative Angabe machbar sein und würde vermutlich schon heute funktionieren, wenn man sich der "process substitution" bedient (sofern man eine bash hat):

https://tldp.org/LDP/abs/html/process-sub.html

vidar:/home/GitHub/YourFritz/signimage $ busybox tar -c -f test.tar -C /tmp/sigtest/ ./var
vidar:/home/GitHub/YourFritz/signimage $ tar -tvf test.tar | wc -l
38
vidar:/home/GitHub/YourFritz/signimage $ yf_sign test.tar > signed.tar

yf_sign, version 1.0.1

Copyright (C) 2016-2021 P. Haemmerlein (peterpawn@yourfritz.de)

Licensed to you according to GPLv2 or a later version, with some additions.
Please refer to the usage screen for detailed license terms.

Found OpenSSL 1.1.1l  24 Aug 2021
Check dgst command ... OK
Check rsa command ... OK
Verify hash algorithm md5 is supported ... OK
Checking input file format ... OK
Enter your password for the signing key:
Checking password for the private key file ... OK
Signing the image hash (md5) with RSA key from /home/peh/.yf_signimage/image_signing.key ... OK
Copying resulting image to output ... OK
vidar:/home/GitHub/YourFritz/signimage $ cat /root/.yf_signimage/image_signing.asc
00b514641bed85d77d32a82f018fc42ed1a49929da2d3be9b7b7ac7b859d8b23d77bff523a1fc7a0762e4a0191c874ea6b18eb24567308350d10d1853c033bf2d9f36d78990a3dc4f2f04d92527960fb75d62a5bb8e677ce816a4cc8839a74901adcf63e450f7ebee95cc9a91c8ab8dd52c6c94b8079181851bd6cff3b40dd58e1
010001
vidar:/home/GitHub/YourFritz/signimage $ read modulus < /root/.yf_signimage/image_signing.asc; printf "%s\n010001" "$modulus"
00b514641bed85d77d32a82f018fc42ed1a49929da2d3be9b7b7ac7b859d8b23d77bff523a1fc7a0762e4a0191c874ea6b18eb24567308350d10d1853c033bf2d9f36d78990a3dc4f2f04d92527960fb75d62a5bb8e677ce816a4cc8839a74901adcf63e450f7ebee95cc9a91c8ab8dd52c6c94b8079181851bd6cff3b40dd58e1
010001
vidar:/home/GitHub/YourFritz/signimage $ ./check_signed_image signed.tar -a <(printf "%s\n010001" "$modulus")
Found OpenSSL 1.1.1l  24 Aug 2021
Check dgst command ... OK
Check rsautl command ... OK
Checking the public key from /dev/fd/63 ... OK
Checking support for the used hash algorithm md5 ... OK
Verification succeeded.
vidar:/home/GitHub/YourFritz/signimage $

Aber tatsächlich funktioniert auch das oben nicht wirklich (jedenfalls im Moment), weil die bisherige Version immer die Existenz einer "Datei" prüft, bevor diese gelesen wird und das /dev/fd/63 oben liefert eben bei einem [ -f "/dev/fd/63" ] einen Fehler, weil das kein "regular file" ist. Da würde ich noch eine zusätzliche Abfrage einbauen, ob der (vermeintliche) Dateinamen mit /dev/fd beginnt und dann diese Prüfung überspringen - dann könnten Aufruf und Ergebnis wie oben aussehen und ich vermute mal, daß Du auch mit so einem Aufruf leben könntest.

Ich würde auch hier nur ungerne auf Kommandozeilen-Parameter ausweichen, weil so ein Modulus schon ganz schön lang ist, wenn man ihn auch noch hexadezimal darstellen will/muß - bei einem 4096-Bit-Key (was der Rest meiner Skripte ja auch kann), sind das dann schon 1024 Zeichen nur für diesen Wert.

Aber ich könnte mir vorstellen (wie gesagt, das check_signature ändere ich jetzt ohnehin erst), da noch einen Parameter hinzuzufügen, der den Modulus (mit festem Exponenten 0x10001) aus einer Environment-Variablen liest (das ist im Skript nur ein einzelnes printf, denn das landet ohnehin alles erst mal intern in einer temporären Datei, von wo das dann zeilenweise wieder gelesen wird), sollte nicht wirklich ein Problem sein.

Übigens wäre es ganz nett falls die Keydatei nicht existiert in der Fehlermeldung angezeigt wird wo gesucht wurde! Ich hab mir mit "sh -x" beholfen, steht aber auch bestimmt irgendwo in der README

Die neue Version ist da schon gesprächiger, auch wenn ich nicht so genau weiß, wo Du da eine Fehlermeldung (dann vermutlich ohnehin bei der alten Version) vermißt hast.

Deinen Ansatz, die Dateien nur pub und prv zu nennen, kann ich nur schwer nachvollziehen ... so, wie Du das umgesetzt hast, verbaust Du den Benutzern nur die Benutzung mehrerer Keys, wenn sie z.B. für jedes Modell einen anderen verwenden (wie AVM das macht) oder wenn sie (für Boxen, die sie "in Pflege" haben - so etwas kommt ja auch vor und es muß nicht immer nur die (nicht erlaubte) Bereitstellung von fertigen Images zum öffentlichen Download sein, wenn man Images "weitergibt") mal eine andere Signatur verwenden wollen, ohne gleich zwei Kopien der Toolchain (oder gar der Build-VM) verwenden zu müssen.

So ein Problem könnte man zwar auch noch mit Unterverzeichnissen lösen - aber wäre es nicht viel schlauer (und komfortabler), wenn das alles nicht fix in der fwmod hinterlegt ist (da kommen .signature, prv und pub ja her im Moment), sondern mit passender Vorbelegung in der .config steht und vom Benutzer selbst geändert werden kann? Dann kann der ja auch einfach in seiner Freetz-NG-Konfiguration für seine 7490 und seine 7590 unterschiedliche Keys verwenden (wenn ihm danach ist) oder in der Konfiguration für Onkel Karl und in der für Tante Erna ebenfalls - alles nach dem gleichen Schema. Ja, wenn man sich auf die Verwendung aus Freetz heraus beschränkt, braucht man nicht mal zwei Dateien, denn pub ist eigentlich unnötig. Den jedesmal bei Bedarf aus der prv zu erstellen, dauert nur Sekundenbruchteile - allerdings braucht es das Kennwort für den privaten Schlüssel, aber das ist bei Dir ja auch IMMER vorhanden bisher.

In der neuen Konfigurationsdatei für yf_signimage (so nenne ich das "Unterprojekt" künftig, ebenso praktisch alle Variablen, die von extern dessen Funktion beeinflussen: https://github.com/PeterPawn/YourFritz/blob/f3fc9a423e1c065c3818f2085c6bdef41e06b69d/signimage/yf_signimage.conf#L77) kann man dann zwar auch die Dateinamenserweiterungen wieder von außen selbst festlegen ... aber bei der "Namenswurzel" würde ich schon weiterhin auf einem "common name" bestehen wollen - einfach damit man die Files auch "beisammen" (und auseinander) halten kann, die auch zusammen gehören. So einem Namen wie pub und prv sieht man nun mal nicht an, was da drin stecken sollte.

und diese dann über das Original verschoben werden müsste.

Das muß auch nicht immer so sein ... die meisten Programme gehen ja auch hin, lesen ihre Daten von der Eingabe und schreiben sie (unter einem neuen Namen) in eine zusätzliche Datei - wenn dann am Ende alles glatt gegangen ist, wird die alte umbenannt (.bak), die neue auch umbenannt und erst danach die alte Datei auch wirklich gelöscht. Dieses "vorsichtige" Vorgehen stellt halt auch sicher, daß mind. eine Version IMMER existiert. Zumal das "in Shell" ja auch schön umzusetzen ist, wenn man das notwendige mv per Condition (&&) an den Erfolg des zuvor ausgeführten Kommandos koppelt (da kriegt man sogar das vorherige Umbenennen einer alten Datei nach .bak noch dazwischen - alles in einem Rutsch).

Freetz hat die pub-keys nicht als 100 Dateien sondern in der .config als Variable

Etwas in der Art ist auch bei mir schon lange vorbereitet - nur werden da die Keys als XML-Datei erfaßt/verwaltet: https://github.com/PeterPawn/YourFritz/blob/signimage/signimage/key_database.xml und bei Bedarf dann die richtigen (als Datei für die Option -c bei der Signatur-Prüfung) anhand der HWRevision extrahiert, wenn man die AVM-Signatur eines bestimmten Modells prüfen will. Wobei ich das mit dem XML natürlich auch so angelegt habe, daß man da auch die eigenen öffentlichen Schlüssel mit eintragen kann und nicht nur die von AVM. Gleichzeitig KANN der Benutzer dann eben auch bei so einer Lösung problemlos seine eigene XML-Datei als "Datenbank" verwenden (die kann sich sogar auf die tatsächlich benötigten Keys beschränken) und muß nicht in den Dateien des Projekts (bei Dir ja dann in den Dateien im config-Verzeichnis) herumändern. Für die notwendige Sicherheit, daß da niemand an den XML-Daten herum gepfuscht hat, sollte die dann signiert werden - dafür gibt es bei XML-Daten ja ein Standardverfahren.

Auch das (automatische) Auslesen der AVM-Keys aus den Images habe ich irgendwo schon mal gemacht (müßte ich mal suchen), deshalb gibt z.B. dieses Skript: https://github.com/PeterPawn/YourFritz/blob/signimage/toolbox/image/extract_version_values auch die Keys mit aus, die es aus dem Image gelesen hat - dessen Ursprung war nämlich genau das Generieren der erwähnten Datenbasis für die Signaturprüfung. Das habe ich nur schon vorab irgendwann "öffentlich" gemacht (und es funktioniert ohnehin nicht mehr 100% in der öffentlichen Version, weil es schon wieder ein paar Monate/Jahre alt ist und nicht alle "Neuerungen" berücksichtigt), weil es irgendwo als Beispiel mal ganz praktisch war. Fertig ist das leider noch nicht - dafür gibt es zu viele offene Baustellen.

Ja, das hab ich auch festgestellt

Ich hoffe, wir sind uns einig, daß das mit dem "nicht wachsen" aber auch bei der Methode mit dem tar --append nur in 18 von 20 Fällen stimmt - oder gibt es zu dem oben Gezeigten mit den 36, 37 oder 38 Records (das könnten ja auch nur 16, 17, 18 oder doch 40976, 40977 oder 40978 Records sein - das Ergebnis ist immer dasselbe, solange im letzten Block weniger als 4 freie Records und mehr als ein einzelner - also eben genau zwei oder drei - vorhanden sind) noch Fragen?

Solange mein Ansatz, die Datei dann bei kritischen Fällen einfach auf eine "sichere Größe" zu erweitern, funktioniert, bleibe ich jedenfalls bei der Methode, nach dem "echten Payload" alle weiteren Daten abzuschneiden und exakt 4 leere Records in die Signatur einzubeziehen. Die ersten beiden werden dann zum Signatur-Member und die letzten beiden bilden die EoA-Marker aus dem Standard-Format.

Etwas anderes bleibt mir auch gar nicht übrig, denn das ganze Signieren und Prüfen soll ja nicht ausschließlich für AVM-Firmware funktionieren bei mir, sondern einen generellen Mechanismus zum sicheren Speichern und Wiederherstellen von Daten bieten. Da wäre es Unsinn, wenn ich mich an den "Fehlern" von AVM orientieren würde bei meinem Ansatz der Prüfung.

Wobei die Prüfung ja ohnehin nicht mein Problem ist (iirc klappt die sogar für die vergurkte 07.29 der 7530 bei mir, weil ja nur die Signatur durch leere Records ersetzt wird), sondern eher das richtige Signieren, damit die AVM-Firmware nicht in ihre eigene Falle tappt - wobei ja niemand bei AVM behauptet, daß ein korrektes TAR-Format auch das Ziel wäre. Es ist vermutlich ohnehin nur Zufall, daß man gerade dieses Format gewählt hat und nicht überall cpio o.ä. nutzt (allerdings gab es das in der BusyBox auch nicht von Beginn an).

PeterPawn commented 2 years ago

Ich habe mal noch ~zwei~ drei Änderungen beim Signieren eingebaut, die vielleicht in die von Dir gewünschte Richtung gehen: https://github.com/PeterPawn/YourFritz/commit/0b8fb11960235bbbe8a039bc9b38cd8dffb3493f

Erstens kannst Du - wenn der Punkt jetzt zur Extension gehört - durch geschicktes Setzen von YF_SIGNIMAGE_PRIVKEYEXT (https://github.com/PeterPawn/YourFritz/blob/0b8fb11960235bbbe8a039bc9b38cd8dffb3493f/signimage/yf_signimage.conf#L77 - hier dann eben prv) und YF_SIGNIMAGE_KEYS (nur auf den Pfad, ohne meinen "common prefix") auch bei Deinem bisherigen Namen für den Key ohne Symlink auskommen.

Zweitens gibt es jetzt eine gesonderte Nachricht, wenn der Key nicht gefunden wird - wobei das natürlich schon dadurch festgelegt wird bzw. wurde, welchen "Pfad" man selbst gesetzt hat(te) über name_prefix in der image_signing_files.inc (in der alten Version, jetzt heißt sie ja yf_signimage.conf und auch die Variablennamen sind anders) oder über FREETZ_IMAGE_SIGNING_PREFIX ... da wird dann halt auch der Key gesucht. Das mit den Extensions hatte ich auch im IPPF-Thread zum Signieren (gleich am Beginn, iirc in Beitrag 2 dort) beschrieben und so ungewöhnlich ist das Arbeiten mit unterschiedlichen Extensions nun auch wieder nicht, das macht Dir jeder Compiler so oder auch jedes gzip o.ä. - eher ist es ungewöhnlich, wenn man KEINE Extensions verwendet, um unterschiedliche Dateien, die zu demselben Kontext gehören, zu unterscheiden.

Drittens gibt es jetzt so etwas wie einen "fake mode", bei dem man das Signieren in einer Pipe aufrufen kann, wo dann halt das zu signierende Image-File auf STDIN reingeht und die signierte Datei auf STDOUT rauskommt. Allerdings ist das eben "geschummelt", weil dabei tatsächlich der komplette Stream von STDIN erst mal in eine temporäre Datei geschrieben wird (sonst könnte das Skript den Inhalt nicht mehrmals verarbeiten) und dann im weiteren Verlauf diese benutzt wird. Das führt dann zu einem höheren Platzbedarf beim temporären Speicherplatz, den das Skript benötigt. Außerdem muß man dabei dann das Kennwort für den privaten Schlüssel (wenn eines erforderlich ist, das Skript prüft das inzwischen auch erst einmal, bevor es ggf. danach fragt) auf irgendeinem anderen Weg schon festgelegt haben (entweder über eine Environment-Variable oder als zweiter Parameter beim Aufruf), weil das Skript es natürlich nicht von STDIN lesen kann (wenn es danach fragt), wenn da gar nicht das Terminal verbunden ist.

fda77 commented 2 years ago

sofern man eine bash hat

Ah, wenn man shebang ersetzt hat man immer eine: https://github.com/Freetz-NG/freetz-ng/blob/master/tools/make/yourfritz-host/yourfritz-host.mk#L6 Vermutlich ist die YOURFRITZ_HOST_BASH_AS_SHEBANG Liste nicht mehr aktuell, jedenfalls mit der neuen Version

Die Sache mit /dev/fd/ find ich nett, hab aber noch nicht so durchgeblickt dass ich selbst damit was schreiben würde

Die neue Version ist da schon gesprächiger, auch wenn ich nicht so genau weiß, wo Du da eine Fehlermeldung (dann vermutlich ohnehin bei der alten Version) vermißt hast.

"the private key file" sagt mir nicht wo die gesucht wird

$  tools/yf/signimage/sign_image  in.image pass > out.image
Found OpenSSL 1.1.1l  FIPS 24 Aug 2021
Check dgst command ... OK
Check rsa command ... OK
Verify hash algorithm md5 is supported ... OK
Checking input file format ... OK
Check the password for the private key file ... FAILED

Wobei "falsche Passwort" nicht ganz korrekt ist da es gar keine Datei zum prüfen gab

$ sh -x  tools/yf/signimage/sign_image  in.image pass > out.image

...
+ echo -en 'Check the password for the private key file ... '
Check the password for the private key file ... + openssl rsa -in /home/me/image_signing.key -noout -passin pass:xxx
                                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ rc=1
+ '[' 1 -eq 0 ']'
+ show_error
+ echo -e '\x1B[1;31mFAILED\x1B[0m'
FAILED
+ exit 1
+ rm -r /tmp/tmp.jPQIYp2RRQ

Deinen Ansatz, die Dateien nur pub und prv zu nennen, kann ich nur schwer nachvollziehen

Jo... mir ist halt nichts netteres eingefallen. Im .signature Verzeichnis liegt normalerweise sonst nichts. Ich glaub die pub hatte ich noch extra (in diesem Format) gespeichert weil die später auch ins Image soll. Evtl gibt es dann auch kein Passwort, da fakeroot sich rekursiv aufruft, mal mit fakeroot/pseudo und mal ohne. Bei Aliens mit mehreren Images sogar noch öfter

unterschiedliche Keys verwenden oder in der Konfiguration für Onkel Karl und in der für Tante Erna ebenfalls

Klar wäre das möglich, wäre aber Aufwand. Und braucht das wirklich jemand? Ich bin mir nicht sicher. Das ".signature" Verzeichnis verhält sich wie das "dl", es wird ein Link nach $HOME erstellt falls es nicht existiert. Ansonsten kann man vorher einen Link oder Verzeichnis erstellen. So kann man den Checkout löschen und behält trotzdem den eigenen Key mit dem man später nochmal updaten kann. Das ganze ohne dass man sich vorher mit dem Signieren überhaupt beschöftigt hat. Ich glaub dazu steht auch was im menuconfig unter help der Option

YF_SIGNIMAGE_PRIVKEYEXT

Prima, dann kann ich das so verwenden

FREETZ_IMAGE_SIGNING_PREFIX=".signature/"
YF_SIGNIMAGE_PRIVKEYEXT="prv"

nur werden da die Keys als XML-Datei erfaßt/verwaltet:

Am besten nimmst du einfach die key1s aus ng, die sind vollständig ausser https://freetz-ng.github.io/freetz-ng/FIRMWARES.html#not-supported-devices Vermutlich gibt es gar nicht mehr alle Images in freetz bei avm zum download. Dir fehlt noch der optionale key4 (btw key3 bei extendern ohne dect). "HWRevision" und "name" kannst du auch aus config/.img/ fischen. "key_location" scheint mir überflüssig

Für die notwendige Sicherheit, daß da niemand an den XML-Daten herum gepfuscht hat, sollte die dann signiert werden

Seit auch andere Schreibrechte in ng haben, hab ich auf signierte Commits umgestellt, das müsste reichen

Auch das (automatische) Auslesen der AVM-Keys aus den Images habe ich irgendwo schon mal gemacht

Das wäre eine schlechte Idee da geprüft werden soll ob die zu entpackende Datei (freetz/: md5 beim download) von avm signiert wurde. Vor allem bei über Juis automatisch heruntergeladene Dateien. Das generate Script für config/.img/ zeigt aber an wenn es einen neuen Key gibt

iirc klappt die sogar für die vergurkte 07.29 der 7530 bei mir

Die funktioniert sogar mit beiden Varianten. :D Wie wahrscheinlich ist Zufall?

Übrigens kann man freetz mit make firmware-nocompile zum testen aufrufen, das spart viel Zeit - ergibt nur kein funktionierendes Image.

Ich warte aber vorerst noch mit dem bump, bis der signimage-Branch gemergt ist. Sonst gibt es nacher im YourFritz-master eine Änderung die unbedingt nötig ist...

PeterPawn commented 2 years ago

"the private key file" sagt mir nicht wo die gesucht wird

Na halt da, wo Du das - in FREETZ_irgendwas - festgelegt hast (und das ist nicht die einzige Option).

Wobei "falsche Passwort" nicht ganz korrekt ist da es gar keine Datei zum prüfen gab

Da steht auch wieder nicht "Das Kennwort ist falsch.", sondern "Das Kennwort für den privaten Schlüssel wird geprüft ... fehlgeschlagen" (und auch das ist schon Absicht, ich versuche nun mal solche Meldungen auch so zu verfassen, daß sie die tatsächlichen Umstände wiedergeben). Das kann nun mal alles sein, was eine erfolgreiche Prüfung des Kennworts verhindert - bis hin zum fehlenden privaten Schlüssel und wo der zu liegen hat, sollte man eben auch vorher schon wissen.

Ja, wer den Key mit dem ebenfalls dafür bereitgestellten Shell-Skript erzeugt hat, der hat dabei auch die Information erhalten (egal, ob sie ihn interessiert oder nicht), wo die Dateien erzeugt wurden: https://github.com/PeterPawn/YourFritz/blob/60deb45a11906080365c08c7f7d924abc720f1f2/signimage/generate_signing_key#L213 - und das ist genau derselbe Platz, wo sie danach auch wieder gesucht werden (wenn man keine Einstellungen ändert/überstimmt).

Aber hier weiß ich jetzt ohnehin nicht genau, worauf Du hinaus willst - schon hier: https://github.com/PeterPawn/YourFritz/issues/12#issuecomment-982259141 habe ich Dir ja in "Zweitens" geschrieben, daß ich dann eben auch noch eine Prüfung (samt Fehlermeldung) eingebaut habe, ob das Key-File beim Signieren existiert oder nicht.

Am besten nimmst du einfach die key1s aus ng

Danke für das Angebot, aber: Danke, nein - keinesfalls.

Du hast vermutlich die mit dieser Datei/XML-Datensammlung verbundenen Intentionen nicht verstanden - vielleicht liegt das ja daran, daß Du das alles immer nur durch die Freetz-Brille betrachtest? Bei mir gibt es schon seit 2 1/2 Jahren diesen Branch: https://github.com/PeterPawn/YourFritz/tree/signimage_database/ und die darin zu findenden Skript-Files (in erster Linie in signimage/database) erzeugen heute schon beim richtigen Aufruf eine solche Datenbank - allerdings nur aus den jeweils letzten Firmware-Images vom AVM-Server.

Etwas anderes braucht es üblicherweise auch nicht (und wer das nicht für "alle" Boxen haben will, kann sich sogar auf ein paar ausgewählte Modelle beschränken - außerdem sind die Keys üblicherweise in allen Firmware-Versionen eines Modells dieselben) und bei den erwähnten Skript-Files wird dann VOR dem (TLS-gesicherten) Download der Benutzer auch noch aufgefordert, sich von der Gültigkeit des AVM-Zertifikats für den Download-Server zu überzeugen und dann werden nur damit gesicherte Verbindungen beim Download irgendwelcher Images akzeptiert. Wenn man dann aus diesen - sicher von AVM stammenden - Images die Keys extrahiert, kann man auch sicher sein, daß man die korrekten Daten erhalten hat und die Datenbank am Ende (als XML-Datei) signieren.

Und DIESE Datenbank kann man dann selbst verwenden oder ich schaffe es irgendwann doch noch, mal eine "komplette" zu veröffentlichen und meinerseits zu "unterschreiben" - dann kann jemand, der mir vertrauen möchte (wozu man nicht gezwungen wird, weil man sich die DB dann auch selbst zusammenstellen kann), auch eine vorbereitete Datenbank verwenden. Diese Datenbank kann man dann beim Download aus unsicheren Quellen verwenden, um die Echtheit der Datei (und auch ihre Integrität, weil Übertragungsfehler ebenfalls die Prüfung fehlschlagen lassen beim Download vom Hersteller) zu prüfen.

Und das eben nicht nur in Freetz, sondern da, wo man es selbst braucht - angefangen hat das ganze Thema für mich überhaupt nur (als "öffentliches" Projekt), weil ich für modfs eine Möglichkeit haben wollte, die Echtheit der Vorlage zu prüfen, um mich nicht dem Vorwurf auszusetzen, mit der Benutzung ohne eine solche Prüfung zusätzliche Sicherheitslücken zu ermöglichen. Man KANN die Signaturprüfung auch übergehen, wenn man bewußt das Risiko eingehen will - der Standard ist (seitdem die Signier-Lösung verwendbar ist) ein anderer.

Du magst ja primär Freetz als Ziel sehen und wenn etwas auf dem Build-Host funktioniert, auch damit zufrieden sein. Das ist aber nicht mein eigener Anspruch - ja, Freetz/-NG ist für mich nur EIN anderes Projekt, was diese Lösung nutzen kann (oder auch nicht, je nach Gusto) und ich werde auch immer eine Implementierung vorziehen, die solche Lösungen allgemeiner einsetzbar macht.

Daher der Drang, so etwas max. POSIX-kompatibel zu machen und auf alles Unnötige (auch an zusätzlichen Programmen) zu verzichten - auch wenn das nicht bei allen Alternativen performant genug zu lösen ist und dann muß man eben auch mal auf andere Tools (hier eben auf openssl und tar) zurückgreifen.

Jedenfalls gibt es eben auch nicht nur Firmware-Files für Boxen und Repeater, sondern auch noch für Zubehör und daher ist Deine Wahl, nur die ersten Keys jeweils zu sichern, zwar für Freetz-NG vielleicht nachvollziehbar, aber das bringt für andere Anwendungen eben nichts. Während man aus einer solchen XML-Datei auch die Daten für Freetz generieren könnte, klappt das umgekehrt schon aus offensichtlichen Gründen (die Daten liegen in Freetz gar nicht ALLE vor) überhaupt nicht.

Und dazu gehört auch die Frage, warum ich jeweils auch die Dateinamen der Key-Files aus der Firmware in der Datensammlung speichere ... die Info, wofür der Schlüssel eigentlich mal gedacht war (als Deduktion aus dem Dateinamen, unter dem er gespeichert war), ist in anderen Anwendungen vielleicht doch mal wichtig - und da juckt es mich nicht einmal, wenn der Zubehör-Key (der mit Index 3) in jeder Box/Firmware derselbe ist. Wenn es nämlich mal nicht so sein sollte, braucht man nur den richtigen, anderen Key einzutragen und die Sache funktioniert wieder wie zuvor.

Dir fehlt noch der optionale key4

Die Definitionen in der XSD-Datei sind jederzeit anpassbar, wenn es neue bekannte "Key-Typen" geben sollte - und wenn ich mich richtig erinnere, interessiert es die Skript-Files zum Generieren der Datenbasis gar nicht, wieviele Key-Files es gibt, sondern es werden einfach alle, die auf die Namensvorgaben passen, ausgelesen und abgelegt - da wo es bekannt ist, wofür die benutzt werden, wird dann key_usage entsprechend gesetzt, ansonsten eben nicht.

Das wäre eine schlechte Idee da geprüft werden soll ob die zu entpackende Datei (freetz/: md5 beim download) von avm signiert wurde.

Da liegt ja auch offensichtlich ein Mißverständnis vor - die Datenbank bei mir soll ja nicht "on the fly" erstellt werden, wenn man ein bestimmtes Image prüfen will, sondern irgendwann zuvor einmalig (ggf. mit Update). Obwohl "on the fly" sogar ginge, denn die Prüfung des TLS-Zertifikats für den Download-Server sollte ebenso sicher sein, wie die Prüfung mit Public-Keys aus unsignierten Quellen - aber das war eigentlich auch nie das Ziel, sondern die Präferenz war/ist die bereits vorliegende Datenbank mit gesichertem Inhalt, so daß die Public-Keys auch nicht verändert worden sein können.

Beim Einsatz auf der FRITZ!Box (da hat das eben - wegen modfs, siehe oben - seinen Ursprung) braucht man so eine Datenbank ohnehin nur dann, wenn das Firmware-Image nicht für das Modell ist, auf dem man sich gerade befindet ... denn da liegen die Keys ohnehin lokal vor (Option -b bei der Prüfung mit yf_check_signature - das ist der neue Name) und müssen nirgendwoanders gesucht werden.

Wie wahrscheinlich ist Zufall?

Ich habe mir das in fwmod bisher nie richtig angesehen bei der Prüfung (ich habe halt meine eigene Lösung und die funktioniert eben nicht nur unter Freetz/-NG) - wenn da der Signatur-Member vor der Prüfung aus dem Image gelöscht wird (tar --delete), dann braucht es gar keinen Zufall, weil damit dann wieder die zwei leeren Blöcke als EoA-Header vorhanden sind und damit bei der Ausgabe kein zusätzlicher 10 KB-Block hinzugefügt werden muß.

Jetzt habe ich doch mal einen Blick in Dein fwmod gewagt - das finde ich jetzt wieder witzig, denn wenn ich das richtig sehe, braucht bei Dir dann die Prüfung der Signatur stattdessen Platz für eine zusätzliche Kopie des Images, was bei mir (bis zu den Änderungen mit dem 'in-place'-Signieren bzw. eigentlich immer noch, weil das ja nur eine gefakete Pipe ist) nur beim Signieren der Fall war.

Aber das mit der Kopie versuche ich mir jetzt als (eigene) Prüfung gerade auf einer FRITZ!Box - sagen wir mal mit 256 MB RAM - vorzustellen ... auch AVM hat da einiges zu tun, um das alles "in einer Pipe" zu erledigen und ohne zusätzliche Kopien des gesamten Images - deshalb lädt man dort gerne mal direkt aus dem Internet und speichert das Image zwischendurch gar nicht erst (bzw. neuerdings dann sogar im NAS-Flash) und nimmt nur den entpackten Archiv-Inhalt ins tmpfs. Spätestens wenn das Image (bei limitiertem Hauptspeicher und eine "echte" Swap-Datei (das ramzswap zähle ich jetzt mal nicht) gibt es i.d.R. nicht) dann zu wachsen beginnt (die für die LTE-Geräte sind ein schönes Beispiel), macht so eine zweite Kopie keinen Sinn mehr bzw. zwingt die Box in die Knie.

DAS habe ich bei der Prüfung schon eleganter gelöst - zwar müssen auch bei mir die Daten irgendwo liegen, aber nur einmal und danach werden sie direkt an das Hashen verfüttert, wobei anstelle der Signatur-Datei dann eben leere Blöcke verwendet werden. Mit diesen drei dd-Kommandos: https://github.com/PeterPawn/YourFritz/blob/60deb45a11906080365c08c7f7d924abc720f1f2/signimage/check_signed_image#L720 wird genau derselbe Effekt erzielt, nur braucht es dafür eben nur eine einzige Kopie der Datei, weil das Ergebnis (und zwar block- und nicht dateiweise) direkt an den openssl-Aufruf geht. Einige Wege, wie man die Anzahl der Blöcke vor und nach dem Signatur-Member ermitteln kann (danach MUSS man eigentlich nicht wissen und kann einfach bis zum Dateiende arbeiten lassen), hatte ich im Signatur-Thread im IPPF erst kürzlich gezeigt - wenn man mit der Suche nach dem Header am Dateiende beginnt, geht das ratz-fatz, auch ohne passendes grep oder ähnliches - alles nur mit dd und cmp.

Und ohne die Veränderungen an der zu prüfenden Image-Datei braucht man auch die ganze Kopie nicht - Deinen "fix" (der für mich selbst bei --blocking-factor=20 keinen richtigen Sinn ergibt und wohl eher dafür sorgen soll, daß sich Dein tar nicht über Dateien ohne EoA-Blöcke beschwert) halte ich (für die eigentliche Prüfung) ohnehin für überflüssig/nicht logisch. Mal ganz abgesehen davon, daß auch das wieder nur dann (bei Dir) funktioniert, wenn man ein tar-Kommando verwendet, was auch tar --delete kann.

Obendrein geht das (so aus dem Kopf und als "erste Überlegung") auch dann schon schief, wenn das zu prüfenden Image mal keine 10 KB-Blöcke verwendet (für das BB-tar habe ich das oben gezeigt - derartige Images kannst Du dann weder signieren noch prüfen mit Deinem Vorgehen) oder generell einen anderen blocking-factor als Dein eigenes tar-Kommando. Denn modifizierst Du das originale Image und ändert sich dabei die Dateigröße (selbst wenn zusätzliche Blöcke ohnehin nur mit Nullen gefüllt sind), dann stimmt auch der zu prüfende Hash in der Signatur nicht mehr.

Letztlich besteht meine Prüfung auch nur aus den drei (bzw. vier mit dem openssl-Aufruf am Ende der Pipe) Kommandos, auf die der Link oben zeigt - alles andere rundherum, ist nur Vorbereitung - das Prüfen des Formats, das Suchen des richtigen Offsets für den Signatur-Member und das Zusammenstellen potentieller öffentlicher Schlüssel (die in verschiedenen Formaten vorliegen können) inkl. der Suche nach dem "passenden" Schlüssel. Und wenn AVM doch mal auf längere Keys umsteigen sollte (solange man bei RSA bleibt), dann sind meine Skript-Dateien darauf auch schon vorbereitet - auch auf eine Änderung beim verwendeten Hash-Algorithmus.

Abseits von der AVM-Firmware kann man auch heute schon mehr Sicherheit nutzen - und auch wenn das mal für AVM-Firmware geschrieben wurde, ist die Verwendung ja nicht darauf limitiert. Schon das Signieren von Images mit dem Box-Schlüssel, der mittlerweile auch ein 2048-Bit-Key ist, war von Beginn an eine "Erweiterung" - wenn ich nur stumpf das AVM-Zeug nachbauen wollte, könnte man sich in der Tat ein paar Kunststücke ersparen ... nur ist das eben (bei mir) gar nicht die Aufgabenstellung.

Das alles sollte man bei einem "geht doch alles viel einfacher" auch immer im Hinterkopf behalten - das KANN stimmen, nur sollte man dann die richtigen "Umstände" und die aus der Implementierung folgenden Limitierungen auch immer mit aufzählen. Das ist in etwa wie bei den vielen (falschen) Anleitungen zum Debranden der 6490-Boxen von den Kabel-Providern - die beziehen sich i.d.R. auch nur auf das Modell, was die jeweiligen Autoren kennen (und das ist meist eben nur eines bzw. ihr eigenes) und da das eben nie klar "herausgearbeitet" wird, fallen so viele 6490-Besitzer auf die falschen Versprechungen dieser Anleitungen herein.

fda77 commented 2 years ago

Na halt da, wo Du das - in FREETZ_irgendwas - festgelegt hast

Ich hatte das Script ohne irgend welche Optionen aufgerufen

wer den Key mit dem ebenfalls dafür bereitgestellten Shell-Skript erzeugt hat

Das hatte ich mir gar nciht angesehen. Wollte ich auch nicht weil ich schon einen Key hab

nur die ersten Keys jeweils zu sichern

Dort wo nötig wird auch der inhaus-key (4) genutzt, zb neueste dvb-c firmware (inhaus) https://github.com/Freetz-NG/freetz-ng/blob/master/config/avm/signature.in#L5 Wenn man ein Image verifiziert hat, kann man den Dect und den anderen Key einfach daraus entnehmen - falls man die wirklich brauchen sollte

wenn da der Signatur-Member vor der Prüfung aus dem Image gelöscht wird (tar --delete), dann braucht es gar keinen Zufall, weil damit dann wieder die zwei leeren Blöcke als EoA-Header vorhanden sind und damit bei der Ausgabe kein zusätzlicher 10 KB-Block hinzugefügt werden muß.

Prima, ich habs nicht gewusst und trotzdem gemacht :D

Jetzt habe ich doch mal einen Blick in Dein fwmod gewagt - das finde ich jetzt wieder witzig, denn wenn ich das richtig sehe, braucht bei Dir dann die Prüfung der Signatur stattdessen Platz für eine zusätzliche Kopie des Images

Beim prüfen ja. Die Funktion legt sich ein Verzeichnis an und löscht es. Wie du das intern gemacht hast weiss ich nicht, ich finde es aber umständlich wenn man FÜR ein Script temporäre Dateien angeben kann und diese nach Aufruf wieder löschen muss.

sich Dein tar nicht über Dateien ohne EoA-Blöcke beschwert)

mein (gnu) tar ist etwas zickig bei kaputten tar-archiven, wenn ich es richtig in Erinnerung hab bleibt es in manchen Fällen einfach stecken und wartet unendlich auf das nicht vorhandene Ende

PeterPawn commented 2 years ago

Die neuen Versionen werden auch komplett ohne tar auskommen (zumindest optional, wenn man keines hat oder keines haben will), womit ich dann wieder eine Abhängigkeit los bin und auch nicht mehr über Blocking-Faktoren und/oder die Fähigkeiten bzw. Mängel irgendeines vorhandenen tar-Kommandos nachdenken muß - eine Nicht-POSIX-Referenz weniger (sogar einigermaßen performant nach den bisherigen Tests).

Nur das OpenSSL werde ich wohl nicht so einfach ersetzen können durch irgendetwas POSIX-Konformes und das ist bei Krypto-Implementierungen ohnehin keine gute Idee, es selbst machen zu wollen. Aber mit dieser einen Abhängigkeit jenseits der POSIX-Spezifikationen kann ich dann leben ... auch die Abhängigkeit von privatekeypassword (wenn man den Key der Box nutzen will) habe ich mittlerweile raus.

Alles das, was ich in den Branch einchecke, ist noch nicht in Stein gemeißelt - daher noch einmal dringend die Bitte, nicht auf dieser Basis jetzt schon irgendetwas irgendwo anders einbauen. Ich mache so etwas i.d.R. iterativ - wenn's erst mal prinzipiell läuft, wird es hinterher "schön" gemacht (sofern ich die Zeit dafür finde, was hier aber so sein wird).

fda77 commented 2 years ago

Jo, ich warte auf den merge zum master-branch. Falls dort zb zuerst ein bootmanager update reinkommt

Prisrak1 commented 2 years ago

etwas bekomme nicht ganz mit der Signierung halt hin..Update über AVM UI gehen nicht.

bash YourFritz/signimage/generate_signing_key Der sign_key liegt dann als image_signing.asc im Home bzw. root Verzeichnis. Das geht.

Wenn ich meine key´s durch die "pub und prv" (avm_firmware_public_key9 = image_signing.asc = pub = oder generiert von Freetz-NG -> avm_firmware_public_key8) in ".freetz-signature" ersetze gehts mit dem Update über AVM UI nicht. Dasselbe ist doch, wenn der Ordner ".freetz-signature" gelöscht wird und neue key´s mit meinem Passwort in "fmod Sign image file ---> erstellt werden. Es wird ein "avm_firmware_public_key8" ... /build/modified/filesystem/etc/.. generiert. Das Image mit meinem generierten öffentlichen key ist schon auf der Box 6660, oder 6490 drauf.

Anders geprüft: meine mit meinem Passwort generierte key´s in YourFritz/signimage/ im Verzeichnis ".freetz-signature" passen umbenannt werden durch mein Passwort vor der Signierung in Freetz-NG überprüft. Wenn das Passwort passt, läuft alles mit dem Bau des Images durch. Was läuft falsch? Die ( ) Use tar --oldgnu / (X) Use yf-signimage Varianten, spielen keine Rolle. Alles ist gleich.

PeterPawn commented 2 years ago

Ich habe nur die Hälfte verstanden beim Versuch, das zu lesen.

Aber zum "Stichwort" 6660 verweise ich auf: https://www.ip-phone-forum.de/threads/update-auf-neue-version-fb6591.311669/ - da stellt(e) sich dann auch heraus, daß es gar nicht an der Signatur scheitert, sondern erst beim Aufruf von burnuimg.

Wenn's bei der 6490 auch Probleme gibt, dann bitte noch einmal versuchen, das irgendwie zu erläutern - diesmal aber bitte verständlich. Wenn's an der deutschen Sprache scheitern sollte, gerne auch in Englisch ... aber aus dem o.G. werde ich bei aller Mühe, die ich mir gebe, nicht schlau. Vielleicht hilft auch eine der neuen Versionen aus dem signimage-Branch - dem fehlen zur Veröffentlichung eigentlich nur noch ein paar Funktionen zum Konvertieren der öffentlichen Schlüssel zwischen verschiedenen Formaten in yf_genkey.

Prisrak1 commented 2 years ago

Ein Image wird signiert und auf die Box 6490 geflasht. Selbes Image kann danach dennoch nicht über die AVM Oberfläche geflasht werden.

PeterPawn commented 2 years ago

Ein Image wird signiert und auf die Box 6490 geflasht.

Wann, wie genau und womit (mit welchem Key, ist der öffentliche schon installiert, etc.) - da gibt es schon beim Signieren mehrere (offene) Fragen und beim Flashen erst recht, denn hier ist nicht mal erwähnt, auf welchem Weg dieses Flashen erfolgt~en~ sein soll.

Selbes Image kann danach dennoch nicht über die AVM Oberfläche geflasht werden.

Das wäre auch nicht wirklich überraschend, wenn z.B. in diesem Image der öffentliche Schlüssel fehlt (jedenfalls der, der zum privaten Key gehört, mit dem das Image signiert wurde) - aber auch hier ist ja nicht wirklich klar, welches OS da gerade auf der Box arbeitet, wenn dieses Flashen über das AVM-GUI nicht funktioniert. Das könnte (a) ein originales von AVM oder (b) ein älteres, bereits modifiziertes oder sogar (c) das zuvor (siehe erstes Zitat) auf anderem Weg geflashte neue OS sein.

Dir mag das ja alles sehr präsent sein, weil Du es gemacht hast - alle anderen fangen mit ihrem Wissensstand (was Dein Problem anbelangt) aber bei Null an und DENEN mußt Du das so erklären, daß sie Dein Problem auch verstehen können. Was mich anbelangt, ist Dir das in Deinen zwei letzten Versuchen nicht gelungen.

Prisrak1 commented 2 years ago

Vor drei Tagen wurde die F!B 6490 mit der Image "6490_07.29.ger_freetz-ng-33164MOA-UNKNOWN_20211224-134437.image" über die Freetz Oberfläche geflasht.

Erstellt wurde dieses Image zum ersten Mal mit den dazu erzeugten keys "image_signing.rnd, mage_signing.pem, age_signing.key, image_signing.asc". Paralel wird ein Ordner ".freetz-signature" im Homeverzeichnis mit 2 Dateien "prv und pub" erstellt. Info. Wenn die beiden Keys im Ordner ".freetz-signature" gelöscht werden, kann man sich neue mit einem neuen Passwort in Freetz-NG erzeugen lassen.

Wenn diese nicht gelöscht werden, das Passwort aber in Freetz-NG verändert wird, wird es keine Signierung geben. Wen alles passt, wird ein "avm_firmware_public_key8" in ... /build/modified/filesystem/etc/.. generiert. Dieser gleicht der Größe zumindest hin den image_signing.asc und dem pub.

Alternativ kann man sich die passenden Keys über dein Skript erzeugen, (YourFritz/signimage/generate_signing_key)

Die Flash-Methode wurde alternativ mit Ftp und Push-Firmware durchgeführt. Ergebnis war gleich: das Flashen über System/Update/FRITZ!Osdatei ging nicht.

Hast Recht: Meine Frage und deren Ausführung muss dem möglichen künftigen Mitleser in etwa nachvollziehbar sich ergeben, obwohl die Problematik vermutlich schon zuvor wohl nachvollziehbar war.

PeterPawn commented 1 year ago

Implementation partially done 8 month ago: https://github.com/PeterPawn/YourFritz/commits/main/signimage