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