Friday, February 14, 2025

Embracing Undefined Behaviour

Suppose you're a pretty seasoned C developer. You've read quite a lot of articles about Undefined Behaviour in C, perhaps you've even read the C standard text to clarify some obscure points. 

You are always careful to avoid UB in your code, and you use all the relevant useful tools in your arsenal - ubsan, compiler warnings, static analyzers - just to be in the safe side. You are pretty sure you understand quite a lot of aspects of UB, while also knowing that in C it's extremely challenging to comprehend UB's full extent and effects, especially in the presence of different compiler optimizations. 

You are familiar with the adage about UB being used to enable compiler optimizations, and you've even seen countless examples in articles and blog posts - like this one, taken from Wikipedia:

int foo(unsigned char x) { int value = 2147483600; /* assuming 32-bit int and 8-bit char */ value += x; if (value < 2147483600) bar(); return value; }

Of course, you're not naive enough to write something like that. You've also come across more complex examples that demonstrate how compilers can misbehave due to accidental UB, so you understand the dangers well.

However, you recognize that many of these examples are specifically designed to frighten you with the dangers of UB - and for good reason. Readers must learn to avoid it. This, however, contrasts starkly with the also stated fact that UB rules (which you must not break!) allow for important compiler optimizations.

You find it a bit difficult to wrap your head around what this means in practice.

One day, you're tasked with writing a function that starts from the unsigned value 0, adds 7 to it N times in a loop (where N is a small positive integer), and returns the unsigned result. Yes, it's a silly example—but bear with me.

You assign this to a junior colleague with not as much exposure to UB as yours, and he comes up with this solution, accustomed to the common idiom of using an int as an induction variable in loops:

unsigned int compute_something_1(int j) {
unsigned int something = 0;
for (int i = 0; i <= j; i++) {
something += 7;
}
return something;
}

Being overtly cautious about UB, you know that signed - unsigned comparisons are risky (though ostensibly most compilers go through some pains to produce what the programmer actually had in mind in the well-formed case, because sign mismatch in comparisons is one of the most common mistakes in C, especially in the induction variable of a loop, like it's the case here). You also know that signed integer overflow is UB too. 

Wanting to avoid these pitfalls, you rewrite your colleagues code like this: 

unsigned int compute_something_2(unsigned int j) {
unsigned int something = 0;
for (unsigned int i = 0; i <= j; i++) {
something += 7;
}
return something;
}

Now, the signedness matches everywhere, including the induction variable. Everything seems fine.

Until your curious coworker fires up godbolt to check the assembly output of the two snippets under GCC -O2 (https://godbolt.org/z/8rEj1qhWq):

compute_something_1:
add w1, w0, 1
cmp w0, 0
lsl w0, w1, 3
sub w0, w0, w1
csel w0, w0, wzr, ge
ret

 

compute_something_2:
mov w1, 0
mov w2, 0
.L2:
add w1, w1, 1
add w2, w2, 7
cmp w0, w1
bcs .L2
mov w0, w2
ret

What happened here? 

Why does the compiler optimized the naive version by hoisting the calculation out of the loop (as you already expected it would do), but leave your "carefully thought-out" implementation unoptimized?

(I use ARM64 code generation because the assembly code is more clear - X86_64 lowers to a LEA instruction which is am optimal but sometimes confusing for the reader way to combine an integer addition with a multiplication - feel free to compare X86_64 output and you'll see essentially the same effect).

The reason this happens is because of incorrect communication of value bounds to the compiler.

In the first case, the compiler assumes that the signed induction variable i cannot overflow beyond MAX_INT (since signed overflow is UB) and optimizes accordingly, hoisting the calculation outside the loop, in this case.

In our "corrected" case however, the compiler actually loses information: Unsigned overflow is NOT Undefined Behaviour - it's well specified to wrap-around to 0. The compiler cannot prove that the loop terminates (and indeed it does not terminate for the case j == MAX_UINT), and leaves the loop unoptimized to cater for the case we indeed did want an infinite loop.

The point I want to make here is: Our well-intentioned effort to eliminate Undefined Behaviour, made the compiler unable to optimize our code!

Note that the code snippets are not functionally identical - there are values of j for which the two snippets produce different results. This is, "of course" our own mistake - we didn't provide value bounds to the compiler. Remember that we assumed "N is a small value"? We assumed that, but the compiler does not.

This is an equally common mistake as the first one - doing signed / unsigned comparisons. Albeit not having any direct evidence, I'd dare to say it's even more common than that.

There are several solutions to this specific problem, and all of them are somewhat unsatisfactory: 

Assume that the upper bound of N is 256.

1) The obvious solution - you can check parameter bounds explicitly inside the function. 

#define N 256

unsigned int compute_something_2_bounds_checked(unsigned int j) {
if (j >= N) {
return 0;
}
unsigned int something = 0;
for (unsigned int i = 0; i <= j; i++) {
something += 7;
}
return something;

This works, and the compiler is doing the hoisting optimization:

compute_something_2_bounds_checked:
add w1, w0, 1
cmp w0, 256
lsl w0, w1, 3
sub w0, w0, w1
csel w0, w0, wzr, cc
ret

The reason that this is unsatisfactory is because we have to decide what to do in the out-of-bounds condition, and check for it every time we use N. This is in fact one of the counter-arguments for automatic bounds checking - not that the bound checking is by itself expensive (most modern branch predictors are smart enough to make the bounds checking essentially costless), but the mere fact that you have to insert explicit bounds checks everywhere complicates the CFG to the degree that other optimizations are elided as undecidable! (notwithstanding the fact that this does not happen in the quite simple example presented here).

We cannot also rely to value range propagation applied by the compiler - it does its best to try, but it cannot always be done. For example, compute_something() might be inside a library.

A very common suggestion is to check your invariables using assert(). This communicates the relevant bounds to the compiler, and has the effect of enabling optimizations (a fact that is also not widely known!). 

This works...

#include <assert.h>
#define N 256

unsigned int compute_something_2_assertion(unsigned int j) {
assert(j < N);
unsigned int something = 0;
for (unsigned int i = 0; i <= j; i++) {
something += 7;
}
return something;
}

...but...

.LC0:
.string "/app/example.c"
.LC1:
.string "j < N"
compute_something_2_assertion:
cmp w0, 255
bhi .L7
add w0, w0, 1
lsl w1, w0, 3
sub w0, w1, w0
ret
.L7:
stp x29, x30, [sp, -16]!
adrp x3, .LANCHOR0
adrp x1, .LC0
mov x29, sp
adrp x0, .LC1
add x3, x3, :lo12:.LANCHOR0
add x1, x1, :lo12:.LC0
add x0, x0, :lo12:.LC1
mov w2, 5
bl __assert_fail
.set .LANCHOR0,. + 0
__PRETTY_FUNCTION__.0:
.string "compute_something_2_bounds_checked"

...it inserts all the overhead of checking for the bound, PLUS the additional overhead of aborting the program if the value is out of bounds.

Another issue with this approach is that it's not unusual for production code to be compiled with NDEBUG defined. This eliminates the entire assertion, together with the optimization that it provides:

#define NDEBUG
#include <assert.h>
#define N 256

unsigned int compute_something_2_assertion_off(unsigned int j) {
assert(j < N);
unsigned int something = 0;
for (unsigned int i = 0; i <= j; i++) {
something += 7;
}
return something;

We're back to square one - and worse: An optimization turned off in production mode, where it's exactly where we need it most: 

compute_something_2_assertion_off:
mov w1, 0
mov w2, 0
.L2:
add w1, w1, 1
add w2, w2, 7
cmp w0, w1
bcs .L2
mov w0, w2
ret

Another solution is using a type whose range is a strict subset of the induction variable bounds that can cause overflow in the loop, thus avoiding any chance of overflow: 

unsigned int compute_something_2_implicit_domain(unsigned char j) {
unsigned int something = 0;
for (unsigned int i = 0; i <= j; i++) {
something += 7;
}
return something;
}


compute_something_2_implicit_domain:
and w0, w0, 255
add w0, w0, 1
lsl w1, w0, 3
sub w0, w1, w0
ret

This one looks clever, but it's not only more contrived and largely unknown, it also does not communicate our intention to the reader of the code. What happens if the bound changes? Plus, of course, the problem that maybe the bound does not allow us to use a convenient sub-type. (e.g. it's 300 instead of 256). We have to get back to the other solutions of explicit checking.

There's just another way to communicate bounds to the compiler just the way we want to. Unfortunately, this way entails the use of two compiler intrinsics, PLUS a macro, if you care about readability (and you should):

#define ASSUME(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)
#define N 256

unsigned int compute_something_2_assume(unsigned int j) {
ASSUME(j < N);
unsigned int something = 0;
for (unsigned int i = 0; i <= j; i++) {
something += 7;
}
return something;
}

This works wonderfully, assuming (pun intended) you do it. It's definitely not a common idiom.

compute_something_2_assume:
add w0, w0, 1
lsl w1, w0, 3
sub w0, w1, w0
ret

But the biggest problem with all these solutions is that they all are just a big digression to the central issue I want to present - they apply just to the specific instance of the problem (and not perfectly - I didn't took the time to check for perfect equivalence of the "solutions").

This is because there are other kinds of UB than the particular example of signed vs unsigned overflow, and they all can be used to enable optimizations, sometimes resulting to counterintuitive results exactly when we are explicitly careful to avoid invoking UB!

A particularly contrived example is pointer aliasing: The mental model of keeping track of exactly what and when might alias can get so burdening that the best solution you often have is to use -fno-strict-aliasing, which is purported to also turn off several optimizations - though I have yet to personally observe this, I have no reason to believe it doesn't happen (I once intentionally compiled a large proprietary codebase with and without -fno-strict-aliasing just to compare the differences in assembly code output - and, curiously, there were none - but I have no doubt that I was just being lucky).

The takeaway lesson is that one does not only have to avoid UB. 

We must avoid UB (something that is already really hard), *while at the same time knowing what the side-effects of avoiding UB are*, in order to not fall into the trap of unintentionally under-specifying something that would be implicitly specified by UB, even if we never invoke UB. 

Looks like we have to *embrace* Undefined Behaviour rather than just knowing how to avoid it.

John Regher, who has written a lot about UB in C/C++ and Rust, believes that maybe Undefined Behaviour is by itself a bad term. Perhaps we should call it something else - but what?

 

If you are interested in a more thorough discourse of UB, I suggest you read the many relevant articles and blog entries by John Regher and Chris Lattner. This blog post was inspired by Chris Lattner's series about Undefined Behaviour, and particularly the paragraph "Advantages of Undefined Behavior in C, with Examples" in the first article of the series - I wanted to present a concrete case of an optimization caused by the assumption of lack of UB in a program, and how this benefit can be lost by unintentionall underspecifying assumed behaviour.

 

Wednesday, October 18, 2023

Πως να διαβάσετε μια ηλεκτρονική ταυτότητα

Πάμε τώρα παιδιά μου να διαβάσουμε μια ταυτότητα; ΠΑΑΑΜΕΕΕΕΕ!




Επειδή όμως δεν έχουμε ταυτότητα, θα διαβάσουμε ενα διαβατήριο. Ο τίτλος ήταν λίγο clickbait.

Θα χρειαστείτε ενα διαβατήριο (duh!) και εναν NFC smart card reader συμβατό με ISO 14443 και PC/SC. Εγω χρησιμοποίησα το DL533R της Digital Logic, αλλά επειδή εσείς σιγά να μην έχετε smart card reader, μπορείτε να δοκιμάσετε να παίξετε με το PC/SC NFC bridge για Android κινητά που θα βρείτε αν γκουκλάρετε για "frankmorgner vsmartcard".

Θα χρειαστείτε επίσης τον κώδικα που εχω γράψει αποκλειστικά για σας, στο

Προς το παρόν διαβάζει μόνο Ελληνικά διαβατήρια (με λίγη τύχη και άλλων εθνικοτήτων), επειδή δεν εχω ταυτότητα για να δοκιμάσω.

Ο,τι γράφουμε παρακάτω για τα διαβατήρια όμως, ισχύουν και για τις ηλεκτρονικές ταυτότητες, δεδομένου οτι βασίζονται ακριβώς στα ίδια πρότυπα.

Εαν θέλετε να προσαρμόσετε τον κώδικα για να λειτουργεί με Ελληνικές ταυτότητες, πιθανότατα θα χρειαστεί να πειράξετε μερικα OIDs και να προσθέσετε CMAC και AES 
αλγόριθμους, ανάλογα με το τί υποστηρίζεται απο την ταυτότητα. Pull requests are welcome.

"Ευτυχώς" τα διαβατήρια δεν έχουν μηχανισμό ασφαλείας που να επιτρέπει μόνο ορισμένο αριθμό λάθος πιστοποιήσεων πρίν κλειδώσουν - υποθέτω επίτηδες, επειδή θα ήταν μάλλον άσχημη εμπειρία να βρεθείτε με κλειδωμένο διαβατήριο μπροστά σε γκαβλωμένο Ισραηλινό ιμμιγκράτσο (σύνθετη λέξη απο το immigration και τον μπάτσο). 

Κάποιες ηλεκτρονικές ταυτότητες όμως έχουν τέτοιο μηχανισμό (οι Γερμανικές παραδείγματος χάριν), και σε περίπτωση που τις κλειδώσετε προσπαθώντας να τις διαβάσετε, θα απαιτήσουν επιπλέον πιστοποίηση με τον ειδικό κωδικό ξεκλειδώματος (ακριβώς όπως οι SIM καρτες με το PUK).

O ICAOς συνιστά όταν ακυρώνεται ενα διαβατήριο με το πανάρχαιο κόλπο "το τρυπάμε με τον διακορευτή" (διακορευτής, που σημαίνει ξεπαρθενιστήρι, είναι το επίσημο όνομα για κείνο το μαντζαφλάρι που ανοίγει τρύπες σε έντυπα), να δίνεται προσοχή ωστε να "διακορεύουμε" και το σημείο που βρίσκεται το NFC chip, ωστε αυτό να καταστρέφεται.

Για κάποιο άγνωστο σε μένα λόγο, ο Έλλην μπάτσος που μου ξεπαρθ... ε, "διακόρευσε" το προηγούμενο διαβατήριο, ξέχασε μάλλον να διαβάσει τη συγκεκριμένη παράγραφο του ICAO 9303, με αποτέλεσμα να εχω στα χέρια μου ενα ληγμένο διαβατήριο με λειτουργικό NFC chip, με το οποίο μπορούσα να κάνω όσες δοκιμές ήθελα.

Για να διαβαστεί το έντυπο, απαιτείται πιστοποίηση δικαιωμάτων ανάγνωσης. Δηλαδή πρέπει να γνωρίζετε είτε τον "Αριθμό Πρόσβασης Κάρτας" είτε τα περιεχόμενα της γραμμής MRZ (Ζώνη Μηχανικής Ανάγνωσης). Το διαβατήριο μου δεν υποστηρίζει αριθμό πρόσβασης, οπότε έχω υλοποιήσει μόνο το μηχανισμό MRZ.

Για να διαβάσετε το διαβατήριο σας θα πρέπει να δώσετε το "password" που προκύπτει απο τα τρία πεδία του MRZ που περιέχουν τον αριθμό εντύπου, το check digit του αριθμού εντύπου, την ημερομηνία γέννησης (τη δικιά σας, όχι του εντύπου), το check digit της, την ημερομηνία λήξης (του εντύπου, οχι τη δικιά σας), και το check digit της.

Ολα τα παραπανω αναφέρονται στο MRZ. Για παράδειγμα, εαν το MRZ σας είναι

I<UTOERIKSSON<<ANNA<MARIA<<<<<<<<<<<
L898902C<3UTO6908061F9406236<<<<<<<8

Tότε το MRZ password που αντιστοιχεί στο έντυπο είναι "L898902C<369080619406236"
Το πιο δύσκολο στην ολη ιστορία είναι η υλοποίηση των κρυπτογραφικών μηχανισμών ασφαλείας του ηλεκτρονικού έντυπου. Υπάρχουν δυο πρωτόκολλα που χρησιμοποιούνται στην πιστοποίηση δικαιωμάτων ανάγνωσης ICAO 9303 documents:

Το παλαιότερο πρωτόκολλο BAC, ονομασμένο προφανώς απο τον μπακαλιάρο, χρησιμοποιεί ενα απλό σχετικά μηχανισμό κρυπτογραφικής πιστοποίησης, με ανταλλαγή κλειδιώνε που προκύπτουν απο ενα hashing του password.

Εδω βρίσκεται και το πρώτο πρόβλημα: Όπως είπαμε παραπάνω, το password αποτελείται απο τον αριθμό εντύπου, την ημερομηνία γέννησης και την ημερομηνία λήξης του εντύπου. Το οποίο σημαίνει οτι η εντροπία των συγκεκριμένων πεδίων είναι τόσο μικρή που μπορεί να κάνει οποιονδήποτε ξέρει πέντε πράγματα απο κρυπτογραφία να αυτοκτονήσει κόβοντας τις φλέβες του με το διαβατήριο:

Οι ημερομηνίες έχουν φορμάτ YYMMDD, όπου το YY κυμαίνεται απο 00-99, δηλαδή συνολικά 100 πιθανές τιμές, το MM κυμαίνεται απο 01 μέχρι 12, και το DD απο 01 εως 30. Δηλαδή οι πιθανοί συνδυασμοί για κάθε ημερομηνία είναι 100 * 12 * 30 = 36000, προσφέροντας συνδιαστικά εντροπία 2 * log2(36000) = 30.271418572208 bits. Πάλι καλά που υπάρχει και ο αριθμός εντύπου μέσα, που στην περίπτωση του Ελληνικού διαβατηρίου (δυο γράμματα λατινικού αλφάβητου + 7 αριθμητικα ψηφία) μας δίνει ακόμα 32.654376100494 bits εντροπίας.

Η εντροπία αυτή μπορεί να μειωθεί ακόμα περισσότερο αν κάνουμε μερικές έξυπνες παρατηρήσεις για το πεδίο ορισμού και τις συσχετίσεις των δεδομένωνε: Στόν αριθμό εντύπου του διαβατηρίου για παράδειγμα - ολα μου τα διαβατήρια άρχιζαν απο AN η AT.

Επίσης, οι ημερομηνίες είναι πάρα πολύ κακή πηγή εντροπίας, καθώς και έχουν περιορισμούς και συνδέονται μεταξύ τους: Π.χ. ξέροντας οτι η ημερομηνία λήξης του εντύπου είναι ακριβώς 5 η 10 χρόνια μετά την ημερομηνία έκδοσης του, μπορούμε να αφαιρέσουμε τα Σαββατοκύριακα (στα οποία πολύ χλωμό να έχει εκδοθεί έντυπο). Η ημερομηνία λήξης του έντυπου είναι εξ'ορισμου τουλάχιστον πέντε (η δέκα) χρόνια μετά την ημερομηνίας γέννησης του κατόχου, ενω εαν δεν θέλουμε να διαβάσουμε ληγμένο διαβατήριο όπως στην περίπτωση μας, μπορούμε να υποθέσουμε οτι αυτό λήγει μέσα σε πέντε (κτλ) χρόνια μετά τη σημερινή ημερομηνία και έχει εκδοθεί τουλάχιστον την ημερομηνία που άρχισαν να εκδίδονται βιομετρικά διαβατήρια.

Σας αφήνω ως άσκηση να σκεφτείτε και άλλους τέτοιους περιορισμούς, και να υπολογίσετε το αποτέλεσμα που έχουν αυτοί οι περιορισμοί στην εντροπία του password του διαβατηρίου.

Αυτό το πρόσεξαν οι Γερμανοί όταν φτιάχνανε τις δικές τους ηλεκτρονικές ταυτότητες, και γι'αυτό το λόγο αναπτύξανε ενα καλύτερο πρωτόκολλο πιστοποίησης δικαιωμάτων απο το μπακαλιάρο, το οποίο λέγεται PACE, και είναι υποχρεωτική η χρήση του σε ολα τα βιομετρικά διαβατήρια που εκδόθηκαν μετά το 2018, ενώ νομίζω μετά το 2025 θα σταματήσουν να εκδίδονται έντυπα με BAC.

Το PACE λύνει το πρόβλημα της εντροπίας χρησιμοποιώντας τον γνωστό κρυπτογραφικό αλγόριθμο ανταλλαγής κλειδιώνε που έχει το όνομα εκείνης της μαγιονέζας. Το password εξακολουθεί να έχει μικρή εντροπία, αλλά δε χρησιμοποιείται άμεσα για την κρυπτογράφηση της επικοινωνίας - χρησιμοποιεί το password αναμεμιγμένο με τα προσωπικά κλειδιά του εντύπου και του μηχανισμού ανάγνωσης ωστε να αυξηθεί η εντροπία του κλειδιού με το οποίο κρυπτογραφείται η επικοινωνία.

Εδω βέβαια υπάρχουν μερικά κλασσικό κόλπα: Ακόμα και ΠΡΙΝ το ξεκλείδωμα του διαβατηρίου και την απόκτηση πρόσβασης ανάγνωσης, υπάρχουν κάποια δεδομένα τα οποία μπορούν να αναγνωστούν. Ενα απο αυτά είναι ο σειριακός αριθμός του NFC chip - για το λόγο αυτό ο ICAO προτείνει να τυχαιοποιείται ο σειριακός αριθμός σε κάθε ανάγνωση, ωστε να αποτρέπεται η σύνδεση σειριακού αριθμού με συγκεκριμένο έντυπο. Οντως, στο Ελληνικό διαβατήριο οι σειριακοί αριθμοί του NFC είναι τυχαιοποιημένοι. Ελπίζω να είναι και στις ταυτότητες.

Το δεύτερο κόλπο είναι πιο υποχθόνιο, αλλά εξίσου κλασσικό στην έρευνα συστημάτωνε ασφαλείας: Το πρωτόκολλο στο οποίο βασίζονται όλες οι έξυπνες κάρτες είναι το ISO 7816, το οποίο προτυποποιεί τις εντολές που δέχεται η έξυπνη κάρτα και τις απαντήσεις που δίνει. Ωστόσο, εαν δοκιμάσουμε να δώσουμε άκυρες εντολές η παραμέτρους για τις οποίες δεν λέει κάτι το πρότυπο, οι απαντήσεις που θα πάρουμε εξαρτώνται απο την υλοποίηση του ISO 7816 στο συγκεκριμένο NFC smartcard chip.

Υπάρχει ενα πολύ ενδιαφέρον paper κάτι Δανών που έκαναν ακριβώς αυτό με το Δανέζικο διαβατήριο καθώς και με μερικά Ευρωπαϊκα, ανακαλύπτοντας οτι σε πολλές περιπτώσεις είναι δυνατόν να αναγνωστούν παραμέτροι που εξαρτώνται απο τον κατασκευαστή του διαβατηρίου, επιτρέποντας σε οποιονδήποτε αναγνώστη να ξεχωρίσει χωρίς καμμία πιστοποίηση εαν έχει μπροστά του π.χ. ενα Γαλλικό η ενα Γερμανικό διαβατήριο, και έφτιαξαν και ενα υποθετικό σενάριο μιας έξυπνης γόμβας που σκάει μόλις περάσουν απο μπροστά της λόγου χάρη είκοσι διαβατήρια Ουρουγουάης. Για σκεφτείτε το!

Απαξ τώρα και ολοκληρωθεί η διαδικασία πιστοποίησης δικαιωμάτων ανάγνωσης, έχετε πρόσβαση για να διαβάσετε όλα τα δεδομένα που βρίσκονται στο έντυπο. Για τα διαβατήρια, τα δεδομένα αυτά βρίσκονται οργανωμένα σε μια ιεραρχία απο Applications.

Προς το παρόν στον κώδικα υποστηρίζω μόνο το application LDS1 που είναι και το μόνο υποχρεωτικό για τα διαβατήρια - υπάρχουν και άλλα Applications που επιτρέπουν την αποθήκευση προσωρινων δεδομένων στο έντυπο, όπως βίζες και άδειες παραμονής.

Στο application LDS1 βρίσκονται οραγανωμένα 16 αρχεία ομάδων δεδομένων (DG) τα οποία μπορούν να αναγνωστούν, και κάθε αρχείο περιέχει ενα είδος δεδομένωνε. Στο Ελληνικό διαβατήριο περιέχονται τα υποχρεωτικά αρχεία που ορίζει το πρότυπο - EF.COM, EF.CARDACCESS, EF.CARDSECURITY.

Το EF.DG1 περιέχει τα δεδομένα της Μηχανικής Ζώνης Ανάγνωσης σε ηλεκτρονική μορφή (μπορείτε να το διαβάσετε).

Το EF.DG2 που περιέχει τη βιομετρική φωτογραφία της μάπας σας. Αυτό έχει ενδιαφέρον, γιατί περιέχει και κάποια μεταδεδομένα - όπως τη γωνία λήψης της φωτογραφίας, το φύλο, την πόζα κτλ. Τα μεταδαδομένα αυτά μπορούν να χρησιμοποιηθούν για την παραμετροποίηση των συστημάτωνε αυτόματης αναγνώρισης μουτσούνας, και στην περίπτωση του ελληνικού διαβατηρίου είναι όλα κενά. Εχει ωστόσο ενδιαφέρον να διαβάσετε το σχετικά πρότυπα.

Το EF.DG3 περιέχει τα δαχτυλικά σας αποτυπώματα, δε μπορείτε να το διαβάσετε γιατί θεωρείται ευαίσθητο προσωπικό δεδομένο - σε αντίθεση με τη μούρη σας, και θα δούμε γιατί. Για να αναγνωστεί αυτό το αρχείο χρειάζονται επιπλέον δικαιώματα πρόσβασης, που απαιτούν ενα πιστοποιητικό που εκδίδεται απο την Αρχή Εκδόσεως Διαβατηρίωνε σε όλους τους χρήστες που έχουν τυπικά το δικαιώμα να αναγνώσουν τα δαχτυλικά αποτυπώματα του κατόχου ενός εντύπου (τους ιμμιγκράτσους, λογικά).

Το σχετικό πρωτόκολλο ονομάζεται Terminal Authentication, και δεν το εχω υλοποιήσει, γιατί υποθέτω οτι αν ζητήσω απο την Αρχή Εκδοσης Διαβατηρίωνε αρκετά ευγενικά ενα 
πιστοποιητικό για να το δοκιμάσω, ΔΕΝ θα μου δώσουν ενα.

Εδω βρίσκεται βέβαια και το δεύτερο σοβαρό πρόβλημα ασφαλείας, που είναι σχεδόν κοινό σε όλες τις υποδομές που χρησιμοποιούν πιστοποιητικά Χ.509 για ασφάλεια δεδομένωνε και ελέγχου πρόσβασης: Το πιστοποιητικό που χρειάζεται για να "ξεκλειδώσουν" τα δαχτυλικά αποτυπώματα, δε μπορεί να ανακληθεί.

Δηλαδή αν εγω καταφέρω να κλέψω ενα τέτοιο πιστοποιητικό (απο ενα αεροβρώμιο λόγου χάρη, λέμε τώρα), αυτό το πιστοποιητικό μπορεί να χρησιμοποιηθεί για να διαβάσει κάθε δαχτυλικό αποτύπωμα κάθε διαβατηρίου που εκδόθηκε μέχρι τότε, και αρκετά ακόμα που θα εκδοθούν εκ των υστέρωνε, μια και το καημένο το διαβατήριο δε διαθέτει Certificate Revocation List, ούτε έχει πρόσβαση στο Ιντερνετ (πάλι καλά!) για να ζητήσει ενα με OCSP (αυτοί είναι οι μεθόδοι ανάκλησης πιστοποιητικώνε που υποστηρίζονται απο το X.509). Εχουν προταθεί κάποια πρωτόκολλα για τη λύση αυτού του προβλήματος, κανένα ωστόσο δεν έχει προτυποποιηθεί μέχρι σήμερα.

Αμα βρείτε κανένα leaked πιστοποιητικό να κάνει γύρες στο Internet, πείτε μου.

Στο DG14 και DG15 θα βρείτε τα δεδομένα ασφαλείας και τα πιστοποιητικά που χρειάζονται για να επιβεβαιώσετε την αυθεντικότητα του διαβατηρίου. Αυτός είναι ο κύριος μηχανισμός που αποτρέπει κάποιον απο το να φτιάξει μια πλήρη ηλεκτρονική κόπια του διαβατηρίου σας που να "περνάει" ως αυθεντικιά (το λεγόμενο cloning), όπως και αποτρέπει κάποιον να "πειράξει" τα δεδομένα που βρίσκονται στο κλωνοποιημένο διαβατήριο - στο αυθεντικό δε μπορείς να πειράξεις τίποτα υποτίθεται, γιατί τα δεδομένα είναι read only. Υποθέτω μέχρι να βρούμε το embedded debugging που κάποιος θα ξέχασε να αφαιρέσει απο το production edition του NFC chip.

Για να πιστοποιήσετε την αυθεντικότητα του εντύπου απαιτείται υλοποίηση ακόμα δυο πρωκτοκόλλωυε που λέγονται Passive και Active Authentication, τα οποία δεν τα υλοποίησα, γιατί βαριέμαι.

Εαν θέλετε να τα υλοποιήσετε μόνοι σας, είναι εξαιρετικά απλό: Θα διαβάσετε το αρχείο EF.SOD που περιέχει το Security Object Document του διαβατηρίου, κωδικοποιημένο μέσα σε ενα Cryptographic Message Syntax αντικείμενο, το format του οποίου περιγράφεται στα πρότυπα RFC 8933, 5652, 3852, 3369, 2630, 6268, 5911, 5753, 3278, και 5084.

Μέσα απο το CMS αντικείμενο θα διαβάσετε το LDSSecurityObject με OID 2.23.136.1.1.1 όπως ορίζεται στο ICAO 9303-10 (προσοχή γιατί υπάρχουν δυο εκδόσεις και άρα πρέπει να ελέγξετε τον αριθμό έκδοσης), και θα εξάγετε τα hashes των Data Groups. Θα διαβάσετε το κάθε data group και θα υπολογίσετε το hash του με βάση τον αλγόριθμο που ορίζεται απο το πεδίο hashAlgorithm.

Αφού βεβαιωθείτε οτι όλα τα hashes των Data Groups είναι σωστα, θα εξάγετε απο το Security Object Document το Document Signer Certificate X.503 πιστοποιητικό, και θα βεβαιωθείτε οτι το Security Object Document είναι υπογεγραμμένο απο αυτό το πιστοποιητικό.

Υστερα θα βεβαιωθείτε οτι το Document Signer Certificate είναι υπογεγραμμένο με το πιστοποιητικό του Country Signing Certificate Authority της Ελλάδας, το οποίο θα ελέγξετε οτι βρίσκεται στο Master List του ICAO το οποίο θα προσέξετε να είναι υπογεγραμμένο απο το πιστοποιητικό του ICAO Master List Signer Certificate, το οποίο θα πρέπει να είναι υπογεγραμμένο απο το πιστοποιητικό του United Nations Country Signing Certificate Authority του ΟΗΕ, το οποίο υποθέτω λογικά είναι υπογεγραμμένο απο το ψηφιακό πιστοποιητικό του Αλλάχ (του ελεήμονος, του φιλεύσπλαφχνουφ).

Σε κάθε βήμα θα πρέπει να ελέγξετε το validity date των πιστοποιητικών και θα τσεκάρετε τις υπογραφές τους με το Certificate Revocation List που θα βρείτε επίσης στο Master List του ICAO.

Εαν όλες οι ψηφιακές υπογραφές είναι σωστές, θα διαβάσετε το αρχείο EF.DG15 και θα εξάγετε το ActiveAuthenticationPublicKeyInfo και θα ακολουθήσετε τον αλγόριθμο που περιγράφεται στην παράγραφο 6.1 του ICAO 9303-10 δημιουργώντας ενα τυχαίο αριθμό και στέλνοντας τον στο διαβατήριο με την εντολη INTERNAL AUTHENTICATE (για να σας διευκολύνω, αυτό το κομμάτι το εχω φτιάξει ήδη, είδατε τι καλός που είμαι).

Την απάντηση που θα λάβετε στο response πακέτο θα την αποκρυπτογραφήσετε με τον αλγόριθμο και το κλειδί που ορίζονται στο ActiveAuthenticationPublicKeyInfo, και θα συγκρίνετε το αποκρυπτογραφημένο μήνυμα με το hash του τυχαίου αριθμό που στείλατε στο προηγούμενο βήμα, όπως περιγράφεται στο Appendix F του ICAO 9303-11.

Με αυτή την παραπάνω απλή απλούστατη διαδικασία, μπορείτε να είστε σίγουροι οτι το διαβατήριο είναι αυθεντικό και δεν έχει κλωνοποιηθεί η παραχαρακτεί κατα οποιοδήποτε τρόπο.

Μάλιστα, η διαδικασία αυτή έχει μια ενδιαφέρουσα ιδιότητα, που αναφέρεται στο ICAO 9303: Η καταγραφή της "συνομιλίας" του διαβατηρίου με τον αναγνώστη σε log file, ισοδυναμεί με απόδειξη (με τη μαθηματική έννοια, που είναι πιο ισχυρή απο τη νομική), οτι το διαβατήριο και ο μηχανισμός ανάγνωσης έχουν βρεθεί στο ίδιο σημείο. Το αν ήσασταν κι εσείς εκεί μαζί με το διαβατήριο είναι άλλο καπέλο με το οποίο θα ασχοληθούμε αυγότερα.

Γενικά το ελληνικό διαβατήριο είναι λίγο φτωχό σε δεδομένα και μεταδεδομένα. Το ICAO 9303 περιλαμβάνει προτυποποιημένα Data Groups για την αναγραφή διαφόρων ειδών προαιρετικών δεδομένων, αλλά το ελληνικό διαβατήριο περιέχει μόνο τα απολύτως απαραίτητα - απο σβέρκο θα ψωνίσανε πάλι.

Για παράδιγμα, εγω θα ήθελα να περιλαμβάνεται το Data Group 16 που περιλαμβάνει στοιχεία επικοινωνίας άμεσης ανάγκης του κατόχου του εντύπου (δηλαδη με ποιόν θα επικοινωνήσουνε σε κείνη την περίπτωση του ανέκδοτου που βρίσκεστε στο αεροπλάνο με το διαβατήριο στα δόντια).

Επίσης, οι αλγόριθμοι κρυπτογραφίας που υποστηρίζει το ελληνικό διαβατήριο είναι οι εντελώς βασικοί και απαραίτητοι, δηλαδή DES3 και SHA1, που με τα 64 bit εντροπίας που προσφέρει ο μπακαλιάρος είναι λιγάκι πασσε για 2023, για να το θέσουμε ευγενικά.

Κάτι άλλο ενδιαφέρον που μπορείτε να κάνετε με το διαβατήριο, είναι να κάνετε brute-force τη δομή αρχείων του εντύπου, για να βρείτε τυχόν "κρυφά" αρχεία που μπορεί να περιέχει. Υπάρχουν δυο είδη αρχείων, Dedicated και Elementary. Τα Dedicated Files μπορούν να περιέχουν άλλα Dedicated Files η Elementary Files, ενω τα Elementary Files περιέχουν δεδομένα (σκεφτείτε τα σαν αρχεία και subdirectories σε μια δενδρική δομή). Τα αρχεία δεν έχουν ονόματα, αλλα αριθμητικούς descriptors, οι οποίοι είναι 16 bit, άρα είναι πολύ εύκολο να δοκιμάσουμε να διαβάσουμε όλους τους descriptors με τη σειρά.

Φυσικά αυτό δε σημαίνει οτι κάποιος δε μπορεί να "κρύψει" ενα αρχείο - μπορεί π.χ. κάποιος να προγραμματίσει το τσιπάκι να απαντάει σε μια "κρυφή" εντολή που δεν περιλαμβάνεται στο πρότυπο - κάτι τέτοιο όμως θα ήταν ηλίθιο (αφήνω ως άσκηση στον αναγνώστη να μας πεί ΓΙΑΤΙ θα ήταν ηλίθιο).

Προσωπικά το δοκίμασα στο διαβατήριο μου, και επιβεβαίωσα οτι δεν υπάρχουν αρχεία πέρα απο αυτά που περιγράφονται στο ICAO 9303-10. Αφού προσπάθησα να διαβάσω και τα 65536 πιθανά αρχεία του καταλόγου LDS1, απο απορία άγγιξα το διαβατήριο, και όπως το ψιλοπερίμενα, είχε θερμανθεί λιγάκι - το NFC chip προφανώς ξοδεύει ενέργεια σε κάθε εντολή που του δίνεις, μέρος της οποίας καταλήγει σε θερμότητα.

Φυσικά το διαβατήριο δε διαθέτει ανεμιστήρι, οπότε θεωρητικά μπορείτε να φτιάξετε ενα loop που διαβάζει το διαβατήριο μέχρι να αρπάξει φωτιά.

Μια κουβέντα τώρα για τα βιομετρικά. Το Ελληνικό διαβατήριο περιέχει τη μουτσούνα σας και τα δαχτυλικά σας αποτυπώματα, με τη μουτσούνα μόνο να είναι δημοσίως αναγνώσιμη. Το πρότυπο ICAO 9303 περιέχει αρκετές δυνατότητες αποθήκευσης βιομετρικών δεδομένων ΚΑΙ μεταδεδομένων.

Το δαχτυλικό αποτύπωμα έχει το πλεονέκτημα οτι δίνει καλύτερη βιομετρική πιστοποίηση απο τη φωτογραφία της μάπας σας, ειδικά δεδομένου οτι πιθανότητα τη μάπα σας την έβγαλε φωτογραφία κάποιος "επαγγελματίας φωτογράφος" συνηθισμένος να φωτογραφίζει βαφτίσια και γαμίσια, αντί για φωτογραφίες ποιότητας κατάλληλης για να χρησιμοποιηθούν σαν πηγή δεδομένων σε αλγόριθμους αυτόματης αναγνώρισης. Το πρόβλημα είναι διεθνές, και αν δείτε τις προδιαγραφές και τα μεταδεδομένα των φωτογραφιών και των βιομετρικώνε που προτείνονται για τις βίζες Σένγκεν στις επόμενες εκδόσεις της, μια αηδία θα σας ψιλοπιάσει σίγουρα.

Αλλα περισσότερα για τα βιομετρικά, θα γράψουμε σε επόμενο πόστι.

Wednesday, April 12, 2023

Γκουζγκουνοατάκες

 Παμε παιδιά μου να αποδομήσουμε ακόμα ενα αστικό μύθο;

ΠΑΜΕΕΕΕΕΕ!

Κώστας Γκουσγκούνης και οι περίφημες εκτός σεναρίου "χιουμοριστικές" ατάκες απο τσόνες του.

Αυτές οι ατάκες κυκλοφορούν σε διάφορα viral meme κείμενα, και κάποια στιγμή σκέφτηκα να φτιάξω μια συρραφή των σχετικών σκηνών, με υποτιτλισμό στα Αγγλικά για περισσότερο virality.

Πόσο δύσκολο πιά να είναι;

Ε, για μαντέψτε.

Απο τις λίστες με ατάκες που κυκλοφορούν, θα βρείτε κυρίως αυτή την εκδοχή. Το πρώτο πράγμα που με ψύλλιασε - εκτός απο τις ομοιότητες - είναι οτι στις λίστες δεν αναφέρονται ποτέ και πουθενά οι ταινίες στις οποίες υποτίθεται οτι ειπώθηκαν.

[ΦΑΙ]
Σε διάλογο με τη σύζυγό του, στην ταινία, ο Γκουσγκούνης ρωτά,
«Τι φαΐ έκανες;». Η σύζυγος του απαντά: «Δεν έκανα φαΐ» και τότε
ο Γκουσγκούνης λέει: «Δεν έκανες φαΐ; Θα σε γ@μ@σω».


[ΜΑΚΑΡΟΝΙΑ]
Ξανά σε διάλογο με τη σύζυγό του για φαγητό, ο Γκουσγκούνης τη ρωτά
«Γυναίκα, τι φαΐ έχουμε;», με αυτή να του απαντά: «Μακαρόνια» και
τότε ο Γκουσγκούνης της λέει: «Τη γ@μ@σες!»

[ΠΟΥΛΑΚΙΑ]
Η παρτενέρ του λέει: «Άκου, πώς κελαηδούν τα πουλάκια» Γκουσγκούνης:
«Άστα αυτά και κοίτα να κάνεις το δικό μου πουλάκι να κελαηδήσει»

[ΤΟΙΧΟΣ]
Γκουσγκούνης στην παρτενέρ του: «Βάστα τοίχο, θα σπρώξω»

[ΒΑΡΚΑΡΗΣ]
Σε ρόλο βαρκάρη, ο Γκουσγκούνης μεταφέρει μια τουρίστρια, η οποία αναφωνεί
«ωχ, έφυγε το ένα» από τα κουπιά. Τότε, ο Γκουσγκούνης ρίχνει και το άλλο,
με την τουρίστρια να τον ρωτάει πώς θα περάσει τώρα απέναντι και τον
Γκουσγκούνη να της απαντά: «Θα σε περάσω γ@μι@ντ@ς».

[ΗΛΙΟΘΕΡΑΠΕΙΑ]
Σε μία παραλία, ο Γκουσγκούνης κόβει βόλτες και βλέπει δυο κοπέλες να κάνουν
ηλιοθεραπεία. «Τι κάνετε εδώ, κορίτσια;» τις ρωτά. «Περιμένουμε να έρθει κάποιος
να μας γ@μ@σει» του απαντούν. Και εκείνος λέει: «Α, ευτυχώς που πέρναγα».

[ΑΧΛΑΔΙ]
Γκουσγκούνης στο σπίτι και ρωτά μια κοπέλα αν θέλει αχλάδι. Όχι, του απαντά εκείνη,
με τον Γκουσγκούνη να της λέει: «Ε τότε δεν μένει τίποτα άλλο παρά να σε γ@μ@σω».

[ΝΕΡΟ]
Σε μία επίσης χωρίς κανένα νόημα ατάκα, ο Γκουσγκούνης είναι σε ένα σπίτι ως
υδραυλικός. Η γυναίκα που είναι εκεί, τον ρωτά αν θέλει νερό. Ο ίδιος της
απαντά «α φιρί φιρί το πας να σε γ@μ@σω».

[ΓΛΩΣΣΕΣ]
Ο Γκουσγκούνης σε ρόλο ψαρά με δυο νοικοκυρές που θέλουν να αγοράσουν ψάρια.
«Γλώσσες έχετε;» τον ρωτούν; Αφού ακολουθεί ό,τι είναι να ακολουθήσει,
ακούγεται να λέει «ψάρια θέλατε, π@τ@ν@ς».

[ΠΡΩΙΝΟ]
Ξημερώνει στη σκηνή μιας ταινίας, με τον Κώστα Γκουσγκούνη να έχει τοποθετήσει
τα επίμαχα σε ένα καλοριφέρ. Η παρτενέρ του ξυπνάει και τον βλέπει, ρωτώντας τον
«Τι κάνεις εκεί;» και τον Γκουσγκούνη να της απαντά «ζεσταίνω το πρωινό σου».



Κυκλοφορούν επίσης και άλλες εκδοχές της λίστας, με διάφορα συν - πλήν απο την παραπάνω λίστα. Οι διαφορές είναι οι εξής - νομίζω οτι κατάφερα να συγκεντρώσω τις περισσότερες, αν όχι ολες.

[ΦΕΤΑ]
Ο Κώστας Γκουσγκούνης είναι αραχτός στο σπίτι. Ανοίγει η πόρτα και
εμφανίζεται η γυναίκα του φορτωμένη με ψώνια.
Γκουσγκούνης: "Φέτα έφερες;”
Σύζυγος: "Όχι”.
Κώστας Γκουσγκούνης: "Μου φαίνεται πως θέλεις να σε γ@μήσω”.

[ΠΙΤΣΕΣ]
Ο Κώστας Γκουσγκούνης σε ρόλο ντελιβερά
Κώστας Γκουσγκούνης: "Έφερα τις πίτσες”.
Γυναίκες: "Μα δεν παραγγείλαμε πίτσες!”.
Κώστας Γκουσγκούνης: "Παραγγείλατε, δεν παραγγείλατε, εγώ θα σας γ@μήσω!”.

[ΡΟΛΟΙ]
Ο Κώστας Γκουσγκούνης σε μπαρ. Βαδίζει προς την μπάρα, βλέπει την
µπαργούµαν. Στον τοίχο υπάρχει ένα ρολόι. Ο Κώστας προσπαθεί να το
κοιτάξει, η μπαργούμαν μπαίνει στη μέση. Κάνει δεξιά, ξαναµπαίνει
µπροστά του η μπαργούμαν. Κάνει αριστερά, πάλι μπροστά του η
μπαργούμαν. Σε κάποια στιγμή γυρνά και της λέει: "Δεν βλέπω
την ώρα να σε γ@µήσω!”.

[ΜΥΤΙΛΗΝΗ]
Ο Κώστας Γκουσγκούνης στη Μυτιλήνη
Κώστας Γκουσγκούνης: "Γεια σας, κορίτσια, ξένες είσαστε;”."
Κορίτσια: "Όχι καλέ, ντόπιες, από τη Μυτιλήνη”.
Κώστας Γκουσγκούνης: "Α! Δηλαδή λεσβίες!”
Κορίτσια: "Ε όχι και λεσβίες!”
Κώστας Γκουσγκούνης: "Ε αποδείξτε το τότε!”

[ΥΔΡΑΥΛΙΚΟΣ]
Ο μέγιστος υποδύεται τον υδραυλικό κι έχει πάει στο σπίτι
μιας κοπέλας προκειμένου να της επιδιορθώσει τη βλάβη.
Κάθεται στο τραπέζι κι ακολουθεί η εξής στιχομυθία:
Κοπέλα: Καφέ θέλεις;
Γκουσγκούνης: Ναι.
Κοπέλα: Πώς τον πίνεις;
Γκουσγκούνης: Πολλά βαρύ κι όχι, με δύο φουσκάλες.
Κοπέλα: Είσαι και μερακλής!
Γκουσγκούνης: Κωλάρα έχεις!

[ΑΛΛΑΓΗ ΣΤΑΣΗΣ]
Παρτενέρ: «Γκουσγκούνη, κουράστηκα, άλλαξε στάση»
Γκουσγκούνης: «Εντάξει, μωρό μου», και βάζει τα χέρια στο κεφάλι.

[ΠΑΓΟΣ]
Ο Γκουσγκούνης μπαίνει στο σαλόνι και βλέπει την κόρη του με μια
φίλη της. Κάθεται λίγο μαζί τους και ξαφνικά:
Γκουσγκούνης: Δε μου λες, απ’ τον κ@λο τον παίρνεις;
Κόρη: Μπαμπά!!!! Τι είναι αυτά που λες;!
Γκουσγκούνης: Ε! Να σπάσει ο πάγος!

[ΠΟΡΤΟΚΑΛΙ]
Χαλάνε τα υδραυλικά μιας γκόμενας. Ο Γκουσγκούνης έρχεται ως υδραυλικός
στο σπίτι της και στρογγυλοκάθεται στο τραπέζι της κουζίνας, όπου έχει
μια μεγάλη φρουτιέρα με πορτοκάλια. Παίρνει ένα πορτοκάλι στο χέρι
του και ρωτάει όλος αβρότητα:
Γκουσγκούνης: Πορτοκάλι θέλεις;
Γκόμενα: Όχι.
Γκουσγκούνης: Να σε γ@μήσ@ θέλεις;
Γκόμενα: Αμέ!

[ΜΠΥΡΑ]
Ο Γκουσγκούνης είναι πρώτη μούρη στο πλάνο και, φυσικά, π@δάει την γκόμενα. Σε μια στιγμή μουρμουρίζει κάπως δυνατά:
Γκουσγκούνης: Πω, πω, να είχα μια μπύρα τώρα…
Και από το πουθενά, σκάει ένα χέρι με μια μπύρα, και ο μάστορας πίνει χωρίς να σταματήσει το έργο του.

[TRES JOLIE]
Ο Γκουσγκούνης με Γαλλίδα παρτεναίρ σε τσόντα:
Γαλλίδα γκόμενα: Aahhh, tres jolie!
Γκουσγκούνης: Τι ζολή, μωρή… ψ@λή το λένε!

[ΚΟΥΚΟΥΤΣΙΑ]
Ο Γκουσγκούνης στο τέλος της σκηνής εκσπερματ@νει στο στόμα της παρτενέρ του, η οποία αρχίζει να τα φτύνει.
Γκουσγκούνης: Τι τα φτύνεις μωρή, κουκούτσια έχουν;

[ΚΛΑΡΙΝΟ]
Ο Γκουσγκούνης κάθεται μπροστά σ’ ένα πιάνο και προσπαθεί να παίξει. Ξαφνικά σκάει
μύτη μια γκόμενα, η οποία τον πειράζει και του τρίβεται. Τότε ο Γκουσγκούνης την
πεταέι έξω την μάνικα, αρπάζει το κεφάλι της και την υποχρεώνει σε στοματικό έρωτα.
Και της λέει: Ωραία, τώρα εγώ θα παίζω πιάνο και εσύ κλαρίνο!!!

[ΡΕΜΑ]
Τρέχει ο Γκουσγκούνης γιατί τον κυνηγάει ολόκληρο χωριό. Προφανώς γιατι είχε μαμήσει
ότι θηλυκό βρήκε. Φτάνει λοιπον σε γκρεμό! Κοιτάει πίσω, βλέπει το εξαγριωμένο πλήθος.
Κοιτάει μπροστά γκρεμός! Κοντινό πλάνο στον υπερήρωα που φαίνεται να αναρωτιέται και
καπάκια μαύρο πλάνο. 2 δευτερόλεπτα μετά, άλλο πλάνο, με το Γκουσγκούνη σε βάρκα να
κάνει κουπί! Και γυρνάει και λέει: “E, τι περιμένατε; Τσόντα γυρνάμε , όχι περιπέτεια!!!”

[ΨΑΡΙΑ]
Γκουσγκούνης: Γειά σας, σας έφερα τα ψάρια που παραγγείλατε!
Ξανθιές: Μα εμείς δεν παραγγείλαμε ψάρια!
Γκουσγκούνης: Να σας μαμήσω τώρα ;

[ΜΑΣΚΑ]
Ο Γκουσγκούνης βγαίνει από τη θάλασσα με μια γκόμενα.
Φοράνε και οι δυο στολή βατραχανθρώπου. Η γκόμενα πάει
να βγάλει τη μάσκα.
Γκουσγκούνης: «Μη βγάλεις τη μάσκα, γιατί θα σου πετάξω τα μάτια έξω!»

[ΑΓΓΛΙΚΑ]
Αλλοδαπή αγγλομαθής προς Γκουσγκούνη: «Fuck me!»
Γκουσγκούνης: «Σκάσε, μωρή, μη σε γ@μήσω!»

[ΒΑΡΕΜΑΡΑ]
Γκουσγκούνης: Τι κάνεις;
Γκόμενα: Βαριέμαι.
Γκουσγκούνης: Κι εγώ! Δεν μαμιόμαστε λέω εγώ;;;

[ΓΝΩΡΙΜΙΑ]
Ο Γκουσγκούνης μετά την ερωτική πράξη: «Πώς σε λένε;»
Παρτενέρ: «Κατερίνα»
Γκουσγκούνης: «Εμένα Κώστα. Για σκέψου, πρώτα πηδηχτήκαμε και μετά γνωριστήκαμε»


Ειναι πολυ προφανες οτι καποιες ατάκες ειναι διπλές σε μικροπαραλλαγες. Ορισμένες απο τις
ατάκες έχουν κάποιες ομοιότητες με τσόντες του '80 στις οποίες επίσης δε συμμετέχει ο
Γκουσγκούνης, αλλά άλλοι ηθοποιοί, π.χ. ο Δημήτρης Βάλλας, ο οποίος κάποια εποχή πλασσαρίστηκε ως "νέος Γκουσγκούνης" λόγω εμφανισιακής ομοιότητας. Σκηνή με υδραυλικό υπάρχει επίσης σε μεταγενέστερες ταινίες του ΄80.

Στην ταινία "Βρώμικη Παρέα" υπάρχουν αναφορές σε κλαρίνα [ΚΛΑΡΙΝΟ] και μια σκηνη με ψαρά που φέρνει ψάρια [ΨΑΡΙΑ], αλλά ΔΕΝ έχουν το χιουμοριστικό χαρακτήρα που τους αποδίδεται στίς λίστες. Πολύ πιθανόν να είναι αυτές οι μεταγενέστερες ταινίες η αρχική πηγή της λίστας.

Επίσης η σκηνή [ΜΠΥΡΑ] θα ήταν ενα εξαίρετο παράδειγμα της τεχνικής που στο σινεμά λέγεται "breaking the fourth wall", εαν υπήρχε κάπου τέτοια σκηνή. Δεν κατάφερα να τη βρώ πουθενά όμως.

Η Φιλμογραφία του Γκουσγκούνη έχει ως εξης, σύμφωνα με τη wikipedia:

    Η Αγνή του λιμανιού (1952)
    Η θεία απ' το Σικάγο (1957) (άνδρας στο δρόμο) - δεν αναφέρεται στους κύριους συντελεστές της ταινίας
    Ο λεφτάς (1958) (άνδρας που χορεύει) - δεν αναφέρεται στους κύριους συντελεστές της ταινίας
    Μια ζωή την έχουμε (1958) - στο ρόλο του καφετζή (ακόμη με μαλλιά)
    Οργισμένοι λόφοι (Angry hills) (1959) (στο ρόλο του τροχονόμου - δεν αναφέρεται στους κύριους συντελεστές της ταινίας) - διεθνής παραγωγή του Ρόμπερτ Όλντριτς με τον Ρόμπερτ Μίτσαμ που γυρίστηκε στην Ελλάδα
    Χωρίς ιδανικά (1965) - πρωταγωνιστής (αστυνομικό - soft core)
    Η λεωφόρος του θανάτου (1966) - πρωταγωνιστής (αστυνομική ταινία)
    Σεξ ... 13 Μποφώρ (1971) - πρωταγωνιστής, πορνό, 85.918 εισιτήρια
    Διεστραμμένοι από τη γέννα τους (1974) -πρωταγωνιστής (αστυνομικό - soft core)
    Συνωμοσία στη Μεσόγειο (1975) - ένας από τους πρωταγωνιστές (αστυνομικό)
    Ο Ανώμαλος (1975) - πρωταγωνιστής, 36.618 εισιτήρια
    Στην παγίδα του σεξ και του εγκλήματος (1975) - πρωταγωνιστής (soft core) 34.299 εισιτήρια
    Ο Χριστός ξανασταυρώνεται (1975) - στο ρόλο του Σεΐζη (επεισόδια 1, 2, 4, 5, 6) (τηλεοπτική σειρά βασισμένη στο ομώνυμο έργο του Νίκου Καζαντζάκη)
    Ήταν άξιος (1982) - πρωταγωνιστής
    Ο ηδονοβλεψίας (ή «Ο Μεγάλος Εραστής») (1984) - πρωταγωνιστής (το μοναδικό σκληρό πορνό του Γκουσγκούνη)
    Πάθος και ηδονή (1984) - πρωταγωνιστής
    Ράδιο Μόσχα (1996) - ένας από τους πρωταγωνιστές
    Το παλτό (1997) (τηλεταινία σκηνοθεσίας Νίκου Τριανταφυλλίδη, βασισμένη στο θεατρικό έργο Το παλτό του Νικολάι Γκόγκολ)
    Μαύρο γάλα (1999) - στο ρόλο του αστυνόμου (μαύρη κωμωδία)
    «Ελληνίδες Next Porn Models σε όργια – η επιστροφή του δασκάλου» ή «Ελληνίδες Next Porn Model By Γκουζγκούνης» (2010)



Η λίστα είναι ακριβώς ίδια στη Βίκη και στο IMDB, μόνη διαφορά οτι το IMDB δεν περιλαμβάνει το Πάθος και Ηδονή, το οποίο είναι στην πραγματικότητα μια συρραφή απο τις υπόλοιπες ταινίες του - δεν περιέχει πρωτότυπες σκηνές.

Μπορούμε με ασφάλεια να αφήσουμε έξω τις πέντε πρώτες.

Μπορούμε επίσης με ασφάλεια να αφήσουμε έξω τις τέσσερις τελευταίες.

Τον Χριστό που Ξανασταυρώνεται υποψιάζομαι οτι μπορούμε επίσης να τον αφήσουμε απ'έξω.

Τις υπόλοιπες τις είδα. Οσες βρήκα δηλαδή. Εστω και μόνο γι αυτό, αξίζω να μου δώσετε κάποιο βραβείο. Μου πήρε αρκετές μέρες γιατί οι ταινίες είναι τόσο απαίσιες που είναι αδύνατον να δείς πάνω απο μια τη μέρα, και πολύ βάζω.

To Χωρίς ιδανικά θεωρείται χαμένο - δε βρήκα ψηφιοποιημένες κόπιες. Λογικά δεν πρέπει να διαφέρει ιδιαίτερα απο τη Λεωφόρο του Θανάτου στο στυλ.

Η Λεωφόρος του Θανάτου είναι ενα ψιλοβαρετό γκανγστερικό θρίλερ με 2 γυμνές σκήνες. Στις οποίες δε συμμετέχει, μαντέψτε ποιός; Ο Γκουσγκούνης. Σε μια σκηνή μάλιστα σώζει την τιμή της κόρης του γκάνγστερ για τον οποίο δουλεύει ως πληρωμένος δολοφόνος, απο κάποιον της αντίπαλης συμμορίας που προσπαθεί να τη βιάσει. Η κόπια της ταινίας που κυκλοφορεί στους ιντερνέδες κόβεται στη μία ωρα και εφτά λεπτά, ακριβώς στη μέση μιας σκηνής με μπιστολίδι οπου σκοτώνονται μεταξύ τους όλοι οι γκάνγστερ. Καμμία ατάκα με χιούμορ.

Το Σεξ 13 Μποφώρ είναι ενα ελαφρό πορνό στο οποίο ο Γκουσγκούνης - όπως και όλοι οι υπόλοιποι - λέει κάτι μελό επικολυρικούς μονόλογους. Δεν κατάφερα να τη δω καν ολόκληρη - ενώ τα αστυνομικά τουλάχιστον βλέπονται - και όση είδα, δε μπορώ να αποφασίσω αν είναι πιο καταθλιπτικό να βλέπεις τον Γκουσγκουνη να φασώνεται η να μιλάει. Καμμία ατάκα με χιούμορ. Αν πρέπει οπωσδήποτε να το δείτε, φροντίστε να μην υπάρχουν πουθενα ξυραφάκια εκεί κοντά.

Η Συνωμοσία στη Μεσόγειο είναι ενα κατασκοπικό θρίλερ που βλέπεται πολυ ευχάριστα σε σχέση με τα υπόλοιπα. Καμμία ατάκα με χιούμορ, ο Γκουσγκούνης παίζει και πάλι τον πληρωμένο δολοφόνο. Συνολικά σε όλες τις ταινίες που βρήκα, πολύ περισσότερες φορές τον είδα να κρατάει όπλο παρά πουλί.

Ο Ηδονοβλεψίας είναι η μόνη hard core ταινία του Γκουσγκούνη. Είναι σκέτο βασανιστήριο να τη βλέπεις - έκανα fast forward τις σκηνές με σεξ - και πάλι δεν περιέχει καμμία χιουμοριστική ατάκα. Γενικά οι ατάκες της λίστας είναι τέτοιου είδους που δύσκολα θα εμφανίζοταν σε soft porn η αστυνομικό με 1-2 σκηνές σεξ, οπότε περιμένεις τουλάχιστον να τις ακούσεις εδω, που και θα ταίριαζαν στο στύλ και δε θα υπόκειντο στη λογοκρισία. Και όμως, η ταινία δεν περιέχει καμμία απο αυτές.

Το Ήταν Άξιος είναι μια τρισάθλια αυτοαναφορική κωμωδία της κακιάς ώρας, στην οποία ο Γκουσγκούνης υποδύεται τον εαυτό του ως ξεπεσμένο πορνοστάρ που δεν τουσηκώνεται (και όταν τελικά τα καταφέρνει, είναι αδύνατον να καταλάβεις γιατί). Είναι τόσο άθλια ταινία που μπροστά της οι χειρότερες στιγμές του Στάθη Ψάλτη φαίνονται κορυφαία αριστουργήματα της τέταρτης τέχνης. Περιέχει διάφορες εντελώς αποτυχημένες προσπάθειες για μικροαστικό χιούμορ (γέλασα μισή φορά σε ολη την ταινία), αλλά πάλι δεν περιέχει καμμία απο τις συγκεκριμένες ατάκες.

Την παγίδα του σέξ και του εγκλήματος δεν κατάφερα να τη βρώ, τη βρήκε όμως ο Σαραντάκος, που και πάλι επιβεβαιώνει οτι δεν περιέχει καμμία απο τις συγκεκριμένες ατάκες.

Δεν κατάφερα να βρώ σε πλήρη μορφή ούτε Τον Ανώμαλο και τους Διεστραμμένους απο τη γέννα τους, παρότι απο αυτές τις δυο ταινίες υπάρχουν αποσπάσματα - που σημαίνει οτι
κάποια στιγμή ψηφιοποιήθηκαν ολόκληρες. Τα αποσπάσματα που κυκλοφορούν δεν περιέχουν κάποια απο τις ατάκες της λίστας. Οι Διεστραμμένοι απο τη Γέννα τους φαίνεται ενδιαφέρουσα ταινία, κρίμα που δεν υπάρχει διαθέσιμη.

Στο Γιουτούμπ υπάρχουν δυο η τρία απανθίσματα απο ατάκες του ελληνικού πορνό, απο τα οποία επίσης λείπουν παντελώς οι συγκεκριμένες ατάκες (ούτε καν και σε μορφή απλού ηχητικού με φωτογραφία, αντί για την κανονική κινηματογραφική σκηνή). Νομίζω οτι άκουσα μόνο το "σκύψε ευλογημένη", αλλά δεν εχω καμμία ένδειξη απο ποιά ταινία προέρχεται η απο ποιόν ηθοποιό εκφέρεται (υπάρχει ομώνυμη ταινία στην οποία δε συμμετέχει ο Γκουσγκούνης).

Επισης, ο Άρης Δημητρίου στο βιβλίο του για το ελληνικό πορνό, παρότι αναφέρεται συχνά στον Γκουσγκούνη, δεν αναφέρει καμμία σχεδόν χιουμοριστικη σκηνή η ατάκα που να την αποδίδει σ'αυτόν - ενώ το κάνει στην περιγραφή άλλων ταινιών.

Πιθανότατα παρόμοιες ατάκες να υπάρχουν σε μεταγενέστερες ταινίες του Ελληνικού πορνό εκτός Γκουσγκούνειας παραγωγής, και απο εκεί να αποδόθηκαν στον Γκουσγκούνη απλά και μόνο επειδή είναι ο πιο γνωστός ηθοποιός του είδους. Η "Βρώμικη Παρέα" είναι μια καλή ένδειξη γι'αυτό, αλλά πραγματικά δεν αντέχω να δω όλη την Ελληνική παραγωγή σεξουαλικου κινηματογράφου του 1980 για να το επιβεβαιώσω.

Πού είναι το "περίφημο" "χιούμορ" του Γκουσγκούνη λοιπόν; Ακόμα και αν υπάρχει, αποτελείται απο ελάχιστες ατάκες (τις πιο "original" της λίστας), στις 2 - 3 ταινίες που δεν κατάφερα να βρώ σε ψηφιακή μορφή.

Τόση γκαντεμιά; 

Ολα αυτά φυσικά σημαίνουν οτι και ο αρχικός δημιουργός της λίστας με ατάκες πιθανότατα την έγραψε με συρραφή απο μνήμης ατακώνε, και πρόσθεσε και μερικές δικές του, χωρίς να έχει άμεσα προσβάσιμες επιβαιώσιμες πηγές ούτε ο ίδιος. Μετά κάποιος πρόσθετε κι απο κάτι στην copypasta.

Μάλλον απίθανο επίσης να υπάρχουν σε υποτιθέμενα bootlegs η inserts (η αρχική έννοια της λέξης "τσόντα") - όλες οι παραγωγές του Γκουσγκούνη είναι δυο συγκεκριμένων παραγωγών, του Χρυσόστομου Λιάμπου και του Νάσου Σύρη. Σιγά μην κυκλοφορούσαν bootleg παραγωγές στους κινηματογράφους του '70 και του '80.

Update 1 επειδή κατηγορήθηκα οτι πέφτω σε μεθοδολογικό σφάλμα λόγω χάσματος γενεών:

Τσόντες τις λενε επειδη προσεθεταν τις καλες σκηνες σε ασχετο σημειο. καμια φορα στην δευτερη ταινι που επαιζαν, συνηθως καρατε. Ωστόσο, οι σκηνές που προστίθεντο ήταν hard core κομμάτια απο μεγαλύτερες ξένες παραγωγές που έμπαιναν στη μέση της ταινίας, εκεί που γινόταν η αλλαγή reel.

Υπάρχουν και κάποιες περιπτώσεις soft porn που διανθίστηκε στο μοντάζ με πάλι hard core κομμάτια πάλι απο ξένες ταινίες.

Αρα πολύ απίθανο οι συγκεκριμένες ατάκες να βρίσκοταν στις προστιθέμενες "τσόντες".

Για την περίπτωση να κόπηκαν οι hard core σκηνές με τις ατάκες: Απλά δε θα ταίριαζαν σε καμμία απο αυτές τις ταινίες τέτοιες ατάκες (και σίγουρα ανάμεσα σε 20+ ατάκες κάποια χιουμοριστική θα την είχε γλυτώσει, ειδικά αν βρισκόταν σε προοίμιο που δεν έδειχνε σεξ - αλλά και πάλι δε βρήκα ούτε μία).

Και στον Ηδονοβλεψία που μια χαρά θα κόλλαγαν - οπότε δεν έχουμε λόγο να υποθέσουμε οτι κόπηκε κάτι - δεν υπάρχει επίσης καμμία.
 
Update 2: Ύστερα απο βοήθεια αναγνωστώνε, άρχισε να επιβεβαιώνεται η αρχική υποψία. Π.χ. η ατάκα [ΜΥΤΙΛΗΝΗ] προέρχεται (σε ελάχιστα διαφορετική μορφή απο την καταγεγραμμένη) απο το καταθλιπτικά αβυσσαλέας αισθητικής αθλιότητας κινηματογραφικό κακούργημα τρίτου βαθμού "Εραστές του Αιγαίου" του 1983, και την λέει ο Νότης Πιτσιλός.