Alternative TLS implementation in Go
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

522 行
16 KiB

  1. // Copyright 2018 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. package tls
  5. // Delegated credentials for TLS
  6. // (https://tools.ietf.org/html/draft-ietf-tls-subcerts) is an IETF Internet
  7. // draft and proposed TLS extension. If the client supports this extension, then
  8. // the server may use a "delegated credential" as the signing key in the
  9. // handshake. A delegated credential is a short lived public/secret key pair
  10. // delegated to the server by an entity trusted by the client. This allows a
  11. // middlebox to terminate a TLS connection on behalf of the entity; for example,
  12. // this can be used to delegate TLS termination to a reverse proxy. Credentials
  13. // can't be revoked; in order to mitigate risk in case the middlebox is
  14. // compromised, the credential is only valid for a short time (days, hours, or
  15. // even minutes).
  16. //
  17. // BUG(cjpatton) Subcerts: Need to add support for PKCS1, PSS, and EdDSA.
  18. // Currently delegated credentials only support ECDSA. The delegator must also
  19. // use an ECDSA key.
  20. import (
  21. "bytes"
  22. "crypto"
  23. "crypto/ecdsa"
  24. "crypto/elliptic"
  25. "crypto/rand"
  26. "crypto/x509"
  27. "crypto/x509/pkix"
  28. "encoding/asn1"
  29. "encoding/binary"
  30. "errors"
  31. "fmt"
  32. "time"
  33. )
  34. const (
  35. dcMaxTTLSeconds = 60 * 60 * 24 * 7 // 7 days
  36. dcMaxTTL = time.Duration(dcMaxTTLSeconds * time.Second)
  37. dcMaxPublicKeyLen = 1 << 16 // Bytes
  38. dcMaxSignatureLen = 1 << 16 // Bytes
  39. )
  40. var errNoDelegationUsage = errors.New("certificate not authorized for delegation")
  41. // delegationUsageId is the DelegationUsage X.509 extension OID
  42. //
  43. // NOTE(cjpatton) This OID is a child of Cloudflare's IANA-assigned OID.
  44. var delegationUsageId = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 44363, 44}
  45. // CreateDelegationUsagePKIXExtension returns a pkix.Extension that every delegation
  46. // certificate must have.
  47. //
  48. // NOTE(cjpatton) Brendan McMillion suggests adding the delegationUsage
  49. // extension as a flag `PermitsDelegationUsage` for the `x509.Certificate`
  50. // structure. But we can't make this change unless tris includes crypto/x509,
  51. // too. Once we upstream this code, we'll want to do modify x509.Certficate and
  52. // do away with this function.
  53. func CreateDelegationUsagePKIXExtension() *pkix.Extension {
  54. return &pkix.Extension{
  55. Id: delegationUsageId,
  56. Critical: false,
  57. Value: nil,
  58. }
  59. }
  60. // canDelegate returns true if a certificate can be used for delegated
  61. // credentials.
  62. func canDelegate(cert *x509.Certificate) bool {
  63. // Check that the digitalSignature key usage is set.
  64. if (cert.KeyUsage & x509.KeyUsageDigitalSignature) == 0 {
  65. return false
  66. }
  67. // Check that the certificate has the DelegationUsage extension and that
  68. // it's non-critical (per the spec).
  69. for _, extension := range cert.Extensions {
  70. if extension.Id.Equal(delegationUsageId) {
  71. return true
  72. }
  73. }
  74. return false
  75. }
  76. // This structure stores the public components of a credential.
  77. type credential struct {
  78. validTime time.Duration
  79. publicKey crypto.PublicKey
  80. scheme SignatureScheme
  81. }
  82. // marshalSubjectPublicKeyInfo returns a DER encoded SubjectPublicKeyInfo structure
  83. // (as defined in the X.509 standard) for the credential.
  84. func (cred *credential) marshalSubjectPublicKeyInfo() ([]byte, error) {
  85. switch cred.scheme {
  86. case ECDSAWithP256AndSHA256,
  87. ECDSAWithP384AndSHA384,
  88. ECDSAWithP521AndSHA512:
  89. serializedPublicKey, err := x509.MarshalPKIXPublicKey(cred.publicKey)
  90. if err != nil {
  91. return nil, err
  92. }
  93. return serializedPublicKey, nil
  94. default:
  95. return nil, fmt.Errorf("unsupported signature scheme: 0x%04x", cred.scheme)
  96. }
  97. }
  98. // marshal encodes a credential as per the spec.
  99. func (cred *credential) marshal() ([]byte, error) {
  100. // Write the valid_time field.
  101. serialized := make([]byte, 6)
  102. binary.BigEndian.PutUint32(serialized, uint32(cred.validTime/time.Second))
  103. // Encode the public key and assert that the encoding is no longer than 2^16
  104. // bytes (per the spect).
  105. serializedPublicKey, err := cred.marshalSubjectPublicKeyInfo()
  106. if err != nil {
  107. return nil, err
  108. }
  109. if len(serializedPublicKey) > dcMaxPublicKeyLen {
  110. return nil, errors.New("public key is too long")
  111. }
  112. // Write the length of the public_key field.
  113. binary.BigEndian.PutUint16(serialized[4:], uint16(len(serializedPublicKey)))
  114. // Write the public key.
  115. return append(serialized, serializedPublicKey...), nil
  116. }
  117. // unmarshalCredential decodes a credential and returns it.
  118. func unmarshalCredential(serialized []byte) (*credential, error) {
  119. // Bytes 0-3 are the validity time field; bytes 4-6 are the length of the
  120. // serialized SubjectPublicKeyInfo.
  121. if len(serialized) < 6 {
  122. return nil, errors.New("credential is too short")
  123. }
  124. // Parse the validity time.
  125. validTime := time.Duration(binary.BigEndian.Uint32(serialized)) * time.Second
  126. // Parse the SubjectPublicKeyInfo.
  127. pk, scheme, err := unmarshalSubjectPublicKeyInfo(serialized[6:])
  128. if err != nil {
  129. return nil, err
  130. }
  131. return &credential{validTime, pk, scheme}, nil
  132. }
  133. // unmarshalSubjectPublicKeyInfo parses a DER encoded SubjectPublicKeyInfo
  134. // structure into a public key and its corresponding algorithm.
  135. func unmarshalSubjectPublicKeyInfo(serialized []byte) (crypto.PublicKey, SignatureScheme, error) {
  136. publicKey, err := x509.ParsePKIXPublicKey(serialized)
  137. if err != nil {
  138. return nil, 0, err
  139. }
  140. switch pk := publicKey.(type) {
  141. case *ecdsa.PublicKey:
  142. curveName := pk.Curve.Params().Name
  143. if curveName == "P-256" {
  144. return pk, ECDSAWithP256AndSHA256, nil
  145. } else if curveName == "P-384" {
  146. return pk, ECDSAWithP384AndSHA384, nil
  147. } else if curveName == "P-521" {
  148. return pk, ECDSAWithP521AndSHA512, nil
  149. } else {
  150. return nil, 0, fmt.Errorf("curve %s s not supported", curveName)
  151. }
  152. default:
  153. return nil, 0, fmt.Errorf("unsupported delgation key type: %T", pk)
  154. }
  155. }
  156. // getCredentialLen returns the number of bytes comprising the serialized
  157. // credential that starts at the beginning of the input slice. It returns an
  158. // error if the input is too short to contain a credential.
  159. func getCredentialLen(serialized []byte) (int, error) {
  160. if len(serialized) < 6 {
  161. return 0, errors.New("credential is too short")
  162. }
  163. // First 4 bytes is the validity time.
  164. serialized = serialized[4:]
  165. // The next 2 bytes are the length of the serialized public key.
  166. serializedPublicKeyLen := int(binary.BigEndian.Uint16(serialized))
  167. serialized = serialized[2:]
  168. if len(serialized) < serializedPublicKeyLen {
  169. return 0, errors.New("public key of credential is too short")
  170. }
  171. return 6 + serializedPublicKeyLen, nil
  172. }
  173. // DelegatedCredential stores a credential and its delegation.
  174. type DelegatedCredential struct {
  175. // The serialized form of the credential.
  176. Raw []byte
  177. // The amount of time for which the credential is valid. Specifically, the
  178. // the credential expires `ValidTime` seconds after the `notBefore` of the
  179. // delegation certificate. The delegator shall not issue delegated
  180. // credentials that are valid for more than 7 days from the current time.
  181. //
  182. // When this data structure is serialized, this value is converted to a
  183. // uint32 representing the duration in seconds.
  184. ValidTime time.Duration
  185. // The credential public key.
  186. PublicKey crypto.PublicKey
  187. // The signature scheme associated with the credential public key.
  188. publicKeyScheme SignatureScheme
  189. // The signature scheme used to sign the credential.
  190. Scheme SignatureScheme
  191. // The credential's delegation.
  192. Signature []byte
  193. }
  194. // NewDelegatedCredential creates a new delegated credential using `cert` for
  195. // delegation. It generates a public/private key pair for the provided signature
  196. // algorithm (`scheme`), validity interval (defined by `cert.Leaf.notBefore` and
  197. // `validTime`), and TLS version (`vers`), and signs it using `cert.PrivateKey`.
  198. func NewDelegatedCredential(cert *Certificate, scheme SignatureScheme, validTime time.Duration, vers uint16) (*DelegatedCredential, crypto.PrivateKey, error) {
  199. // The granularity of DC validity is seconds.
  200. validTime = validTime.Round(time.Second)
  201. // Parse the leaf certificate if needed.
  202. var err error
  203. if cert.Leaf == nil {
  204. if len(cert.Certificate[0]) == 0 {
  205. return nil, nil, errors.New("missing leaf certificate")
  206. }
  207. cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
  208. if err != nil {
  209. return nil, nil, err
  210. }
  211. }
  212. // Check that the leaf certificate can be used for delegation.
  213. if !canDelegate(cert.Leaf) {
  214. return nil, nil, errNoDelegationUsage
  215. }
  216. // Extract the delegator signature scheme from the certificate.
  217. var delegatorScheme SignatureScheme
  218. switch sk := cert.PrivateKey.(type) {
  219. case *ecdsa.PrivateKey:
  220. // Set scheme.
  221. pk := sk.Public().(*ecdsa.PublicKey)
  222. curveName := pk.Curve.Params().Name
  223. certAlg := cert.Leaf.SignatureAlgorithm
  224. if certAlg == x509.ECDSAWithSHA256 && curveName == "P-256" {
  225. delegatorScheme = ECDSAWithP256AndSHA256
  226. } else if certAlg == x509.ECDSAWithSHA384 && curveName == "P-384" {
  227. delegatorScheme = ECDSAWithP384AndSHA384
  228. } else if certAlg == x509.ECDSAWithSHA512 && curveName == "P-521" {
  229. delegatorScheme = ECDSAWithP521AndSHA512
  230. } else {
  231. return nil, nil, fmt.Errorf(
  232. "using curve %s for %s is not supported",
  233. curveName, cert.Leaf.SignatureAlgorithm)
  234. }
  235. default:
  236. return nil, nil, fmt.Errorf("unsupported delgation key type: %T", sk)
  237. }
  238. // Generate a new key pair.
  239. var sk crypto.PrivateKey
  240. var pk crypto.PublicKey
  241. switch scheme {
  242. case ECDSAWithP256AndSHA256,
  243. ECDSAWithP384AndSHA384,
  244. ECDSAWithP521AndSHA512:
  245. sk, err = ecdsa.GenerateKey(getCurve(scheme), rand.Reader)
  246. if err != nil {
  247. return nil, nil, err
  248. }
  249. pk = sk.(*ecdsa.PrivateKey).Public()
  250. default:
  251. return nil, nil, fmt.Errorf("unsupported signature scheme: 0x%04x", scheme)
  252. }
  253. // Prepare the credential for digital signing.
  254. hash := getHash(delegatorScheme)
  255. cred := &credential{validTime, pk, scheme}
  256. in, err := prepareDelegation(hash, cred, cert.Leaf.Raw, delegatorScheme, vers)
  257. if err != nil {
  258. return nil, nil, err
  259. }
  260. // Sign the credential.
  261. var sig []byte
  262. switch sk := cert.PrivateKey.(type) {
  263. case *ecdsa.PrivateKey:
  264. opts := crypto.SignerOpts(hash)
  265. sig, err = sk.Sign(rand.Reader, in, opts)
  266. if err != nil {
  267. return nil, nil, err
  268. }
  269. default:
  270. return nil, nil, fmt.Errorf("unsupported delgation key type: %T", sk)
  271. }
  272. return &DelegatedCredential{
  273. ValidTime: validTime,
  274. PublicKey: pk,
  275. publicKeyScheme: scheme,
  276. Scheme: delegatorScheme,
  277. Signature: sig,
  278. }, sk, nil
  279. }
  280. // IsExpired returns true if the credential has expired. The end of the validity
  281. // interval is defined as the delegator certificate's notBefore field (`start`)
  282. // plus ValidTime seconds. This function simply checks that the current time
  283. // (`now`) is before the end of the valdity interval.
  284. func (dc *DelegatedCredential) IsExpired(start, now time.Time) bool {
  285. end := start.Add(dc.ValidTime)
  286. return !now.Before(end)
  287. }
  288. // InvalidTTL returns true if the credential's validity period is longer than the
  289. // maximum permitted. This is defined by the certificate's notBefore field
  290. // (`start`) plus the ValidTime, minus the current time (`now`).
  291. func (dc *DelegatedCredential) InvalidTTL(start, now time.Time) bool {
  292. return dc.ValidTime > (now.Sub(start) + dcMaxTTL).Round(time.Second)
  293. }
  294. // Validate checks that that the signature is valid, that the credential hasn't
  295. // expired, and that the TTL is valid. It also checks that certificate can be
  296. // used for delegation.
  297. func (dc *DelegatedCredential) Validate(cert *x509.Certificate, vers uint16, now time.Time) (bool, error) {
  298. // Check that the cert can delegate.
  299. if !canDelegate(cert) {
  300. return false, errNoDelegationUsage
  301. }
  302. if dc.IsExpired(cert.NotBefore, now) {
  303. return false, errors.New("credential has expired")
  304. }
  305. if dc.InvalidTTL(cert.NotBefore, now) {
  306. return false, errors.New("credential TTL is invalid")
  307. }
  308. // Prepare the credential for verification.
  309. hash := getHash(dc.Scheme)
  310. cred := &credential{dc.ValidTime, dc.PublicKey, dc.publicKeyScheme}
  311. in, err := prepareDelegation(hash, cred, cert.Raw, dc.Scheme, vers)
  312. if err != nil {
  313. return false, err
  314. }
  315. // TODO(any) This code overlaps signficantly with verifyHandshakeSignature()
  316. // in ../auth.go. This should be refactored.
  317. switch dc.Scheme {
  318. case ECDSAWithP256AndSHA256,
  319. ECDSAWithP384AndSHA384,
  320. ECDSAWithP521AndSHA512:
  321. pk, ok := cert.PublicKey.(*ecdsa.PublicKey)
  322. if !ok {
  323. return false, errors.New("expected ECDSA public key")
  324. }
  325. sig := new(ecdsaSignature)
  326. if _, err = asn1.Unmarshal(dc.Signature, sig); err != nil {
  327. return false, err
  328. }
  329. return ecdsa.Verify(pk, in, sig.R, sig.S), nil
  330. default:
  331. return false, fmt.Errorf(
  332. "unsupported signature scheme: 0x%04x", dc.Scheme)
  333. }
  334. }
  335. // Marshal encodes a DelegatedCredential structure per the spec. It also sets
  336. // dc.Raw to the output as a side effect.
  337. func (dc *DelegatedCredential) Marshal() ([]byte, error) {
  338. // The credential.
  339. cred := &credential{dc.ValidTime, dc.PublicKey, dc.publicKeyScheme}
  340. serialized, err := cred.marshal()
  341. if err != nil {
  342. return nil, err
  343. }
  344. // The scheme.
  345. serializedScheme := make([]byte, 2)
  346. binary.BigEndian.PutUint16(serializedScheme, uint16(dc.Scheme))
  347. serialized = append(serialized, serializedScheme...)
  348. // The signature.
  349. if len(dc.Signature) > dcMaxSignatureLen {
  350. return nil, errors.New("signature is too long")
  351. }
  352. serializedSignature := make([]byte, 2)
  353. binary.BigEndian.PutUint16(serializedSignature, uint16(len(dc.Signature)))
  354. serializedSignature = append(serializedSignature, dc.Signature...)
  355. serialized = append(serialized, serializedSignature...)
  356. dc.Raw = serialized
  357. return serialized, nil
  358. }
  359. // UnmarshalDelegatedCredential decodes a DelegatedCredential structure.
  360. func UnmarshalDelegatedCredential(serialized []byte) (*DelegatedCredential, error) {
  361. // Get the length of the serialized credential that begins at the start of
  362. // the input slice.
  363. serializedCredentialLen, err := getCredentialLen(serialized)
  364. if err != nil {
  365. return nil, err
  366. }
  367. // Parse the credential.
  368. cred, err := unmarshalCredential(serialized[:serializedCredentialLen])
  369. if err != nil {
  370. return nil, err
  371. }
  372. // Parse the signature scheme.
  373. serialized = serialized[serializedCredentialLen:]
  374. if len(serialized) < 4 {
  375. return nil, errors.New("delegated credential is too short")
  376. }
  377. scheme := SignatureScheme(binary.BigEndian.Uint16(serialized))
  378. // Parse the signature length.
  379. serialized = serialized[2:]
  380. serializedSignatureLen := binary.BigEndian.Uint16(serialized)
  381. // Prase the signature.
  382. serialized = serialized[2:]
  383. if len(serialized) < int(serializedSignatureLen) {
  384. return nil, errors.New("signature of delegated credential is too short")
  385. }
  386. sig := serialized[:serializedSignatureLen]
  387. return &DelegatedCredential{
  388. ValidTime: cred.validTime,
  389. PublicKey: cred.publicKey,
  390. publicKeyScheme: cred.scheme,
  391. Scheme: scheme,
  392. Signature: sig,
  393. }, nil
  394. }
  395. // getCurve maps the SignatureScheme to its corresponding elliptic.Curve.
  396. func getCurve(scheme SignatureScheme) elliptic.Curve {
  397. switch scheme {
  398. case ECDSAWithP256AndSHA256:
  399. return elliptic.P256()
  400. case ECDSAWithP384AndSHA384:
  401. return elliptic.P384()
  402. case ECDSAWithP521AndSHA512:
  403. return elliptic.P521()
  404. default:
  405. return nil
  406. }
  407. }
  408. // getHash maps the SignatureScheme to its corresponding hash function.
  409. //
  410. // TODO(any) This function overlaps with hashForSignatureScheme in 13.go.
  411. func getHash(scheme SignatureScheme) crypto.Hash {
  412. switch scheme {
  413. case ECDSAWithP256AndSHA256:
  414. return crypto.SHA256
  415. case ECDSAWithP384AndSHA384:
  416. return crypto.SHA384
  417. case ECDSAWithP521AndSHA512:
  418. return crypto.SHA512
  419. default:
  420. return 0 // Unknown hash function
  421. }
  422. }
  423. // prepareDelegation returns a hash of the message that the delegator is to
  424. // sign. The inputs are the credential (cred), the DER-encoded delegator
  425. // certificate (`delegatorCert`), the signature scheme of the delegator
  426. // (`delegatorScheme`), and the protocol version (`vers`) in which the credential
  427. // is to be used.
  428. func prepareDelegation(hash crypto.Hash, cred *credential, delegatorCert []byte, delegatorScheme SignatureScheme, vers uint16) ([]byte, error) {
  429. h := hash.New()
  430. // The header.
  431. h.Write(bytes.Repeat([]byte{0x20}, 64))
  432. h.Write([]byte("TLS, server delegated credentials"))
  433. h.Write([]byte{0x00})
  434. // The protocol version.
  435. var serializedVers [2]byte
  436. binary.BigEndian.PutUint16(serializedVers[:], uint16(vers))
  437. h.Write(serializedVers[:])
  438. // The delegation certificate.
  439. h.Write(delegatorCert)
  440. // The delegator signature scheme.
  441. var serializedScheme [2]byte
  442. binary.BigEndian.PutUint16(serializedScheme[:], uint16(delegatorScheme))
  443. h.Write(serializedScheme[:])
  444. // The credential.
  445. serializedCred, err := cred.marshal()
  446. if err != nil {
  447. return nil, err
  448. }
  449. h.Write(serializedCred)
  450. return h.Sum(nil), nil
  451. }