#!/bin/sh

#
# Author: Jamie Strandboge <jamie@canonical.com>
# Copyright (C) 2008 Canonical Ltd.
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
# http://www.gnu.org/copyleft/gpl.html
#

#
# USAGE:
# gen_certs.sh 512 1024 2048 ...
#
# Results:
# certs/${bits}/cert-${bits}-${type}-${i}-${machine}.pem
# certs/${bits}/key-${bits}-${type}-${i}-${machine}.pem
# certs/${bits}/blacklist-$bits.db
#
# There are 3 types of vulnerable moduli:
# 1. ~/.rnd does not exist when openssl is run
# 2. ~/.rnd existed, but was not readable when openssl is run
# 3. ~/.rnd is readable and writable when openssl is run
#
# Note that on 0.9.8e and lower, 1 and 2 are the same
#

getpid="./getpid.so"
if [ ! -e "$getpid" ]; then
    WORKDIR=$(mktemp -d -t blacklist-XXXXXX)
    cd "$WORKDIR"

cat >getpid.c <<EOM
/*
 * Compile:

gcc -fPIC -c getpid.c -o getpid.o
gcc -shared -o getpid.so getpid.o

 * Use:
 
FORCE_PID=1234 LD_PRELOAD=./getpid.so bash

#
# Copyright (C) 2001-2008 Kees Cook
# kees@outflux.net, http://outflux.net/
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
# http://www.gnu.org/copyleft/gpl.html

*/

#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

pid_t getpid(void)
{
    return atoi(getenv("FORCE_PID"));
}
EOM

    gcc -fPIC -c getpid.c -o getpid.o
    gcc -shared -o getpid.so getpid.o

    cd - >/dev/null
    mv $WORKDIR/getpid.so ./
    rm -rf $WORKDIR
fi

machine=`uname -m`
rand="$HOME/.rnd"

if [ -z "$1" ]; then
    echo "Must supply a bit length"
    exit 1
fi

if [ ! -f "$getpid" ]; then
    echo "$getpid does not exist, exiting"
    exit 1
fi

for bits in $@
do
    dir="certs/${bits}"
    mkdir -p $dir 2> /dev/null || true
    for type in rnd nornd noreadrnd
    do
        if [ "$type" = "noreadrnd" ]; then
            # make $rand unreadable for when people used 'sudo openssl ...' and
            # rand is unreadble
            echo "Zeroing $rand"
            rm -f $rand
            cat /dev/null > $rand
            chmod 0 $rand
            ls -l $rand
        elif [ "$type" = "rnd" ]; then
            # seed $rand and make it writable for PID updates
            echo "Enabling $rand"
            rm -f $rand
            openssl req -newkey rsa:$bits -x509 -nodes -keyout $dir/foo.pem -subj '/C=US/ST=Arizona/O=Testlib/OU=Test/CN=CA' -out $dir/bar.pem
            rm -f $dir/foo.pem $dir/bar.pem
            ls -l $rand
        else
            # take $rand out of the picture to simulate first runs
            echo "Removing $rand"
            rm -f $rand
        fi

        for i in $(seq 0 32767);
        do
            if [ "$type" = "nornd" ]; then
                # take $rand out of the picture to simulate first runs
                rm -f $rand
            fi
            n="${bits}-${type}-${i}-${machine}"
            if [ -e "${dir}/cert-${n}.pem" ]; then
                continue
            fi
            FORCE_PID=$i LD_PRELOAD="$getpid" openssl req -newkey rsa:${bits} -x509 -nodes -keyout $dir/key-$n.pem -subj '/C=US/ST=Arizona/O=Testlib/OU=Test/CN=CA' -out $dir/cert-$n.pem
            echo -n "${bits} ${i} ${type} ${machine} " >> $dir/blacklist-${bits}.db
            openssl rsa -noout -modulus -in $dir/key-$n.pem | sha1sum | cut -d ' ' -f 1 >> $dir/blacklist-${bits}.db
        done
    done
done

