Building OpenSSL for Android on Windows with the Visual Studio 2017 native Toolchain and Cygwin
Building OpenSSL is an arcane thing to do sometimes. I have nowhere on the web found a real simple solution to build OpenSSL for Android that met the number one requirement for me: Being able to build on a build host (or development host) that runs Windows. I simply do not want to maintain another build machine running some Linux flavor only in order to be able to build an OpenSSL static library and a shared library that uses the former. I would rather want to use Visual Studio 2017 with its support for native C/C++ development which also suggests using the same toolchain for building the static OpenSSL library and the shared libraries that are going to consume it. Since I am planning to use Xamarin for my mobile apps, having the entire development and build process on a Windows box would be a big win for me.
DISCLAIMER: I have not yet tried, whether the OpenSSL libraries produced with my set of scripts and configuration files actually work in a real world Android app. But the build procedures themselves succeed and create the familiar libcrypto.a, libcrypto.so.1.0.0, libssl.a and libssl.so.1.0.0 files which are also all in the correct binary format as you can easily verify running readelf on them (the build script actually does this).
Challenges
Since OpenSSL for Android is usually built on a Linux host using Google's NDK, its entire build procedure also heavily relies on infrastructure that is usually found on a Linux box: Shell scripts, PERL, symbolic links and build tools like make and friends. None of these infrastructure elements can be found on a standard Windows box and things like symbolic links have been unfeasible until the arrival of Windows 10 Build 10.0.15063, at least for non-administrative accounts (you do develop and build as a LUA user, don't ya?). So we need a Unix-like environment for this purpose running on Windows plus some other arcane preconditions set which we will see in a moment. WSL cannot be used for this purpose because it only allows 64-bit Linux applications to be executed. However, the NDK that Google ships for Linux comes with a number of 32-bit applications which are not a problem when executed on a "real" installation of Linux but call for trouble on WSL. So the only option left over for this purpose is Cygwin.
Using the scripts
In order to use the scripts I have written, follow theses steps:
- Make sure all preconditions are fulfilled, as described in the paragraph below
- Unpack the zip File (Download) into a writable directory, make sure that you have the "Change permissions" right for the directory and all its files and subdirectories granted, otherwise the calls to chmod in the build scripts will fail (cygwin places some strange NULL SID ACEs into the DACL of files that are granted execution right using chmod which requires the "Change permissions" access right)
- Download openssl-1.0.2q.tar.gz from openssl.org (Download) and copy it into the directory created in the previous step.
- Open a windows command prompt and change the current directory to the directory from the above steps
- Execute "build.bat" and wait (on my Ryzen Vega this takes something like 22 minutes)
- Find the header files and libraries for the build in a platform specific subdirectory like arch-x86, arch-arm in the subdirectory build\<android-api-version>
Preconditions
In order to use the build scripts, you need Microsoft Visual Studio 2017 installed with the "Mobile development with C++" workload enabled. Unless disabled during Visual Studio Setup, this will create subdirectories like these in c:\Microsoft\AndroidNDK64: android-ndk-r12b, android-ndk-r13b, android-ndk-r15c. You might have them also in the directory c:\Microsoft\AndroidNDK. These directories contain the NDK in different versions and I assume that later versions of Visual Studio will ship with even newer Versions of the NDK than the ones mentioned here. The scripts of mine will assume that the r15c-Version of the NDK is installed in c:\Microsoft\AndroidNDK64\android-ndk-r15c but you can set your installation directory of the NDK prior to execution of the build scripts by setting the OPENSSL_ANDROID_NDK_ROOT environment variable in the command prompt to something like c:\Microsoft\AndroidNDK64\android-ndk-r12b like this:
set OPENSSL_ANDROID_NDK_ROOT=c:\Microsoft\AndroidNDK64\android-ndk-r12b
You also have to install cygwin, I have not tried with the 32-bit version of cygwin but I assume it works as well. Cygwin is a huge beast and we have to use only a tiny fraction of it for our purposes. Unfortunately is installer is not even digitally signed with an Authenticode signature, so be sure to check it with its signature file and a tool like Kleopatra in order to verify authenticity. When installing cygwin you can use the standard installation options (which will create a bash environment with PERL and other good stuff) but be sure to also install the following programs: dos2unix, makedepend, automake. We need dos2unix in order to convert a dynamically created shell script from CRLF-notation to LF-notation consumable by the cygwin bash and we need makedepend and automake for building via the OpenSSL shell scripts. The build scripts of mine assume that cygwin is installed in the c:\cygwin64 directory but you can override this much like with the above OPENSSL_ANDROID_NDK_ROOT environment variable. So, e.g. if you have installed cygwin into d:\cygwin64, type the following in the command prompt prior to execution of build.bat:
set CYGWIN_PATH=d:\cygwin64
You might want to create a permanent CYGWIN_PATH environment variable for you development or build machine unless it is installed at the default location c:\cygwin64.
Since the build scripts for OpenSSL on Linux make heavy use of symbolic links for header files, you should also turn on "Developer Mode" on your build and development host (which should be Windows 10 10.0.15063 or later), otherwise the build scripts cannot be executed successfully by a standard user. From Windows 10 10.0.15063 on, symbolic links can be created on Windows machines without administrative permissions if the box is running in "Developer Mode".
How it works
build.bat will invoke creatcfg.bat and buildall.bat in succession. The purpose of creatcfg.bat is to create the Setenv-build.sh build script and the buildall.bat batch file with the configuration set via the CYGWIN_PATH and the OPENSSL_ANDROID_NDK_ROOT environment variables. While we are at it: You can also set the Android API version to be used for the build with the ANDROID_API environment variable (default value: android-21) like this prior to execution of build.bat:
set ANDROID_API=android-26
buildall.bat, which is created by creatcfg.bat is then executed by build.bat and will invoke the cygwin bash three times with arguments to execute. The first one will convert the newly created Setenv-build.sh from CRLF notation to LF notation with dos2unix, so the cygwin bash can consume it properly. The second will execute "chmod a+x" for all shell script files (this is the place where you will get an Access Denied error if the user executing this script does not have the "Change permissions" access right). And the last one will execute the buildall.sh shell script.
buildall.sh will first clean up the build subdirectory, if it exists and will recreate it and grant everyone full control to the build subdirectory (ok, this is cargo cult, I don't really know if we really need this with developer mode turned on and the "Change permissions" access right set as documented before). After that it will invoke buildplatform.sh or each Android hardware platform and pipe stdout and stderr into a log file (arm64_build.log, arm_build.log, mips64_build.log, mips_build.log, x86_64_build.log and x86_build.log).
buildplatform.sh takes the build architecture as an argument and will first invoke the dynamically created shell script Setenv-build.sh, which will set a couple of environment variables that depend on your cygwin installation path, the NDK path being set and the Android API version chosen, as explained above. After that, buildplatform.sh will invoke an architecture specific configuraton file like Setenv-mips.sh which will set architecture specific environment variables. It then creates a subdirectory for the architecture value passed as an argument and will then unpack the openssl tarball into this directory. It is the buildplatform.sh shell script where you also would want to change the name of this tarball once a newer version as 1.0.2q has been released, simply by changing the value of the OPENSSLNAME variable.
After the tarball has been unpacked, the buildplatform.sh script will copy the Configure file from my set of script files over the one that comes with the tarball. The reason is that the Configure file in the tarball is missing entries for the x86_64 build, the arm64 build and the mips64 build. You might want to check, once a newer version than 1.0.2q is used, if this copy step is still necessary and if it doesn't break other builds, e.g. if the compiler options for GCC are changed in the standard Configure file from the tarball.
After that, the buildplatform.sh will perform the usual OpenSSL build sequence of
perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org
perl configure $OPENSSL_CONFIG_ARCH shared no-asm no-ssl2 no-ssl3 no-comp no-hw no-engine make depend
make all
in order to build the platform (OPENSSL_CONFIG_ARCH is a variable denoting the hardware platform name).
Once a hardware platform is built with make all, the buildplatform.sh script invokes readelf for the generated library files so you can verify in the platform build log, that the created binaries have the proper format. The subsequent make install_sw step will then copy the build output into the build subdirectory. For some reason, this step fails, as you can see in the log files, but library files and header files are copied successfully, so I assume this step is complete enough to be usable.
Fun fact: Try to observe a running build with Process Explorer and the image path being shown as a column. You will then notice that the actual make.exe being invoked in the build process is not the one from cygwin but instead a binary that is part of the Visual Studio NDK installation.
Leftover stuff
I would guess that the same result with my scripts could be achieved with the Windows version of Google's NDK. Drop me a note if you would like to share your results. Initially, some three years ago, I had started creating a build recipe for OpenSSL on Windows with Cygwin which finally emerged into today's version of the build scripts, so simply pointing the OPENSSL_ANDROID_NDK_ROOT environment variable to the location where the Google NDK is installed might already work. At some point I decided to give the Microsoft Compilers a chance and this worked out pretty flawlessly. This also relieved me from having to install yet another SDK on my development and build boxes, this time Google's NDK.
License
All the files I have written use the OpenSSL license, so nothing should change for you if you are already using OpenSSL.
Witzle Punkt IM, "Fuckup as a Service"
Nexus vom CCC Hannover nimmt whistle.im auseinander und nimmt dabei keine Gefangenen. Nee, nee, Jungs. Krypto ist nicht so einfach wie Ihr denkt. Dass whistle.im broken by design ist, war mir schon, ohne mich naeher damit zu beschaeftigen, schon klar, als da deren Crypto als JavaScript im Browser angekuendigt wurde. Wegwerfen, das Ganze, ein paar gute Buecher ueber Crypto lesen und dann einen Messenger schaffen, der mit PGP-Keys funktioniert. Und den auditen lassen ohne Ende. So koennte das vielleicht funktionieren.
Certified for Windows 8.1
...der IDERI Note Client. Seit heute. Bin stolz auf mein Baby. Und das von Joe, Alex und Sebastian. Leider kann ich noch keine Logografik dazu abbilden, weil es die anscheinend noch nicht gibt. Wir haben auf der Preview von Ende Juni getestet, einen Waiver gut begründet und scheinen einer der ersten zu sein, die überhaupt das Logo bekommen, denn Windows 8.1 wird offiziell ja erst im Oktober releast. Wir wollen früher am Start sein und im September releasen :-)
Surprise, surprise! The windows installer lies!
Yesterday I lost sort of like two hours of work because of a behaviour of the Windows Installer that I haven't come across before. I was testing an installer of mine on Windows 7 and I was really surprised from the behaviour of a Custom Action (CA) in my installer. Inside the CA my code determined if it is running on Windows 7 or later and in that case, the CA was supposed to execute a certain piece of code. But that code never seemed to execute at all. I inspected the code, but there was no apparent bug in it. I wrote a small executable that did the same thing but that binary worked as expected. I added log messages to the code, but those log messages never appeared in the log file. Finally I attached the debugger and was baffled when I stepped over the code that executes the GetVersionEx API, our beloved old friend from kernel32. It returned major version 6 and minor version 0, which is the version number tuple for Windows Vista, not Windows 7. "Oh, stupid", I thought, "you thought you were testing on Windows 7, but it was actually a Window Vista VM". I fired up winver, but it showed that this was clearly Windows 7. So I started scratching my head and googling. Here is, where I found an answer. It turns out that this is on purpose. Beginning with Windows 7, the GetVersionEx API is shimmed with a VersionLie shim in msiexec.exe. Purportedly this is, because so many developers were not competent enough to properly determine the operating system version inside their CAs, so the Windows Installer Team (or the app compat team) decided to always lie to CAs from Windows 7 onwards. CAs will always think they are running on Windows Vista, no matter what the real operating system version is. This is quite unusual because up to now I was under the impression that VersionLies are only applied to third party processes, not MS's own programs, such as msiexec.exe.
The moral of the story is: Never call GetVersionEx from a CA. Do any conditioning by conditioning (yeah, I like to verb words!) your CA itself with the VersionNT property, not by conditioning inside your CA, even if you then end up with twice the number of CAs. I wonder if the fine folks from the WINE project got that right...
Sie können's einfach nicht lassen
Just venting...
Wenn es etwas gibt, weswegen ich ballistisch werde, dann sind es Leute, die einfach nichts lernen wollen, die beratungsresistent bis zum Umfallen sind und die Fehler der Vergangenheit ohne Unterlass wiederholen. Wenn es aber etwas gibt, das mich darüber nachdenken lässt, mir mal eine Knarre kaufen zu wollen, dann sind es Leute, die unter die vorgenannte Kategorie fallen, das mit einer politischen Agenda im Hinterkopf tun und die unglückseligen Auswirkungen ihres Handelns nicht verantworten werden müssen.
In diese Kategorie fällt ein MDB der CSU, Norbert Geis. Der hat heute laut heise online gefordert, dass man hierzulande auch einen Opt-Out P0rn0filter für Internetnutzer verpflichtend machen soll, so wie es in Grossbritannien ab demnächst der Fall sein wird. Die Idee ist: Will ich P0rnos im Webbrowser sehen, muss ich zuerst meinem Provider sagen meinen Provider bitten, für mich P0rnos freizuschalten. Das klingt natürlich wie eine hehre Idee, etwas, wo man sich in Wahlkampfzeiten an die Familienmenschen ranschmeissen kann.
Im naechsten Moment merkt man, dass da ein Politiker der grössten Regierungsfraktion den Menschen zuruft: "Kuckt mal, da hinten, ein dreiköpfiger Affe!" Und alle schauen abgelenkt nach hinten, und vergessen, dass hier vorne gerade eine Regierung einen gigantischen Abhörskandal aussitzt und netzpolitisch nach Strich und Faden und einfach ganz episch verkackt.
Bei der Beurteilung von solchen Ideen sollte man zudem ein paar Dinge im Hinterkopf haben. Wer so etwas fordert, der fordert damit eine Infrastruktur, die der Überwachung dient. Und diese Überwachung kann für alles mögliche verwendet werden. Heute nur P0rnos, morgen sind es irgendwelche missliebige Meinungen, Gewerkschafter, Kirchen, NGOs wie Greenpeace, Amnesty oder PETA. Wenn die Infrastruktur da ist, wird sie verwendet und missbraucht werden, die NSA lässt schliesslich auch alles von amerikanischen Geheimgerichten durchwinken um ihre staatsterroristischen Akte durchzuführen, weil sie die technischen Mittel dazu haben und auch betreiben duerfen.
Interessanterweise ist es ja so, dass bei der Idee nach Verabschiedung des Gesetzes in GB nach kurzer Zeit auffiel, dass ja die nackte junge Dame auf Seite 2 der "Sun" (das ist die englische Variante der Bild-"Zeitung") ja auch darunter fiele. Also musste man nachbessern, soviel zur Doppelmoral bei diesem Ansinnen...
Und dann kommt da ja vielleicht noch eine rechtliche und eine kulturelle Komponent hinzu: Wann ist denn etwas ein P0rno? Wann ist es Filmkunst? Gibt es dazwischen vielleicht eine Grauzone bei manchem? Wer beurteilt sowas? Ein Richter? Ist das ein Sachverstaendiger oder sollte man da nicht vielleicht Experten zurate ziehen, die keine Juristen sind? Ist etwas, was heute grosses Kino ist, morgen vielleicht P0rno? Weil sich gesellschaftliche Kriterien und Geschmaecker aendern? Was tun denn dann Webseitenbetreiber, wenn sie Rechtssicherheit haben wollen?
Update (08/07/2013): Nicht vergessen darf man ja auch nicht, wie transparent denn die Liste von zu sperrenden Seiten sein wird. In einem Rechtsstaat, in dem wir uns ja waehnen, muesste das ja schon frei einsichtig sein oder nicht? Denn irgendwelche geheimen Listen, das ist ja intransparente Willkuer. Also muss das schon veroeffentlicht werden. Aber durch die Veroeffentlichung von solchen Listen gebe ich den Menschen, die P0rnos haben wollen, doch auf dem Silbertablett eine Liste von P0rnos. Ich bin mir da nicht so ganz sicher, ob Herr Geis den Leuten Anleitungen an die Hand geben wollte, moeglichst effektiv P0rnos runterzuladen. Denn ein anderer DNS-Server oder spaetestens ein Proxy konfiguriert oder TOR, und man kommt dann trotz Sperre auf diese Seiten, alles andere wuerde einen unverantwortbaren Aufwand seitens der ISPs bedeuten, stelle ich mir da so vor.
Und dann versetzen wir uns mal in einen jungen Menschen mit Familie und Internetanschluss. Der muss sich dann überlegen: "Will ich das freigeschaltet haben? Wenn ja und das kommt irgendwie raus, weil einer das BKA oder meinen Provider hackt, was habe ich dann fuer Konsequenzen zu befürchten? Ich bin Lehrer, wenn das rauskommt, weil das BKA das ans Kultusministerium weitergibt oder irgendeiner bei meinem Provider petzt, dann ist meine Karriere ruiniert. Nicht nur das, ich bin unten durch in der Gesellschaft. Generationen von Schülern werden das einander weitererzählen. Jemand wird seinen Kompromatkoffer bis zum Anschlag voll haben gegen mich." Mit solchen Überlegungen beginnt der Abschied von der pluralistischen Zivilgesellschaft in den totalitären Staat. Wir werden uns fragen: "Was hat mein Gegenüber gegen mich in der Hand? Oh, einer von meinem Provider, dann doch lieber kuschen. Öha, jemand vom Ministerium. Ob der wohl was weiss oder nicht? Kann ich dem gegenüber souverän auftreten oder doch lieber vorsichtig, weil er was gegen mich in der Hand hat? " Das ist der Abschied von der Freiheit in die Unfreiheit. Von der Souveränität in die Unmündigkeit. Sounds familiar?
Aber das schlimme ist an dem Ganzen: Wir hatten das doch alles schon mal. Zensursula von der Leyen wollte das doch schon mal in der Form installieren und ihr Zugangserschwerungsgesetz ist gescheitert. Vor vier Jahren. Bundespräsident Hotte Köhler hatte seine Unterschrift verweigert, was eine noble Geste von ihm war. Und die SPD liess sich mal ausnahmsweise nicht vor der Union hertreiben und wollte nicht mehr mittun. Aber jetzt geht das schon wieder los. Wieder wollen Menschen wie Norbert Geis (Jahrgang 1939), die sich zuhause das Internet ausdrucken, ein Mensch, für den es eventuell bald eine biologische Lösung gibt, für Millionen von Menschen eine Unterdrückertechnologie etablieren.
Geht's noch? Reicht es noch nicht, dass die NSA und der BND alle unsere Verbindungsdaten und alle unsere unverschlüsselten Kommunikationsdaten dreist abschnorcheln?
Geis ist nicht im nächsten Bundestag. Drum wird er auch nicht für einen Vorschlag wie seinen jüngsten verantwortet werden. Ich bin ja für ein three-strikes-Modell im Bundestag: Wer dreimal für eine Gesetz stimmt, das hinterher vom BVerfG wieder einkassiert wird, der muss ohne Nachruecker gehen. Nur so bekommen wir eine Politik hin, die sich am Höchsten und Besten hierzulande orientiert, unserer Verfassung.
Auch das Vorbild Grossbritannien ist bei seinem Vorschlag wenig hilfreich. Was ist daran vorbildhaft, an jeder Strassenecke CCTVs zur Überwachung installiert zu haben? Wer will sowas, ausser einer Clique von Menschen, die Macht haben und mehr und absolute Macht haben wollen über ihre Mitmenschen? Vielleicht muss ja GB auch erst mal zwei Diktaturen in einem Jahrhundert mitgemacht haben, um für derlei Dinge eine Sensibilität zu entwickeln, um es mal zynisch auszudrücken.
tl;dr
Menschen in der CDU/CSU wollen wieder Netzsperren einrichten. Hoffen wir, dass das nur ein alter Mann war, der sich im Sommerloch hervortun wollte. Das nervt.