Certificate Authority Certificates

The Public Key Inrastructure is used for many security issues in a Linux system. In order for a certificate to be trusted, it must be signed by a trusted agent called a Certificate Authority (CA). The certificates loaded by this section are from the list on the Mozilla version control system and formats it into a form used by OpenSSL-1.0.0e. The certificates can also be used by other applications either directly of indirectly through openssl.

This package is known to build and work properly using an LFS-7.0 platform.

Introduction to Certificate Authorities

Package Information

Certificate Authority Certificates Dependencies

Required

OpenSSL-1.0.0e

Optional

Wget-1.13.4

User Notes: http://wiki.linuxfromscratch.org/blfs/wiki/cacerts

Installation of Certificate Authority Certificates

First create a script to reformat a certificate into a form needed by openssl. As the root user:

cat > /bin/make-cert.pl << "EOF"
#!/usr/bin/perl -w

# Used to generate PEM encoded files from Mozilla certdata.txt.
# Run as ./mkcrt.pl > certificate.crt
#
# Parts of this script courtesy of RedHat (mkcabundle.pl)
#
# This script modified for use with single file data (tempfile.cer) extracted
# from certdata.txt, taken from the latest version in the Mozilla NSS source.
# mozilla/security/nss/lib/ckfw/builtins/certdata.txt
#
# Authors: DJ Lucas
#          Bruce Dubbs

my $certdata = './tempfile.cer';

open( IN, "cat $certdata|" )
    || die "could not open $certdata";

my $incert = 0;

while ( <IN> ) 
{
    if ( /^CKA_VALUE MULTILINE_OCTAL/ ) 
    {
        $incert = 1;
        open( OUT, "|openssl x509 -text -inform DER -fingerprint" )
            || die "could not pipe to openssl x509";
    } 
    
    elsif ( /^END/ && $incert ) 
    {
        close( OUT );
        $incert = 0;
        print "\n\n";
    } 
    
    elsif ($incert) 
    {
        my @bs = split( /\\/ );
        foreach my $b (@bs) 
        {
            chomp $b;
            printf( OUT "%c", oct($b) ) unless $b eq '';
        }
    }
}
EOF

chmod +x /bin/make-cert.pl

The following script creates the certificates and a bundle of all the certificates. It creates a ./certs directory and ./BLFS-ca-bundle-${VERSION}.crt. Again create this script as the root user:

cat > /bin/make-ca.sh << "EOF"
#!/bin/bash
# Begin make-ca.sh
# Script to populate OpenSSL's CApath from a bundle of PEM formatted CAs
#
# The file certdata.txt must exist in the local directory
# Version number is obtained from the version of the data.
#
# Authors: DJ Lucas
#          Bruce Dubbs

certdata="certdata.txt"

if [ ! -r $certdata ]; then
  echo "$certdata must be in the local directory"
  exit 1
fi

REVISION=$(grep CVS_ID $certdata | cut -f4 -d'$')

if [ -z "${REVISION}" ]; then
  echo "$certfile has no 'Revision' in CVS_ID"
  exit 1
fi

VERSION=$(echo $REVISION | cut -f2 -d" ")

TEMPDIR=$(mktemp -d)
TRUSTATTRIBUTES="CKA_TRUST_SERVER_AUTH"
BUNDLE="BLFS-ca-bundle-${VERSION}.crt"
CONVERTSCRIPT="make-cert.pl"
SSLDIR="/etc/ssl"

mkdir "${TEMPDIR}/certs"

# Get a list of staring lines for each cert
CERTBEGINLIST=$(grep -n "^# Certificate" "${certdata}" | cut -d ":" -f1)

# Get a list of ending lines for each cert
CERTENDLIST=`grep -n "^CKA_TRUST_STEP_UP_APPROVED" "${certdata}" | cut -d ":" -f 1`

# Start a loop
for certbegin in ${CERTBEGINLIST}; do
  for certend in ${CERTENDLIST}; do
    if test "${certend}" -gt "${certbegin}"; then
      break
    fi
  done

  # Dump to a temp file with the name of the file as the beginning line number
  sed -n "${certbegin},${certend}p" "${certdata}" > "${TEMPDIR}/certs/${certbegin}.tmp"
done

unset CERTBEGINLIST CERTDATA CERTENDLIST certebegin certend

mkdir -p certs
rm certs/*      # Make sure the directory is clean

for tempfile in ${TEMPDIR}/certs/*.tmp; do
  # Make sure that the cert is trusted...
  grep "CKA_TRUST_SERVER_AUTH" "${tempfile}" | \
    grep "CKT_NETSCAPE_TRUST_UNKNOWN" > /dev/null

  if test "${?}" = "0"; then
    # Throw a meaningful error and remove the file
    cp "${tempfile}" tempfile.cer
    "${CONVERTSCRIPT}" > tempfile.crt
    keyhash=$(openssl x509 -noout -in tempfile.crt -hash)
    echo "Certificate ${keyhash} is not trusted!  Removing..."
    rm -f tempfile.cer tempfile.crt "${tempfile}"
    continue
  fi

  # If execution made it to here in the loop, the temp cert is trusted
  # Find the cert data and generate a cert file for it

  cp "${tempfile}" tempfile.cer
  "${CONVERTSCRIPT}" > tempfile.crt
  keyhash=$(openssl x509 -noout -in tempfile.crt -hash)
  mv tempfile.crt "certs/${keyhash}.pem"
  rm -f tempfile.cer "${tempfile}"
  echo "Created ${keyhash}.pem"
done

# Remove blacklisted files
# MD5 Collision Proof of Concept CA
if test -f certs/8f111d69.pem; then
  echo "Certificate 8f111d69 is not trusted!  Removing..."
  rm -f certs/8f111d69.pem
fi

# Finally, generate the bundle and clean up.
cat certs/*.pem >  ${BUNDLE}
rm -r "${TEMPDIR}"
EOF

chmod +x /bin/make-ca.sh

Add a short script to remove expired certifictes from a directory. Again create this script as the root user:

cat > /bin/remove-expired-certs.sh << "EOF"
#!/bin/bash
# Begin /bin/remove-expired-certs.sh

OPENSSL=/usr/bin/openssl
DIR=/etc/ssl/certs

if [ $# -gt 0 ]; then
  DIR="$1"
fi

certs=$( find ${DIR} -type f -name "*.pem" -o -name "*.crt" )
today=$( date +%Y%m%d )

for cert in $certs; do
  notafter=$( $OPENSSL x509 -enddate -in "${cert}" -noout )
  date=$( echo ${notafter} |  sed 's/^notAfter=//' )

  if [ $( date -d "${date}" +%Y%m%d ) -lt ${today} ]; then
     echo "${cert} is expired! Removing..."
     rm -f "${cert}"
  fi
done
EOF

chmod +x /bin/remove-expired-certs.sh

The following commands will fetch the certificates and convert them to the correct format. If desired, a web browser may be used instead of wget but the file will need to be saved with the name certdata.txt. These commands can be repeated as necessary to update the CA Certificates.

certhost='http://mxr.mozilla.org'                        &&
certdir='/mozilla/source/security/nss/lib/ckfw/builtins' &&
url="$certhost$certdir/certdata.txt?raw=1"               &&

wget --output-document certdata.txt $url &&
unset certhost certdir url               &&
make-ca.sh                               &&
remove-expired-certs.sh certs

Now, as the root user:

SSLDIR=/etc/ssl                                     &&
install -d ${SSLDIR}/certs                          &&
cp -v certs/*.pem ${SSLDIR}/certs                   &&
c_rehash                                            &&
install BLFS-ca-bundle*.crt ${SSLDIR}/ca-bundle.crt &&
unset SSLDIR

Finally, clean up the current directory:

rm -r certs BLFS-ca-bundle*

Contents

Installed Programs: make-ca.sh, make-cert.pl and remove-expired-certs.sh
Installed Libraries: None
Installed Directories: /etc/ssl/certs

Short Descriptions

make-ca.sh

is a bash script that reformats the certdata.txt file for use by openssl.

make-cert.pl

is a utility perl script that converts a single binary certificate (.der format) into .pem format.

remove-expired-certs.sh

is a utility perl script that removed expired certificates fom a directory. The defaut directory is /etc/ssl/ceerts.

Last updated on 2011-11-01 09:10:22 +0000