diff --git a/pom.xml b/pom.xml
index c8bc2c78..3ace1b00 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,8 +65,8 @@ DO NOT MODIFY - GENERATED CODE
     ${bc.versions}
     3.0.2
     -W0
-    9.2.19.0
-    9.2.19.0
+    9.1.17.0
+    9.1.17.0
     2.0.2
     2.0.2
     pom.xml
@@ -274,7 +274,6 @@ DO NOT MODIFY - GENERATED CODE
         
           1.8
           1.8
-          8
           UTF-8
           true
           true
diff --git a/src/main/java/org/jruby/ext/openssl/PKeyEC.java b/src/main/java/org/jruby/ext/openssl/PKeyEC.java
index 21d9733d..5e4a8624 100644
--- a/src/main/java/org/jruby/ext/openssl/PKeyEC.java
+++ b/src/main/java/org/jruby/ext/openssl/PKeyEC.java
@@ -58,10 +58,14 @@
 import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
 import org.bouncycastle.jce.spec.ECNamedCurveSpec;
 
+import org.bouncycastle.math.ec.ECAlgorithms;
+import org.bouncycastle.math.ec.ECCurve;
 import org.jruby.Ruby;
 import org.jruby.RubyArray;
+import org.jruby.RubyBignum;
 import org.jruby.RubyBoolean;
 import org.jruby.RubyClass;
+import org.jruby.RubyFixnum;
 import org.jruby.RubyModule;
 import org.jruby.RubyObject;
 import org.jruby.RubyString;
@@ -931,44 +935,54 @@ private static RaiseException newError(final Ruby runtime, final String message)
             return Utils.newError(runtime, Error, message);
         }
 
-        @JRubyMethod(rest = true, visibility = Visibility.PRIVATE)
-        public IRubyObject initialize(final ThreadContext context, final IRubyObject[] args) {
-            final Ruby runtime = context.runtime;
+        @JRubyMethod(visibility = Visibility.PRIVATE)
+        public IRubyObject initialize(final ThreadContext context, final IRubyObject groupOrPoint) {
+            getPointAndGroup(context, groupOrPoint);
 
-            final int argc = Arity.checkArgumentCount(runtime, args, 1, 2);
-            final IRubyObject arg = args[0];
+            return this;
+        }
 
-            if ( arg instanceof Point ) {
-                this.group = ((Point) arg).group;
-                this.point = ((Point) arg).point;
+        @JRubyMethod(visibility = Visibility.PRIVATE)
+        public IRubyObject initialize(final ThreadContext context, final IRubyObject groupOrPoint, final IRubyObject bn) {
+            if (getPointAndGroup(context, groupOrPoint)) {
                 return this;
             }
 
-            if ( arg instanceof Group ) {
-                this.group = (Group) arg;
+            final byte[] encoded;
+            if (bn instanceof BN) {
+                encoded = ((BN) bn).getValue().abs().toByteArray();
             } else {
-                throw runtime.newTypeError(arg, _EC(runtime).getClass("Group"));
+                encoded = bn.convertToString().getBytes();
             }
-
-            if ( argc == 2 ) { // (group, bn)
-                final byte[] encoded;
-                if (args[1] instanceof BN) {
-                    encoded = ((BN) args[1]).getValue().abs().toByteArray();
-                } else {
-                    encoded = args[1].convertToString().getBytes();
-                }
-                try {
-                    this.point = ECPointUtil.decodePoint(group.getCurve(), encoded);
-                }
-                catch (IllegalArgumentException ex) {
-                    // MRI: OpenSSL::PKey::EC::Point::Error: invalid encoding
-                    throw newError(context.runtime, ex.getMessage());
-                }
+            try {
+                this.point = ECPointUtil.decodePoint(group.getCurve(), encoded);
+            }
+            catch (IllegalArgumentException ex) {
+                // MRI: OpenSSL::PKey::EC::Point::Error: invalid encoding
+                throw newError(context.runtime, ex.getMessage());
             }
 
             return this;
         }
 
+        private boolean getPointAndGroup(ThreadContext context, IRubyObject groupOrPoint) {
+            final Ruby runtime = context.runtime;
+
+            if ( groupOrPoint instanceof Point) {
+                this.group = ((Point) groupOrPoint).group;
+                this.point = ((Point) groupOrPoint).point;
+                return true;
+            }
+
+            if ( groupOrPoint instanceof Group) {
+                this.group = (Group) groupOrPoint;
+                this.point = this.group.getParamSpec().getGenerator();
+            } else {
+                throw runtime.newTypeError(groupOrPoint, _EC(runtime).getClass("Group"));
+            }
+            return false;
+        }
+
         @Override
         @JRubyMethod(name = { "==", "eql?" })
         public IRubyObject op_equal(final ThreadContext context, final IRubyObject obj) {
@@ -1059,6 +1073,121 @@ public IRubyObject inspect() {
             return ObjectSupport.inspect(this, (List) Collections.singletonList(entry));
         }
 
+        @JRubyMethod(name = "add")
+        public IRubyObject add(final ThreadContext context, final IRubyObject other) {
+            Ruby runtime = context.runtime;
+
+            org.bouncycastle.math.ec.ECPoint pointSelf, pointOther, pointResult;
+
+            Group groupV = this.group;
+            Point result;
+
+            ECCurve selfCurve = EC5Util.convertCurve(groupV.getCurve());
+            pointSelf = EC5Util.convertPoint(selfCurve, asECPoint());
+
+            Point otherPoint = (Point) other;
+            ECCurve otherCurve = EC5Util.convertCurve(otherPoint.group.getCurve());
+            pointOther = EC5Util.convertPoint(otherCurve, otherPoint.asECPoint());
+
+            pointResult = pointSelf.add(pointOther);
+            if (pointResult == null) {
+                newECError(runtime, "EC_POINT_add");
+            }
+
+            result = new Point(runtime, EC5Util.convertPoint(pointResult), group);
+
+            return result;
+        }
+
+        @JRubyMethod(name = "mul")
+        public IRubyObject mul(final ThreadContext context, final IRubyObject bn1) {
+            Ruby runtime = context.runtime;
+
+            if (bn1 instanceof RubyArray) {
+                throw runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version");
+            }
+
+            org.bouncycastle.math.ec.ECPoint pointSelf;
+
+            Group groupV = this.group;
+
+            ECCurve selfCurve = EC5Util.convertCurve(groupV.getCurve());
+            pointSelf = EC5Util.convertPoint(selfCurve, asECPoint());
+
+            BigInteger bn = getBigInteger(context, bn1);
+
+            org.bouncycastle.math.ec.ECPoint mulPoint = ECAlgorithms.referenceMultiply(pointSelf, bn);
+            if (mulPoint == null) {
+                throw newECError(runtime, "bad multiply result");
+            }
+
+            return new Point(runtime, EC5Util.convertPoint(mulPoint), groupV);
+        }
+
+        @JRubyMethod(name = "mul")
+        public IRubyObject mul(final ThreadContext context, final IRubyObject bn1, final IRubyObject bn2) {
+            Ruby runtime = context.runtime;
+
+            if (bn1 instanceof RubyArray) {
+                throw runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version");
+            }
+
+            org.bouncycastle.math.ec.ECPoint pointSelf, pointResult;
+
+            Group groupV = this.group;
+
+            ECCurve selfCurve = EC5Util.convertCurve(groupV.getCurve());
+            pointSelf = EC5Util.convertPoint(selfCurve, asECPoint());
+
+            ECCurve resultCurve = EC5Util.convertCurve(groupV.getCurve());
+            pointResult = EC5Util.convertPoint(resultCurve, ((Point) groupV.generator(context)).asECPoint());
+
+            BigInteger bn = getBigInteger(context, bn1);
+            BigInteger bn_g = getBigInteger(context, bn2);
+
+            org.bouncycastle.math.ec.ECPoint mulPoint = ECAlgorithms.sumOfTwoMultiplies(pointResult, bn_g, pointSelf, bn);
+
+            if (mulPoint == null) {
+                throw newECError(runtime, "bad multiply result");
+            }
+
+            return new Point(runtime, EC5Util.convertPoint(mulPoint), groupV);
+        }
+
+        @JRubyMethod(name = "mul")
+        public IRubyObject mul(final ThreadContext context, final IRubyObject bns, final IRubyObject points, final IRubyObject bn2) {
+            throw context.runtime.newNotImplementedError("calling #mul with arrays is not supported by this OpenSSL version");
+        }
+
+        @Deprecated
+        public IRubyObject initialize(final ThreadContext context, final IRubyObject[] args) {
+            final int argc = Arity.checkArgumentCount(context.runtime, args, 1, 2);
+
+            switch (argc) {
+                case 1:
+                    return initialize(context, args[0]);
+                case 2:
+                    return initialize(context, args[0], args[1]);
+                default:
+                    throw context.runtime.newArgumentError(args.length, 1);
+            }
+        }
+
+    }
+
+    private static BigInteger getBigInteger(ThreadContext context, IRubyObject arg1) {
+        BigInteger bn;
+        if (arg1 instanceof RubyFixnum) {
+            bn = BigInteger.valueOf(arg1.convertToInteger().getLongValue());
+        } else if (arg1 instanceof RubyBignum) {
+            bn = ((RubyBignum) arg1).getValue();
+        } else if (arg1 instanceof BN) {
+            bn = ((BN) arg1).getValue();
+        } else {
+            Ruby runtime = context.runtime;
+            throw runtime.newTypeError(arg1, runtime.getInteger());
+        }
+        return bn;
     }
 
     static byte[] encode(final ECPublicKey pubKey) {