Subject: x509

From: Markus Friedl <[email-masked]>
Date: Wed, 30 Jan 2002 22:39:14 +0100

I'm trying to figure out how x509 support should actually work.

I think about sending certs encoded as "x509v3-sign-rsa" and the actual
signature as "ssh-rsa", since there is no spec for what a matching
x509-signature should look like.

How should certificates be encoded in "x509v3-sign-rsa"?

The spec seems a little bit ambigous to me:

   Certificates and public keys are encoded as follows:

     string   certificate or public key format identifier
     byte[n]  key/certificate data

   The certificate part may have be a zero length string, but a public
   key is required.  This is the public key that will be used for
   authentication; the certificate sequence contained in the certificate
   blob can be used to provide authorization.

Does this mean that "x509v3-sign-rsa"
is encoded as

	string "x509v3-sign-rsa"
	byte[n] DER-encoded x509 cert

	string "x509v3-sign-rsa"
	int32	n
	byte[n] DER-encoded x509 cert

What does "but a public key is required" mean?  Zero length strings
for certificates?  Are they always required?

How is the encoding for userauth?

     byte      SSH_MSG_USERAUTH_REQUEST
     string    user name
     string    service
     string    "publickey"
     boolean   FALSE
     string    public key algorithm name
     string    public key blob

For RSA keys the 'public key algorithm name' is "ssh-rsa"
and the 'public key blob' is
     string    "ssh-rsa"
     mpint     e
     mpint     n

What is used for x509 certs?

-m

---

From: "Joseph Galbraith" <[email-masked]>
Date: Wed, 30 Jan 2002 16:59:51 -0700

This is clearly still an open issue--

We discussed it on the list before the
August meeting, at the August meeting,
and it has been brought up at least
once recently.

Here is a email I sent right before the
August meeting with a proposed change:

> In the transport draft, Section 4.6, we specify that
> public keys are, in general encoded as:
>
> However, the sections on x.509 are less clear.  And in fact,
> SSH Communications current x.509 implementation omits the
> string, including only the certificate data -- although
> the string is included when sending signatures.
>
> I would suggest we include the following text in section
> documenting "x509v3-sign-rsa":
>
> The "x509v3-sign-rsa" key format has the following specific encoding:
>
>      string    "x509v3-sign-rsa"
>      byte[n]   x.509v3 compatible der encoded certificate data
>
> The resulting signature is encoded as follows:
>
>      string    "x509v3-sign-rsa"
>      string    rsa_signature_blob
>
>
> Variants to this go in the other x.509 sections as appropriate.
>
> In addition, I would suggest that we note that signatures
> made with x509v3-sign-rsa keys MUST use the SHA-1 hash, and
> be done using PKCS1.

During the August meeting, we decided that
we needed to use PKCS 7, because if a hardware
device was in play, it might not be possible
to control the hash algorithm it uses.

Here is an email I sent after the meeting
with this proposed change in it:

> --------- Transport draft, Section 4.6
>
> (We might want to number the different sections
> of this, so that ssh-dss becomes 4.6.1, ssh-rsa
> becomes 4.6.2, and x509v3-* becomes 4.6.3)
>
> 4.6.3 x.509v3 certificates
>
>   The "x509v3-*" methods indicate that the certificates, the
>   public key, and the resulting signature are in X.509v3 compatible
>   DER-encoded format.  The formats used in X.509v3 are described in
>   [RFC2459].  The formats used for signatures are described in
>   [PKCS7].
>
>   Note, that there is no such algorithm as "x509v3-*", but the
>   * is used only in this document to denote all algorithms
>   beginning with x509v3.
>
>   There are currently two such algorithms defined:
>     x509v3-sign-rsa      RECOMMENDED  sign    X.509 certificates (RSA key)
>     x509v3-sign-dss      RECOMMENDED  sign    X.509 certificates (DSS key)
>
>   The "x509v3-*" key format has the following generic encoding:
>
>     string    "x509v3-*"
>     string    x.509v3 compatible der encoded certificate data
>
>   The resulting signature is encoded as follows:
>
>     string    "pkcs7"
>     string    PKCS-7 signature, DER encoded
>
>   The "x509v3-sign-rsa" method indicates that the key
>   (or one of the keys in the certificate) is an RSA-key.
>
>   The "x509v3-sign-dss".  As above, but indicates that the key (or
>   one of the keys in the certificate) is a DSS-key.

Now -- on further reflection, I'm not sure.  Do hardware
devices like smartcards do a hashing operation, or are
they passed the hash to sign?

If they don't do the hashing operation, and we don't think
we need to provide that kind of flexibility, we can probably
get away without PKCS 7, and do something like what Markus is
proposing in this email:

> i don't see why we cannot use the current "ssh-rsa" encoding:
> transfer a x509 certificate in addition to "ssh-rsa" encoded
> signature?
>
> since "x509v3-sign-rsa" is not specified in detail, it should be
> dropped from the draft and replaced by something like
> "x509v5-ssh-rsa"
> meaning:
> public key is transfered in "x509v3" format and
> the current "ssh-rsa" is used for encoding for signatures.
>
> i think all the confusion is due to the fact that a single
> identifier is used for specifying to encoding of
> keys, certificates and signatures.
>
> i don't see why the current signature formats cannot
> be used together with x509 certificates.

- Joseph

---

From: Damien Miller <[email-masked]>
Date: Thu, 31 Jan 2002 11:29:58 +1100 (EST)

> > the current "ssh-rsa" is used for encoding for signatures.

I like the idea of removing the underspecified Public Key Algorithms and
replacing them with equivalents based on the current ssh-rsa and ssh-dss
methods.

e.g.

string "ssh-rsa-x509v3"
mpint e
mpint n
string der_encoded_certificate

This scales nicely to the other certificate (SPKI, OpenPGP) methods. 

It also allows implementations which don't directly support the 
certificate format to continue authentication with the pubkey only. Though 
this may be dangerous as it would miss additional restrictions implicit in 
the certificate, e.g. validity periods in X.509v3 & OpenPGP or 
restrictions in SPKI.

-d

---

From: Markus Friedl <[email-masked]>
Date: Thu, 31 Jan 2002 11:10:48 +0100

> > the string is included when sending signatures.

I think they use
	byte[n]  der-encoded-x509-cert
instead of
	string	 "x509v3-sign-rsa"
	byte[n]  der-encoded-x509-cert
because with the 2nd encoding the length of the DER blob is not made
explicit, while with the 1st encoding you have length, because the
pubkey is usually wrapped into a
	string	pubkeyorcertblob

An encoding similar to
	string	 "x509v3-sign-rsa"
	int32	 n
	byte[n]  der-encoded-x509-cert
would be more in line with the other encodings.

However, the transport draft also state:

   The key type MUST always be explicitly known (from algorithm
   negotiation or some other source).  It is not normally included in
   the key blob.

This does not match with:

Or am I missing something?

-m

---

From: Markus Friedl <[email-masked]>
Date: Thu, 31 Jan 2002 11:21:40 +0100

> > transfer a x509 certificate in addition to "ssh-rsa" encoded

In the initial keyexchange both parties agree on the used host-key
encoding and on supported signature encodings.  So If both parties
agree on "x509v3-sign-rsa" for the public key encoding, you cannot
assume that the peer can decode a "ssh-rsa" type signature.  So the
"name" from the public key and the "name" of the signature encoding
must always match.  This means you cannot mix a  "x509v3-sign-rsa" host
key cert and a "ssh-rsa" signature.

But there still seems to be an open issue:

   The "x509v3-sign-rsa" method indicates that the certificates, the
   public key, and the resulting signature are in X.509v3 compatible
   DER-encoded format.  The formats used in X.509v3 is described in
   [RFC2459].  This method indicates that the key (or one of the keys in
   the certificate) is an RSA-key.

Does this mean the signature will look like a

     string    "ssh-rsa"

but with a different name tag instead?

     string    "x509v3-sign-rsa"

Do they differ otherwise?

-m

---

From: [email-masked] (Niels Möller)
Date: 31 Jan 2002 11:59:58 +0100

A few comments on some of the issues here.

> > > transfer a x509 certificate in addition to "ssh-rsa" encoded

I think it makes sense to keep the ssh-dsa and ssh-rsa encodings for
signatures. Certificate standards typically don't define formats for
detached signatures. Whether or not a new name is attached to the data
isn't terribly important, but I'd prefer *not* introducing new
redundant names.

> This scales nicely to the other certificate (SPKI, OpenPGP) methods. 

This has one big advantage: The ssh(d) program can verify the
signature, and delegate processing of the certificates to an external
program or library, which doesn't need to know the SSH protocol data
that was signed.

One potential disadvantage is that it might encourage implementations
to claim they understand x509, and silently ignore the certificate
data. In this situation, the right thing to do is to use only plain
"ssh-rsa".

The certificate blob is still slightly underdefined:

There may be more than one certificate, and there's more than one way
to represent a certificate chain (e.g. pure x.509 and SSL do it
differently). The spec should at least say explicitly what type of
ASN.1-object is expected inside the DER encoding.

(Personally, I dislike x.509, but these encoding issues are quite
similar for spki).

/Niels

---

From: Markus Friedl <[email-masked]>
Date: Thu, 31 Jan 2002 12:11:23 +0100

> isn't terribly important, but I'd prefer *not* introducing new

ok, then the transport draft must say:

signatures for hostkeys of type "ssh-rsa-x509v3" are
encoded as
	string	"ssh-rsa"
	string	rsa_signature_blob.

-m

---

From: [email-masked] (Niels Möller)
Date: 31 Jan 2002 13:01:04 +0100

> program or library, which doesn't need to know the SSH protocol data

But on second thought, this beautiful separation of SSH things from
x.509 things doesn't quite work. Somebody *has* to check that the e
and n above equals the key that is somewhere inside the ASN.1
certificate chain, otherwise, the certificate checking has a hole you
can drive a 20 ton truck right through.

So now I think it's best to *not* duplicate crucial security
information like this. If we do, I'm sure some implementation will
forget to check that the information is consistent.

Regards,
/Niels

---

From: Damien Miller <[email-masked]>
Date: 31 Jan 2002 23:16:17 +1100

> 	string	rsa_signature_blob.

Here is a modified modified version of the relevent section of the 
draft. I have removed the "old" certificate-based formats, perhaps they 
need to be included? The contents of the certificate blobs themselves 
need further specification too.

--------------------------------
4.6 Public Key Algorithms

   This protocol has been designed to be able to operate with almost any
   public key format, encoding, and algorithm (signature and/or
   encryption).

   There are several aspects that define a public key type:
   o  Key format: how is the key encoded and how are certificates
      represented.  The key blobs in this protocol MAY contain
      certificates in addition to keys.
   o  Signature and/or encryption algorithms.  Some key types may not
      support both signing and encryption.  Key usage may also be
      restricted by policy statements in e.g.  certificates.  In this
      case, different key types SHOULD be defined for the different
      policy alternatives.
   o  Encoding of signatures and/or encrypted data.  This includes but
      is not limited to padding, byte order, and data formats.

   The following public key and/or certificate formats are currently
   defined:

   ssh-dss        REQUIRED    sign  no-cert Simple DSS
   ssh-rsa        RECOMMENDED sign  no-cert Simple RSA
   ssh-dss-x509v3 RECOMMENDED sign  cert    X.509 certificates (DSS)
   ssh-rsa-x509v3 RECOMMENDED sign  cert    X.509 certificates (RSA)
   ssh-dss-spki   OPTIONAL    sign  cert    SPKI certificates (DSS)
   ssh-rsa-spki   OPTIONAL    sign  cert    SPKI certificates (RSA)
   ssh-dss-pgp    OPTIONAL    sign  cert    OpenPGP certificates (DSS)
   ssh-rsa-pgp    OPTIONAL    sign  cert    OpenPGP certificates (RSA)

   Additional key types may be defined as specified in [SSH-ARCH].

     string   certificate or public key format identifier
     mpint[n] key data
     string   certificate data (optional)

   The certificate part should not be included for formats which include
   signatures only, but a public key is required.  This is the public
   key that will be used for authentication; the certificate sequence
   contained in the certificate blob can be used to provide
   authorization.

   The "ssh-dss" key format has the following specific encoding:

     string    "ssh-dss"
     mpint     p
     mpint     q
     mpint     g
     mpint     y

   Here the p, q, g, and y parameters form the signature key blob.

   Signing and verifying using this key format is done according to the
   Digital Signature Standard [FIPS-186] using the SHA-1 hash.  A
   description can also be found in [SCHNEIER].

   The certificate formats based on ssh-dss extend the public key 
   format to include certificate data:

     string    "ssh-dss-x509v3" / "ssh-dss-spki" / "ssh-dss-pgp"
     mpint     p
     mpint     q
     mpint     g
     mpint     y
     string    certificate

   In the case of "ssh-dss-x509v3", the certificate must be in a X.509v3
   compatible DER-encoded format.  The formats used in X.509v3 are 
   described in [RFC2459].  The key (or one of the keys in
   the certificate) MUST be a DSA key which matches the p, q, g and y 
   public key portions present in the first part of the packet.

   The "ssh-dss-spki" method indicates that the certificate blob
   contains a sequence of SPKI certificates.  The format of SPKI
   certificates is described in [RFC2693].  The key (or one of the keys 
   in the certificate) MUST be a DSA key which matches the p, q, g and y
   public key portions present in the first part of the packet.

   The "ssh-dss-pgp" method indicates the certificate is in an OpenPGP
   compatible binary format ([RFC2440]).  The key in the certificate 
   MUST be a DSS key which matches the p, q, g and y public key portions
   present in the first part of the packet..

   For all DSS algorithms he resulting signature is encoded as follows:

     string    "ssh-dss"
     string    dss_signature_blob

   dss_signature_blob is encoded as a string containing r followed by s
   (which are 160 bits long integers, without lengths or padding,
   unsigned and in network byte order).

   The "ssh-rsa" key format has the following specific encoding:

     string    "ssh-rsa"
     mpint     e
     mpint     n

   Here the e and n parameters form the signature key blob.

   Signing and verifying using this key format is done according to
   [SCHNEIER] and [PKCS1] using the SHA-1 hash.

   The certificate formats based on ssh-rsa extend the public key 
   format to include certificate data:

     string    "ssh-rsa-x509v3" / "ssh-rsa-spki" / "ssh-rsa-pgp"
     mpint     e
     mpint     n
     string    certificate

   The format of the certificate string for each of these algorithms is
   that same as the DSS certificate algorithms specified above. In all 
   cases the certificate MUST contain an RSA key which matches the 
   n and e components sent in the first portion of the packet.

     string    "ssh-rsa"

   rsa_signature_blob is encoded as a string containing s (which is an
   integer, without lengths or padding, unsigned and in network byte
   order).

--------------------------------------

-d

-- 
| By convention there is color,       \\ Damien Miller <[email-masked]>
| By convention sweetness, By convention bitterness, \\ www.mindrot.org
| But in reality there are atoms and space - Democritus (c. 400 BCE)

---

From: Damien Miller <[email-masked]>
Date: 31 Jan 2002 23:27:27 +1100

> forget to check that the information is consistent.

I think that is putting it a little strong - you still have to present a
valid signature. You run into problems if the remote end grants
additionak trust (e.g. automatically accepting a host key) based on
information in the certificate.

It seems unlikely that implementors would go to all the trouble of
implementing certificate chain checking, etc only to miss something so
basic.

-d

---

From: Markus Friedl <[email-masked]>
Date: Thu, 31 Jan 2002 13:43:46 +0100

> would be more in line with the other encodings.

i.e.
	string	"x509v3-sign-rsa"
	string	der-encoded-x509-cert

---

From: "Andersson, Mats" <[email-masked]>
Date: Thu, 31 Jan 2002 14:39:54 +0100 (CET)

> 	string	der-encoded-x509-cert

Hi,

This is in fact inconsistent with the other encodings for keys(/certs).
For example:

     string    "ssh-dss"
     mpint     p
	...

It is the signature-blob that should be "enclosed" in a ssh2 string. This
is the issue, i.e. the format of the signature is not _explicitly_ defined
in the draft (hence the discussion on how it should look like I guess).

However, in rfc2459 it says:
   When signing, the DSA algorithm generates two values.  These values
   are commonly referred to as r and s.  To easily transfer these two
   values as one signature, they shall be ASN.1 encoded using the
   following ASN.1 structure:
	Dss-Sig-Value  ::=  SEQUENCE  {
                   r       INTEGER,
                   s       INTEGER  }

Which is pretty specific to me. It also refers pkcs1 for RSA which also
defines the format of the signature.

I might have missed the start of the thread but what is the issue here?  
The transport draft refers rfc2459 which states the format for both RSA
and DSA so what is it that is not clear in all this except for the detail
that it doesn't say explicitly something like:

     string    "ssh-rsa"
     string    dss_signature_value

dss_signature_value is the DER encoded value of the Dss-Sig-Value as
defined in rfc2459.

Cheers,

/Mats

---

From: Markus Friedl <[email-masked]>
Date: Thu, 31 Jan 2002 14:58:40 +0100

> that it doesn't say explicitly something like:
s/rsa/dss/

> dss_signature_value is the DER encoded value of the Dss-Sig-Value as

the exact format for a "x509v3-sign-rsa" type signature
is not specified, i.e.:

is it
	string	"x509v3-sign-rsa"
	string	"DER-encoded format à la RFC2459"
or
	string	"x509v3-sign-rsa"
	byte[n]	"DER-encoded format à la RFC2459"

because the definition for the "x509v3-sign-rsa" type cert is:
	string	"x509v3-sign-rsa"
	byte[n]	"DER-encoded cert"
instead of a
	string	"x509v3-sign-rsa"
	string	"DER-encoded cert"

moreover, implementations supporting x509 (e.g. ssh.com)
currently send
	string	"DER-encoded cert"
without even sending the key type.

additionally, the draft says:

but:

so, i'm confused by the draft and the implementations.

-m

---

From: [email-masked] (Niels Möller)
Date: 31 Jan 2002 15:10:11 +0100

[ Ok, I'll better send my reply to the list as well. The message I'm
  replying to first arrived only in my private mailbox. /Niels ]

Damien Miller <[email-masked]> writes:

> valid signature.

But that's trivial, in the scenario I'm thinking about. If I copy the
certificate chain that proves that your key is authorized, and then I
stuff in my own n and e values, together with a matching signature on
the session id, then (i) the x.509 certificate chain is perfectly ok,
and (ii) my signature matches the n and e, so I could get access. The
result is that the certification-check is completely by-passed.

> implementing certificate chain checking, etc only to miss something so

I look at from the opposite direction. The trouble of implementing
certificate checking *must* include digging out the *certified* public
key from the certificate structures. Adding another *uncertified* copy
of the (hopefully same) key in the protocol is totally useless, and
only invites mistakes. The value of it is null and void, so just kill
it.

/Niels

---

From: "Andersson, Mats" <[email-masked]>
Date: Thu, 31 Jan 2002 15:17:15 +0100 (CET)

> > dss_signature_value is the DER encoded value of the Dss-Sig-Value as

Ouch, the above should have been ssh-dss of course, copy/paste error :-).

> 	string	"DER-encoded format à la RFC2459"

This should be the right form (it's the only thing one can deduce from the
transport draft).

> 	byte[n]	"DER-encoded cert"

Yes, but the encodings for ssh-dss/ssh-rsa keys and signature differs in
the same way (i.e. the key is byte[n] and the signature is enclosed in a
string.

> without even sending the key type.

This is obviously wrong, since this is the only thing specifically stated
in the draft as:

This is a unique definition in my oppinion, though it has happened before
that ssh.com implementors have confused the definitions of byte[n] and
string if I remember it correctly...

...
> so, i'm confused by the draft and the implementations.

Yeah, I totally agree that it's kind of confusing, however since it's
strictly defined in some sense (in the case of single keys/certs apart
from the sentence: "The certificate part may have be a zero length
string,..." which occurs after the definition) in the draft I don't care
:-).

However, the signature-blob should be equally well defined as you said
along the lines of:

   Signatures are encoded as follows:
     string   certificate or public key format identifier
     string   signature_blob (as defined by algorithm used)

OR, one might say that the format should be same as for 
Certificates/public keys with the argument that the ssh-dss/ssh-rsa 
signature_blob formats are really:

	string signature_blob (as defined by draft)

On the subject of whether to use PKCS7 or not I'm not sure what it would
add, it's a generic enclosure where the algorithm et.c. is explicitly
given along with some other specifics but the format of the signature
itself is still as defined in rfc2459 and PKCS1 (for DSA/RSA keys) hence
it would suffice IMHO to just use the formats defined without further
"complexity".

Cheers,

/Mats

---

From: "Andersson, Mats" <[email-masked]>
Date: Thu, 31 Jan 2002 15:20:46 +0100 (CET)

> Ouch, the above should have been ssh-dss of course, copy/paste error :-).

Argh! should have been "x509v3-sign-dss" of course, that's what we are
discussing here... :-). Same applies for "x509v3-sign-rsa" of course,
anyway, the essence of my arguments are otherwise correct IMHO.

Cheers,

/Mats

---

From: Markus Friedl <[email-masked]>
Date: Thu, 31 Jan 2002 15:35:22 +0100

> the same way (i.e. the key is byte[n] and the signature is enclosed in a

ok, but 'blobs' using non-transport-draft types are usually encoded as
	string	blob

> string,..." which occurs after the definition) in the draft I don't care

hm, a "zero length string" would be
	int32	0

-m

---

From: "Joseph Galbraith" <[email-masked]>
Date: Thu, 31 Jan 2002 08:58:35 -0700

> string der_encoded_certificate

I don't like this at all.  Whereas before, I could
just pass the certificate data to some library
that did certificates, now I have to understand
x.509 enough to dig out the public key.

Also, as Niels pointed out, one must also
now enforce that e,n encoded via SSH match
e,n encoded in the certificate.

I have more work to do, and the specification
has more opportunity for an implementation
to have a bug that seriously impacts security.
I'd prefer we didn't do this.

- Joseph

---

From: Damien Miller <[email-masked]>
Date: 01 Feb 2002 08:24:59 +1100

> x.509 enough to dig out the public key.

After sleeping on it, I agree that it doesn't add as much as I
originally thought. I humbly retract the suggestion.

-d