Elfsign Object Signing on Solaris

elfsign icon Elfsign Object Signing on Solaris

Picture of what happens if you do not use elfsign
Ballet Second Position
Don't let this happen to
you—use elfsign!
Solaris elfsign(1) is a command that signs and verifies ELF format executables. That includes not just executable programs (such as "ls" or "cp"), but other ELF format files including libraries (such as "libnvpair.so") and kernel modules (such as "autofs"). Elfsign has been available starting with Solaris 10. Starting at the same time ELF format files distributed with Solaris are signed using elfsign by either Sun Microsystems or its successor, Oracle Corporation.

When an ELF file is signed, elfsign adds a new section the ELF file, .SUNW_signature, that contains a RSA public key signature and other information about the signer. That is, the algorithm used, algorithm OID, signer CN/OU, and time stamp. The signature section can later be verified by elfsign or other software by matching the signature in the file agains the ELF file contents (excluding the signature).

ELF executable files may also be signed by a 3rd-party or by the customer. This is useful for verifying the origin and authenticity of executable files installed on a system. The 3rd-party or customer public key certificate should be installed in /etc/certs/ to allow verification by elfsign. For currently-released versions of Solaris, only cryptographic framework plugin libraries are verified by Solaris. However, all ELF files may be verified by the elfsign command at any time.

elfsign icon Elfsign Algorithms

Elfsign signatures are created by taking a digest of the ELF section contents, then signing the digest with RSA. To verify, one takes a digest of ELF file and compares with the expected digest that's computed from the signature and RSA public key.

Originally elfsign took a MD5 digest of a SHA-1 digest of the ELF file sections, then signed the resulting digest with RSA. In Solaris 11.1 then again with Solaris 11.1 SRU 7 (5/2013), we have expanded the elfsign crypto algorithms available to keep up with evolving cryptography. The following table shows the elfsign algorithms available:

Elfsign Algorithm Solaris Releases Comments
elfsign sign -F rsa_sha256 S11.1 patch SRU7+   Recommended
elfsign sign -F rsa_sha1 S11.1 Default for S11.1.
Not recommended
elfsign sign -F rsa_md5_sha1   S10, S11.0, S11.1 Default for S10.
Not recommended*
*Most or all CAs do not accept MD5 CSRs and do not issue MD5
certs due to MD5 hash collision problems.

RSA Key Length. I recommend using RSA-2048 key length with elfsign is RSA-2048 as the best balance between a long expected "life time", interoperability, and performance. RSA-2048 keys have an expected lifetime through 2030 (and probably beyond). For details, see Recommendation for Key Management: Part 1: General, NIST Publication SP 800-57 part 1 (rev. 3, 7/2012, PDF), tables 2 and 4 (pp. 64, 67).

elfsign icon Step 1: create or obtain a key and cert

The first step in using elfsign is to obtain a key and cert from a public Certificate Authority (CA), or create your own self-signed key and cert. I'll briefly explain both methods.

Obtaining a Certificate from a CA

To obtain a cert from a CA, such as Verisign, Thawte, or Go Daddy (to name a few random examples), you create a private key and a Certificate Signing Request (CSR) file and send it to the CA, following the instructions of the CA on their website. They send back a signed public key certificate. The public key cert, along with the private key you created is used by elfsign to sign an ELF file. The public key cert is distributed with the software and is used by elfsign to verify elfsign signatures in ELF files. You need to request a RSA "Class 3 public key certificate", which is used for servers and software signing. Elfsign uses RSA and we recommend RSA-2048 keys.

The private key and CSR can be generated with openssl(1) or pktool(1) on Solaris. Here's a simple example that uses pktool to generate a private RSA_2048 key and a CSR for sending to a CA:

$ pktool gencsr keystore=file format=pem outcsr=MYCSR.p10 \
   subject="CN=canineswworks.com,OU=Canine SW object signing" \
$ openssl rsa -noout -text -in MYPRIVATEKEY.key
Private-Key: (2048 bit)
    . . . [omitted for brevity] . . .
publicExponent: 65537 (0x10001)
    . . . [omitted for brevity] . . .
    . . . [omitted for brevity] . . .
    . . . [omitted for brevity] . . .
    . . . [omitted for brevity] . . .
    . . . [omitted for brevity] . . .
    . . . [omitted for brevity] . . .
$ openssl req -noout -text -in MYCSR.p10
Certificate Request:
        Version: 2 (0x2)
        Subject: OU=Canine SW object signing, CN=canineswworks.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                    . . . [omitted for brevity] . . .
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha1WithRSAEncryption
        . . . [omitted for brevity] . . .

Secure storage of RSA private key. The private key needs to be protected if the key signing is used for production (as opposed to just testing). That is, protect the key to protect against unauthorized signatures by others. One method is to use a PIN-protected PKCS#11 keystore. The private key you generate should be stored in a secure manner, such as in a PKCS#11 keystore using pktool(1). Otherwise, someone else can sign with your signature. Other secure key storage mechanisms include a SCA-6000 crypto card, a USB thumb drive stored in a secured area, a ZFS encrypted drive, a TPM hardware keystore, a dedicated server with restricted access, Oracle Key Manager (OKM), or some combination of these. I also recommend secure backup of the private key.

Here's an example of generating a private key protected in the PKCS#11 keystore, and a CSR.

$ pktool setpin # use if PIN not set yet
Enter token passphrase: changeme
Create new passphrase:
Re-enter new passphrase:
Passphrase changed.

$ pktool gencsr keystore=pkcs11 label=MYPRIVATEKEY \
   format=pem outcsr=MYCSR.p10 \
   subject="CN=canineswworks.com,OU=Canine SW object signing"
$ pktool list keystore=pkcs11
Enter PIN for Sun Software PKCS#11 softtoken: 
Found 1 asymmetric public keys.
Key #1 - RSA public key:  MYPRIVATEKEY

Here's another example that uses openssl instead of pktool to generate a private key and CSR:

$ openssl genrsa -out cert.key 2048
$ openssl req -new -key cert.key -out MYCSR.p10

Self-Signed Cert

You can use openssl or pktool to create a private key and a self-signed public key certificate. A self-signed cert is useful for development, testing, and internal use. The private key created should be stored in a secure manner, as mentioned above. The following example creates a private key, MYSELFSIGNED.key, and a public key cert, MYSELFSIGNED.pem, using pktool and displays the contents with the openssl command.

$ pktool gencert keystore=file format=pem serial=0xD06F00D lifetime=20-year \
    keytype=rsa hash=sha256 outcert=MYSELFSIGNED.pem outkey=MYSELFSIGNED.key \
    subject="O=Canine Software Works, OU=Self-signed CA, CN=canineswworks.com"

$ pktool list keystore=file objtype=cert infile=MYSELFSIGNED.pem
Found 1 certificates.
1. (X.509 certificate)
        Filename: MYSELFSIGNED.pem
        ID: c8:24:59:08:2b:ae:6e:5c:bc:26:bd:ef:0a:9c:54:de:dd:0f:60:46
        Subject: O=Canine Software Works, OU=Self-signed CA, CN=canineswworks.com
        Issuer: O=Canine Software Works, OU=Self-signed CA, CN=canineswworks.com
        Not Before: Oct 17 23:18:00 2013 GMT
        Not After: Oct 12 23:18:00 2033 GMT
        Serial: 0xD06F00D0
        Signature Algorithm: sha256WithRSAEncryption

$ openssl x509 -noout -text -in MYSELFSIGNED.pem
        Version: 3 (0x2)
        Serial Number: 3496935632 (0xd06f00d0)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: O=Canine Software Works, OU=Self-signed CA, CN=canineswworks.com
            Not Before: Oct 17 23:18:00 2013 GMT
            Not After : Oct 12 23:18:00 2033 GMT
        Subject: O=Canine Software Works, OU=Self-signed CA, CN=canineswworks.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                    . . . [omitted for brevity] . . .
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
        . . . [omitted for brevity] . . .

$ openssl rsa -noout -text -in MYSELFSIGNED.key
Private-Key: (2048 bit)
    . . . [omitted for brevity] . . .
publicExponent: 65537 (0x10001)
    . . . [omitted for brevity] . . .
    . . . [omitted for brevity] . . .
    . . . [omitted for brevity] . . .
    . . . [omitted for brevity] . . .
    . . . [omitted for brevity] . . .
    . . . [omitted for brevity] . . .

elfsign icon Step 2: Sign the ELF File object

By now you should have your private key, and obtained, by hook or crook, a cert (either from a CA or use one you created (a self-signed cert). The next step is to sign one or more objects with your private key and cert. Here's a simple example that creates an object file, signs, verifies, and lists the contents of the ELF signature.

$ echo '#include <stdio.h>\nint main(){printf("Hello\\n");}'>hello.c
$ make hello
cc    -o hello hello.c 
$ elfsign verify -v -c MYSELFSIGNED.pem -e hello
elfsign: no signature found in hello.
$ elfsign sign -F rsa_sha256 -v -k MYSELFSIGNED.key -c MYSELFSIGNED.pem -e hello
elfsign: hello signed successfully.
format: rsa_sha256.
signer: O=Canine Software Works, OU=Self-signed CA, CN=canineswworks.com.
signed on: October 17, 2013 04:22:49 PM PDT.
$ elfsign list -f format -e hello
$ elfsign list -f signer -e hello
O=Canine Software Works, OU=Self-signed CA, CN=canineswworks.com
$ elfsign list -f time -e hello
October 17, 2013 04:22:49 PM PDT
$ elfsign verify -v -c MYSELFSIGNED.pem -e hello
elfsign: verification of hello passed.
format: rsa_sha256.
signer: O=Canine Software Works, OU=Self-signed CA, CN=canineswworks.com.
signed on: October 17, 2013 04:22:49 PM PDT.

Signing using the pkcs11 keystore To sign the ELF file using a private key in the secure pkcs11 keystore, replace "-k MYSELFSIGNED.key" in the "elfsign sign" command line with "-T MYPRIVATEKEY", where MYPRIVATKEY is the pkcs11 token label.

elfsign icon Step 3: Install the cert and test on another system

Just signing the object isn't enough. You need to copy or install the cert and the signed ELF file(s) on another system to test that the signature is OK. Your public key cert should be installed in /etc/certs. Use elfsign verify to verify the signature. Elfsign verify checks each cert in /etc/certs until it finds one that matches the elfsign signature in the file. If one isn't found, the verification fails. Here's an example:

$ su
# cp MYSELFSIGNED.pem /etc/certs
# exit
$ elfsign verify -v hello
elfsign: verification of hello passed.
format: rsa_sha256.
signer: O=Canine Software Works, OU=Self-signed CA, CN=canineswworks.com.
signed on: October 17, 2013 04:24:20 PM PDT.

After testing, package your cert along with your ELF object to allow elfsign verification after your cert and object are installed or copied.

elfsign icon Under the Hood: elfsign verification

Here's the steps taken to verify a ELF file signed with elfsign. The steps to sign the file are similar except the private key exponent is used instead of the public key exponent and the .SUNW_signature section is written to the ELF file instead of being read from the file.

  • Generate a digest (SHA-256) of the ELF file sections. This digest uses all ELF sections loaded in memory, but excludes the ELF header, the .SUNW_signature section, and the symbol table
  • Extract the RSA signature (RSA-2048) from the .SUNW_signature section
  • Extract the RSA public key modulus and public key exponent (65537) from the public key cert
  • Calculate the expected digest as follows:
        signaturepublicKeyExponent % publicKeyModulus
  • Strip the PKCS#1 padding (most significant bytes) from the above. The padding is 0x00, 0x01, 0xff, 0xff, . . ., 0xff, 0x00.
  • If the actual digest == expected digest, the ELF file is verified (OK).

elfsign icon Best Practices for Software Vendors

  • Sign all ELF object files you distribute. That is, executable files, libraries, and Solaris kernel modules.
  • Although self-signed certificates are permitted, obtaining a cert from a CA is best as it can be independently verified.
  • Distribute your public key cert in /etc/certs/. Do not use /etc/crypto/certs/ except for PKCS#11 crypto token libraries.
  • Protect your private key and do not distribute it, as mentioned above.
  • Use one cert, if possible, for signing all Solaris modules. You can even use the same cert for signing non-Solaris operating system software.
  • If you develop a Solaris driver for your hardware, consider having your driver distributed "in-box" as part of Solaris by joining the Oracle Solaris Independent Hardware Vendor (IHV) program.

elfsign icon Further Information

  • elfsign(1), elfdump(1), pktool(1), and openssl(1) man pages
    • Note that the elfsign(1) man page mentions directory /etc/crypto/certs. elfsign actually searches /etc/certs and /etc/crypto/certs and all third-party certs should be installed in /etc/certs (/etc/crypto/certs is reserved for a handful of crypto modules) (man page bug 18092519).
  • "Signed Solaris 10 Binaries?" blog by Darren Moffat (2005) shows how to use elfsign.
  • "Simple CLI based CA on Solaris" blog by Darren Moffat (2008) shows how to set up a simple CA for use with self-signed certificates.
  • "How to Create a Certificate by Using the pktool gencert Command" System Administration Guide: Security Services (available at docs.oracle.com)
  • Solaris Verified Boot verifies the elfsign signature before loading kernel modules.

Post a Comment:
Comments are closed for this entry.

Solaris cryptography and optimization.


« April 2015