summaryrefslogtreecommitdiff
path: root/crypto/secp256k1/scalar_mult_cgo.go
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/secp256k1/scalar_mult_cgo.go')
-rw-r--r--crypto/secp256k1/scalar_mult_cgo.go58
1 files changed, 58 insertions, 0 deletions
diff --git a/crypto/secp256k1/scalar_mult_cgo.go b/crypto/secp256k1/scalar_mult_cgo.go
new file mode 100644
index 000000000..8e29d65b0
--- /dev/null
+++ b/crypto/secp256k1/scalar_mult_cgo.go
@@ -0,0 +1,58 @@
+// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+// +build !gofuzz
+// +build cgo
+
+package secp256k1
+
+import (
+ "math/big"
+ "unsafe"
+)
+
+/*
+
+#include "libsecp256k1/include/secp256k1.h"
+
+extern int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, const unsigned char *point, const unsigned char *scalar);
+
+*/
+import "C"
+
+// ScalarMult func
+func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
+ // Ensure scalar is exactly 32 bytes. We pad always, even if
+ // scalar is 32 bytes long, to avoid a timing side channel.
+ if len(scalar) > 32 {
+ panic("can't handle scalars > 256 bits")
+ }
+ // NOTE: potential timing issue
+ padded := make([]byte, 32)
+ copy(padded[32-len(scalar):], scalar)
+ scalar = padded
+
+ // Do the multiplication in C, updating point.
+ point := make([]byte, 64)
+ readBits(Bx, point[:32])
+ readBits(By, point[32:])
+
+ pointPtr := (*C.uchar)(unsafe.Pointer(&point[0]))
+ scalarPtr := (*C.uchar)(unsafe.Pointer(&scalar[0]))
+ res := C.secp256k1_ext_scalar_mul(context, pointPtr, scalarPtr)
+
+ // Unpack the result and clear temporaries.
+ x := new(big.Int).SetBytes(point[:32])
+ y := new(big.Int).SetBytes(point[32:])
+ for i := range point {
+ point[i] = 0
+ }
+ for i := range padded {
+ scalar[i] = 0
+ }
+ if res != 1 {
+ return nil, nil
+ }
+ return x, y
+}