OpenSolaris

X.509v3 support for SunSSH

Jan.Pechanec (at) Sun.COM

Version Description
2008-05-11 some information on existing drafts added
2008-02-18 initial version of this document

Contents

Overview
Existing IETF drafts
Key Management Framework
Server authentication
Client authentication
Modifying SSH agent
Certificate to user/server name mapping
KMF policies in general
Interaction with PAM framework
Examples
Notes
Open issues
References

Overview

This design document specifies how X.509v3 certificates should be used in SSH2 protocol within SunSSH for server authentication and user public key authentication. Note: using v3 certificates will not be necessary and KMF policy can be configured the way that no extensions are needed. This project has 3 different but mutually connected parts:

We will follow the latest IETF informational draft on X.509 authentication in SSH but if the draft becomes an RFC with incompatible changes we will follow RFC even if it involves losing backwards compatibility.

Existing IETF drafts

There hasn't been much progress recently in IETF with regards to X.509v3 support in SSH. The last IETF document draft released on this topic from the now defunct SSH working group was draft-ietf-secsh-x509-03.txt[1]. The draft expired on September 1, 2006 and specified 3 key and signature formats x509v3-sign, x509v3-sign-rsa-sha1 and x509v3-sign-dss-sha1. The most generic one, x509v3-sign allowed use of a certificate chain for full PKIX path validation[4], together with sending optional OCSP responses. However, before any RFC was released, IETF SSH working group[9] closed down. From that reason, a new, and now informational only draft[10] was released in the Network working group. The draft expired on August 11, 2007 and no new version was released since then.

While the previous draft was about to define what it should be done, given the fact that the group closed down, the new draft was released as informational only, and its purpose was to inform what was implemented in existing SSH software. The biggest difference in comparison to the draft filed in SSH working group is the use of existing public key formats ssh-(rsa|dsa). The problem with existing key formats is that there is no way to define a chain of certificates. Both the host and client certificates must be directly signed by a trusted anchor since there is no way to communicate to the other side that there might be another certificate between them.

Thanks to one of the author, Joseph Galbraith from Van Dyke, for clarification. There is a chance that the work on the last draft filed in SSH working group might be continued.

Key Management Framework

KMF provides a unified set of interfaces (both programming APIs and administrative tools) for managing PKI objects in Solaris. Currently, there are several different "keystore systems" that developers and administrators must choose when designing systems that employ PKI technologies - NSS, OpenSSL, and PKCS#11 are the 3 main choices. Each of these systems presents very different programming APIs and administrative tools and none of them has any sort of concept of a PKI policy enforcement system.

One of the unique features of KMF is that it provides a system-wide policy database that KMF can use to apply to applications. The administrator or user creates policy definitions in a database file. KMF applications can then choose which policy they want to assert and then all subsequent KMF operations will behave according to the limitations of that policy. Policy definitions include rules for how validation is to be performed, key usage and extended key usage requirements, trust anchor definitions, OCSP parameters, and CRL DB parameters (location, etc). This means that all parameters will be configured via the KMF policy mechanism. This should make SSH configuration simpler.

See KMF project[8] for more information.

Server authentication

Server side of server authentication

The server has a certificate and a corresponding private host key. This certificate is sent to the client during key exchange (KEX), see [1]. Whether RSA or DSS host key algorithm will be offered depends on the server certificate (there can be only one server certificate). The private key is used to prove the server's identity during the server authentication[2]. The client is expected to trust (= have) the CA certificate that signed the server's certificate in order to proceed in the key exchange. We call such a certificate a Trusted Anchor (TA).

We use the HostKey keyword to specify the private key and certificate. The certificate for the private key must be stored using the same object label name. We need new option keywords for specifying the server's KMF policy. Example for a server host (asiasf.sfbay.sun.com) key using a pin in the URI (prototype version only):

HostKey="pkcs11:token=Sun Software PKCS#11 softtoken;pin=password;object=asiasf"

Private key and certificate

An existing server option (HostKey) will reference a private key, and only PKCS#11 token rings will be supported for now. While the project assumes the existence of other KMF plugins (OpenSSL, NSS) PKCS#11 will be the only supported plugin for now. If the private key is:

The PIN for a token could be specified using one of these methods:

The last suggestion appears to be the best solution since that way we can store the PIN in a file accessible by root only and the server configuration file can remain readable for all. The security of this solution is not a regression from current behaviour as the host private keys are protected by UNIX file permissions only.

Client side of server authentication

The client specifies policies for individual servers, through Host sections in the client's config file. Every policy specifies one trusted anchor via ta-name and ta-serial attributes of the kmf-policy element. See kmfcfg(1) for more information.

The KMFPolicyDatabase option keyword will be used to set the KMF policy file, KMFPolicyName will specify a policy name. The default value will be empty. If at least one of them is non-empty, x509v3-sign-(rsa|dss) will be added to the host key algorithms for key exchange, and will be preferred. Whether RSA or DSS type will be added will be decided from the TA certificate. It is up to the administrator to correctly specify KMF policy. For example, to make sure that TA certificate specified in the policy is accessible. So far, the name for the PKCS#11 keystore for the TA's location can't be in the policy database. The KMF team is working on a solution, we will rely on that and won't provide an additional option keyword.

OCSP in server authentication

OCSP support is not SunSSH's job. This is taken care of through KMF policy, see kmfcfg(1) man page[5].

In general, a server certificate that contains id-ad-ocsp in the certificate's accessMethod extension, together with a KMF policy that specifies OCSP in the validation-methods element and apropriate attributes of the ocsp-basic element, will be checked using OCSP during certificate validation. In that case, accessLocation will be used if uri-from-cert is set in the policy file. See also /etc/security/kmfpolicy.xml[6].

CRL in server authentication

As with OCSP, defining CRL support is out of scope of SunSSH and is also done through client KMF policy, see kmfcfg(1) man page[5].

In general, a server certificate that contains the cRLDistributionPoints extension, together with a KMF policy that specifies a CRL in the validation-methods element and apropriate attributes of the crl element, will be checked in the certificate revocation list.

Client authentication

Client side of client authentication

Similar to server authentication, the client specifies its private host keys and a corresponding certificates. The only difference is that IdentityFile is used instead of HostKey and that the client can specify more keys in KMF keystores.

The PIN will be asked for before any connection is established. However, using modified SSH agent might be encouraged. We will also provide a similar attribute as for the server - to set an external command which provides the PIN.

Server side of client authentication

Similar to the client side of server authentication, the server specifies a trusted anchor via the ta-name and ta-serial attributes of the kmf-policy element in the KMF policy. For now, we can have only one Trusted Anchor per SunSSH server. However, this could probably be extended to multiple policies through resyncing the Match option keyword from OpenSSH. See RFE 6655613[7] for more information.

OCSP and CRL

See server authentication -- this will be configured through KMF policy, not SunSSH.

Modifying SSH agent

We must modify the SSH agent for X.509v3 support. One issue we see is how to keep a private key in the agent, expecially when we expect that users will use smart cards that won't allow any private keys to be extracted. Storing private keys corresponding to X.509v3 certificates in the agent is not a good solution.

The agent needs a handle for every private key in a keystore to sign data requests. The problem is how to provide an agent with the key handle. The ideal situation would be if ssh-add asked for a PIN, got a KMF session and a private key handle and passed that to the agent. That's not possible but we can provide the agent with a PIN. So, ssh-add will ask for a PIN and add it to a PKCS#11 URI that is sent in a comment field to the agent. There is no need to extend the agent protocol.

When listing the keys we can't provide a fingerprint since we might not have access to the private key (remember, signing may happen inside of a hardware token). So, we could provide a DN for the corresponding certificate instead, maybe in double quotes for easier parsing, and type of the keystore. ssh-add -L could then list the whole certificate.

$ ssh-add -l
1024 90:44:85:88:e6:d4:b8:54:a7:89:5d:e3:94:90:51:08 .ssh/id_dsa (DSA)
1024 "CN=jp,C=CZ,ST=Czech Republic" pkcs11-keystore (X509/RSA)

If the agent protocol needed to be extended we should probably do that through IETF. As far as I know, there is no existing RFC defining the protocol, only a very old draft[11]. Thus, OpenSSH (and SunSSH) uses the protocol as defined in the original SSH specification[12], with some extensions. Having described current situation, I think that no new extensions should be used without re-opening the discussion about the protocol.

Certificate to user/server name mapping

When the receiving party gets a certificate for a specified server or user, there needs to be a way to decide that the certificate was really issued for that server host or user name. So, we need a way how to map a certificate to a FQDN, IP address, UNIX user name or UNIX UID.

Unfortunately, that's not part of KMF yet but is planned as a future project. We expect that mapping will be tied to a specified TA and that there is no need to change it per connection on the receiving side. Another assumption is that certidicate-to-username mapping will be configurable through the KMF policy only. We don't want to configure through SunSSH which certificate field is to be used for a host or a client name, or possibly how such field should be rewritten.

Certificate to username mapping

The username we get from KMF according to policy settings must be equal to what we get from 2nd field in SSH_MSG_USERAUTH_REQUEST SSH packet, see RFC 4252[13] for more information. We don't intend to support adding @domainname suffix, for example, at least not in the 1st phase of this project.

Certificate to hostname mapping

More interesting than username mapping is hostname mapping. Whether we get the hostname as specified in the certificate from CN, AltName or something else will be up to the KMF mapping as configured in the policy.

Security of certificate to hostname mapping

The interesting part is what hostname to use for comparison to the hostname extracted from the certificate. We can't look up and use a canonical name for the host specified on the command line (say, good-guy.company.com) since we could get a different canonical hostname (say, bad-guy.company.com) and IP adress from a compromised DNS server. However, the certificate sent for bad-guy.company.com might have been signed by a valid CA so we could end up connected to a different server than we wanted. In that case, the compromised DNS server and one host with a valid certificate could be enough to impersonate any other host. User wouldn't notice that at all during the server authentication -- remember, we don't have any location bar where you might notice the change between hostnames.

From that reason, we must always use a hostname in the form as was specified on the command line or in the HostName option. That means that users might be required to use hostnames in FQDN form because that's what we suppose is going to be used in host certificates. Or, if CA is willing to sign certificates with short names like my-machine, users could use short names. Important thing is that if we had a compromised DNS server and one compromised machine as in the previous situation, bad-guy.company.com machine couldn't impersonate my-machine now since we couldn't be tricked into using a different hostname. Machine bad-guy.company.com would have to posses my-machine's private key in order to mount the attack.

Having to use the hostname exactly in the form as specified in the certificate might be annoying. We might want to offer a list of domains that could be used to complete the hostname before doing the comparison. Obvious candidate /etc/resolv.conf is not good enough because a different naming service might be in use. One option would be to use the KMFDomainNames-like option with a list of domain names. In corporate environment, we expect that internal CAs would issue host certificates with unified hostnames so adding such option with my-company.com domain name into a system wide ssh_config might be useful.

If a user uses an IP address, the client would use the exact IP address as specified for comparison.

KMF policies in general

A new policy template for sshd/ssh will be delivered with the SunSSH packages. We might even ship more example policy templates, showing example of OCSP vers CRL usage etc.

Interaction with PAM framework

As with the current implementation of public key user authentication, sshd will not call pam_authenticate(3PAM) for authentication, only for account management and session management.

Examples

This is how client prototype is used:

ssh -p 2222 \
    -o KMFPolicyDatabase=/etc/security/testpolicy.xml \
    -o KMFPolicyName=test
    -o IdentityFile="pkcs11:token=Sun Software PKCS#11 softtoken;object=jp" \
    asiasf.sfbay

This is server prototype is used:

sshd -p 2222 \
    -o HostKey="pkcs11:token=Sun Software PKCS#11 softtoken;object=asiasf" \
    -o KMFPolicyDatabase=/etc/security/testpolicy.xml \
    -o KMFPolicyName=test

And in the soft token on the client side there is a test TA certificate (label is "ta") and a certificate for the user "jp", together with a private key.

$ pktool list objtype=both
Enter PIN for Sun Software PKCS#11 softtoken  : 
Found 1 asymmetric private keys.
Key #1 - RSA private key:  jp
Found 2 certificates.
1. (X.509 certificate)
        Label: ta
        ID: 74:23:e3:ea:d7:f7:42:db:bf:78:c8:a5:d6:82:7e:c8:70:03:8a:81
        Subject: C=CZ, ST=Czech Republic, CN=authority
        Issuer: C=CZ, ST=Czech Republic, CN=authority
        Not Before: Jan 23 12:57:00 2008 GMT
        Not After: Jan 22 12:57:00 2009 GMT
        Serial: 0x01

2. (X.509 certificate)
        Label: jp
        ID: 86:05:e8:53:b3:fb:7a:80:8c:c1:61:50:87:5c:80:1a:49:a6:fe:66
        Subject: C=CZ, ST=Czech Republic, O=Sun, OU=Sec, CN=jp
        Issuer: C=CZ, ST=Czech Republic, CN=authority
        Not Before: Feb  5 14:32:29 2008 GMT
        Not After: Feb  4 14:32:29 2009 GMT
        Serial: 0x05
        X509v3 Key Usage: Digital Signature, Non Repudiation, Key Encipherment

KMF policy is very simple - the TA's DN was added to the template. Remember that the policy file is configured through kmfcfg(1) - there is no need to manually edit it.

$ cat /etc/security/testpolicy.xml 
<?xml version="1.0"?>
<!DOCTYPE kmf-policy-db SYSTEM "/usr/share/lib/xml/dtd/kmfpolicy.dtd">
<kmf-policy-db>
  <kmf-policy name="test" ta-name="C=CZ, ST=Czech Republic, CN=authority" ta-serial="0x01">
        <validation-methods>
        </validation-methods>
</kmf-policy>
</kmf-policy-db>

Notes

Open Issues

References


Last changed: Mon Feb 18 16:42:54 CET 2008