crypto.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package dtls
  2. import (
  3. "crypto"
  4. "crypto/ecdsa"
  5. "crypto/ed25519"
  6. "crypto/rand"
  7. "crypto/rsa"
  8. "crypto/sha256"
  9. "crypto/x509"
  10. "encoding/asn1"
  11. "encoding/binary"
  12. "math/big"
  13. "time"
  14. "github.com/pion/dtls/v2/pkg/crypto/elliptic"
  15. "github.com/pion/dtls/v2/pkg/crypto/hash"
  16. )
  17. type ecdsaSignature struct {
  18. R, S *big.Int
  19. }
  20. func valueKeyMessage(clientRandom, serverRandom, publicKey []byte, namedCurve elliptic.Curve) []byte {
  21. serverECDHParams := make([]byte, 4)
  22. serverECDHParams[0] = 3 // named curve
  23. binary.BigEndian.PutUint16(serverECDHParams[1:], uint16(namedCurve))
  24. serverECDHParams[3] = byte(len(publicKey))
  25. plaintext := []byte{}
  26. plaintext = append(plaintext, clientRandom...)
  27. plaintext = append(plaintext, serverRandom...)
  28. plaintext = append(plaintext, serverECDHParams...)
  29. plaintext = append(plaintext, publicKey...)
  30. return plaintext
  31. }
  32. // If the client provided a "signature_algorithms" extension, then all
  33. // certificates provided by the server MUST be signed by a
  34. // hash/signature algorithm pair that appears in that extension
  35. //
  36. // https://tools.ietf.org/html/rfc5246#section-7.4.2
  37. func generateKeySignature(clientRandom, serverRandom, publicKey []byte, namedCurve elliptic.Curve, privateKey crypto.PrivateKey, hashAlgorithm hash.Algorithm) ([]byte, error) {
  38. msg := valueKeyMessage(clientRandom, serverRandom, publicKey, namedCurve)
  39. switch p := privateKey.(type) {
  40. case ed25519.PrivateKey:
  41. // https://crypto.stackexchange.com/a/55483
  42. return p.Sign(rand.Reader, msg, crypto.Hash(0))
  43. case *ecdsa.PrivateKey:
  44. hashed := hashAlgorithm.Digest(msg)
  45. return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
  46. case *rsa.PrivateKey:
  47. hashed := hashAlgorithm.Digest(msg)
  48. return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
  49. }
  50. return nil, errKeySignatureGenerateUnimplemented
  51. }
  52. func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.Algorithm, rawCertificates [][]byte) error { //nolint:dupl
  53. if len(rawCertificates) == 0 {
  54. return errLengthMismatch
  55. }
  56. certificate, err := x509.ParseCertificate(rawCertificates[0])
  57. if err != nil {
  58. return err
  59. }
  60. switch p := certificate.PublicKey.(type) {
  61. case ed25519.PublicKey:
  62. if ok := ed25519.Verify(p, message, remoteKeySignature); !ok {
  63. return errKeySignatureMismatch
  64. }
  65. return nil
  66. case *ecdsa.PublicKey:
  67. ecdsaSig := &ecdsaSignature{}
  68. if _, err := asn1.Unmarshal(remoteKeySignature, ecdsaSig); err != nil {
  69. return err
  70. }
  71. if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
  72. return errInvalidECDSASignature
  73. }
  74. hashed := hashAlgorithm.Digest(message)
  75. if !ecdsa.Verify(p, hashed, ecdsaSig.R, ecdsaSig.S) {
  76. return errKeySignatureMismatch
  77. }
  78. return nil
  79. case *rsa.PublicKey:
  80. switch certificate.SignatureAlgorithm {
  81. case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:
  82. hashed := hashAlgorithm.Digest(message)
  83. return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature)
  84. default:
  85. return errKeySignatureVerifyUnimplemented
  86. }
  87. }
  88. return errKeySignatureVerifyUnimplemented
  89. }
  90. // If the server has sent a CertificateRequest message, the client MUST send the Certificate
  91. // message. The ClientKeyExchange message is now sent, and the content
  92. // of that message will depend on the public key algorithm selected
  93. // between the ClientHello and the ServerHello. If the client has sent
  94. // a certificate with signing ability, a digitally-signed
  95. // CertificateVerify message is sent to explicitly verify possession of
  96. // the private key in the certificate.
  97. // https://tools.ietf.org/html/rfc5246#section-7.3
  98. func generateCertificateVerify(handshakeBodies []byte, privateKey crypto.PrivateKey, hashAlgorithm hash.Algorithm) ([]byte, error) {
  99. if p, ok := privateKey.(ed25519.PrivateKey); ok {
  100. // https://pkg.go.dev/crypto/ed25519#PrivateKey.Sign
  101. // Sign signs the given message with priv. Ed25519 performs two passes over
  102. // messages to be signed and therefore cannot handle pre-hashed messages.
  103. return p.Sign(rand.Reader, handshakeBodies, crypto.Hash(0))
  104. }
  105. h := sha256.New()
  106. if _, err := h.Write(handshakeBodies); err != nil {
  107. return nil, err
  108. }
  109. hashed := h.Sum(nil)
  110. switch p := privateKey.(type) {
  111. case *ecdsa.PrivateKey:
  112. return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
  113. case *rsa.PrivateKey:
  114. return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
  115. }
  116. return nil, errInvalidSignatureAlgorithm
  117. }
  118. func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorithm, remoteKeySignature []byte, rawCertificates [][]byte) error { //nolint:dupl
  119. if len(rawCertificates) == 0 {
  120. return errLengthMismatch
  121. }
  122. certificate, err := x509.ParseCertificate(rawCertificates[0])
  123. if err != nil {
  124. return err
  125. }
  126. switch p := certificate.PublicKey.(type) {
  127. case ed25519.PublicKey:
  128. if ok := ed25519.Verify(p, handshakeBodies, remoteKeySignature); !ok {
  129. return errKeySignatureMismatch
  130. }
  131. return nil
  132. case *ecdsa.PublicKey:
  133. ecdsaSig := &ecdsaSignature{}
  134. if _, err := asn1.Unmarshal(remoteKeySignature, ecdsaSig); err != nil {
  135. return err
  136. }
  137. if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
  138. return errInvalidECDSASignature
  139. }
  140. hash := hashAlgorithm.Digest(handshakeBodies)
  141. if !ecdsa.Verify(p, hash, ecdsaSig.R, ecdsaSig.S) {
  142. return errKeySignatureMismatch
  143. }
  144. return nil
  145. case *rsa.PublicKey:
  146. switch certificate.SignatureAlgorithm {
  147. case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:
  148. hash := hashAlgorithm.Digest(handshakeBodies)
  149. return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hash, remoteKeySignature)
  150. default:
  151. return errKeySignatureVerifyUnimplemented
  152. }
  153. }
  154. return errKeySignatureVerifyUnimplemented
  155. }
  156. func loadCerts(rawCertificates [][]byte) ([]*x509.Certificate, error) {
  157. if len(rawCertificates) == 0 {
  158. return nil, errLengthMismatch
  159. }
  160. certs := make([]*x509.Certificate, 0, len(rawCertificates))
  161. for _, rawCert := range rawCertificates {
  162. cert, err := x509.ParseCertificate(rawCert)
  163. if err != nil {
  164. return nil, err
  165. }
  166. certs = append(certs, cert)
  167. }
  168. return certs, nil
  169. }
  170. func verifyClientCert(rawCertificates [][]byte, roots *x509.CertPool) (chains [][]*x509.Certificate, err error) {
  171. certificate, err := loadCerts(rawCertificates)
  172. if err != nil {
  173. return nil, err
  174. }
  175. intermediateCAPool := x509.NewCertPool()
  176. for _, cert := range certificate[1:] {
  177. intermediateCAPool.AddCert(cert)
  178. }
  179. opts := x509.VerifyOptions{
  180. Roots: roots,
  181. CurrentTime: time.Now(),
  182. Intermediates: intermediateCAPool,
  183. KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
  184. }
  185. return certificate[0].Verify(opts)
  186. }
  187. func verifyServerCert(rawCertificates [][]byte, roots *x509.CertPool, serverName string) (chains [][]*x509.Certificate, err error) {
  188. certificate, err := loadCerts(rawCertificates)
  189. if err != nil {
  190. return nil, err
  191. }
  192. intermediateCAPool := x509.NewCertPool()
  193. for _, cert := range certificate[1:] {
  194. intermediateCAPool.AddCert(cert)
  195. }
  196. opts := x509.VerifyOptions{
  197. Roots: roots,
  198. CurrentTime: time.Now(),
  199. DNSName: serverName,
  200. Intermediates: intermediateCAPool,
  201. }
  202. return certificate[0].Verify(opts)
  203. }