Checking SSL Certificates

Posted on 2012-05-08

Verify whether a certificate matches a private key and has valid timestamp

The certificate is the signed public key (and some meta data); to verify whether a certificate matches the private key, one has to extract the public key of both and compare them.

Both the rsa and the x509 subcommand of openssl have a -modulus option to extract the modulus; they can also extract the complete public key, but the option has a different name for each of the subcommands:

1
2
openssl x509 -in "$CRT" -noout -pubkey
openssl rsa -in "$KEY" -pubout 2>/dev/null

The timestamps are in the text output of the certificate in the fields “Not Before:” and “Not After :”:

1
2
openssl x509 -in "$CRT" -text -noout | \
awk -- 'BEGIN {FS=": ";b="";e=""}  /^ *Not Before *: / { b = $2 } /^ *Not After *: / { e = $2 } END { print b; print e }

You can convert those timestamps to “seconds since 1970-01-01 00:00:00 UTC” width date +%s, making it easy to compare them to the current date (in the same format).

All in one script (you have to set KEY and CRT before; you probably may want to check whether the files exist too):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
A=$(openssl x509 -in "$CRT" -noout -pubkey)
B=$(openssl rsa -in "$KEY" -pubout 2>/dev/null)
if [ "$A" != "$B" ]; then
    echo "cert doesn't match private key" >&2
    printf "$CRT pubkey:\n%s\n$KEY pubkey:\n%s\n" "$A" "$B" >&2
else
    DATES=$(openssl x509 -in "$CRT" -text -noout |
        awk -- 'BEGIN {FS=": ";b="";e=""}  /^ *Not Before *: / { b = $2 } /^ *Not After *: / { e = $2 } END { print b; print e }')
    begin=$(echo "$DATES" | head -n1)
    end=$(echo "$DATES" | tail -n1)
    ubegin=$(date -d "$begin" +%s)
    uend=$(date -d "$end" +%s)
    unow=$(date +%s)
    if [ $unow -lt $ubegin -o $uend -lt $unow ]; then
        echo "Invalid timestamps for $CRT, was valid for:" >&2
        echo "$DATES" >&2
    else
        echo "Valid timestamps for $CRT (which matches privkey):"
        echo "$DATES"
    fi
fi

Complete story with comments

Cross compile Windows Applications

Posted on 2012-04-09

There is a nice repository on build.opensuse.org which provides some useful packages to cross compile from linux, and I’m going to describe a simple setup using cmake and Qt:

First install openSUSE 12.1 into a virtual machine (unless you want to do it on a real machine).

Then add the extra repositories and install the needed packages (as root):

1
2
3
4
zypper ar http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_12.1/windows:mingw:win32.repo
zypper install mingw32-cross-gcc mingw32-cross-gcc-c++ mingw32-libjpeg-devel mingw32-libpng-devel mingw32-libqt4 mingw32-libqt4-devel mingw32-libtiff-devel mingw32-zlib-devel
zypper ar http://download.opensuse.org/repositories/devel:/tools:/building/openSUSE_12.1/devel:tools:building.repo
zypper install cmake-2.8.7 binutils git
  • The second repository is needed for an updated cmake-2.8.7 which includes http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6ddb1e5b9a3eff941ad12d29609839871fe518ed
  • binutils includes “strings” which is needed in one of the scripts below.

Then login with your normal user, and prepare the cmake toolchain file:

~/toolchain-windows.cmake:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
SET(CMAKE_SYSTEM_NAME Windows)

SET(CMAKE_C_COMPILER   i686-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)
SET(CMAKE_RC_COMPILER  i686-w64-mingw32-windres)

SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32/sys-root/mingw)

SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

SET(QT_QMAKE_EXECUTABLE /usr/i686-w64-mingw32/bin/qmake CACHE INTERNAL "" FORCE)
SET(QT_MOC_EXECUTABLE /usr/i686-w64-mingw32/bin/moc CACHE INTERNAL "" FORCE)
SET(QT_RCC_EXECUTABLE /usr/i686-w64-mingw32/bin/rcc CACHE INTERNAL "" FORCE)
SET(QT_UIC_EXECUTABLE /usr/i686-w64-mingw32/bin/uic CACHE INTERNAL "" FORCE)

Now checkout your favorite project which uses cmake+qt and build it with cmake in a subdirectory:

1
2
3
4
5
6
git clone -b stefan-wip git://stbuehler.de/qcross.git
cd qcross
mkdir winbuild
cd winbuild
cmake -DCMAKE_TOOLCHAIN_FILE=~/toolchain-windows.cmake ..
make

The resulting binaries will need some DLLs; with the two scripts below (chmod +x) they should be easy to install into a directory:

1
$ installapp ~/qcross/winbuild ~/app/qcross

Now all the needed files should be in ~/app/qcross.

bin/installexe:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/bash

if [ -z "$1" -o -z "$2" ]; then
    echo "Syntax: $0 <source> <targetdir> [optionall dll dirs]" 1>&2
    exit 1
fi

SOURCE=$1
shift
TARGET=$1
shift

DLLSOURCE=/usr/i686-w64-mingw32/sys-root/mingw/

if [ ! -f "$SOURCE" ]; then
    echo "source '$SOURCE' doesn't exist"
fi

mkdir -p "$TARGET"

walk() {
    b="$(basename $1)"
    d="$TARGET/$b"
    if [ -f "$d" -a ! "$d" -ot "$1" ]; then
        echo "Skipping   '$b' [current version already present]"
    else
        echo "Installing '$b'"
        cp -a "$1" "$TARGET/"

        # Hack to find dependencies
        strings "$1" | grep '\.dll' | while read dll
        do
            DLL=`find "$DLLSOURCE" "$@" -name "$dll" -print -quit`
            if [ ! -z "$DLL" -a -f "$DLL" ]; then
                walk "$DLL"
            fi
        done
    fi
}

walk "$SOURCE"
exit 0

bin/installapp:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/bin/bash

if [ -z "$1" -o -z "$2" ]; then
    echo "Syntax: $0 <sourcedir> <targetdir>" 1>&2
    exit 1
fi

SOURCE=$1
shift
TARGET=$1
shift

for exe in $(find "$SOURCE" -name '*.exe' | grep -v CMakeFiles); do
    echo "Installing executable $exe -> $TARGET"
    installexe "$exe" "$TARGET" "$TARGET" "$@"
done

Complete story with comments

Hidden Finalizers in Ada

Posted on 2011-09-11

“It’s not a bug, it’s a feature!”

Often you want to execute specific code when a object is destroyed – for example free all pointers in it. In Ada you need the Ada.Finalization package for this, which provides you with the Controlled and the Limited_Controlled tagged types; they allow custom action for “Initialize”, “Adjust” (not for limited) and “Finalize”.

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
with Ada.Finalization;
with Ada.Unchecked_Deallocation;

procedure Example is
   package X is
      type Container is limited private; --  limited, so you don't accidentally copy a container

   private
      type Tree;
      type Tree_Access is access Tree;
      type Tree is null record;  --  this obviously needs more details :)

      type Container is new Ada.Finalization.Limited_Controlled with record
         Root : Tree_Access;
      end record;

      overriding procedure Initialize (C : in out Container);
      overriding procedure Finalize (C : in out Container);
   end X;

   package body X is
      procedure Initialize (C : in out Container) is
      begin
         C.Root := null;
      end Initialize;

      procedure Finalize (C : in out Container) is
         procedure Free is
            new Ada.Unchecked_Deallocation (Tree, Tree_Access);
      begin
         Free (C.Root);
      end Finalize;
   end X;
begin
   null;
end Example;

This solution has a drawback: Container becomes a tagged type (you could say tagged types are the object-orientation in Ada), but you only see the negative effects on the outside: you can’t use methods that “dispatch” in one more than one tagged type like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
procedure Example is
   package X is
      type A is tagged null record;
      type B is tagged null record;

      procedure Foo (x : in out A; y : in out B);
   end X;

   package body X is
      procedure Foo (x : in out A; y : in out B) is
      begin
         null;
      end;
   end X;

begin
   null;
end Example;

results in:

1
2
3
4
$ gnatmake example.adb
gcc-4.4 -c example.adb
example.adb:6:17: operation can be dispatching in only one type
gnatmake: "example.adb" compilation error

Now you could for example replace the parameter “B” with “B’Class” in Foo; it then would only dispatch in x, not in y. But as the taggedness is private in the Container example above (and there is no reason to make it public), you cannot use Container’Class outside the private part of the package.

The solution is mix-in I found in a forum:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
with Ada.Finalization;
with Ada.Unchecked_Deallocation;

procedure Example is
   package X is
      type Container is limited private;

   private
      type Tree;
      type Tree_Access is access Tree;
      type Tree is null record;  --  this obviously needs more details :)

      type Container_Control (Enclosing : access Container) is
         new Ada.Finalization.Limited_Controlled with null record;

      type Container is limited record
         Root : Tree_Access;
         Control : Container_Control (Container'Access);
      end record;

      overriding procedure Initialize (C : in out Container_Control);
      overriding procedure Finalize (C : in out Container_Control);
   end X;

   package body X is
      procedure Initialize (C : in out Container_Control) is
      begin
         C.Enclosing.all.Root := null;
      end Initialize;

      procedure Finalize (C : in out Container_Control) is
         procedure Free is
            new Ada.Unchecked_Deallocation (Tree, Tree_Access);
      begin
         Free (C.Enclosing.all.Root);
      end Finalize;
   end X;
begin
   null;
end Example;

The access discriminant “Enclosing” and “Container’Access” is a hack with a special syntax; I couldn’t find it in the Ada reference manual, but wikibooks knows it too and explains why this only works for limited types too (and more).

References


Complete story with comments