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