Alternative TLS implementation in Go
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

110 lignes
3.6 KiB

  1. // Copyright 2017 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. import (
  6. "crypto"
  7. "crypto/ecdsa"
  8. "crypto/rsa"
  9. "encoding/asn1"
  10. "errors"
  11. "fmt"
  12. )
  13. // pickSignatureAlgorithm selects a signature algorithm that is compatible with
  14. // the given public key and the list of algorithms from both sides of connection.
  15. // The lists of signature algorithms (peerSigAlgs and ourSigAlgs) are ignored
  16. // for tlsVersion < VersionTLS12.
  17. //
  18. // The returned SignatureScheme codepoint is only meaningful for TLS 1.2 and newer
  19. // previous TLS versions have a fixed hash function.
  20. func pickSignatureAlgorithm(pubkey crypto.PublicKey, peerSigAlgs, ourSigAlgs []SignatureScheme, tlsVersion uint16) (SignatureScheme, uint8, crypto.Hash, error) {
  21. if tlsVersion < VersionTLS12 || len(peerSigAlgs) == 0 {
  22. // If the client didn't specify any signature_algorithms
  23. // extension then we can assume that it supports SHA1. See
  24. // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
  25. switch pubkey.(type) {
  26. case *rsa.PublicKey:
  27. if tlsVersion < VersionTLS12 {
  28. return 0, signaturePKCS1v15, crypto.MD5SHA1, nil
  29. } else {
  30. return PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1, nil
  31. }
  32. case *ecdsa.PublicKey:
  33. return ECDSAWithSHA1, signatureECDSA, crypto.SHA1, nil
  34. default:
  35. return 0, 0, 0, fmt.Errorf("tls: unsupported public key: %T", pubkey)
  36. }
  37. }
  38. for _, sigAlg := range peerSigAlgs {
  39. if !isSupportedSignatureAlgorithm(sigAlg, ourSigAlgs) {
  40. continue
  41. }
  42. hashAlg, err := lookupTLSHash(sigAlg)
  43. if err != nil {
  44. panic("tls: supported signature algorithm has an unknown hash function")
  45. }
  46. sigType := signatureFromSignatureScheme(sigAlg)
  47. if (sigType == signaturePKCS1v15 || hashAlg == crypto.SHA1) && tlsVersion >= VersionTLS13 {
  48. // TLS 1.3 forbids RSASSA-PKCS1-v1_5 and SHA-1 for
  49. // handshake messages.
  50. continue
  51. }
  52. switch pubkey.(type) {
  53. case *rsa.PublicKey:
  54. if sigType == signaturePKCS1v15 || sigType == signatureRSAPSS {
  55. return sigAlg, sigType, hashAlg, nil
  56. }
  57. case *ecdsa.PublicKey:
  58. if sigType == signatureECDSA {
  59. return sigAlg, sigType, hashAlg, nil
  60. }
  61. }
  62. }
  63. return 0, 0, 0, errors.New("tls: peer doesn't support any common signature algorithms")
  64. }
  65. // verifyHandshakeSignature verifies a signature against pre-hashed handshake
  66. // contents.
  67. func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc crypto.Hash, digest, sig []byte) error {
  68. switch sigType {
  69. case signatureECDSA:
  70. pubKey, ok := pubkey.(*ecdsa.PublicKey)
  71. if !ok {
  72. return errors.New("tls: ECDSA signing requires a ECDSA public key")
  73. }
  74. ecdsaSig := new(ecdsaSignature)
  75. if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
  76. return err
  77. }
  78. if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
  79. return errors.New("tls: ECDSA signature contained zero or negative values")
  80. }
  81. if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
  82. return errors.New("tls: ECDSA verification failure")
  83. }
  84. case signaturePKCS1v15:
  85. pubKey, ok := pubkey.(*rsa.PublicKey)
  86. if !ok {
  87. return errors.New("tls: RSA signing requires a RSA public key")
  88. }
  89. if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
  90. return err
  91. }
  92. case signatureRSAPSS:
  93. pubKey, ok := pubkey.(*rsa.PublicKey)
  94. if !ok {
  95. return errors.New("tls: RSA signing requires a RSA public key")
  96. }
  97. signOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}
  98. if err := rsa.VerifyPSS(pubKey, hashFunc, digest, sig, signOpts); err != nil {
  99. return err
  100. }
  101. default:
  102. return errors.New("tls: unknown signature algorithm")
  103. }
  104. return nil
  105. }