crypto.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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. h := sha256.New()
  100. if _, err := h.Write(handshakeBodies); err != nil {
  101. return nil, err
  102. }
  103. hashed := h.Sum(nil)
  104. switch p := privateKey.(type) {
  105. case ed25519.PrivateKey:
  106. // https://crypto.stackexchange.com/a/55483
  107. return p.Sign(rand.Reader, hashed, crypto.Hash(0))
  108. case *ecdsa.PrivateKey:
  109. return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
  110. case *rsa.PrivateKey:
  111. return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash())
  112. }
  113. return nil, errInvalidSignatureAlgorithm
  114. }
  115. func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorithm, remoteKeySignature []byte, rawCertificates [][]byte) error { //nolint:dupl
  116. if len(rawCertificates) == 0 {
  117. return errLengthMismatch
  118. }
  119. certificate, err := x509.ParseCertificate(rawCertificates[0])
  120. if err != nil {
  121. return err
  122. }
  123. switch p := certificate.PublicKey.(type) {
  124. case ed25519.PublicKey:
  125. if ok := ed25519.Verify(p, handshakeBodies, remoteKeySignature); !ok {
  126. return errKeySignatureMismatch
  127. }
  128. return nil
  129. case *ecdsa.PublicKey:
  130. ecdsaSig := &ecdsaSignature{}
  131. if _, err := asn1.Unmarshal(remoteKeySignature, ecdsaSig); err != nil {
  132. return err
  133. }
  134. if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
  135. return errInvalidECDSASignature
  136. }
  137. hash := hashAlgorithm.Digest(handshakeBodies)
  138. if !ecdsa.Verify(p, hash, ecdsaSig.R, ecdsaSig.S) {
  139. return errKeySignatureMismatch
  140. }
  141. return nil
  142. case *rsa.PublicKey:
  143. switch certificate.SignatureAlgorithm {
  144. case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA:
  145. hash := hashAlgorithm.Digest(handshakeBodies)
  146. return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hash, remoteKeySignature)
  147. default:
  148. return errKeySignatureVerifyUnimplemented
  149. }
  150. }
  151. return errKeySignatureVerifyUnimplemented
  152. }
  153. func loadCerts(rawCertificates [][]byte) ([]*x509.Certificate, error) {
  154. if len(rawCertificates) == 0 {
  155. return nil, errLengthMismatch
  156. }
  157. certs := make([]*x509.Certificate, 0, len(rawCertificates))
  158. for _, rawCert := range rawCertificates {
  159. cert, err := x509.ParseCertificate(rawCert)
  160. if err != nil {
  161. return nil, err
  162. }
  163. certs = append(certs, cert)
  164. }
  165. return certs, nil
  166. }
  167. func verifyClientCert(rawCertificates [][]byte, roots *x509.CertPool) (chains [][]*x509.Certificate, err error) {
  168. certificate, err := loadCerts(rawCertificates)
  169. if err != nil {
  170. return nil, err
  171. }
  172. intermediateCAPool := x509.NewCertPool()
  173. for _, cert := range certificate[1:] {
  174. intermediateCAPool.AddCert(cert)
  175. }
  176. opts := x509.VerifyOptions{
  177. Roots: roots,
  178. CurrentTime: time.Now(),
  179. Intermediates: intermediateCAPool,
  180. KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
  181. }
  182. return certificate[0].Verify(opts)
  183. }
  184. func verifyServerCert(rawCertificates [][]byte, roots *x509.CertPool, serverName string) (chains [][]*x509.Certificate, err error) {
  185. certificate, err := loadCerts(rawCertificates)
  186. if err != nil {
  187. return nil, err
  188. }
  189. intermediateCAPool := x509.NewCertPool()
  190. for _, cert := range certificate[1:] {
  191. intermediateCAPool.AddCert(cert)
  192. }
  193. opts := x509.VerifyOptions{
  194. Roots: roots,
  195. CurrentTime: time.Now(),
  196. DNSName: serverName,
  197. Intermediates: intermediateCAPool,
  198. }
  199. return certificate[0].Verify(opts)
  200. }