...

Source file src/golang.org/x/crypto/ssh/certs.go

Documentation: golang.org/x/crypto/ssh

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssh
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	"io"
    12  	"net"
    13  	"sort"
    14  	"time"
    15  )
    16  
    17  // Certificate algorithm names from [PROTOCOL.certkeys]. These values can appear
    18  // in Certificate.Type, PublicKey.Type, and ClientConfig.HostKeyAlgorithms.
    19  // Unlike key algorithm names, these are not passed to AlgorithmSigner nor
    20  // returned by MultiAlgorithmSigner and don't appear in the Signature.Format
    21  // field.
    22  const (
    23  	CertAlgoRSAv01        = "ssh-rsa-cert-v01@openssh.com"
    24  	CertAlgoDSAv01        = "ssh-dss-cert-v01@openssh.com"
    25  	CertAlgoECDSA256v01   = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
    26  	CertAlgoECDSA384v01   = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
    27  	CertAlgoECDSA521v01   = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
    28  	CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
    29  	CertAlgoED25519v01    = "ssh-ed25519-cert-v01@openssh.com"
    30  	CertAlgoSKED25519v01  = "sk-ssh-ed25519-cert-v01@openssh.com"
    31  
    32  	// CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a
    33  	// Certificate.Type (or PublicKey.Type), but only in
    34  	// ClientConfig.HostKeyAlgorithms.
    35  	CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com"
    36  	CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com"
    37  )
    38  
    39  const (
    40  	// Deprecated: use CertAlgoRSAv01.
    41  	CertSigAlgoRSAv01 = CertAlgoRSAv01
    42  	// Deprecated: use CertAlgoRSASHA256v01.
    43  	CertSigAlgoRSASHA2256v01 = CertAlgoRSASHA256v01
    44  	// Deprecated: use CertAlgoRSASHA512v01.
    45  	CertSigAlgoRSASHA2512v01 = CertAlgoRSASHA512v01
    46  )
    47  
    48  // Certificate types distinguish between host and user
    49  // certificates. The values can be set in the CertType field of
    50  // Certificate.
    51  const (
    52  	UserCert = 1
    53  	HostCert = 2
    54  )
    55  
    56  // Signature represents a cryptographic signature.
    57  type Signature struct {
    58  	Format string
    59  	Blob   []byte
    60  	Rest   []byte `ssh:"rest"`
    61  }
    62  
    63  // CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that
    64  // a certificate does not expire.
    65  const CertTimeInfinity = 1<<64 - 1
    66  
    67  // An Certificate represents an OpenSSH certificate as defined in
    68  // [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the
    69  // PublicKey interface, so it can be unmarshaled using
    70  // ParsePublicKey.
    71  type Certificate struct {
    72  	Nonce           []byte
    73  	Key             PublicKey
    74  	Serial          uint64
    75  	CertType        uint32
    76  	KeyId           string
    77  	ValidPrincipals []string
    78  	ValidAfter      uint64
    79  	ValidBefore     uint64
    80  	Permissions
    81  	Reserved     []byte
    82  	SignatureKey PublicKey
    83  	Signature    *Signature
    84  }
    85  
    86  // genericCertData holds the key-independent part of the certificate data.
    87  // Overall, certificates contain an nonce, public key fields and
    88  // key-independent fields.
    89  type genericCertData struct {
    90  	Serial          uint64
    91  	CertType        uint32
    92  	KeyId           string
    93  	ValidPrincipals []byte
    94  	ValidAfter      uint64
    95  	ValidBefore     uint64
    96  	CriticalOptions []byte
    97  	Extensions      []byte
    98  	Reserved        []byte
    99  	SignatureKey    []byte
   100  	Signature       []byte
   101  }
   102  
   103  func marshalStringList(namelist []string) []byte {
   104  	var to []byte
   105  	for _, name := range namelist {
   106  		s := struct{ N string }{name}
   107  		to = append(to, Marshal(&s)...)
   108  	}
   109  	return to
   110  }
   111  
   112  type optionsTuple struct {
   113  	Key   string
   114  	Value []byte
   115  }
   116  
   117  type optionsTupleValue struct {
   118  	Value string
   119  }
   120  
   121  // serialize a map of critical options or extensions
   122  // issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
   123  // we need two length prefixes for a non-empty string value
   124  func marshalTuples(tups map[string]string) []byte {
   125  	keys := make([]string, 0, len(tups))
   126  	for key := range tups {
   127  		keys = append(keys, key)
   128  	}
   129  	sort.Strings(keys)
   130  
   131  	var ret []byte
   132  	for _, key := range keys {
   133  		s := optionsTuple{Key: key}
   134  		if value := tups[key]; len(value) > 0 {
   135  			s.Value = Marshal(&optionsTupleValue{value})
   136  		}
   137  		ret = append(ret, Marshal(&s)...)
   138  	}
   139  	return ret
   140  }
   141  
   142  // issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
   143  // we need two length prefixes for a non-empty option value
   144  func parseTuples(in []byte) (map[string]string, error) {
   145  	tups := map[string]string{}
   146  	var lastKey string
   147  	var haveLastKey bool
   148  
   149  	for len(in) > 0 {
   150  		var key, val, extra []byte
   151  		var ok bool
   152  
   153  		if key, in, ok = parseString(in); !ok {
   154  			return nil, errShortRead
   155  		}
   156  		keyStr := string(key)
   157  		// according to [PROTOCOL.certkeys], the names must be in
   158  		// lexical order.
   159  		if haveLastKey && keyStr <= lastKey {
   160  			return nil, fmt.Errorf("ssh: certificate options are not in lexical order")
   161  		}
   162  		lastKey, haveLastKey = keyStr, true
   163  		// the next field is a data field, which if non-empty has a string embedded
   164  		if val, in, ok = parseString(in); !ok {
   165  			return nil, errShortRead
   166  		}
   167  		if len(val) > 0 {
   168  			val, extra, ok = parseString(val)
   169  			if !ok {
   170  				return nil, errShortRead
   171  			}
   172  			if len(extra) > 0 {
   173  				return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value")
   174  			}
   175  			tups[keyStr] = string(val)
   176  		} else {
   177  			tups[keyStr] = ""
   178  		}
   179  	}
   180  	return tups, nil
   181  }
   182  
   183  func parseCert(in []byte, privAlgo string) (*Certificate, error) {
   184  	nonce, rest, ok := parseString(in)
   185  	if !ok {
   186  		return nil, errShortRead
   187  	}
   188  
   189  	key, rest, err := parsePubKey(rest, privAlgo)
   190  	if err != nil {
   191  		return nil, err
   192  	}
   193  
   194  	var g genericCertData
   195  	if err := Unmarshal(rest, &g); err != nil {
   196  		return nil, err
   197  	}
   198  
   199  	c := &Certificate{
   200  		Nonce:       nonce,
   201  		Key:         key,
   202  		Serial:      g.Serial,
   203  		CertType:    g.CertType,
   204  		KeyId:       g.KeyId,
   205  		ValidAfter:  g.ValidAfter,
   206  		ValidBefore: g.ValidBefore,
   207  	}
   208  
   209  	for principals := g.ValidPrincipals; len(principals) > 0; {
   210  		principal, rest, ok := parseString(principals)
   211  		if !ok {
   212  			return nil, errShortRead
   213  		}
   214  		c.ValidPrincipals = append(c.ValidPrincipals, string(principal))
   215  		principals = rest
   216  	}
   217  
   218  	c.CriticalOptions, err = parseTuples(g.CriticalOptions)
   219  	if err != nil {
   220  		return nil, err
   221  	}
   222  	c.Extensions, err = parseTuples(g.Extensions)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	c.Reserved = g.Reserved
   227  	k, err := ParsePublicKey(g.SignatureKey)
   228  	if err != nil {
   229  		return nil, err
   230  	}
   231  
   232  	c.SignatureKey = k
   233  	c.Signature, rest, ok = parseSignatureBody(g.Signature)
   234  	if !ok || len(rest) > 0 {
   235  		return nil, errors.New("ssh: signature parse error")
   236  	}
   237  
   238  	return c, nil
   239  }
   240  
   241  type openSSHCertSigner struct {
   242  	pub    *Certificate
   243  	signer Signer
   244  }
   245  
   246  type algorithmOpenSSHCertSigner struct {
   247  	*openSSHCertSigner
   248  	algorithmSigner AlgorithmSigner
   249  }
   250  
   251  // NewCertSigner returns a Signer that signs with the given Certificate, whose
   252  // private key is held by signer. It returns an error if the public key in cert
   253  // doesn't match the key used by signer.
   254  func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
   255  	if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) {
   256  		return nil, errors.New("ssh: signer and cert have different public key")
   257  	}
   258  
   259  	switch s := signer.(type) {
   260  	case MultiAlgorithmSigner:
   261  		return &multiAlgorithmSigner{
   262  			AlgorithmSigner: &algorithmOpenSSHCertSigner{
   263  				&openSSHCertSigner{cert, signer}, s},
   264  			supportedAlgorithms: s.Algorithms(),
   265  		}, nil
   266  	case AlgorithmSigner:
   267  		return &algorithmOpenSSHCertSigner{
   268  			&openSSHCertSigner{cert, signer}, s}, nil
   269  	default:
   270  		return &openSSHCertSigner{cert, signer}, nil
   271  	}
   272  }
   273  
   274  func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
   275  	return s.signer.Sign(rand, data)
   276  }
   277  
   278  func (s *openSSHCertSigner) PublicKey() PublicKey {
   279  	return s.pub
   280  }
   281  
   282  func (s *algorithmOpenSSHCertSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
   283  	return s.algorithmSigner.SignWithAlgorithm(rand, data, algorithm)
   284  }
   285  
   286  const sourceAddressCriticalOption = "source-address"
   287  
   288  // CertChecker does the work of verifying a certificate. Its methods
   289  // can be plugged into ClientConfig.HostKeyCallback and
   290  // ServerConfig.PublicKeyCallback. For the CertChecker to work,
   291  // minimally, the IsAuthority callback should be set.
   292  type CertChecker struct {
   293  	// SupportedCriticalOptions lists the CriticalOptions that the
   294  	// server application layer understands. These are only used
   295  	// for user certificates.
   296  	SupportedCriticalOptions []string
   297  
   298  	// IsUserAuthority should return true if the key is recognized as an
   299  	// authority for the given user certificate. This allows for
   300  	// certificates to be signed by other certificates. This must be set
   301  	// if this CertChecker will be checking user certificates.
   302  	IsUserAuthority func(auth PublicKey) bool
   303  
   304  	// IsHostAuthority should report whether the key is recognized as
   305  	// an authority for this host. This allows for certificates to be
   306  	// signed by other keys, and for those other keys to only be valid
   307  	// signers for particular hostnames. This must be set if this
   308  	// CertChecker will be checking host certificates.
   309  	IsHostAuthority func(auth PublicKey, address string) bool
   310  
   311  	// Clock is used for verifying time stamps. If nil, time.Now
   312  	// is used.
   313  	Clock func() time.Time
   314  
   315  	// UserKeyFallback is called when CertChecker.Authenticate encounters a
   316  	// public key that is not a certificate. It must implement validation
   317  	// of user keys or else, if nil, all such keys are rejected.
   318  	UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
   319  
   320  	// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
   321  	// public key that is not a certificate. It must implement host key
   322  	// validation or else, if nil, all such keys are rejected.
   323  	HostKeyFallback HostKeyCallback
   324  
   325  	// IsRevoked is called for each certificate so that revocation checking
   326  	// can be implemented. It should return true if the given certificate
   327  	// is revoked and false otherwise. If nil, no certificates are
   328  	// considered to have been revoked.
   329  	IsRevoked func(cert *Certificate) bool
   330  }
   331  
   332  // CheckHostKey checks a host key certificate. This method can be
   333  // plugged into ClientConfig.HostKeyCallback.
   334  func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error {
   335  	cert, ok := key.(*Certificate)
   336  	if !ok {
   337  		if c.HostKeyFallback != nil {
   338  			return c.HostKeyFallback(addr, remote, key)
   339  		}
   340  		return errors.New("ssh: non-certificate host key")
   341  	}
   342  	if cert.CertType != HostCert {
   343  		return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType)
   344  	}
   345  	if !c.IsHostAuthority(cert.SignatureKey, addr) {
   346  		return fmt.Errorf("ssh: no authorities for hostname: %v", addr)
   347  	}
   348  
   349  	hostname, _, err := net.SplitHostPort(addr)
   350  	if err != nil {
   351  		return err
   352  	}
   353  
   354  	// Pass hostname only as principal for host certificates (consistent with OpenSSH)
   355  	return c.CheckCert(hostname, cert)
   356  }
   357  
   358  // Authenticate checks a user certificate. Authenticate can be used as
   359  // a value for ServerConfig.PublicKeyCallback.
   360  func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) {
   361  	cert, ok := pubKey.(*Certificate)
   362  	if !ok {
   363  		if c.UserKeyFallback != nil {
   364  			return c.UserKeyFallback(conn, pubKey)
   365  		}
   366  		return nil, errors.New("ssh: normal key pairs not accepted")
   367  	}
   368  
   369  	if cert.CertType != UserCert {
   370  		return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType)
   371  	}
   372  	if !c.IsUserAuthority(cert.SignatureKey) {
   373  		return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority")
   374  	}
   375  
   376  	if err := c.CheckCert(conn.User(), cert); err != nil {
   377  		return nil, err
   378  	}
   379  
   380  	return &cert.Permissions, nil
   381  }
   382  
   383  // CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and
   384  // the signature of the certificate.
   385  func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
   386  	if c.IsRevoked != nil && c.IsRevoked(cert) {
   387  		return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial)
   388  	}
   389  
   390  	for opt := range cert.CriticalOptions {
   391  		// sourceAddressCriticalOption will be enforced by
   392  		// serverAuthenticate
   393  		if opt == sourceAddressCriticalOption {
   394  			continue
   395  		}
   396  
   397  		found := false
   398  		for _, supp := range c.SupportedCriticalOptions {
   399  			if supp == opt {
   400  				found = true
   401  				break
   402  			}
   403  		}
   404  		if !found {
   405  			return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt)
   406  		}
   407  	}
   408  
   409  	if len(cert.ValidPrincipals) > 0 {
   410  		// By default, certs are valid for all users/hosts.
   411  		found := false
   412  		for _, p := range cert.ValidPrincipals {
   413  			if p == principal {
   414  				found = true
   415  				break
   416  			}
   417  		}
   418  		if !found {
   419  			return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals)
   420  		}
   421  	}
   422  
   423  	clock := c.Clock
   424  	if clock == nil {
   425  		clock = time.Now
   426  	}
   427  
   428  	unixNow := clock().Unix()
   429  	if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) {
   430  		return fmt.Errorf("ssh: cert is not yet valid")
   431  	}
   432  	if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) {
   433  		return fmt.Errorf("ssh: cert has expired")
   434  	}
   435  	if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil {
   436  		return fmt.Errorf("ssh: certificate signature does not verify")
   437  	}
   438  
   439  	return nil
   440  }
   441  
   442  // SignCert signs the certificate with an authority, setting the Nonce,
   443  // SignatureKey, and Signature fields. If the authority implements the
   444  // MultiAlgorithmSigner interface the first algorithm in the list is used. This
   445  // is useful if you want to sign with a specific algorithm.
   446  func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
   447  	c.Nonce = make([]byte, 32)
   448  	if _, err := io.ReadFull(rand, c.Nonce); err != nil {
   449  		return err
   450  	}
   451  	c.SignatureKey = authority.PublicKey()
   452  
   453  	if v, ok := authority.(MultiAlgorithmSigner); ok {
   454  		if len(v.Algorithms()) == 0 {
   455  			return errors.New("the provided authority has no signature algorithm")
   456  		}
   457  		// Use the first algorithm in the list.
   458  		sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), v.Algorithms()[0])
   459  		if err != nil {
   460  			return err
   461  		}
   462  		c.Signature = sig
   463  		return nil
   464  	} else if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA {
   465  		// Default to KeyAlgoRSASHA512 for ssh-rsa signers.
   466  		// TODO: consider using KeyAlgoRSASHA256 as default.
   467  		sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), KeyAlgoRSASHA512)
   468  		if err != nil {
   469  			return err
   470  		}
   471  		c.Signature = sig
   472  		return nil
   473  	}
   474  
   475  	sig, err := authority.Sign(rand, c.bytesForSigning())
   476  	if err != nil {
   477  		return err
   478  	}
   479  	c.Signature = sig
   480  	return nil
   481  }
   482  
   483  // certKeyAlgoNames is a mapping from known certificate algorithm names to the
   484  // corresponding public key signature algorithm.
   485  //
   486  // This map must be kept in sync with the one in agent/client.go.
   487  var certKeyAlgoNames = map[string]string{
   488  	CertAlgoRSAv01:        KeyAlgoRSA,
   489  	CertAlgoRSASHA256v01:  KeyAlgoRSASHA256,
   490  	CertAlgoRSASHA512v01:  KeyAlgoRSASHA512,
   491  	CertAlgoDSAv01:        KeyAlgoDSA,
   492  	CertAlgoECDSA256v01:   KeyAlgoECDSA256,
   493  	CertAlgoECDSA384v01:   KeyAlgoECDSA384,
   494  	CertAlgoECDSA521v01:   KeyAlgoECDSA521,
   495  	CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256,
   496  	CertAlgoED25519v01:    KeyAlgoED25519,
   497  	CertAlgoSKED25519v01:  KeyAlgoSKED25519,
   498  }
   499  
   500  // underlyingAlgo returns the signature algorithm associated with algo (which is
   501  // an advertised or negotiated public key or host key algorithm). These are
   502  // usually the same, except for certificate algorithms.
   503  func underlyingAlgo(algo string) string {
   504  	if a, ok := certKeyAlgoNames[algo]; ok {
   505  		return a
   506  	}
   507  	return algo
   508  }
   509  
   510  // certificateAlgo returns the certificate algorithms that uses the provided
   511  // underlying signature algorithm.
   512  func certificateAlgo(algo string) (certAlgo string, ok bool) {
   513  	for certName, algoName := range certKeyAlgoNames {
   514  		if algoName == algo {
   515  			return certName, true
   516  		}
   517  	}
   518  	return "", false
   519  }
   520  
   521  func (cert *Certificate) bytesForSigning() []byte {
   522  	c2 := *cert
   523  	c2.Signature = nil
   524  	out := c2.Marshal()
   525  	// Drop trailing signature length.
   526  	return out[:len(out)-4]
   527  }
   528  
   529  // Marshal serializes c into OpenSSH's wire format. It is part of the
   530  // PublicKey interface.
   531  func (c *Certificate) Marshal() []byte {
   532  	generic := genericCertData{
   533  		Serial:          c.Serial,
   534  		CertType:        c.CertType,
   535  		KeyId:           c.KeyId,
   536  		ValidPrincipals: marshalStringList(c.ValidPrincipals),
   537  		ValidAfter:      uint64(c.ValidAfter),
   538  		ValidBefore:     uint64(c.ValidBefore),
   539  		CriticalOptions: marshalTuples(c.CriticalOptions),
   540  		Extensions:      marshalTuples(c.Extensions),
   541  		Reserved:        c.Reserved,
   542  		SignatureKey:    c.SignatureKey.Marshal(),
   543  	}
   544  	if c.Signature != nil {
   545  		generic.Signature = Marshal(c.Signature)
   546  	}
   547  	genericBytes := Marshal(&generic)
   548  	keyBytes := c.Key.Marshal()
   549  	_, keyBytes, _ = parseString(keyBytes)
   550  	prefix := Marshal(&struct {
   551  		Name  string
   552  		Nonce []byte
   553  		Key   []byte `ssh:"rest"`
   554  	}{c.Type(), c.Nonce, keyBytes})
   555  
   556  	result := make([]byte, 0, len(prefix)+len(genericBytes))
   557  	result = append(result, prefix...)
   558  	result = append(result, genericBytes...)
   559  	return result
   560  }
   561  
   562  // Type returns the certificate algorithm name. It is part of the PublicKey interface.
   563  func (c *Certificate) Type() string {
   564  	certName, ok := certificateAlgo(c.Key.Type())
   565  	if !ok {
   566  		panic("unknown certificate type for key type " + c.Key.Type())
   567  	}
   568  	return certName
   569  }
   570  
   571  // Verify verifies a signature against the certificate's public
   572  // key. It is part of the PublicKey interface.
   573  func (c *Certificate) Verify(data []byte, sig *Signature) error {
   574  	return c.Key.Verify(data, sig)
   575  }
   576  
   577  func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) {
   578  	format, in, ok := parseString(in)
   579  	if !ok {
   580  		return
   581  	}
   582  
   583  	out = &Signature{
   584  		Format: string(format),
   585  	}
   586  
   587  	if out.Blob, in, ok = parseString(in); !ok {
   588  		return
   589  	}
   590  
   591  	switch out.Format {
   592  	case KeyAlgoSKECDSA256, CertAlgoSKECDSA256v01, KeyAlgoSKED25519, CertAlgoSKED25519v01:
   593  		out.Rest = in
   594  		return out, nil, ok
   595  	}
   596  
   597  	return out, in, ok
   598  }
   599  
   600  func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) {
   601  	sigBytes, rest, ok := parseString(in)
   602  	if !ok {
   603  		return
   604  	}
   605  
   606  	out, trailing, ok := parseSignatureBody(sigBytes)
   607  	if !ok || len(trailing) > 0 {
   608  		return nil, nil, false
   609  	}
   610  	return
   611  }
   612  

View as plain text