1// Copyright 2019 The Go Authors. All rights reserved.
 2// Use of this source code is governed by a BSD-style
 3// license that can be found in the LICENSE file.
 4
 5// Package curve25519 provides an implementation of the X25519 function, which
 6// performs scalar multiplication on the elliptic curve known as Curve25519
 7// according to [RFC 7748].
 8//
 9// The curve25519 package is a wrapper for the X25519 implementation in the
10// crypto/ecdh package. It is [frozen] and is not accepting new features.
11//
12// [RFC 7748]: https://datatracker.ietf.org/doc/html/rfc7748
13// [frozen]: https://go.dev/wiki/Frozen
14package curve25519
15
16import "crypto/ecdh"
17
18// ScalarMult sets dst to the product scalar * point.
19//
20// Deprecated: when provided a low-order point, ScalarMult will set dst to all
21// zeroes, irrespective of the scalar. Instead, use the X25519 function, which
22// will return an error.
23func ScalarMult(dst, scalar, point *[32]byte) {
24	if _, err := x25519(dst, scalar[:], point[:]); err != nil {
25		// The only error condition for x25519 when the inputs are 32 bytes long
26		// is if the output would have been the all-zero value.
27		for i := range dst {
28			dst[i] = 0
29		}
30	}
31}
32
33// ScalarBaseMult sets dst to the product scalar * base where base is the
34// standard generator.
35//
36// It is recommended to use the X25519 function with Basepoint instead, as
37// copying into fixed size arrays can lead to unexpected bugs.
38func ScalarBaseMult(dst, scalar *[32]byte) {
39	curve := ecdh.X25519()
40	priv, err := curve.NewPrivateKey(scalar[:])
41	if err != nil {
42		panic("curve25519: " + err.Error())
43	}
44	copy(dst[:], priv.PublicKey().Bytes())
45}
46
47const (
48	// ScalarSize is the size of the scalar input to X25519.
49	ScalarSize = 32
50	// PointSize is the size of the point input to X25519.
51	PointSize = 32
52)
53
54// Basepoint is the canonical Curve25519 generator.
55var Basepoint []byte
56
57var basePoint = [32]byte{9}
58
59func init() { Basepoint = basePoint[:] }
60
61// X25519 returns the result of the scalar multiplication (scalar * point),
62// according to RFC 7748, Section 5. scalar, point and the return value are
63// slices of 32 bytes.
64//
65// scalar can be generated at random, for example with crypto/rand. point should
66// be either Basepoint or the output of another X25519 call.
67//
68// If point is Basepoint (but not if it's a different slice with the same
69// contents) a precomputed implementation might be used for performance.
70func X25519(scalar, point []byte) ([]byte, error) {
71	// Outline the body of function, to let the allocation be inlined in the
72	// caller, and possibly avoid escaping to the heap.
73	var dst [32]byte
74	return x25519(&dst, scalar, point)
75}
76
77func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
78	curve := ecdh.X25519()
79	pub, err := curve.NewPublicKey(point)
80	if err != nil {
81		return nil, err
82	}
83	priv, err := curve.NewPrivateKey(scalar)
84	if err != nil {
85		return nil, err
86	}
87	out, err := priv.ECDH(pub)
88	if err != nil {
89		return nil, err
90	}
91	copy(dst[:], out)
92	return dst[:], nil
93}