func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { return nil, errClientKeyExchange } if ka.curveid == X25519 { if len(ckx.ciphertext) != 1+32 { return nil, errClientKeyExchange } var theirPublic, sharedKey, scalar [32]byte copy(theirPublic[:], ckx.ciphertext[1:]) copy(scalar[:], ka.privateKey) curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic) return sharedKey[:], nil } curve, ok := curveForCurveID(ka.curveid) if !ok { panic("internal error") } x, y := elliptic.Unmarshal(curve, ckx.ciphertext[1:]) if x == nil { return nil, errClientKeyExchange } if !curve.IsOnCurve(x, y) { return nil, errClientKeyExchange } x, _ = curve.ScalarMult(x, y, ka.privateKey) preMasterSecret := make([]byte, (curve.Params().BitSize+7)>>3) xBytes := x.Bytes() copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) return preMasterSecret, nil }
func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { if ka.curveid == 0 { return nil, nil, errors.New("tls: missing ServerKeyExchange message") } var serialized, preMasterSecret []byte if ka.curveid == X25519 { var ourPublic, theirPublic, sharedKey, scalar [32]byte if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil { return nil, nil, err } copy(theirPublic[:], ka.publicKey) curve25519.ScalarBaseMult(&ourPublic, &scalar) curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic) serialized = ourPublic[:] preMasterSecret = sharedKey[:] } else { curve, ok := curveForCurveID(ka.curveid) if !ok { panic("internal error") } priv, mx, my, err := elliptic.GenerateKey(curve, config.rand()) if err != nil { return nil, nil, err } x, _ := curve.ScalarMult(ka.x, ka.y, priv) preMasterSecret = make([]byte, (curve.Params().BitSize+7)>>3) xBytes := x.Bytes() copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes) serialized = elliptic.Marshal(curve, mx, my) } ckx := new(clientKeyExchangeMsg) ckx.ciphertext = make([]byte, 1+len(serialized)) ckx.ciphertext[0] = byte(len(serialized)) copy(ckx.ciphertext[1:], serialized) return preMasterSecret, ckx, nil }