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