Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bcd010f1c | ||
|
|
3375612bf4 | ||
|
|
bb80217080 | ||
|
|
6879722274 | ||
|
|
e983fa2741 | ||
|
|
80fd97208d | ||
|
|
f2bc3a617a | ||
|
|
d66d9c31b4 | ||
|
|
9fadb0b165 | ||
|
|
a6a393ffd6 | ||
|
|
1c7450041f | ||
|
|
d4e7c9cb6c | ||
|
|
332fd656f4 | ||
|
|
0b431c7de3 | ||
|
|
349231f7e4 | ||
|
|
44c9b0ff9e | ||
|
|
67b13616a5 | ||
|
|
477a5b4c32 | ||
|
|
59b5a86796 | ||
|
|
10f366e7a2 | ||
|
|
905d78a692 | ||
|
|
ebb717d630 | ||
|
|
0da2a6a1bb | ||
|
|
5defcc193a | ||
|
|
d042a396a6 | ||
|
|
b92bf9480d | ||
|
|
6f79b5a20c | ||
|
|
8d0d405eed | ||
|
|
b91329d961 | ||
|
|
7067223927 | ||
|
|
0d2316b267 | ||
|
|
0aab8d07ae | ||
|
|
5bead598a0 | ||
|
|
1a865804d5 | ||
|
|
1c981e6f81 | ||
|
|
62c9f1799c | ||
|
|
405cb3bdea | ||
|
|
913d3ae741 | ||
|
|
dbb6ec16ec | ||
|
|
403f69900e | ||
|
|
055043dfed | ||
|
|
08396bb92b | ||
|
|
9d2ee975ef | ||
|
|
4e5a26183e | ||
|
|
152cdb1503 | ||
|
|
fdfe1f8531 | ||
|
|
b8ffc16e10 | ||
|
|
7e6fbd82c8 | ||
|
|
bda2f3f5cf | ||
|
|
325b735346 | ||
|
|
1eadac50a5 | ||
|
|
b2d7c26edb | ||
|
|
1c17e20020 | ||
|
|
270bf2552c | ||
|
|
1cf1811d71 | ||
|
|
a2edfb5072 | ||
|
|
ff15cd57d1 | ||
|
|
eb61739cd9 | ||
|
|
42c83fffff | ||
|
|
e668aa9b45 | ||
|
|
df0bc9e1bb | ||
|
|
74c2ba9521 | ||
|
|
cf8dcb0f7d | ||
|
|
4f30245552 | ||
|
|
1d57292618 | ||
|
|
8779cbd1c9 | ||
|
|
2aeefc3f8a | ||
|
|
e3cc52e598 | ||
|
|
833695f0a5 | ||
|
|
ec07f4e35b | ||
|
|
b665ba6f6f | ||
|
|
a1aeb9b34e | ||
|
|
28c53ff63c | ||
|
|
3f0842a464 | ||
|
|
e90f1e17ee | ||
|
|
d359caa4a3 | ||
|
|
c5370d2cc6 | ||
|
|
0d375be9b6 | ||
|
|
b4ddeeda5b | ||
|
|
edc325d13a | ||
|
|
eab9315960 | ||
|
|
ddfa82138e | ||
|
|
d08e19beac | ||
|
|
12e1fcd8c0 | ||
|
|
3f8f0645c2 | ||
|
|
5df3b59941 | ||
|
|
2e82bdd171 | ||
|
|
64e0e99383 | ||
|
|
23b1b90df2 | ||
|
|
e98487292d | ||
|
|
183630ada7 | ||
|
|
a9e447dde7 | ||
|
|
64c3993f5c | ||
|
|
5fe8145aca | ||
|
|
043e94c17a | ||
|
|
0d502d7cd6 | ||
|
|
0ff60057bb | ||
|
|
8e447d8cc5 | ||
|
|
22c9997952 | ||
|
|
d0b316056b | ||
|
|
16222386f4 | ||
|
|
a4e984136a | ||
|
|
3ef8056490 | ||
|
|
a8cc953517 | ||
|
|
7d6d3f5d4a | ||
|
|
1faeef9713 | ||
|
|
00fd4ff485 | ||
|
|
018c28f8a1 | ||
|
|
9cd0187c09 | ||
|
|
c6a20f9984 | ||
|
|
776e461a4e | ||
|
|
ebe92624d1 | ||
|
|
a9f661cb6e | ||
|
|
310bfa40f1 | ||
|
|
59ff47295c | ||
|
|
3d872d0428 | ||
|
|
bc7d1d1eb5 | ||
|
|
7e3ac2043e | ||
|
|
23edec0b38 | ||
|
|
f495dc37d5 | ||
|
|
eb2c406296 | ||
|
|
2c476679df |
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
Copyright 2009 The Go Authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
* Neither the name of Google LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
|
||||
+9
-22
@@ -354,11 +354,12 @@ func TestWaitAuthorization(t *testing.T) {
|
||||
})
|
||||
}
|
||||
t.Run("context cancel", func(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
_, err := runWaitAuthorization(ctx, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Retry-After", "60")
|
||||
fmt.Fprintf(w, `{"status":"pending"}`)
|
||||
time.AfterFunc(1*time.Millisecond, cancel)
|
||||
})
|
||||
if err == nil {
|
||||
t.Error("err is nil")
|
||||
@@ -373,28 +374,14 @@ func runWaitAuthorization(ctx context.Context, t *testing.T, h http.HandlerFunc)
|
||||
h(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
type res struct {
|
||||
authz *Authorization
|
||||
err error
|
||||
|
||||
client := &Client{
|
||||
Key: testKey,
|
||||
DirectoryURL: ts.URL,
|
||||
dir: &Directory{},
|
||||
KID: "some-key-id", // set to avoid lookup attempt
|
||||
}
|
||||
ch := make(chan res, 1)
|
||||
go func() {
|
||||
client := &Client{
|
||||
Key: testKey,
|
||||
DirectoryURL: ts.URL,
|
||||
dir: &Directory{},
|
||||
KID: "some-key-id", // set to avoid lookup attempt
|
||||
}
|
||||
a, err := client.WaitAuthorization(ctx, ts.URL)
|
||||
ch <- res{a, err}
|
||||
}()
|
||||
select {
|
||||
case <-time.After(3 * time.Second):
|
||||
t.Fatal("WaitAuthorization took too long to return")
|
||||
case v := <-ch:
|
||||
return v.authz, v.err
|
||||
}
|
||||
panic("runWaitAuthorization: out of select")
|
||||
return client.WaitAuthorization(ctx, ts.URL)
|
||||
}
|
||||
|
||||
func TestRevokeAuthorization(t *testing.T) {
|
||||
|
||||
@@ -427,18 +427,7 @@ func TestGetCertificate(t *testing.T) {
|
||||
|
||||
man.Client = &acme.Client{DirectoryURL: s.URL()}
|
||||
|
||||
var tlscert *tls.Certificate
|
||||
var err error
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
tlscert, err = man.GetCertificate(tt.hello)
|
||||
close(done)
|
||||
}()
|
||||
select {
|
||||
case <-time.After(time.Minute):
|
||||
t.Fatal("man.GetCertificate took too long to return")
|
||||
case <-done:
|
||||
}
|
||||
tlscert, err := man.GetCertificate(tt.hello)
|
||||
if tt.expectError != "" {
|
||||
if err == nil {
|
||||
t.Fatal("expected error, got certificate")
|
||||
@@ -515,15 +504,12 @@ func TestGetCertificate_failedAttempt(t *testing.T) {
|
||||
if _, err := man.GetCertificate(hello); err == nil {
|
||||
t.Error("GetCertificate: err is nil")
|
||||
}
|
||||
select {
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Errorf("took too long to remove the %q state", exampleCertKey)
|
||||
case <-done:
|
||||
man.stateMu.Lock()
|
||||
defer man.stateMu.Unlock()
|
||||
if v, exist := man.state[exampleCertKey]; exist {
|
||||
t.Errorf("state exists for %v: %+v", exampleCertKey, v)
|
||||
}
|
||||
|
||||
<-done
|
||||
man.stateMu.Lock()
|
||||
defer man.stateMu.Unlock()
|
||||
if v, exist := man.state[exampleCertKey]; exist {
|
||||
t.Errorf("state exists for %v: %+v", exampleCertKey, v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,8 +528,9 @@ func TestRevokeFailedAuthz(t *testing.T) {
|
||||
t.Fatal("expected GetCertificate to fail")
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
for time.Since(start) < 3*time.Second {
|
||||
logTicker := time.NewTicker(3 * time.Second)
|
||||
defer logTicker.Stop()
|
||||
for {
|
||||
authz, err := m.Client.GetAuthorization(context.Background(), ca.URL()+"/authz/0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -551,10 +538,14 @@ func TestRevokeFailedAuthz(t *testing.T) {
|
||||
if authz.Status == acme.StatusDeactivated {
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case <-logTicker.C:
|
||||
t.Logf("still waiting on revocations")
|
||||
default:
|
||||
}
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
t.Error("revocations took too long")
|
||||
|
||||
}
|
||||
|
||||
func TestHTTPHandlerDefaultFallback(t *testing.T) {
|
||||
|
||||
+20
-1
@@ -15,6 +15,7 @@ import (
|
||||
"io"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -271,9 +272,27 @@ func (c *Client) httpClient() *http.Client {
|
||||
}
|
||||
|
||||
// packageVersion is the version of the module that contains this package, for
|
||||
// sending as part of the User-Agent header. It's set in version_go112.go.
|
||||
// sending as part of the User-Agent header.
|
||||
var packageVersion string
|
||||
|
||||
func init() {
|
||||
// Set packageVersion if the binary was built in modules mode and x/crypto
|
||||
// was not replaced with a different module.
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
for _, m := range info.Deps {
|
||||
if m.Path != "golang.org/x/crypto" {
|
||||
continue
|
||||
}
|
||||
if m.Replace == nil {
|
||||
packageVersion = m.Version
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// userAgent returns the User-Agent header value. It includes the package name,
|
||||
// the module version (if available), and the c.UserAgent value (if set).
|
||||
func (c *Client) userAgent() string {
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ func (c *Client) updateRegRFC(ctx context.Context, a *Account) (*Account, error)
|
||||
return responseAccount(res)
|
||||
}
|
||||
|
||||
// getGegRFC is equivalent to c.GetReg but for CAs implementing RFC 8555.
|
||||
// getRegRFC is equivalent to c.GetReg but for CAs implementing RFC 8555.
|
||||
// It expects c.Discover to have already been called.
|
||||
func (c *Client) getRegRFC(ctx context.Context) (*Account, error) {
|
||||
req := json.RawMessage(`{"onlyReturnExisting": true}`)
|
||||
|
||||
+25
-50
@@ -177,8 +177,7 @@ func TestRFC_postKID(t *testing.T) {
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
ctx := context.Background()
|
||||
cl := &Client{
|
||||
Key: testKey,
|
||||
DirectoryURL: ts.URL,
|
||||
@@ -316,8 +315,7 @@ func TestRFC_Register(t *testing.T) {
|
||||
s.start()
|
||||
defer s.close()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
ctx := context.Background()
|
||||
cl := &Client{
|
||||
Key: testKeyEC,
|
||||
DirectoryURL: s.url("/"),
|
||||
@@ -454,8 +452,7 @@ func TestRFC_RegisterExternalAccountBinding(t *testing.T) {
|
||||
s.start()
|
||||
defer s.close()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
ctx := context.Background()
|
||||
cl := &Client{
|
||||
Key: testKeyEC,
|
||||
DirectoryURL: s.url("/"),
|
||||
@@ -867,24 +864,13 @@ func testWaitOrderStatus(t *testing.T, okStatus string) {
|
||||
s.start()
|
||||
defer s.close()
|
||||
|
||||
var order *Order
|
||||
var err error
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")}
|
||||
order, err = cl.WaitOrder(context.Background(), s.url("/orders/1"))
|
||||
close(done)
|
||||
}()
|
||||
select {
|
||||
case <-time.After(3 * time.Second):
|
||||
t.Fatal("WaitOrder took too long to return")
|
||||
case <-done:
|
||||
if err != nil {
|
||||
t.Fatalf("WaitOrder: %v", err)
|
||||
}
|
||||
if order.Status != okStatus {
|
||||
t.Errorf("order.Status = %q; want %q", order.Status, okStatus)
|
||||
}
|
||||
cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")}
|
||||
order, err := cl.WaitOrder(context.Background(), s.url("/orders/1"))
|
||||
if err != nil {
|
||||
t.Fatalf("WaitOrder: %v", err)
|
||||
}
|
||||
if order.Status != okStatus {
|
||||
t.Errorf("order.Status = %q; want %q", order.Status, okStatus)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -909,30 +895,20 @@ func TestRFC_WaitOrderError(t *testing.T) {
|
||||
s.start()
|
||||
defer s.close()
|
||||
|
||||
var err error
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")}
|
||||
_, err = cl.WaitOrder(context.Background(), s.url("/orders/1"))
|
||||
close(done)
|
||||
}()
|
||||
select {
|
||||
case <-time.After(3 * time.Second):
|
||||
t.Fatal("WaitOrder took too long to return")
|
||||
case <-done:
|
||||
if err == nil {
|
||||
t.Fatal("WaitOrder returned nil error")
|
||||
}
|
||||
e, ok := err.(*OrderError)
|
||||
if !ok {
|
||||
t.Fatalf("err = %v (%T); want OrderError", err, err)
|
||||
}
|
||||
if e.OrderURL != s.url("/orders/1") {
|
||||
t.Errorf("e.OrderURL = %q; want %q", e.OrderURL, s.url("/orders/1"))
|
||||
}
|
||||
if e.Status != StatusInvalid {
|
||||
t.Errorf("e.Status = %q; want %q", e.Status, StatusInvalid)
|
||||
}
|
||||
cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")}
|
||||
_, err := cl.WaitOrder(context.Background(), s.url("/orders/1"))
|
||||
if err == nil {
|
||||
t.Fatal("WaitOrder returned nil error")
|
||||
}
|
||||
e, ok := err.(*OrderError)
|
||||
if !ok {
|
||||
t.Fatalf("err = %v (%T); want OrderError", err, err)
|
||||
}
|
||||
if e.OrderURL != s.url("/orders/1") {
|
||||
t.Errorf("e.OrderURL = %q; want %q", e.OrderURL, s.url("/orders/1"))
|
||||
}
|
||||
if e.Status != StatusInvalid {
|
||||
t.Errorf("e.Status = %q; want %q", e.Status, StatusInvalid)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -972,8 +948,7 @@ func TestRFC_CreateOrderCert(t *testing.T) {
|
||||
})
|
||||
s.start()
|
||||
defer s.close()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
ctx := context.Background()
|
||||
|
||||
cl := &Client{Key: testKeyEC, DirectoryURL: s.url("/")}
|
||||
cert, curl, err := cl.CreateOrderCert(ctx, s.url("/pleaseissue"), csr, true)
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.12
|
||||
// +build go1.12
|
||||
|
||||
package acme
|
||||
|
||||
import "runtime/debug"
|
||||
|
||||
func init() {
|
||||
// Set packageVersion if the binary was built in modules mode and x/crypto
|
||||
// was not replaced with a different module.
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
for _, m := range info.Deps {
|
||||
if m.Path != "golang.org/x/crypto" {
|
||||
continue
|
||||
}
|
||||
if m.Replace == nil {
|
||||
packageVersion = m.Version
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && gc && !purego
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
package argon2
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && gc && !purego
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
@@ -200,8 +199,8 @@ TEXT ·mixBlocksSSE2(SB), 4, $0-32
|
||||
MOVQ out+0(FP), DX
|
||||
MOVQ a+8(FP), AX
|
||||
MOVQ b+16(FP), BX
|
||||
MOVQ a+24(FP), CX
|
||||
MOVQ $128, BP
|
||||
MOVQ c+24(FP), CX
|
||||
MOVQ $128, DI
|
||||
|
||||
loop:
|
||||
MOVOU 0(AX), X0
|
||||
@@ -214,7 +213,7 @@ loop:
|
||||
ADDQ $16, BX
|
||||
ADDQ $16, CX
|
||||
ADDQ $16, DX
|
||||
SUBQ $2, BP
|
||||
SUBQ $2, DI
|
||||
JA loop
|
||||
RET
|
||||
|
||||
@@ -223,8 +222,8 @@ TEXT ·xorBlocksSSE2(SB), 4, $0-32
|
||||
MOVQ out+0(FP), DX
|
||||
MOVQ a+8(FP), AX
|
||||
MOVQ b+16(FP), BX
|
||||
MOVQ a+24(FP), CX
|
||||
MOVQ $128, BP
|
||||
MOVQ c+24(FP), CX
|
||||
MOVQ $128, DI
|
||||
|
||||
loop:
|
||||
MOVOU 0(AX), X0
|
||||
@@ -239,6 +238,6 @@ loop:
|
||||
ADDQ $16, BX
|
||||
ADDQ $16, CX
|
||||
ADDQ $16, DX
|
||||
SUBQ $2, BP
|
||||
SUBQ $2, DI
|
||||
JA loop
|
||||
RET
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !amd64 || purego || !gc
|
||||
// +build !amd64 purego !gc
|
||||
|
||||
package argon2
|
||||
|
||||
|
||||
+10
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
// Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing
|
||||
// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
|
||||
package bcrypt // import "golang.org/x/crypto/bcrypt"
|
||||
package bcrypt
|
||||
|
||||
// The code is a port of Provos and Mazières's C implementation.
|
||||
import (
|
||||
@@ -82,11 +82,20 @@ type hashed struct {
|
||||
minor byte
|
||||
}
|
||||
|
||||
// ErrPasswordTooLong is returned when the password passed to
|
||||
// GenerateFromPassword is too long (i.e. > 72 bytes).
|
||||
var ErrPasswordTooLong = errors.New("bcrypt: password length exceeds 72 bytes")
|
||||
|
||||
// GenerateFromPassword returns the bcrypt hash of the password at the given
|
||||
// cost. If the cost given is less than MinCost, the cost will be set to
|
||||
// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
|
||||
// to compare the returned hashed password with its cleartext version.
|
||||
// GenerateFromPassword does not accept passwords longer than 72 bytes, which
|
||||
// is the longest password bcrypt will operate on.
|
||||
func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
|
||||
if len(password) > 72 {
|
||||
return nil, ErrPasswordTooLong
|
||||
}
|
||||
p, err := newFromPassword(password, cost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -241,3 +241,10 @@ func TestNoSideEffectsFromCompare(t *testing.T) {
|
||||
t.Errorf("got=%q want=%q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswordTooLong(t *testing.T) {
|
||||
_, err := GenerateFromPassword(make([]byte, 73), 1)
|
||||
if err != ErrPasswordTooLong {
|
||||
t.Errorf("unexpected error: got %q, want %q", err, ErrPasswordTooLong)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.7 && amd64 && gc && !purego
|
||||
// +build go1.7,amd64,gc,!purego
|
||||
//go:build amd64 && gc && !purego
|
||||
|
||||
package blake2b
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.7 && amd64 && gc && !purego
|
||||
// +build go1.7,amd64,gc,!purego
|
||||
//go:build amd64 && gc && !purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.7 && amd64 && gc && !purego
|
||||
// +build !go1.7,amd64,gc,!purego
|
||||
|
||||
package blake2b
|
||||
|
||||
import "golang.org/x/sys/cpu"
|
||||
|
||||
func init() {
|
||||
useSSE4 = cpu.X86.HasSSE41
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
|
||||
|
||||
func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
|
||||
if useSSE4 {
|
||||
hashBlocksSSE4(h, c, flag, blocks)
|
||||
} else {
|
||||
hashBlocksGeneric(h, c, flag, blocks)
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && gc && !purego
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !amd64 || purego || !gc
|
||||
// +build !amd64 purego !gc
|
||||
|
||||
package blake2b
|
||||
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.9
|
||||
// +build go1.9
|
||||
|
||||
package blake2b
|
||||
|
||||
import (
|
||||
|
||||
+9
-1
@@ -16,9 +16,10 @@
|
||||
//
|
||||
// BLAKE2X is a construction to compute hash values larger than 32 bytes. It
|
||||
// can produce hash values between 0 and 65535 bytes.
|
||||
package blake2s // import "golang.org/x/crypto/blake2s"
|
||||
package blake2s
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"hash"
|
||||
@@ -55,6 +56,13 @@ func Sum256(data []byte) [Size]byte {
|
||||
// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash.
|
||||
func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
|
||||
|
||||
func init() {
|
||||
crypto.RegisterHash(crypto.BLAKE2s_256, func() hash.Hash {
|
||||
h, _ := New256(nil)
|
||||
return h
|
||||
})
|
||||
}
|
||||
|
||||
// New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a
|
||||
// non-empty key. Note that a 128-bit digest is too small to be secure as a
|
||||
// cryptographic hash and should only be used as a MAC, thus the key argument
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build 386 && gc && !purego
|
||||
// +build 386,gc,!purego
|
||||
|
||||
package blake2s
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build 386 && gc && !purego
|
||||
// +build 386,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && gc && !purego
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
package blake2s
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build amd64 && gc && !purego
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (!amd64 && !386) || !gc || purego
|
||||
// +build !amd64,!386 !gc purego
|
||||
|
||||
package blake2s
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.9
|
||||
// +build go1.9
|
||||
|
||||
package blake2s
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"hash"
|
||||
)
|
||||
|
||||
func init() {
|
||||
newHash256 := func() hash.Hash {
|
||||
h, _ := New256(nil)
|
||||
return h
|
||||
}
|
||||
|
||||
crypto.RegisterHash(crypto.BLAKE2s_256, newHash256)
|
||||
}
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
// Deprecated: any new system should use AES (from crypto/aes, if necessary in
|
||||
// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from
|
||||
// golang.org/x/crypto/chacha20poly1305).
|
||||
package blowfish // import "golang.org/x/crypto/blowfish"
|
||||
package blowfish
|
||||
|
||||
// The code is a port of Bruce Schneier's C implementation.
|
||||
// See https://www.schneier.com/blowfish.html.
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
// elliptic curve. This package is frozen, and not implemented in constant time.
|
||||
// There is a more complete implementation at github.com/cloudflare/bn256, but
|
||||
// note that it suffers from the same security issues of the underlying curve.
|
||||
package bn256 // import "golang.org/x/crypto/bn256"
|
||||
package bn256
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
// Deprecated: any new system should use AES (from crypto/aes, if necessary in
|
||||
// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from
|
||||
// golang.org/x/crypto/chacha20poly1305).
|
||||
package cast5 // import "golang.org/x/crypto/cast5"
|
||||
package cast5
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.11 && gc && !purego
|
||||
// +build go1.11,gc,!purego
|
||||
//go:build gc && !purego
|
||||
|
||||
package chacha20
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.11 && gc && !purego
|
||||
// +build go1.11,gc,!purego
|
||||
//go:build gc && !purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (!arm64 && !s390x && !ppc64le) || (arm64 && !go1.11) || !gc || purego
|
||||
// +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego
|
||||
//go:build (!arm64 && !s390x && !ppc64le) || !gc || purego
|
||||
|
||||
package chacha20
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
package chacha20
|
||||
|
||||
|
||||
+52
-59
@@ -20,7 +20,6 @@
|
||||
// due to the calling conventions and initialization of constants.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
@@ -34,6 +33,9 @@
|
||||
#define CONSTBASE R16
|
||||
#define BLOCKS R17
|
||||
|
||||
// for VPERMXOR
|
||||
#define MASK R18
|
||||
|
||||
DATA consts<>+0x00(SB)/8, $0x3320646e61707865
|
||||
DATA consts<>+0x08(SB)/8, $0x6b20657479622d32
|
||||
DATA consts<>+0x10(SB)/8, $0x0000000000000001
|
||||
@@ -54,7 +56,11 @@ DATA consts<>+0x80(SB)/8, $0x6b2065746b206574
|
||||
DATA consts<>+0x88(SB)/8, $0x6b2065746b206574
|
||||
DATA consts<>+0x90(SB)/8, $0x0000000100000000
|
||||
DATA consts<>+0x98(SB)/8, $0x0000000300000002
|
||||
GLOBL consts<>(SB), RODATA, $0xa0
|
||||
DATA consts<>+0xa0(SB)/8, $0x5566774411223300
|
||||
DATA consts<>+0xa8(SB)/8, $0xddeeffcc99aabb88
|
||||
DATA consts<>+0xb0(SB)/8, $0x6677445522330011
|
||||
DATA consts<>+0xb8(SB)/8, $0xeeffccddaabb8899
|
||||
GLOBL consts<>(SB), RODATA, $0xc0
|
||||
|
||||
//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
|
||||
TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
|
||||
@@ -71,6 +77,9 @@ TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
|
||||
MOVD $48, R10
|
||||
MOVD $64, R11
|
||||
SRD $6, LEN, BLOCKS
|
||||
// for VPERMXOR
|
||||
MOVD $consts<>+0xa0(SB), MASK
|
||||
MOVD $16, R20
|
||||
// V16
|
||||
LXVW4X (CONSTBASE)(R0), VS48
|
||||
ADD $80,CONSTBASE
|
||||
@@ -88,6 +97,10 @@ TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
|
||||
// V28
|
||||
LXVW4X (CONSTBASE)(R11), VS60
|
||||
|
||||
// Load mask constants for VPERMXOR
|
||||
LXVW4X (MASK)(R0), V20
|
||||
LXVW4X (MASK)(R20), V21
|
||||
|
||||
// splat slot from V19 -> V26
|
||||
VSPLTW $0, V19, V26
|
||||
|
||||
@@ -98,7 +111,7 @@ TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
|
||||
|
||||
MOVD $10, R14
|
||||
MOVD R14, CTR
|
||||
|
||||
PCALIGN $16
|
||||
loop_outer_vsx:
|
||||
// V0, V1, V2, V3
|
||||
LXVW4X (R0)(CONSTBASE), VS32
|
||||
@@ -129,22 +142,17 @@ loop_outer_vsx:
|
||||
VSPLTISW $12, V28
|
||||
VSPLTISW $8, V29
|
||||
VSPLTISW $7, V30
|
||||
|
||||
PCALIGN $16
|
||||
loop_vsx:
|
||||
VADDUWM V0, V4, V0
|
||||
VADDUWM V1, V5, V1
|
||||
VADDUWM V2, V6, V2
|
||||
VADDUWM V3, V7, V3
|
||||
|
||||
VXOR V12, V0, V12
|
||||
VXOR V13, V1, V13
|
||||
VXOR V14, V2, V14
|
||||
VXOR V15, V3, V15
|
||||
|
||||
VRLW V12, V27, V12
|
||||
VRLW V13, V27, V13
|
||||
VRLW V14, V27, V14
|
||||
VRLW V15, V27, V15
|
||||
VPERMXOR V12, V0, V21, V12
|
||||
VPERMXOR V13, V1, V21, V13
|
||||
VPERMXOR V14, V2, V21, V14
|
||||
VPERMXOR V15, V3, V21, V15
|
||||
|
||||
VADDUWM V8, V12, V8
|
||||
VADDUWM V9, V13, V9
|
||||
@@ -166,15 +174,10 @@ loop_vsx:
|
||||
VADDUWM V2, V6, V2
|
||||
VADDUWM V3, V7, V3
|
||||
|
||||
VXOR V12, V0, V12
|
||||
VXOR V13, V1, V13
|
||||
VXOR V14, V2, V14
|
||||
VXOR V15, V3, V15
|
||||
|
||||
VRLW V12, V29, V12
|
||||
VRLW V13, V29, V13
|
||||
VRLW V14, V29, V14
|
||||
VRLW V15, V29, V15
|
||||
VPERMXOR V12, V0, V20, V12
|
||||
VPERMXOR V13, V1, V20, V13
|
||||
VPERMXOR V14, V2, V20, V14
|
||||
VPERMXOR V15, V3, V20, V15
|
||||
|
||||
VADDUWM V8, V12, V8
|
||||
VADDUWM V9, V13, V9
|
||||
@@ -196,15 +199,10 @@ loop_vsx:
|
||||
VADDUWM V2, V7, V2
|
||||
VADDUWM V3, V4, V3
|
||||
|
||||
VXOR V15, V0, V15
|
||||
VXOR V12, V1, V12
|
||||
VXOR V13, V2, V13
|
||||
VXOR V14, V3, V14
|
||||
|
||||
VRLW V15, V27, V15
|
||||
VRLW V12, V27, V12
|
||||
VRLW V13, V27, V13
|
||||
VRLW V14, V27, V14
|
||||
VPERMXOR V15, V0, V21, V15
|
||||
VPERMXOR V12, V1, V21, V12
|
||||
VPERMXOR V13, V2, V21, V13
|
||||
VPERMXOR V14, V3, V21, V14
|
||||
|
||||
VADDUWM V10, V15, V10
|
||||
VADDUWM V11, V12, V11
|
||||
@@ -226,15 +224,10 @@ loop_vsx:
|
||||
VADDUWM V2, V7, V2
|
||||
VADDUWM V3, V4, V3
|
||||
|
||||
VXOR V15, V0, V15
|
||||
VXOR V12, V1, V12
|
||||
VXOR V13, V2, V13
|
||||
VXOR V14, V3, V14
|
||||
|
||||
VRLW V15, V29, V15
|
||||
VRLW V12, V29, V12
|
||||
VRLW V13, V29, V13
|
||||
VRLW V14, V29, V14
|
||||
VPERMXOR V15, V0, V20, V15
|
||||
VPERMXOR V12, V1, V20, V12
|
||||
VPERMXOR V13, V2, V20, V13
|
||||
VPERMXOR V14, V3, V20, V14
|
||||
|
||||
VADDUWM V10, V15, V10
|
||||
VADDUWM V11, V12, V11
|
||||
@@ -250,48 +243,48 @@ loop_vsx:
|
||||
VRLW V6, V30, V6
|
||||
VRLW V7, V30, V7
|
||||
VRLW V4, V30, V4
|
||||
BC 16, LT, loop_vsx
|
||||
BDNZ loop_vsx
|
||||
|
||||
VADDUWM V12, V26, V12
|
||||
|
||||
WORD $0x13600F8C // VMRGEW V0, V1, V27
|
||||
WORD $0x13821F8C // VMRGEW V2, V3, V28
|
||||
VMRGEW V0, V1, V27
|
||||
VMRGEW V2, V3, V28
|
||||
|
||||
WORD $0x10000E8C // VMRGOW V0, V1, V0
|
||||
WORD $0x10421E8C // VMRGOW V2, V3, V2
|
||||
VMRGOW V0, V1, V0
|
||||
VMRGOW V2, V3, V2
|
||||
|
||||
WORD $0x13A42F8C // VMRGEW V4, V5, V29
|
||||
WORD $0x13C63F8C // VMRGEW V6, V7, V30
|
||||
VMRGEW V4, V5, V29
|
||||
VMRGEW V6, V7, V30
|
||||
|
||||
XXPERMDI VS32, VS34, $0, VS33
|
||||
XXPERMDI VS32, VS34, $3, VS35
|
||||
XXPERMDI VS59, VS60, $0, VS32
|
||||
XXPERMDI VS59, VS60, $3, VS34
|
||||
|
||||
WORD $0x10842E8C // VMRGOW V4, V5, V4
|
||||
WORD $0x10C63E8C // VMRGOW V6, V7, V6
|
||||
VMRGOW V4, V5, V4
|
||||
VMRGOW V6, V7, V6
|
||||
|
||||
WORD $0x13684F8C // VMRGEW V8, V9, V27
|
||||
WORD $0x138A5F8C // VMRGEW V10, V11, V28
|
||||
VMRGEW V8, V9, V27
|
||||
VMRGEW V10, V11, V28
|
||||
|
||||
XXPERMDI VS36, VS38, $0, VS37
|
||||
XXPERMDI VS36, VS38, $3, VS39
|
||||
XXPERMDI VS61, VS62, $0, VS36
|
||||
XXPERMDI VS61, VS62, $3, VS38
|
||||
|
||||
WORD $0x11084E8C // VMRGOW V8, V9, V8
|
||||
WORD $0x114A5E8C // VMRGOW V10, V11, V10
|
||||
VMRGOW V8, V9, V8
|
||||
VMRGOW V10, V11, V10
|
||||
|
||||
WORD $0x13AC6F8C // VMRGEW V12, V13, V29
|
||||
WORD $0x13CE7F8C // VMRGEW V14, V15, V30
|
||||
VMRGEW V12, V13, V29
|
||||
VMRGEW V14, V15, V30
|
||||
|
||||
XXPERMDI VS40, VS42, $0, VS41
|
||||
XXPERMDI VS40, VS42, $3, VS43
|
||||
XXPERMDI VS59, VS60, $0, VS40
|
||||
XXPERMDI VS59, VS60, $3, VS42
|
||||
|
||||
WORD $0x118C6E8C // VMRGOW V12, V13, V12
|
||||
WORD $0x11CE7E8C // VMRGOW V14, V15, V14
|
||||
VMRGOW V12, V13, V12
|
||||
VMRGOW V14, V15, V14
|
||||
|
||||
VSPLTISW $4, V27
|
||||
VADDUWM V26, V27, V26
|
||||
@@ -432,7 +425,7 @@ tail_vsx:
|
||||
ADD $-1, R11, R12
|
||||
ADD $-1, INP
|
||||
ADD $-1, OUT
|
||||
|
||||
PCALIGN $16
|
||||
looptail_vsx:
|
||||
// Copying the result to OUT
|
||||
// in bytes.
|
||||
@@ -440,7 +433,7 @@ looptail_vsx:
|
||||
MOVBZU 1(INP), TMP
|
||||
XOR KEY, TMP, KEY
|
||||
MOVBU KEY, 1(OUT)
|
||||
BC 16, LT, looptail_vsx
|
||||
BDNZ looptail_vsx
|
||||
|
||||
// Clear the stack values
|
||||
STXVW4X VS48, (R11)(R0)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
package chacha20
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
#include "go_asm.h"
|
||||
#include "textflag.h"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD and its
|
||||
// extended nonce variant XChaCha20-Poly1305, as specified in RFC 8439 and
|
||||
// draft-irtf-cfrg-xchacha-01.
|
||||
package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305"
|
||||
package chacha20poly1305
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
package chacha20poly1305
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
// This file was originally from https://golang.org/cl/24717 by Vlad Krasnov of CloudFlare.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
// General register allocation
|
||||
@@ -184,11 +183,31 @@ GLOBL ·andMask<>(SB), (NOPTR+RODATA), $240
|
||||
#define shiftD1Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x04 // PALIGNR $4, X10, X10
|
||||
#define shiftD2Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X11, X11
|
||||
#define shiftD3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x04 // PALIGNR $4, X15, X15
|
||||
|
||||
// Some macros
|
||||
|
||||
// ROL rotates the uint32s in register R left by N bits, using temporary T.
|
||||
#define ROL(N, R, T) \
|
||||
MOVO R, T; PSLLL $(N), T; PSRLL $(32-(N)), R; PXOR T, R
|
||||
|
||||
// ROL16 rotates the uint32s in register R left by 16, using temporary T if needed.
|
||||
#ifdef GOAMD64_v2
|
||||
#define ROL16(R, T) PSHUFB ·rol16<>(SB), R
|
||||
#else
|
||||
#define ROL16(R, T) ROL(16, R, T)
|
||||
#endif
|
||||
|
||||
// ROL8 rotates the uint32s in register R left by 8, using temporary T if needed.
|
||||
#ifdef GOAMD64_v2
|
||||
#define ROL8(R, T) PSHUFB ·rol8<>(SB), R
|
||||
#else
|
||||
#define ROL8(R, T) ROL(8, R, T)
|
||||
#endif
|
||||
|
||||
#define chachaQR(A, B, C, D, T) \
|
||||
PADDD B, A; PXOR A, D; PSHUFB ·rol16<>(SB), D \
|
||||
PADDD B, A; PXOR A, D; ROL16(D, T) \
|
||||
PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $12, T; PSRLL $20, B; PXOR T, B \
|
||||
PADDD B, A; PXOR A, D; PSHUFB ·rol8<>(SB), D \
|
||||
PADDD B, A; PXOR A, D; ROL8(D, T) \
|
||||
PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $7, T; PSRLL $25, B; PXOR T, B
|
||||
|
||||
#define chachaQR_AVX2(A, B, C, D, T) \
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !amd64 || !gc || purego
|
||||
// +build !amd64 !gc purego
|
||||
|
||||
package chacha20poly1305
|
||||
|
||||
|
||||
+56
-40
@@ -264,36 +264,35 @@ func (s *String) ReadASN1Boolean(out *bool) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()
|
||||
|
||||
// ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does
|
||||
// not point to an integer or to a big.Int, it panics. It reports whether the
|
||||
// read was successful.
|
||||
// not point to an integer, to a big.Int, or to a []byte it panics. Only
|
||||
// positive and zero values can be decoded into []byte, and they are returned as
|
||||
// big-endian binary values that share memory with s. Positive values will have
|
||||
// no leading zeroes, and zero will be returned as a single zero byte.
|
||||
// ReadASN1Integer reports whether the read was successful.
|
||||
func (s *String) ReadASN1Integer(out interface{}) bool {
|
||||
if reflect.TypeOf(out).Kind() != reflect.Ptr {
|
||||
panic("out is not a pointer")
|
||||
}
|
||||
switch reflect.ValueOf(out).Elem().Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
switch out := out.(type) {
|
||||
case *int, *int8, *int16, *int32, *int64:
|
||||
var i int64
|
||||
if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) {
|
||||
return false
|
||||
}
|
||||
reflect.ValueOf(out).Elem().SetInt(i)
|
||||
return true
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
case *uint, *uint8, *uint16, *uint32, *uint64:
|
||||
var u uint64
|
||||
if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) {
|
||||
return false
|
||||
}
|
||||
reflect.ValueOf(out).Elem().SetUint(u)
|
||||
return true
|
||||
case reflect.Struct:
|
||||
if reflect.TypeOf(out).Elem() == bigIntType {
|
||||
return s.readASN1BigInt(out.(*big.Int))
|
||||
}
|
||||
case *big.Int:
|
||||
return s.readASN1BigInt(out)
|
||||
case *[]byte:
|
||||
return s.readASN1Bytes(out)
|
||||
default:
|
||||
panic("out does not point to an integer type")
|
||||
}
|
||||
panic("out does not point to an integer type")
|
||||
}
|
||||
|
||||
func checkASN1Integer(bytes []byte) bool {
|
||||
@@ -333,6 +332,21 @@ func (s *String) readASN1BigInt(out *big.Int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *String) readASN1Bytes(out *[]byte) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) {
|
||||
return false
|
||||
}
|
||||
if bytes[0]&0x80 == 0x80 {
|
||||
return false
|
||||
}
|
||||
for len(bytes) > 1 && bytes[0] == 0 {
|
||||
bytes = bytes[1:]
|
||||
}
|
||||
*out = bytes
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *String) readASN1Int64(out *int64) bool {
|
||||
var bytes String
|
||||
if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) {
|
||||
@@ -417,6 +431,14 @@ func (s *String) readBase128Int(out *int) bool {
|
||||
}
|
||||
ret <<= 7
|
||||
b := s.read(1)[0]
|
||||
|
||||
// ITU-T X.690, section 8.19.2:
|
||||
// The subidentifier shall be encoded in the fewest possible octets,
|
||||
// that is, the leading octet of the subidentifier shall not have the value 0x80.
|
||||
if i == 0 && b == 0x80 {
|
||||
return false
|
||||
}
|
||||
|
||||
ret |= int(b & 0x7f)
|
||||
if b&0x80 == 0 {
|
||||
*out = ret
|
||||
@@ -545,7 +567,7 @@ func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It is
|
||||
// ReadASN1BitStringAsBytes decodes an ASN.1 BIT STRING into out and advances. It is
|
||||
// an error if the BIT STRING is not a whole number of bytes. It reports
|
||||
// whether the read was successful.
|
||||
func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool {
|
||||
@@ -654,34 +676,27 @@ func (s *String) SkipOptionalASN1(tag asn1.Tag) bool {
|
||||
return s.ReadASN1(&unused, tag)
|
||||
}
|
||||
|
||||
// ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER
|
||||
// explicitly tagged with tag into out and advances. If no element with a
|
||||
// matching tag is present, it writes defaultValue into out instead. If out
|
||||
// does not point to an integer or to a big.Int, it panics. It reports
|
||||
// whether the read was successful.
|
||||
// ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER explicitly
|
||||
// tagged with tag into out and advances. If no element with a matching tag is
|
||||
// present, it writes defaultValue into out instead. Otherwise, it behaves like
|
||||
// ReadASN1Integer.
|
||||
func (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultValue interface{}) bool {
|
||||
if reflect.TypeOf(out).Kind() != reflect.Ptr {
|
||||
panic("out is not a pointer")
|
||||
}
|
||||
var present bool
|
||||
var i String
|
||||
if !s.ReadOptionalASN1(&i, &present, tag) {
|
||||
return false
|
||||
}
|
||||
if !present {
|
||||
switch reflect.ValueOf(out).Elem().Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
switch out.(type) {
|
||||
case *int, *int8, *int16, *int32, *int64,
|
||||
*uint, *uint8, *uint16, *uint32, *uint64, *[]byte:
|
||||
reflect.ValueOf(out).Elem().Set(reflect.ValueOf(defaultValue))
|
||||
case reflect.Struct:
|
||||
if reflect.TypeOf(out).Elem() != bigIntType {
|
||||
panic("invalid integer type")
|
||||
}
|
||||
if reflect.TypeOf(defaultValue).Kind() != reflect.Ptr ||
|
||||
reflect.TypeOf(defaultValue).Elem() != bigIntType {
|
||||
case *big.Int:
|
||||
if defaultValue, ok := defaultValue.(*big.Int); ok {
|
||||
out.(*big.Int).Set(defaultValue)
|
||||
} else {
|
||||
panic("out points to big.Int, but defaultValue does not")
|
||||
}
|
||||
out.(*big.Int).Set(defaultValue.(*big.Int))
|
||||
default:
|
||||
panic("invalid integer type")
|
||||
}
|
||||
@@ -718,13 +733,14 @@ func (s *String) ReadOptionalASN1OctetString(out *[]byte, outPresent *bool, tag
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadOptionalASN1Boolean sets *out to the value of the next ASN.1 BOOLEAN or,
|
||||
// if the next bytes are not an ASN.1 BOOLEAN, to the value of defaultValue.
|
||||
// It reports whether the operation was successful.
|
||||
func (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool {
|
||||
// ReadOptionalASN1Boolean attempts to read an optional ASN.1 BOOLEAN
|
||||
// explicitly tagged with tag into out and advances. If no element with a
|
||||
// matching tag is present, it sets "out" to defaultValue instead. It reports
|
||||
// whether the read was successful.
|
||||
func (s *String) ReadOptionalASN1Boolean(out *bool, tag asn1.Tag, defaultValue bool) bool {
|
||||
var present bool
|
||||
var child String
|
||||
if !s.ReadOptionalASN1(&child, &present, asn1.BOOLEAN) {
|
||||
if !s.ReadOptionalASN1(&child, &present, tag) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -733,7 +749,7 @@ func (s *String) ReadOptionalASN1Boolean(out *bool, defaultValue bool) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
return s.ReadASN1Boolean(out)
|
||||
return child.ReadASN1Boolean(out)
|
||||
}
|
||||
|
||||
func (s *String) readASN1(out *String, outTag *asn1.Tag, skipHeader bool) bool {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
// Package asn1 contains supporting types for parsing and building ASN.1
|
||||
// messages with the cryptobyte package.
|
||||
package asn1 // import "golang.org/x/crypto/cryptobyte/asn1"
|
||||
package asn1
|
||||
|
||||
// Tag represents an ASN.1 identifier octet, consisting of a tag number
|
||||
// (indicating a type) and class (such as context-specific or constructed).
|
||||
|
||||
@@ -115,6 +115,28 @@ func TestReadASN1OptionalInteger(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
const defaultBool = false
|
||||
|
||||
var optionalBoolTestData = []readASN1Test{
|
||||
{"empty", []byte{}, 0xa0, true, false},
|
||||
{"invalid", []byte{0xa1, 0x3, 0x1, 0x2, 0x7f}, 0xa1, false, defaultBool},
|
||||
{"missing", []byte{0xa1, 0x3, 0x1, 0x1, 0x7f}, 0xa0, true, defaultBool},
|
||||
{"present", []byte{0xa1, 0x3, 0x1, 0x1, 0xff}, 0xa1, true, true},
|
||||
}
|
||||
|
||||
func TestReadASN1OptionalBoolean(t *testing.T) {
|
||||
for _, test := range optionalBoolTestData {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
in := String(test.in)
|
||||
var out bool
|
||||
ok := in.ReadOptionalASN1Boolean(&out, test.tag, defaultBool)
|
||||
if ok != test.ok || ok && out != test.out.(bool) {
|
||||
t.Errorf("in.ReadOptionalASN1Boolean() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadASN1IntegerSigned(t *testing.T) {
|
||||
testData64 := []struct {
|
||||
in []byte
|
||||
@@ -154,6 +176,32 @@ func TestReadASN1IntegerSigned(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
// Repeat the same cases, reading into a []byte.
|
||||
t.Run("bytes", func(t *testing.T) {
|
||||
for i, test := range testData64 {
|
||||
in := String(test.in)
|
||||
var out []byte
|
||||
ok := in.ReadASN1Integer(&out)
|
||||
if test.out < 0 {
|
||||
if ok {
|
||||
t.Errorf("#%d: in.ReadASN1Integer(%d) = %v, want false", i, test.out, ok)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !ok {
|
||||
t.Errorf("#%d: in.ReadASN1Integer() = %v, want true", i, ok)
|
||||
continue
|
||||
}
|
||||
n := new(big.Int).SetBytes(out).Int64()
|
||||
if n != test.out {
|
||||
t.Errorf("#%d: in.ReadASN1Integer() = %v, want true; out = %x, want %d", i, ok, out, test.out)
|
||||
}
|
||||
if out[0] == 0 && len(out) > 1 {
|
||||
t.Errorf("#%d: in.ReadASN1Integer() = %v; out = %x, has leading zeroes", i, ok, out)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Repeat with the implicit-tagging functions
|
||||
t.Run("WithTag", func(t *testing.T) {
|
||||
for i, test := range testData64 {
|
||||
@@ -250,6 +298,7 @@ func TestASN1ObjectIdentifier(t *testing.T) {
|
||||
{[]byte{6, 7, 85, 0x02, 0x85, 0xc7, 0xcc, 0xfb, 0x01}, true, []int{2, 5, 2, 1492336001}},
|
||||
{[]byte{6, 7, 0x55, 0x02, 0x87, 0xff, 0xff, 0xff, 0x7f}, true, []int{2, 5, 2, 2147483647}}, // 2**31-1
|
||||
{[]byte{6, 7, 0x55, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00}, false, []int{}}, // 2**31
|
||||
{[]byte{6, 3, 85, 0x80, 0x02}, false, []int{}}, // leading 0x80 octet
|
||||
}
|
||||
|
||||
for i, test := range testData {
|
||||
|
||||
+11
-3
@@ -95,6 +95,11 @@ func (b *Builder) AddUint32(v uint32) {
|
||||
b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
|
||||
}
|
||||
|
||||
// AddUint48 appends a big-endian, 48-bit value to the byte string.
|
||||
func (b *Builder) AddUint48(v uint64) {
|
||||
b.add(byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
|
||||
}
|
||||
|
||||
// AddUint64 appends a big-endian, 64-bit value to the byte string.
|
||||
func (b *Builder) AddUint64(v uint64) {
|
||||
b.add(byte(v>>56), byte(v>>48), byte(v>>40), byte(v>>32), byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
|
||||
@@ -303,9 +308,9 @@ func (b *Builder) add(bytes ...byte) {
|
||||
b.result = append(b.result, bytes...)
|
||||
}
|
||||
|
||||
// Unwrite rolls back n bytes written directly to the Builder. An attempt by a
|
||||
// child builder passed to a continuation to unwrite bytes from its parent will
|
||||
// panic.
|
||||
// Unwrite rolls back non-negative n bytes written directly to the Builder.
|
||||
// An attempt by a child builder passed to a continuation to unwrite bytes
|
||||
// from its parent will panic.
|
||||
func (b *Builder) Unwrite(n int) {
|
||||
if b.err != nil {
|
||||
return
|
||||
@@ -317,6 +322,9 @@ func (b *Builder) Unwrite(n int) {
|
||||
if length < 0 {
|
||||
panic("cryptobyte: internal error")
|
||||
}
|
||||
if n < 0 {
|
||||
panic("cryptobyte: attempted to unwrite negative number of bytes")
|
||||
}
|
||||
if n > length {
|
||||
panic("cryptobyte: attempted to unwrite more than was written")
|
||||
}
|
||||
|
||||
@@ -179,6 +179,27 @@ func TestUint32(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUint48(t *testing.T) {
|
||||
var b Builder
|
||||
var u uint64 = 0xfefcff3cfdfc
|
||||
b.AddUint48(u)
|
||||
if err := builderBytesEq(&b, 254, 252, 255, 60, 253, 252); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var s String = b.BytesOrPanic()
|
||||
var v uint64
|
||||
if !s.ReadUint48(&v) {
|
||||
t.Error("ReadUint48() = false, want true")
|
||||
}
|
||||
if v != u {
|
||||
t.Errorf("v = %x, want %x", v, u)
|
||||
}
|
||||
if len(s) != 0 {
|
||||
t.Errorf("len(s) = %d, want 0", len(s))
|
||||
}
|
||||
}
|
||||
|
||||
func TestUint64(t *testing.T) {
|
||||
var b Builder
|
||||
b.AddUint64(0xf2fefefcff3cfdfc)
|
||||
|
||||
+12
-1
@@ -15,7 +15,7 @@
|
||||
//
|
||||
// See the documentation and examples for the Builder and String types to get
|
||||
// started.
|
||||
package cryptobyte // import "golang.org/x/crypto/cryptobyte"
|
||||
package cryptobyte
|
||||
|
||||
// String represents a string of bytes. It provides methods for parsing
|
||||
// fixed-length and length-prefixed values from it.
|
||||
@@ -81,6 +81,17 @@ func (s *String) ReadUint32(out *uint32) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadUint48 decodes a big-endian, 48-bit value into out and advances over it.
|
||||
// It reports whether the read was successful.
|
||||
func (s *String) ReadUint48(out *uint64) bool {
|
||||
v := s.read(6)
|
||||
if v == nil {
|
||||
return false
|
||||
}
|
||||
*out = uint64(v[0])<<40 | uint64(v[1])<<32 | uint64(v[2])<<24 | uint64(v[3])<<16 | uint64(v[4])<<8 | uint64(v[5])
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadUint64 decodes a big-endian, 64-bit value into out and advances over it.
|
||||
// It reports whether the read was successful.
|
||||
func (s *String) ReadUint64(out *uint64) bool {
|
||||
|
||||
+29
-85
@@ -5,15 +5,12 @@
|
||||
// Package curve25519 provides an implementation of the X25519 function, which
|
||||
// performs scalar multiplication on the elliptic curve known as Curve25519.
|
||||
// See RFC 7748.
|
||||
package curve25519 // import "golang.org/x/crypto/curve25519"
|
||||
//
|
||||
// This package is a wrapper for the X25519 implementation
|
||||
// in the crypto/ecdh package.
|
||||
package curve25519
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/crypto/curve25519/internal/field"
|
||||
)
|
||||
import "crypto/ecdh"
|
||||
|
||||
// ScalarMult sets dst to the product scalar * point.
|
||||
//
|
||||
@@ -21,55 +18,13 @@ import (
|
||||
// zeroes, irrespective of the scalar. Instead, use the X25519 function, which
|
||||
// will return an error.
|
||||
func ScalarMult(dst, scalar, point *[32]byte) {
|
||||
var e [32]byte
|
||||
|
||||
copy(e[:], scalar[:])
|
||||
e[0] &= 248
|
||||
e[31] &= 127
|
||||
e[31] |= 64
|
||||
|
||||
var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element
|
||||
x1.SetBytes(point[:])
|
||||
x2.One()
|
||||
x3.Set(&x1)
|
||||
z3.One()
|
||||
|
||||
swap := 0
|
||||
for pos := 254; pos >= 0; pos-- {
|
||||
b := e[pos/8] >> uint(pos&7)
|
||||
b &= 1
|
||||
swap ^= int(b)
|
||||
x2.Swap(&x3, swap)
|
||||
z2.Swap(&z3, swap)
|
||||
swap = int(b)
|
||||
|
||||
tmp0.Subtract(&x3, &z3)
|
||||
tmp1.Subtract(&x2, &z2)
|
||||
x2.Add(&x2, &z2)
|
||||
z2.Add(&x3, &z3)
|
||||
z3.Multiply(&tmp0, &x2)
|
||||
z2.Multiply(&z2, &tmp1)
|
||||
tmp0.Square(&tmp1)
|
||||
tmp1.Square(&x2)
|
||||
x3.Add(&z3, &z2)
|
||||
z2.Subtract(&z3, &z2)
|
||||
x2.Multiply(&tmp1, &tmp0)
|
||||
tmp1.Subtract(&tmp1, &tmp0)
|
||||
z2.Square(&z2)
|
||||
|
||||
z3.Mult32(&tmp1, 121666)
|
||||
x3.Square(&x3)
|
||||
tmp0.Add(&tmp0, &z3)
|
||||
z3.Multiply(&x1, &z2)
|
||||
z2.Multiply(&tmp1, &tmp0)
|
||||
if _, err := x25519(dst, scalar[:], point[:]); err != nil {
|
||||
// The only error condition for x25519 when the inputs are 32 bytes long
|
||||
// is if the output would have been the all-zero value.
|
||||
for i := range dst {
|
||||
dst[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
x2.Swap(&x3, swap)
|
||||
z2.Swap(&z3, swap)
|
||||
|
||||
z2.Invert(&z2)
|
||||
x2.Multiply(&x2, &z2)
|
||||
copy(dst[:], x2.Bytes())
|
||||
}
|
||||
|
||||
// ScalarBaseMult sets dst to the product scalar * base where base is the
|
||||
@@ -78,7 +33,12 @@ func ScalarMult(dst, scalar, point *[32]byte) {
|
||||
// It is recommended to use the X25519 function with Basepoint instead, as
|
||||
// copying into fixed size arrays can lead to unexpected bugs.
|
||||
func ScalarBaseMult(dst, scalar *[32]byte) {
|
||||
ScalarMult(dst, scalar, &basePoint)
|
||||
curve := ecdh.X25519()
|
||||
priv, err := curve.NewPrivateKey(scalar[:])
|
||||
if err != nil {
|
||||
panic("curve25519: internal error: scalarBaseMult was not 32 bytes")
|
||||
}
|
||||
copy(dst[:], priv.PublicKey().Bytes())
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -91,21 +51,10 @@ const (
|
||||
// Basepoint is the canonical Curve25519 generator.
|
||||
var Basepoint []byte
|
||||
|
||||
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
var basePoint = [32]byte{9}
|
||||
|
||||
func init() { Basepoint = basePoint[:] }
|
||||
|
||||
func checkBasepoint() {
|
||||
if subtle.ConstantTimeCompare(Basepoint, []byte{
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}) != 1 {
|
||||
panic("curve25519: global Basepoint value was modified")
|
||||
}
|
||||
}
|
||||
|
||||
// X25519 returns the result of the scalar multiplication (scalar * point),
|
||||
// according to RFC 7748, Section 5. scalar, point and the return value are
|
||||
// slices of 32 bytes.
|
||||
@@ -123,24 +72,19 @@ func X25519(scalar, point []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
|
||||
var in [32]byte
|
||||
if l := len(scalar); l != 32 {
|
||||
return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32")
|
||||
curve := ecdh.X25519()
|
||||
pub, err := curve.NewPublicKey(point)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if l := len(point); l != 32 {
|
||||
return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32")
|
||||
priv, err := curve.NewPrivateKey(scalar)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(in[:], scalar)
|
||||
if &point[0] == &Basepoint[0] {
|
||||
checkBasepoint()
|
||||
ScalarBaseMult(dst, &in)
|
||||
} else {
|
||||
var base, zero [32]byte
|
||||
copy(base[:], point)
|
||||
ScalarMult(dst, &in, &base)
|
||||
if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
|
||||
return nil, errors.New("bad input point: low order point")
|
||||
}
|
||||
out, err := priv.ECDH(pub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(dst[:], out)
|
||||
return dst[:], nil
|
||||
}
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package curve25519
|
||||
package curve25519_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/curve25519"
|
||||
)
|
||||
|
||||
const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a"
|
||||
@@ -19,7 +21,7 @@ func TestX25519Basepoint(t *testing.T) {
|
||||
|
||||
for i := 0; i < 200; i++ {
|
||||
var err error
|
||||
x, err = X25519(x, Basepoint)
|
||||
x, err = curve25519.X25519(x, curve25519.Basepoint)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -32,12 +34,12 @@ func TestX25519Basepoint(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLowOrderPoints(t *testing.T) {
|
||||
scalar := make([]byte, ScalarSize)
|
||||
scalar := make([]byte, curve25519.ScalarSize)
|
||||
if _, err := rand.Read(scalar); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, p := range lowOrderPoints {
|
||||
out, err := X25519(scalar, p)
|
||||
out, err := curve25519.X25519(scalar, p)
|
||||
if err == nil {
|
||||
t.Errorf("%d: expected error, got nil", i)
|
||||
}
|
||||
@@ -48,10 +50,10 @@ func TestLowOrderPoints(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTestVectors(t *testing.T) {
|
||||
t.Run("Legacy", func(t *testing.T) { testTestVectors(t, ScalarMult) })
|
||||
t.Run("Legacy", func(t *testing.T) { testTestVectors(t, curve25519.ScalarMult) })
|
||||
t.Run("X25519", func(t *testing.T) {
|
||||
testTestVectors(t, func(dst, scalar, point *[32]byte) {
|
||||
out, err := X25519(scalar[:], point[:])
|
||||
out, err := curve25519.X25519(scalar[:], point[:])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -88,10 +90,10 @@ func TestHighBitIgnored(t *testing.T) {
|
||||
var hi0, hi1 [32]byte
|
||||
|
||||
u[31] &= 0x7f
|
||||
ScalarMult(&hi0, &s, &u)
|
||||
curve25519.ScalarMult(&hi0, &s, &u)
|
||||
|
||||
u[31] |= 0x80
|
||||
ScalarMult(&hi1, &s, &u)
|
||||
curve25519.ScalarMult(&hi1, &s, &u)
|
||||
|
||||
if !bytes.Equal(hi0[:], hi1[:]) {
|
||||
t.Errorf("high bit of group point should not affect result")
|
||||
@@ -101,14 +103,14 @@ func TestHighBitIgnored(t *testing.T) {
|
||||
var benchmarkSink byte
|
||||
|
||||
func BenchmarkX25519Basepoint(b *testing.B) {
|
||||
scalar := make([]byte, ScalarSize)
|
||||
scalar := make([]byte, curve25519.ScalarSize)
|
||||
if _, err := rand.Read(scalar); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
out, err := X25519(scalar, Basepoint)
|
||||
out, err := curve25519.X25519(scalar, curve25519.Basepoint)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
@@ -117,11 +119,11 @@ func BenchmarkX25519Basepoint(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkX25519(b *testing.B) {
|
||||
scalar := make([]byte, ScalarSize)
|
||||
scalar := make([]byte, curve25519.ScalarSize)
|
||||
if _, err := rand.Read(scalar); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
point, err := X25519(scalar, Basepoint)
|
||||
point, err := curve25519.X25519(scalar, curve25519.Basepoint)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
@@ -131,7 +133,7 @@ func BenchmarkX25519(b *testing.B) {
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
out, err := X25519(scalar, point)
|
||||
out, err := curve25519.X25519(scalar, point)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
This package is kept in sync with crypto/ed25519/internal/edwards25519/field in
|
||||
the standard library.
|
||||
|
||||
If there are any changes in the standard library that need to be synced to this
|
||||
package, run sync.sh. It will not overwrite any local changes made since the
|
||||
previous sync, so it's ok to land changes in this package first, and then sync
|
||||
to the standard library later.
|
||||
@@ -1,298 +0,0 @@
|
||||
// Copyright (c) 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
. "github.com/mmcloughlin/avo/build"
|
||||
. "github.com/mmcloughlin/avo/gotypes"
|
||||
. "github.com/mmcloughlin/avo/operand"
|
||||
. "github.com/mmcloughlin/avo/reg"
|
||||
|
||||
// Ensure "go mod tidy" doesn't remove the golang.org/x/crypto module
|
||||
// dependency, which is necessary to access the field.Element type.
|
||||
_ "golang.org/x/crypto/curve25519"
|
||||
)
|
||||
|
||||
//go:generate go run . -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field
|
||||
|
||||
func main() {
|
||||
Package("golang.org/x/crypto/curve25519/internal/field")
|
||||
ConstraintExpr("amd64,gc,!purego")
|
||||
feMul()
|
||||
feSquare()
|
||||
Generate()
|
||||
}
|
||||
|
||||
type namedComponent struct {
|
||||
Component
|
||||
name string
|
||||
}
|
||||
|
||||
func (c namedComponent) String() string { return c.name }
|
||||
|
||||
type uint128 struct {
|
||||
name string
|
||||
hi, lo GPVirtual
|
||||
}
|
||||
|
||||
func (c uint128) String() string { return c.name }
|
||||
|
||||
func feSquare() {
|
||||
TEXT("feSquare", NOSPLIT, "func(out, a *Element)")
|
||||
Doc("feSquare sets out = a * a. It works like feSquareGeneric.")
|
||||
Pragma("noescape")
|
||||
|
||||
a := Dereference(Param("a"))
|
||||
l0 := namedComponent{a.Field("l0"), "l0"}
|
||||
l1 := namedComponent{a.Field("l1"), "l1"}
|
||||
l2 := namedComponent{a.Field("l2"), "l2"}
|
||||
l3 := namedComponent{a.Field("l3"), "l3"}
|
||||
l4 := namedComponent{a.Field("l4"), "l4"}
|
||||
|
||||
// r0 = l0×l0 + 19×2×(l1×l4 + l2×l3)
|
||||
r0 := uint128{"r0", GP64(), GP64()}
|
||||
mul64(r0, 1, l0, l0)
|
||||
addMul64(r0, 38, l1, l4)
|
||||
addMul64(r0, 38, l2, l3)
|
||||
|
||||
// r1 = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3
|
||||
r1 := uint128{"r1", GP64(), GP64()}
|
||||
mul64(r1, 2, l0, l1)
|
||||
addMul64(r1, 38, l2, l4)
|
||||
addMul64(r1, 19, l3, l3)
|
||||
|
||||
// r2 = = 2×l0×l2 + l1×l1 + 19×2×l3×l4
|
||||
r2 := uint128{"r2", GP64(), GP64()}
|
||||
mul64(r2, 2, l0, l2)
|
||||
addMul64(r2, 1, l1, l1)
|
||||
addMul64(r2, 38, l3, l4)
|
||||
|
||||
// r3 = = 2×l0×l3 + 2×l1×l2 + 19×l4×l4
|
||||
r3 := uint128{"r3", GP64(), GP64()}
|
||||
mul64(r3, 2, l0, l3)
|
||||
addMul64(r3, 2, l1, l2)
|
||||
addMul64(r3, 19, l4, l4)
|
||||
|
||||
// r4 = = 2×l0×l4 + 2×l1×l3 + l2×l2
|
||||
r4 := uint128{"r4", GP64(), GP64()}
|
||||
mul64(r4, 2, l0, l4)
|
||||
addMul64(r4, 2, l1, l3)
|
||||
addMul64(r4, 1, l2, l2)
|
||||
|
||||
Comment("First reduction chain")
|
||||
maskLow51Bits := GP64()
|
||||
MOVQ(Imm((1<<51)-1), maskLow51Bits)
|
||||
c0, r0lo := shiftRightBy51(&r0)
|
||||
c1, r1lo := shiftRightBy51(&r1)
|
||||
c2, r2lo := shiftRightBy51(&r2)
|
||||
c3, r3lo := shiftRightBy51(&r3)
|
||||
c4, r4lo := shiftRightBy51(&r4)
|
||||
maskAndAdd(r0lo, maskLow51Bits, c4, 19)
|
||||
maskAndAdd(r1lo, maskLow51Bits, c0, 1)
|
||||
maskAndAdd(r2lo, maskLow51Bits, c1, 1)
|
||||
maskAndAdd(r3lo, maskLow51Bits, c2, 1)
|
||||
maskAndAdd(r4lo, maskLow51Bits, c3, 1)
|
||||
|
||||
Comment("Second reduction chain (carryPropagate)")
|
||||
// c0 = r0 >> 51
|
||||
MOVQ(r0lo, c0)
|
||||
SHRQ(Imm(51), c0)
|
||||
// c1 = r1 >> 51
|
||||
MOVQ(r1lo, c1)
|
||||
SHRQ(Imm(51), c1)
|
||||
// c2 = r2 >> 51
|
||||
MOVQ(r2lo, c2)
|
||||
SHRQ(Imm(51), c2)
|
||||
// c3 = r3 >> 51
|
||||
MOVQ(r3lo, c3)
|
||||
SHRQ(Imm(51), c3)
|
||||
// c4 = r4 >> 51
|
||||
MOVQ(r4lo, c4)
|
||||
SHRQ(Imm(51), c4)
|
||||
maskAndAdd(r0lo, maskLow51Bits, c4, 19)
|
||||
maskAndAdd(r1lo, maskLow51Bits, c0, 1)
|
||||
maskAndAdd(r2lo, maskLow51Bits, c1, 1)
|
||||
maskAndAdd(r3lo, maskLow51Bits, c2, 1)
|
||||
maskAndAdd(r4lo, maskLow51Bits, c3, 1)
|
||||
|
||||
Comment("Store output")
|
||||
out := Dereference(Param("out"))
|
||||
Store(r0lo, out.Field("l0"))
|
||||
Store(r1lo, out.Field("l1"))
|
||||
Store(r2lo, out.Field("l2"))
|
||||
Store(r3lo, out.Field("l3"))
|
||||
Store(r4lo, out.Field("l4"))
|
||||
|
||||
RET()
|
||||
}
|
||||
|
||||
func feMul() {
|
||||
TEXT("feMul", NOSPLIT, "func(out, a, b *Element)")
|
||||
Doc("feMul sets out = a * b. It works like feMulGeneric.")
|
||||
Pragma("noescape")
|
||||
|
||||
a := Dereference(Param("a"))
|
||||
a0 := namedComponent{a.Field("l0"), "a0"}
|
||||
a1 := namedComponent{a.Field("l1"), "a1"}
|
||||
a2 := namedComponent{a.Field("l2"), "a2"}
|
||||
a3 := namedComponent{a.Field("l3"), "a3"}
|
||||
a4 := namedComponent{a.Field("l4"), "a4"}
|
||||
|
||||
b := Dereference(Param("b"))
|
||||
b0 := namedComponent{b.Field("l0"), "b0"}
|
||||
b1 := namedComponent{b.Field("l1"), "b1"}
|
||||
b2 := namedComponent{b.Field("l2"), "b2"}
|
||||
b3 := namedComponent{b.Field("l3"), "b3"}
|
||||
b4 := namedComponent{b.Field("l4"), "b4"}
|
||||
|
||||
// r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1)
|
||||
r0 := uint128{"r0", GP64(), GP64()}
|
||||
mul64(r0, 1, a0, b0)
|
||||
addMul64(r0, 19, a1, b4)
|
||||
addMul64(r0, 19, a2, b3)
|
||||
addMul64(r0, 19, a3, b2)
|
||||
addMul64(r0, 19, a4, b1)
|
||||
|
||||
// r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2)
|
||||
r1 := uint128{"r1", GP64(), GP64()}
|
||||
mul64(r1, 1, a0, b1)
|
||||
addMul64(r1, 1, a1, b0)
|
||||
addMul64(r1, 19, a2, b4)
|
||||
addMul64(r1, 19, a3, b3)
|
||||
addMul64(r1, 19, a4, b2)
|
||||
|
||||
// r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3)
|
||||
r2 := uint128{"r2", GP64(), GP64()}
|
||||
mul64(r2, 1, a0, b2)
|
||||
addMul64(r2, 1, a1, b1)
|
||||
addMul64(r2, 1, a2, b0)
|
||||
addMul64(r2, 19, a3, b4)
|
||||
addMul64(r2, 19, a4, b3)
|
||||
|
||||
// r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4
|
||||
r3 := uint128{"r3", GP64(), GP64()}
|
||||
mul64(r3, 1, a0, b3)
|
||||
addMul64(r3, 1, a1, b2)
|
||||
addMul64(r3, 1, a2, b1)
|
||||
addMul64(r3, 1, a3, b0)
|
||||
addMul64(r3, 19, a4, b4)
|
||||
|
||||
// r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0
|
||||
r4 := uint128{"r4", GP64(), GP64()}
|
||||
mul64(r4, 1, a0, b4)
|
||||
addMul64(r4, 1, a1, b3)
|
||||
addMul64(r4, 1, a2, b2)
|
||||
addMul64(r4, 1, a3, b1)
|
||||
addMul64(r4, 1, a4, b0)
|
||||
|
||||
Comment("First reduction chain")
|
||||
maskLow51Bits := GP64()
|
||||
MOVQ(Imm((1<<51)-1), maskLow51Bits)
|
||||
c0, r0lo := shiftRightBy51(&r0)
|
||||
c1, r1lo := shiftRightBy51(&r1)
|
||||
c2, r2lo := shiftRightBy51(&r2)
|
||||
c3, r3lo := shiftRightBy51(&r3)
|
||||
c4, r4lo := shiftRightBy51(&r4)
|
||||
maskAndAdd(r0lo, maskLow51Bits, c4, 19)
|
||||
maskAndAdd(r1lo, maskLow51Bits, c0, 1)
|
||||
maskAndAdd(r2lo, maskLow51Bits, c1, 1)
|
||||
maskAndAdd(r3lo, maskLow51Bits, c2, 1)
|
||||
maskAndAdd(r4lo, maskLow51Bits, c3, 1)
|
||||
|
||||
Comment("Second reduction chain (carryPropagate)")
|
||||
// c0 = r0 >> 51
|
||||
MOVQ(r0lo, c0)
|
||||
SHRQ(Imm(51), c0)
|
||||
// c1 = r1 >> 51
|
||||
MOVQ(r1lo, c1)
|
||||
SHRQ(Imm(51), c1)
|
||||
// c2 = r2 >> 51
|
||||
MOVQ(r2lo, c2)
|
||||
SHRQ(Imm(51), c2)
|
||||
// c3 = r3 >> 51
|
||||
MOVQ(r3lo, c3)
|
||||
SHRQ(Imm(51), c3)
|
||||
// c4 = r4 >> 51
|
||||
MOVQ(r4lo, c4)
|
||||
SHRQ(Imm(51), c4)
|
||||
maskAndAdd(r0lo, maskLow51Bits, c4, 19)
|
||||
maskAndAdd(r1lo, maskLow51Bits, c0, 1)
|
||||
maskAndAdd(r2lo, maskLow51Bits, c1, 1)
|
||||
maskAndAdd(r3lo, maskLow51Bits, c2, 1)
|
||||
maskAndAdd(r4lo, maskLow51Bits, c3, 1)
|
||||
|
||||
Comment("Store output")
|
||||
out := Dereference(Param("out"))
|
||||
Store(r0lo, out.Field("l0"))
|
||||
Store(r1lo, out.Field("l1"))
|
||||
Store(r2lo, out.Field("l2"))
|
||||
Store(r3lo, out.Field("l3"))
|
||||
Store(r4lo, out.Field("l4"))
|
||||
|
||||
RET()
|
||||
}
|
||||
|
||||
// mul64 sets r to i * aX * bX.
|
||||
func mul64(r uint128, i int, aX, bX namedComponent) {
|
||||
switch i {
|
||||
case 1:
|
||||
Comment(fmt.Sprintf("%s = %s×%s", r, aX, bX))
|
||||
Load(aX, RAX)
|
||||
case 2:
|
||||
Comment(fmt.Sprintf("%s = 2×%s×%s", r, aX, bX))
|
||||
Load(aX, RAX)
|
||||
SHLQ(Imm(1), RAX)
|
||||
default:
|
||||
panic("unsupported i value")
|
||||
}
|
||||
MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX
|
||||
MOVQ(RAX, r.lo)
|
||||
MOVQ(RDX, r.hi)
|
||||
}
|
||||
|
||||
// addMul64 sets r to r + i * aX * bX.
|
||||
func addMul64(r uint128, i uint64, aX, bX namedComponent) {
|
||||
switch i {
|
||||
case 1:
|
||||
Comment(fmt.Sprintf("%s += %s×%s", r, aX, bX))
|
||||
Load(aX, RAX)
|
||||
default:
|
||||
Comment(fmt.Sprintf("%s += %d×%s×%s", r, i, aX, bX))
|
||||
IMUL3Q(Imm(i), Load(aX, GP64()), RAX)
|
||||
}
|
||||
MULQ(mustAddr(bX)) // RDX, RAX = RAX * bX
|
||||
ADDQ(RAX, r.lo)
|
||||
ADCQ(RDX, r.hi)
|
||||
}
|
||||
|
||||
// shiftRightBy51 returns r >> 51 and r.lo.
|
||||
//
|
||||
// After this function is called, the uint128 may not be used anymore.
|
||||
func shiftRightBy51(r *uint128) (out, lo GPVirtual) {
|
||||
out = r.hi
|
||||
lo = r.lo
|
||||
SHLQ(Imm(64-51), r.lo, r.hi)
|
||||
r.lo, r.hi = nil, nil // make sure the uint128 is unusable
|
||||
return
|
||||
}
|
||||
|
||||
// maskAndAdd sets r = r&mask + c*i.
|
||||
func maskAndAdd(r, mask, c GPVirtual, i uint64) {
|
||||
ANDQ(mask, r)
|
||||
if i != 1 {
|
||||
IMUL3Q(Imm(i), c, c)
|
||||
}
|
||||
ADDQ(c, r)
|
||||
}
|
||||
|
||||
func mustAddr(c Component) Op {
|
||||
b, err := c.Resolve()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return b.Addr
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
module asm
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/mmcloughlin/avo v0.4.0
|
||||
golang.org/x/crypto v0.0.0
|
||||
)
|
||||
|
||||
replace golang.org/x/crypto v0.0.0 => ../../../..
|
||||
@@ -1,34 +0,0 @@
|
||||
github.com/mmcloughlin/avo v0.4.0 h1:jeHDRktVD+578ULxWpQHkilor6pkdLF7u7EiTzDbfcU=
|
||||
github.com/mmcloughlin/avo v0.4.0/go.mod h1:RW9BfYA3TgO9uCdNrKU2h6J8cPD8ZLznvfgHAeszb1s=
|
||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021 h1:giLT+HuUP/gXYrG2Plg9WTjj4qhfgaW424ZIFog3rlk=
|
||||
golang.org/x/sys v0.0.0-20211030160813-b3129d9d1021/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
|
||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
@@ -1,416 +0,0 @@
|
||||
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package field implements fast arithmetic modulo 2^255-19.
|
||||
package field
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"encoding/binary"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// Element represents an element of the field GF(2^255-19). Note that this
|
||||
// is not a cryptographically secure group, and should only be used to interact
|
||||
// with edwards25519.Point coordinates.
|
||||
//
|
||||
// This type works similarly to math/big.Int, and all arguments and receivers
|
||||
// are allowed to alias.
|
||||
//
|
||||
// The zero value is a valid zero element.
|
||||
type Element struct {
|
||||
// An element t represents the integer
|
||||
// t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204
|
||||
//
|
||||
// Between operations, all limbs are expected to be lower than 2^52.
|
||||
l0 uint64
|
||||
l1 uint64
|
||||
l2 uint64
|
||||
l3 uint64
|
||||
l4 uint64
|
||||
}
|
||||
|
||||
const maskLow51Bits uint64 = (1 << 51) - 1
|
||||
|
||||
var feZero = &Element{0, 0, 0, 0, 0}
|
||||
|
||||
// Zero sets v = 0, and returns v.
|
||||
func (v *Element) Zero() *Element {
|
||||
*v = *feZero
|
||||
return v
|
||||
}
|
||||
|
||||
var feOne = &Element{1, 0, 0, 0, 0}
|
||||
|
||||
// One sets v = 1, and returns v.
|
||||
func (v *Element) One() *Element {
|
||||
*v = *feOne
|
||||
return v
|
||||
}
|
||||
|
||||
// reduce reduces v modulo 2^255 - 19 and returns it.
|
||||
func (v *Element) reduce() *Element {
|
||||
v.carryPropagate()
|
||||
|
||||
// After the light reduction we now have a field element representation
|
||||
// v < 2^255 + 2^13 * 19, but need v < 2^255 - 19.
|
||||
|
||||
// If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1,
|
||||
// generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise.
|
||||
c := (v.l0 + 19) >> 51
|
||||
c = (v.l1 + c) >> 51
|
||||
c = (v.l2 + c) >> 51
|
||||
c = (v.l3 + c) >> 51
|
||||
c = (v.l4 + c) >> 51
|
||||
|
||||
// If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's
|
||||
// effectively applying the reduction identity to the carry.
|
||||
v.l0 += 19 * c
|
||||
|
||||
v.l1 += v.l0 >> 51
|
||||
v.l0 = v.l0 & maskLow51Bits
|
||||
v.l2 += v.l1 >> 51
|
||||
v.l1 = v.l1 & maskLow51Bits
|
||||
v.l3 += v.l2 >> 51
|
||||
v.l2 = v.l2 & maskLow51Bits
|
||||
v.l4 += v.l3 >> 51
|
||||
v.l3 = v.l3 & maskLow51Bits
|
||||
// no additional carry
|
||||
v.l4 = v.l4 & maskLow51Bits
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// Add sets v = a + b, and returns v.
|
||||
func (v *Element) Add(a, b *Element) *Element {
|
||||
v.l0 = a.l0 + b.l0
|
||||
v.l1 = a.l1 + b.l1
|
||||
v.l2 = a.l2 + b.l2
|
||||
v.l3 = a.l3 + b.l3
|
||||
v.l4 = a.l4 + b.l4
|
||||
// Using the generic implementation here is actually faster than the
|
||||
// assembly. Probably because the body of this function is so simple that
|
||||
// the compiler can figure out better optimizations by inlining the carry
|
||||
// propagation. TODO
|
||||
return v.carryPropagateGeneric()
|
||||
}
|
||||
|
||||
// Subtract sets v = a - b, and returns v.
|
||||
func (v *Element) Subtract(a, b *Element) *Element {
|
||||
// We first add 2 * p, to guarantee the subtraction won't underflow, and
|
||||
// then subtract b (which can be up to 2^255 + 2^13 * 19).
|
||||
v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0
|
||||
v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1
|
||||
v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2
|
||||
v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3
|
||||
v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4
|
||||
return v.carryPropagate()
|
||||
}
|
||||
|
||||
// Negate sets v = -a, and returns v.
|
||||
func (v *Element) Negate(a *Element) *Element {
|
||||
return v.Subtract(feZero, a)
|
||||
}
|
||||
|
||||
// Invert sets v = 1/z mod p, and returns v.
|
||||
//
|
||||
// If z == 0, Invert returns v = 0.
|
||||
func (v *Element) Invert(z *Element) *Element {
|
||||
// Inversion is implemented as exponentiation with exponent p − 2. It uses the
|
||||
// same sequence of 255 squarings and 11 multiplications as [Curve25519].
|
||||
var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element
|
||||
|
||||
z2.Square(z) // 2
|
||||
t.Square(&z2) // 4
|
||||
t.Square(&t) // 8
|
||||
z9.Multiply(&t, z) // 9
|
||||
z11.Multiply(&z9, &z2) // 11
|
||||
t.Square(&z11) // 22
|
||||
z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0
|
||||
|
||||
t.Square(&z2_5_0) // 2^6 - 2^1
|
||||
for i := 0; i < 4; i++ {
|
||||
t.Square(&t) // 2^10 - 2^5
|
||||
}
|
||||
z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0
|
||||
|
||||
t.Square(&z2_10_0) // 2^11 - 2^1
|
||||
for i := 0; i < 9; i++ {
|
||||
t.Square(&t) // 2^20 - 2^10
|
||||
}
|
||||
z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0
|
||||
|
||||
t.Square(&z2_20_0) // 2^21 - 2^1
|
||||
for i := 0; i < 19; i++ {
|
||||
t.Square(&t) // 2^40 - 2^20
|
||||
}
|
||||
t.Multiply(&t, &z2_20_0) // 2^40 - 2^0
|
||||
|
||||
t.Square(&t) // 2^41 - 2^1
|
||||
for i := 0; i < 9; i++ {
|
||||
t.Square(&t) // 2^50 - 2^10
|
||||
}
|
||||
z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0
|
||||
|
||||
t.Square(&z2_50_0) // 2^51 - 2^1
|
||||
for i := 0; i < 49; i++ {
|
||||
t.Square(&t) // 2^100 - 2^50
|
||||
}
|
||||
z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0
|
||||
|
||||
t.Square(&z2_100_0) // 2^101 - 2^1
|
||||
for i := 0; i < 99; i++ {
|
||||
t.Square(&t) // 2^200 - 2^100
|
||||
}
|
||||
t.Multiply(&t, &z2_100_0) // 2^200 - 2^0
|
||||
|
||||
t.Square(&t) // 2^201 - 2^1
|
||||
for i := 0; i < 49; i++ {
|
||||
t.Square(&t) // 2^250 - 2^50
|
||||
}
|
||||
t.Multiply(&t, &z2_50_0) // 2^250 - 2^0
|
||||
|
||||
t.Square(&t) // 2^251 - 2^1
|
||||
t.Square(&t) // 2^252 - 2^2
|
||||
t.Square(&t) // 2^253 - 2^3
|
||||
t.Square(&t) // 2^254 - 2^4
|
||||
t.Square(&t) // 2^255 - 2^5
|
||||
|
||||
return v.Multiply(&t, &z11) // 2^255 - 21
|
||||
}
|
||||
|
||||
// Set sets v = a, and returns v.
|
||||
func (v *Element) Set(a *Element) *Element {
|
||||
*v = *a
|
||||
return v
|
||||
}
|
||||
|
||||
// SetBytes sets v to x, which must be a 32-byte little-endian encoding.
|
||||
//
|
||||
// Consistent with RFC 7748, the most significant bit (the high bit of the
|
||||
// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1)
|
||||
// are accepted. Note that this is laxer than specified by RFC 8032.
|
||||
func (v *Element) SetBytes(x []byte) *Element {
|
||||
if len(x) != 32 {
|
||||
panic("edwards25519: invalid field element input size")
|
||||
}
|
||||
|
||||
// Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51).
|
||||
v.l0 = binary.LittleEndian.Uint64(x[0:8])
|
||||
v.l0 &= maskLow51Bits
|
||||
// Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51).
|
||||
v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3
|
||||
v.l1 &= maskLow51Bits
|
||||
// Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51).
|
||||
v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6
|
||||
v.l2 &= maskLow51Bits
|
||||
// Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51).
|
||||
v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1
|
||||
v.l3 &= maskLow51Bits
|
||||
// Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51).
|
||||
// Note: not bytes 25:33, shift 4, to avoid overread.
|
||||
v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12
|
||||
v.l4 &= maskLow51Bits
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// Bytes returns the canonical 32-byte little-endian encoding of v.
|
||||
func (v *Element) Bytes() []byte {
|
||||
// This function is outlined to make the allocations inline in the caller
|
||||
// rather than happen on the heap.
|
||||
var out [32]byte
|
||||
return v.bytes(&out)
|
||||
}
|
||||
|
||||
func (v *Element) bytes(out *[32]byte) []byte {
|
||||
t := *v
|
||||
t.reduce()
|
||||
|
||||
var buf [8]byte
|
||||
for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} {
|
||||
bitsOffset := i * 51
|
||||
binary.LittleEndian.PutUint64(buf[:], l<<uint(bitsOffset%8))
|
||||
for i, bb := range buf {
|
||||
off := bitsOffset/8 + i
|
||||
if off >= len(out) {
|
||||
break
|
||||
}
|
||||
out[off] |= bb
|
||||
}
|
||||
}
|
||||
|
||||
return out[:]
|
||||
}
|
||||
|
||||
// Equal returns 1 if v and u are equal, and 0 otherwise.
|
||||
func (v *Element) Equal(u *Element) int {
|
||||
sa, sv := u.Bytes(), v.Bytes()
|
||||
return subtle.ConstantTimeCompare(sa, sv)
|
||||
}
|
||||
|
||||
// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise.
|
||||
func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) }
|
||||
|
||||
// Select sets v to a if cond == 1, and to b if cond == 0.
|
||||
func (v *Element) Select(a, b *Element, cond int) *Element {
|
||||
m := mask64Bits(cond)
|
||||
v.l0 = (m & a.l0) | (^m & b.l0)
|
||||
v.l1 = (m & a.l1) | (^m & b.l1)
|
||||
v.l2 = (m & a.l2) | (^m & b.l2)
|
||||
v.l3 = (m & a.l3) | (^m & b.l3)
|
||||
v.l4 = (m & a.l4) | (^m & b.l4)
|
||||
return v
|
||||
}
|
||||
|
||||
// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v.
|
||||
func (v *Element) Swap(u *Element, cond int) {
|
||||
m := mask64Bits(cond)
|
||||
t := m & (v.l0 ^ u.l0)
|
||||
v.l0 ^= t
|
||||
u.l0 ^= t
|
||||
t = m & (v.l1 ^ u.l1)
|
||||
v.l1 ^= t
|
||||
u.l1 ^= t
|
||||
t = m & (v.l2 ^ u.l2)
|
||||
v.l2 ^= t
|
||||
u.l2 ^= t
|
||||
t = m & (v.l3 ^ u.l3)
|
||||
v.l3 ^= t
|
||||
u.l3 ^= t
|
||||
t = m & (v.l4 ^ u.l4)
|
||||
v.l4 ^= t
|
||||
u.l4 ^= t
|
||||
}
|
||||
|
||||
// IsNegative returns 1 if v is negative, and 0 otherwise.
|
||||
func (v *Element) IsNegative() int {
|
||||
return int(v.Bytes()[0] & 1)
|
||||
}
|
||||
|
||||
// Absolute sets v to |u|, and returns v.
|
||||
func (v *Element) Absolute(u *Element) *Element {
|
||||
return v.Select(new(Element).Negate(u), u, u.IsNegative())
|
||||
}
|
||||
|
||||
// Multiply sets v = x * y, and returns v.
|
||||
func (v *Element) Multiply(x, y *Element) *Element {
|
||||
feMul(v, x, y)
|
||||
return v
|
||||
}
|
||||
|
||||
// Square sets v = x * x, and returns v.
|
||||
func (v *Element) Square(x *Element) *Element {
|
||||
feSquare(v, x)
|
||||
return v
|
||||
}
|
||||
|
||||
// Mult32 sets v = x * y, and returns v.
|
||||
func (v *Element) Mult32(x *Element, y uint32) *Element {
|
||||
x0lo, x0hi := mul51(x.l0, y)
|
||||
x1lo, x1hi := mul51(x.l1, y)
|
||||
x2lo, x2hi := mul51(x.l2, y)
|
||||
x3lo, x3hi := mul51(x.l3, y)
|
||||
x4lo, x4hi := mul51(x.l4, y)
|
||||
v.l0 = x0lo + 19*x4hi // carried over per the reduction identity
|
||||
v.l1 = x1lo + x0hi
|
||||
v.l2 = x2lo + x1hi
|
||||
v.l3 = x3lo + x2hi
|
||||
v.l4 = x4lo + x3hi
|
||||
// The hi portions are going to be only 32 bits, plus any previous excess,
|
||||
// so we can skip the carry propagation.
|
||||
return v
|
||||
}
|
||||
|
||||
// mul51 returns lo + hi * 2⁵¹ = a * b.
|
||||
func mul51(a uint64, b uint32) (lo uint64, hi uint64) {
|
||||
mh, ml := bits.Mul64(a, uint64(b))
|
||||
lo = ml & maskLow51Bits
|
||||
hi = (mh << 13) | (ml >> 51)
|
||||
return
|
||||
}
|
||||
|
||||
// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3.
|
||||
func (v *Element) Pow22523(x *Element) *Element {
|
||||
var t0, t1, t2 Element
|
||||
|
||||
t0.Square(x) // x^2
|
||||
t1.Square(&t0) // x^4
|
||||
t1.Square(&t1) // x^8
|
||||
t1.Multiply(x, &t1) // x^9
|
||||
t0.Multiply(&t0, &t1) // x^11
|
||||
t0.Square(&t0) // x^22
|
||||
t0.Multiply(&t1, &t0) // x^31
|
||||
t1.Square(&t0) // x^62
|
||||
for i := 1; i < 5; i++ { // x^992
|
||||
t1.Square(&t1)
|
||||
}
|
||||
t0.Multiply(&t1, &t0) // x^1023 -> 1023 = 2^10 - 1
|
||||
t1.Square(&t0) // 2^11 - 2
|
||||
for i := 1; i < 10; i++ { // 2^20 - 2^10
|
||||
t1.Square(&t1)
|
||||
}
|
||||
t1.Multiply(&t1, &t0) // 2^20 - 1
|
||||
t2.Square(&t1) // 2^21 - 2
|
||||
for i := 1; i < 20; i++ { // 2^40 - 2^20
|
||||
t2.Square(&t2)
|
||||
}
|
||||
t1.Multiply(&t2, &t1) // 2^40 - 1
|
||||
t1.Square(&t1) // 2^41 - 2
|
||||
for i := 1; i < 10; i++ { // 2^50 - 2^10
|
||||
t1.Square(&t1)
|
||||
}
|
||||
t0.Multiply(&t1, &t0) // 2^50 - 1
|
||||
t1.Square(&t0) // 2^51 - 2
|
||||
for i := 1; i < 50; i++ { // 2^100 - 2^50
|
||||
t1.Square(&t1)
|
||||
}
|
||||
t1.Multiply(&t1, &t0) // 2^100 - 1
|
||||
t2.Square(&t1) // 2^101 - 2
|
||||
for i := 1; i < 100; i++ { // 2^200 - 2^100
|
||||
t2.Square(&t2)
|
||||
}
|
||||
t1.Multiply(&t2, &t1) // 2^200 - 1
|
||||
t1.Square(&t1) // 2^201 - 2
|
||||
for i := 1; i < 50; i++ { // 2^250 - 2^50
|
||||
t1.Square(&t1)
|
||||
}
|
||||
t0.Multiply(&t1, &t0) // 2^250 - 1
|
||||
t0.Square(&t0) // 2^251 - 2
|
||||
t0.Square(&t0) // 2^252 - 4
|
||||
return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3)
|
||||
}
|
||||
|
||||
// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion.
|
||||
var sqrtM1 = &Element{1718705420411056, 234908883556509,
|
||||
2233514472574048, 2117202627021982, 765476049583133}
|
||||
|
||||
// SqrtRatio sets r to the non-negative square root of the ratio of u and v.
|
||||
//
|
||||
// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio
|
||||
// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00,
|
||||
// and returns r and 0.
|
||||
func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) {
|
||||
var a, b Element
|
||||
|
||||
// r = (u * v3) * (u * v7)^((p-5)/8)
|
||||
v2 := a.Square(v)
|
||||
uv3 := b.Multiply(u, b.Multiply(v2, v))
|
||||
uv7 := a.Multiply(uv3, a.Square(v2))
|
||||
r.Multiply(uv3, r.Pow22523(uv7))
|
||||
|
||||
check := a.Multiply(v, a.Square(r)) // check = v * r^2
|
||||
|
||||
uNeg := b.Negate(u)
|
||||
correctSignSqrt := check.Equal(u)
|
||||
flippedSignSqrt := check.Equal(uNeg)
|
||||
flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1))
|
||||
|
||||
rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r
|
||||
// r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r)
|
||||
r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI)
|
||||
|
||||
r.Absolute(r) // Choose the nonnegative square root.
|
||||
return r, correctSignSqrt | flippedSignSqrt
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package field
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"testing/quick"
|
||||
)
|
||||
|
||||
func checkAliasingOneArg(f func(v, x *Element) *Element) func(v, x Element) bool {
|
||||
return func(v, x Element) bool {
|
||||
x1, v1 := x, x
|
||||
|
||||
// Calculate a reference f(x) without aliasing.
|
||||
if out := f(&v, &x); out != &v && isInBounds(out) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Test aliasing the argument and the receiver.
|
||||
if out := f(&v1, &v1); out != &v1 || v1 != v {
|
||||
return false
|
||||
}
|
||||
|
||||
// Ensure the arguments was not modified.
|
||||
return x == x1
|
||||
}
|
||||
}
|
||||
|
||||
func checkAliasingTwoArgs(f func(v, x, y *Element) *Element) func(v, x, y Element) bool {
|
||||
return func(v, x, y Element) bool {
|
||||
x1, y1, v1 := x, y, Element{}
|
||||
|
||||
// Calculate a reference f(x, y) without aliasing.
|
||||
if out := f(&v, &x, &y); out != &v && isInBounds(out) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Test aliasing the first argument and the receiver.
|
||||
v1 = x
|
||||
if out := f(&v1, &v1, &y); out != &v1 || v1 != v {
|
||||
return false
|
||||
}
|
||||
// Test aliasing the second argument and the receiver.
|
||||
v1 = y
|
||||
if out := f(&v1, &x, &v1); out != &v1 || v1 != v {
|
||||
return false
|
||||
}
|
||||
|
||||
// Calculate a reference f(x, x) without aliasing.
|
||||
if out := f(&v, &x, &x); out != &v {
|
||||
return false
|
||||
}
|
||||
|
||||
// Test aliasing the first argument and the receiver.
|
||||
v1 = x
|
||||
if out := f(&v1, &v1, &x); out != &v1 || v1 != v {
|
||||
return false
|
||||
}
|
||||
// Test aliasing the second argument and the receiver.
|
||||
v1 = x
|
||||
if out := f(&v1, &x, &v1); out != &v1 || v1 != v {
|
||||
return false
|
||||
}
|
||||
// Test aliasing both arguments and the receiver.
|
||||
v1 = x
|
||||
if out := f(&v1, &v1, &v1); out != &v1 || v1 != v {
|
||||
return false
|
||||
}
|
||||
|
||||
// Ensure the arguments were not modified.
|
||||
return x == x1 && y == y1
|
||||
}
|
||||
}
|
||||
|
||||
// TestAliasing checks that receivers and arguments can alias each other without
|
||||
// leading to incorrect results. That is, it ensures that it's safe to write
|
||||
//
|
||||
// v.Invert(v)
|
||||
//
|
||||
// or
|
||||
//
|
||||
// v.Add(v, v)
|
||||
//
|
||||
// without any of the inputs getting clobbered by the output being written.
|
||||
func TestAliasing(t *testing.T) {
|
||||
type target struct {
|
||||
name string
|
||||
oneArgF func(v, x *Element) *Element
|
||||
twoArgsF func(v, x, y *Element) *Element
|
||||
}
|
||||
for _, tt := range []target{
|
||||
{name: "Absolute", oneArgF: (*Element).Absolute},
|
||||
{name: "Invert", oneArgF: (*Element).Invert},
|
||||
{name: "Negate", oneArgF: (*Element).Negate},
|
||||
{name: "Set", oneArgF: (*Element).Set},
|
||||
{name: "Square", oneArgF: (*Element).Square},
|
||||
{name: "Multiply", twoArgsF: (*Element).Multiply},
|
||||
{name: "Add", twoArgsF: (*Element).Add},
|
||||
{name: "Subtract", twoArgsF: (*Element).Subtract},
|
||||
{
|
||||
name: "Select0",
|
||||
twoArgsF: func(v, x, y *Element) *Element {
|
||||
return (*Element).Select(v, x, y, 0)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Select1",
|
||||
twoArgsF: func(v, x, y *Element) *Element {
|
||||
return (*Element).Select(v, x, y, 1)
|
||||
},
|
||||
},
|
||||
} {
|
||||
var err error
|
||||
switch {
|
||||
case tt.oneArgF != nil:
|
||||
err = quick.Check(checkAliasingOneArg(tt.oneArgF), &quick.Config{MaxCountScale: 1 << 8})
|
||||
case tt.twoArgsF != nil:
|
||||
err = quick.Check(checkAliasingTwoArgs(tt.twoArgsF), &quick.Config{MaxCountScale: 1 << 8})
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("%v: %v", tt.name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.
|
||||
|
||||
//go:build amd64 && gc && !purego
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
package field
|
||||
|
||||
// feMul sets out = a * b. It works like feMulGeneric.
|
||||
//
|
||||
//go:noescape
|
||||
func feMul(out *Element, a *Element, b *Element)
|
||||
|
||||
// feSquare sets out = a * a. It works like feSquareGeneric.
|
||||
//
|
||||
//go:noescape
|
||||
func feSquare(out *Element, a *Element)
|
||||
@@ -1,379 +0,0 @@
|
||||
// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.
|
||||
|
||||
//go:build amd64 && gc && !purego
|
||||
// +build amd64,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// func feMul(out *Element, a *Element, b *Element)
|
||||
TEXT ·feMul(SB), NOSPLIT, $0-24
|
||||
MOVQ a+8(FP), CX
|
||||
MOVQ b+16(FP), BX
|
||||
|
||||
// r0 = a0×b0
|
||||
MOVQ (CX), AX
|
||||
MULQ (BX)
|
||||
MOVQ AX, DI
|
||||
MOVQ DX, SI
|
||||
|
||||
// r0 += 19×a1×b4
|
||||
MOVQ 8(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 32(BX)
|
||||
ADDQ AX, DI
|
||||
ADCQ DX, SI
|
||||
|
||||
// r0 += 19×a2×b3
|
||||
MOVQ 16(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 24(BX)
|
||||
ADDQ AX, DI
|
||||
ADCQ DX, SI
|
||||
|
||||
// r0 += 19×a3×b2
|
||||
MOVQ 24(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 16(BX)
|
||||
ADDQ AX, DI
|
||||
ADCQ DX, SI
|
||||
|
||||
// r0 += 19×a4×b1
|
||||
MOVQ 32(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 8(BX)
|
||||
ADDQ AX, DI
|
||||
ADCQ DX, SI
|
||||
|
||||
// r1 = a0×b1
|
||||
MOVQ (CX), AX
|
||||
MULQ 8(BX)
|
||||
MOVQ AX, R9
|
||||
MOVQ DX, R8
|
||||
|
||||
// r1 += a1×b0
|
||||
MOVQ 8(CX), AX
|
||||
MULQ (BX)
|
||||
ADDQ AX, R9
|
||||
ADCQ DX, R8
|
||||
|
||||
// r1 += 19×a2×b4
|
||||
MOVQ 16(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 32(BX)
|
||||
ADDQ AX, R9
|
||||
ADCQ DX, R8
|
||||
|
||||
// r1 += 19×a3×b3
|
||||
MOVQ 24(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 24(BX)
|
||||
ADDQ AX, R9
|
||||
ADCQ DX, R8
|
||||
|
||||
// r1 += 19×a4×b2
|
||||
MOVQ 32(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 16(BX)
|
||||
ADDQ AX, R9
|
||||
ADCQ DX, R8
|
||||
|
||||
// r2 = a0×b2
|
||||
MOVQ (CX), AX
|
||||
MULQ 16(BX)
|
||||
MOVQ AX, R11
|
||||
MOVQ DX, R10
|
||||
|
||||
// r2 += a1×b1
|
||||
MOVQ 8(CX), AX
|
||||
MULQ 8(BX)
|
||||
ADDQ AX, R11
|
||||
ADCQ DX, R10
|
||||
|
||||
// r2 += a2×b0
|
||||
MOVQ 16(CX), AX
|
||||
MULQ (BX)
|
||||
ADDQ AX, R11
|
||||
ADCQ DX, R10
|
||||
|
||||
// r2 += 19×a3×b4
|
||||
MOVQ 24(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 32(BX)
|
||||
ADDQ AX, R11
|
||||
ADCQ DX, R10
|
||||
|
||||
// r2 += 19×a4×b3
|
||||
MOVQ 32(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 24(BX)
|
||||
ADDQ AX, R11
|
||||
ADCQ DX, R10
|
||||
|
||||
// r3 = a0×b3
|
||||
MOVQ (CX), AX
|
||||
MULQ 24(BX)
|
||||
MOVQ AX, R13
|
||||
MOVQ DX, R12
|
||||
|
||||
// r3 += a1×b2
|
||||
MOVQ 8(CX), AX
|
||||
MULQ 16(BX)
|
||||
ADDQ AX, R13
|
||||
ADCQ DX, R12
|
||||
|
||||
// r3 += a2×b1
|
||||
MOVQ 16(CX), AX
|
||||
MULQ 8(BX)
|
||||
ADDQ AX, R13
|
||||
ADCQ DX, R12
|
||||
|
||||
// r3 += a3×b0
|
||||
MOVQ 24(CX), AX
|
||||
MULQ (BX)
|
||||
ADDQ AX, R13
|
||||
ADCQ DX, R12
|
||||
|
||||
// r3 += 19×a4×b4
|
||||
MOVQ 32(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 32(BX)
|
||||
ADDQ AX, R13
|
||||
ADCQ DX, R12
|
||||
|
||||
// r4 = a0×b4
|
||||
MOVQ (CX), AX
|
||||
MULQ 32(BX)
|
||||
MOVQ AX, R15
|
||||
MOVQ DX, R14
|
||||
|
||||
// r4 += a1×b3
|
||||
MOVQ 8(CX), AX
|
||||
MULQ 24(BX)
|
||||
ADDQ AX, R15
|
||||
ADCQ DX, R14
|
||||
|
||||
// r4 += a2×b2
|
||||
MOVQ 16(CX), AX
|
||||
MULQ 16(BX)
|
||||
ADDQ AX, R15
|
||||
ADCQ DX, R14
|
||||
|
||||
// r4 += a3×b1
|
||||
MOVQ 24(CX), AX
|
||||
MULQ 8(BX)
|
||||
ADDQ AX, R15
|
||||
ADCQ DX, R14
|
||||
|
||||
// r4 += a4×b0
|
||||
MOVQ 32(CX), AX
|
||||
MULQ (BX)
|
||||
ADDQ AX, R15
|
||||
ADCQ DX, R14
|
||||
|
||||
// First reduction chain
|
||||
MOVQ $0x0007ffffffffffff, AX
|
||||
SHLQ $0x0d, DI, SI
|
||||
SHLQ $0x0d, R9, R8
|
||||
SHLQ $0x0d, R11, R10
|
||||
SHLQ $0x0d, R13, R12
|
||||
SHLQ $0x0d, R15, R14
|
||||
ANDQ AX, DI
|
||||
IMUL3Q $0x13, R14, R14
|
||||
ADDQ R14, DI
|
||||
ANDQ AX, R9
|
||||
ADDQ SI, R9
|
||||
ANDQ AX, R11
|
||||
ADDQ R8, R11
|
||||
ANDQ AX, R13
|
||||
ADDQ R10, R13
|
||||
ANDQ AX, R15
|
||||
ADDQ R12, R15
|
||||
|
||||
// Second reduction chain (carryPropagate)
|
||||
MOVQ DI, SI
|
||||
SHRQ $0x33, SI
|
||||
MOVQ R9, R8
|
||||
SHRQ $0x33, R8
|
||||
MOVQ R11, R10
|
||||
SHRQ $0x33, R10
|
||||
MOVQ R13, R12
|
||||
SHRQ $0x33, R12
|
||||
MOVQ R15, R14
|
||||
SHRQ $0x33, R14
|
||||
ANDQ AX, DI
|
||||
IMUL3Q $0x13, R14, R14
|
||||
ADDQ R14, DI
|
||||
ANDQ AX, R9
|
||||
ADDQ SI, R9
|
||||
ANDQ AX, R11
|
||||
ADDQ R8, R11
|
||||
ANDQ AX, R13
|
||||
ADDQ R10, R13
|
||||
ANDQ AX, R15
|
||||
ADDQ R12, R15
|
||||
|
||||
// Store output
|
||||
MOVQ out+0(FP), AX
|
||||
MOVQ DI, (AX)
|
||||
MOVQ R9, 8(AX)
|
||||
MOVQ R11, 16(AX)
|
||||
MOVQ R13, 24(AX)
|
||||
MOVQ R15, 32(AX)
|
||||
RET
|
||||
|
||||
// func feSquare(out *Element, a *Element)
|
||||
TEXT ·feSquare(SB), NOSPLIT, $0-16
|
||||
MOVQ a+8(FP), CX
|
||||
|
||||
// r0 = l0×l0
|
||||
MOVQ (CX), AX
|
||||
MULQ (CX)
|
||||
MOVQ AX, SI
|
||||
MOVQ DX, BX
|
||||
|
||||
// r0 += 38×l1×l4
|
||||
MOVQ 8(CX), AX
|
||||
IMUL3Q $0x26, AX, AX
|
||||
MULQ 32(CX)
|
||||
ADDQ AX, SI
|
||||
ADCQ DX, BX
|
||||
|
||||
// r0 += 38×l2×l3
|
||||
MOVQ 16(CX), AX
|
||||
IMUL3Q $0x26, AX, AX
|
||||
MULQ 24(CX)
|
||||
ADDQ AX, SI
|
||||
ADCQ DX, BX
|
||||
|
||||
// r1 = 2×l0×l1
|
||||
MOVQ (CX), AX
|
||||
SHLQ $0x01, AX
|
||||
MULQ 8(CX)
|
||||
MOVQ AX, R8
|
||||
MOVQ DX, DI
|
||||
|
||||
// r1 += 38×l2×l4
|
||||
MOVQ 16(CX), AX
|
||||
IMUL3Q $0x26, AX, AX
|
||||
MULQ 32(CX)
|
||||
ADDQ AX, R8
|
||||
ADCQ DX, DI
|
||||
|
||||
// r1 += 19×l3×l3
|
||||
MOVQ 24(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 24(CX)
|
||||
ADDQ AX, R8
|
||||
ADCQ DX, DI
|
||||
|
||||
// r2 = 2×l0×l2
|
||||
MOVQ (CX), AX
|
||||
SHLQ $0x01, AX
|
||||
MULQ 16(CX)
|
||||
MOVQ AX, R10
|
||||
MOVQ DX, R9
|
||||
|
||||
// r2 += l1×l1
|
||||
MOVQ 8(CX), AX
|
||||
MULQ 8(CX)
|
||||
ADDQ AX, R10
|
||||
ADCQ DX, R9
|
||||
|
||||
// r2 += 38×l3×l4
|
||||
MOVQ 24(CX), AX
|
||||
IMUL3Q $0x26, AX, AX
|
||||
MULQ 32(CX)
|
||||
ADDQ AX, R10
|
||||
ADCQ DX, R9
|
||||
|
||||
// r3 = 2×l0×l3
|
||||
MOVQ (CX), AX
|
||||
SHLQ $0x01, AX
|
||||
MULQ 24(CX)
|
||||
MOVQ AX, R12
|
||||
MOVQ DX, R11
|
||||
|
||||
// r3 += 2×l1×l2
|
||||
MOVQ 8(CX), AX
|
||||
IMUL3Q $0x02, AX, AX
|
||||
MULQ 16(CX)
|
||||
ADDQ AX, R12
|
||||
ADCQ DX, R11
|
||||
|
||||
// r3 += 19×l4×l4
|
||||
MOVQ 32(CX), AX
|
||||
IMUL3Q $0x13, AX, AX
|
||||
MULQ 32(CX)
|
||||
ADDQ AX, R12
|
||||
ADCQ DX, R11
|
||||
|
||||
// r4 = 2×l0×l4
|
||||
MOVQ (CX), AX
|
||||
SHLQ $0x01, AX
|
||||
MULQ 32(CX)
|
||||
MOVQ AX, R14
|
||||
MOVQ DX, R13
|
||||
|
||||
// r4 += 2×l1×l3
|
||||
MOVQ 8(CX), AX
|
||||
IMUL3Q $0x02, AX, AX
|
||||
MULQ 24(CX)
|
||||
ADDQ AX, R14
|
||||
ADCQ DX, R13
|
||||
|
||||
// r4 += l2×l2
|
||||
MOVQ 16(CX), AX
|
||||
MULQ 16(CX)
|
||||
ADDQ AX, R14
|
||||
ADCQ DX, R13
|
||||
|
||||
// First reduction chain
|
||||
MOVQ $0x0007ffffffffffff, AX
|
||||
SHLQ $0x0d, SI, BX
|
||||
SHLQ $0x0d, R8, DI
|
||||
SHLQ $0x0d, R10, R9
|
||||
SHLQ $0x0d, R12, R11
|
||||
SHLQ $0x0d, R14, R13
|
||||
ANDQ AX, SI
|
||||
IMUL3Q $0x13, R13, R13
|
||||
ADDQ R13, SI
|
||||
ANDQ AX, R8
|
||||
ADDQ BX, R8
|
||||
ANDQ AX, R10
|
||||
ADDQ DI, R10
|
||||
ANDQ AX, R12
|
||||
ADDQ R9, R12
|
||||
ANDQ AX, R14
|
||||
ADDQ R11, R14
|
||||
|
||||
// Second reduction chain (carryPropagate)
|
||||
MOVQ SI, BX
|
||||
SHRQ $0x33, BX
|
||||
MOVQ R8, DI
|
||||
SHRQ $0x33, DI
|
||||
MOVQ R10, R9
|
||||
SHRQ $0x33, R9
|
||||
MOVQ R12, R11
|
||||
SHRQ $0x33, R11
|
||||
MOVQ R14, R13
|
||||
SHRQ $0x33, R13
|
||||
ANDQ AX, SI
|
||||
IMUL3Q $0x13, R13, R13
|
||||
ADDQ R13, SI
|
||||
ANDQ AX, R8
|
||||
ADDQ BX, R8
|
||||
ANDQ AX, R10
|
||||
ADDQ DI, R10
|
||||
ANDQ AX, R12
|
||||
ADDQ R9, R12
|
||||
ANDQ AX, R14
|
||||
ADDQ R11, R14
|
||||
|
||||
// Store output
|
||||
MOVQ out+0(FP), AX
|
||||
MOVQ SI, (AX)
|
||||
MOVQ R8, 8(AX)
|
||||
MOVQ R10, 16(AX)
|
||||
MOVQ R12, 24(AX)
|
||||
MOVQ R14, 32(AX)
|
||||
RET
|
||||
@@ -1,12 +0,0 @@
|
||||
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !amd64 || !gc || purego
|
||||
// +build !amd64 !gc purego
|
||||
|
||||
package field
|
||||
|
||||
func feMul(v, x, y *Element) { feMulGeneric(v, x, y) }
|
||||
|
||||
func feSquare(v, x *Element) { feSquareGeneric(v, x) }
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright (c) 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64 && gc && !purego
|
||||
// +build arm64,gc,!purego
|
||||
|
||||
package field
|
||||
|
||||
//go:noescape
|
||||
func carryPropagate(v *Element)
|
||||
|
||||
func (v *Element) carryPropagate() *Element {
|
||||
carryPropagate(v)
|
||||
return v
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright (c) 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64 && gc && !purego
|
||||
// +build arm64,gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// carryPropagate works exactly like carryPropagateGeneric and uses the
|
||||
// same AND, ADD, and LSR+MADD instructions emitted by the compiler, but
|
||||
// avoids loading R0-R4 twice and uses LDP and STP.
|
||||
//
|
||||
// See https://golang.org/issues/43145 for the main compiler issue.
|
||||
//
|
||||
// func carryPropagate(v *Element)
|
||||
TEXT ·carryPropagate(SB),NOFRAME|NOSPLIT,$0-8
|
||||
MOVD v+0(FP), R20
|
||||
|
||||
LDP 0(R20), (R0, R1)
|
||||
LDP 16(R20), (R2, R3)
|
||||
MOVD 32(R20), R4
|
||||
|
||||
AND $0x7ffffffffffff, R0, R10
|
||||
AND $0x7ffffffffffff, R1, R11
|
||||
AND $0x7ffffffffffff, R2, R12
|
||||
AND $0x7ffffffffffff, R3, R13
|
||||
AND $0x7ffffffffffff, R4, R14
|
||||
|
||||
ADD R0>>51, R11, R11
|
||||
ADD R1>>51, R12, R12
|
||||
ADD R2>>51, R13, R13
|
||||
ADD R3>>51, R14, R14
|
||||
// R4>>51 * 19 + R10 -> R10
|
||||
LSR $51, R4, R21
|
||||
MOVD $19, R22
|
||||
MADD R22, R10, R21, R10
|
||||
|
||||
STP (R10, R11), 0(R20)
|
||||
STP (R12, R13), 16(R20)
|
||||
MOVD R14, 32(R20)
|
||||
|
||||
RET
|
||||
@@ -1,12 +0,0 @@
|
||||
// Copyright (c) 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm64 || !gc || purego
|
||||
// +build !arm64 !gc purego
|
||||
|
||||
package field
|
||||
|
||||
func (v *Element) carryPropagate() *Element {
|
||||
return v.carryPropagateGeneric()
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// Copyright (c) 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package field
|
||||
|
||||
import "testing"
|
||||
|
||||
func BenchmarkAdd(b *testing.B) {
|
||||
var x, y Element
|
||||
x.One()
|
||||
y.Add(feOne, feOne)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
x.Add(&x, &y)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMultiply(b *testing.B) {
|
||||
var x, y Element
|
||||
x.One()
|
||||
y.Add(feOne, feOne)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
x.Multiply(&x, &y)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMult32(b *testing.B) {
|
||||
var x Element
|
||||
x.One()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
x.Mult32(&x, 0xaa42aa42)
|
||||
}
|
||||
}
|
||||
@@ -1,264 +0,0 @@
|
||||
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package field
|
||||
|
||||
import "math/bits"
|
||||
|
||||
// uint128 holds a 128-bit number as two 64-bit limbs, for use with the
|
||||
// bits.Mul64 and bits.Add64 intrinsics.
|
||||
type uint128 struct {
|
||||
lo, hi uint64
|
||||
}
|
||||
|
||||
// mul64 returns a * b.
|
||||
func mul64(a, b uint64) uint128 {
|
||||
hi, lo := bits.Mul64(a, b)
|
||||
return uint128{lo, hi}
|
||||
}
|
||||
|
||||
// addMul64 returns v + a * b.
|
||||
func addMul64(v uint128, a, b uint64) uint128 {
|
||||
hi, lo := bits.Mul64(a, b)
|
||||
lo, c := bits.Add64(lo, v.lo, 0)
|
||||
hi, _ = bits.Add64(hi, v.hi, c)
|
||||
return uint128{lo, hi}
|
||||
}
|
||||
|
||||
// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits.
|
||||
func shiftRightBy51(a uint128) uint64 {
|
||||
return (a.hi << (64 - 51)) | (a.lo >> 51)
|
||||
}
|
||||
|
||||
func feMulGeneric(v, a, b *Element) {
|
||||
a0 := a.l0
|
||||
a1 := a.l1
|
||||
a2 := a.l2
|
||||
a3 := a.l3
|
||||
a4 := a.l4
|
||||
|
||||
b0 := b.l0
|
||||
b1 := b.l1
|
||||
b2 := b.l2
|
||||
b3 := b.l3
|
||||
b4 := b.l4
|
||||
|
||||
// Limb multiplication works like pen-and-paper columnar multiplication, but
|
||||
// with 51-bit limbs instead of digits.
|
||||
//
|
||||
// a4 a3 a2 a1 a0 x
|
||||
// b4 b3 b2 b1 b0 =
|
||||
// ------------------------
|
||||
// a4b0 a3b0 a2b0 a1b0 a0b0 +
|
||||
// a4b1 a3b1 a2b1 a1b1 a0b1 +
|
||||
// a4b2 a3b2 a2b2 a1b2 a0b2 +
|
||||
// a4b3 a3b3 a2b3 a1b3 a0b3 +
|
||||
// a4b4 a3b4 a2b4 a1b4 a0b4 =
|
||||
// ----------------------------------------------
|
||||
// r8 r7 r6 r5 r4 r3 r2 r1 r0
|
||||
//
|
||||
// We can then use the reduction identity (a * 2²⁵⁵ + b = a * 19 + b) to
|
||||
// reduce the limbs that would overflow 255 bits. r5 * 2²⁵⁵ becomes 19 * r5,
|
||||
// r6 * 2³⁰⁶ becomes 19 * r6 * 2⁵¹, etc.
|
||||
//
|
||||
// Reduction can be carried out simultaneously to multiplication. For
|
||||
// example, we do not compute r5: whenever the result of a multiplication
|
||||
// belongs to r5, like a1b4, we multiply it by 19 and add the result to r0.
|
||||
//
|
||||
// a4b0 a3b0 a2b0 a1b0 a0b0 +
|
||||
// a3b1 a2b1 a1b1 a0b1 19×a4b1 +
|
||||
// a2b2 a1b2 a0b2 19×a4b2 19×a3b2 +
|
||||
// a1b3 a0b3 19×a4b3 19×a3b3 19×a2b3 +
|
||||
// a0b4 19×a4b4 19×a3b4 19×a2b4 19×a1b4 =
|
||||
// --------------------------------------
|
||||
// r4 r3 r2 r1 r0
|
||||
//
|
||||
// Finally we add up the columns into wide, overlapping limbs.
|
||||
|
||||
a1_19 := a1 * 19
|
||||
a2_19 := a2 * 19
|
||||
a3_19 := a3 * 19
|
||||
a4_19 := a4 * 19
|
||||
|
||||
// r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1)
|
||||
r0 := mul64(a0, b0)
|
||||
r0 = addMul64(r0, a1_19, b4)
|
||||
r0 = addMul64(r0, a2_19, b3)
|
||||
r0 = addMul64(r0, a3_19, b2)
|
||||
r0 = addMul64(r0, a4_19, b1)
|
||||
|
||||
// r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2)
|
||||
r1 := mul64(a0, b1)
|
||||
r1 = addMul64(r1, a1, b0)
|
||||
r1 = addMul64(r1, a2_19, b4)
|
||||
r1 = addMul64(r1, a3_19, b3)
|
||||
r1 = addMul64(r1, a4_19, b2)
|
||||
|
||||
// r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3)
|
||||
r2 := mul64(a0, b2)
|
||||
r2 = addMul64(r2, a1, b1)
|
||||
r2 = addMul64(r2, a2, b0)
|
||||
r2 = addMul64(r2, a3_19, b4)
|
||||
r2 = addMul64(r2, a4_19, b3)
|
||||
|
||||
// r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4
|
||||
r3 := mul64(a0, b3)
|
||||
r3 = addMul64(r3, a1, b2)
|
||||
r3 = addMul64(r3, a2, b1)
|
||||
r3 = addMul64(r3, a3, b0)
|
||||
r3 = addMul64(r3, a4_19, b4)
|
||||
|
||||
// r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0
|
||||
r4 := mul64(a0, b4)
|
||||
r4 = addMul64(r4, a1, b3)
|
||||
r4 = addMul64(r4, a2, b2)
|
||||
r4 = addMul64(r4, a3, b1)
|
||||
r4 = addMul64(r4, a4, b0)
|
||||
|
||||
// After the multiplication, we need to reduce (carry) the five coefficients
|
||||
// to obtain a result with limbs that are at most slightly larger than 2⁵¹,
|
||||
// to respect the Element invariant.
|
||||
//
|
||||
// Overall, the reduction works the same as carryPropagate, except with
|
||||
// wider inputs: we take the carry for each coefficient by shifting it right
|
||||
// by 51, and add it to the limb above it. The top carry is multiplied by 19
|
||||
// according to the reduction identity and added to the lowest limb.
|
||||
//
|
||||
// The largest coefficient (r0) will be at most 111 bits, which guarantees
|
||||
// that all carries are at most 111 - 51 = 60 bits, which fits in a uint64.
|
||||
//
|
||||
// r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1)
|
||||
// r0 < 2⁵²×2⁵² + 19×(2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵²)
|
||||
// r0 < (1 + 19 × 4) × 2⁵² × 2⁵²
|
||||
// r0 < 2⁷ × 2⁵² × 2⁵²
|
||||
// r0 < 2¹¹¹
|
||||
//
|
||||
// Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most
|
||||
// 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and
|
||||
// allows us to easily apply the reduction identity.
|
||||
//
|
||||
// r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0
|
||||
// r4 < 5 × 2⁵² × 2⁵²
|
||||
// r4 < 2¹⁰⁷
|
||||
//
|
||||
|
||||
c0 := shiftRightBy51(r0)
|
||||
c1 := shiftRightBy51(r1)
|
||||
c2 := shiftRightBy51(r2)
|
||||
c3 := shiftRightBy51(r3)
|
||||
c4 := shiftRightBy51(r4)
|
||||
|
||||
rr0 := r0.lo&maskLow51Bits + c4*19
|
||||
rr1 := r1.lo&maskLow51Bits + c0
|
||||
rr2 := r2.lo&maskLow51Bits + c1
|
||||
rr3 := r3.lo&maskLow51Bits + c2
|
||||
rr4 := r4.lo&maskLow51Bits + c3
|
||||
|
||||
// Now all coefficients fit into 64-bit registers but are still too large to
|
||||
// be passed around as a Element. We therefore do one last carry chain,
|
||||
// where the carries will be small enough to fit in the wiggle room above 2⁵¹.
|
||||
*v = Element{rr0, rr1, rr2, rr3, rr4}
|
||||
v.carryPropagate()
|
||||
}
|
||||
|
||||
func feSquareGeneric(v, a *Element) {
|
||||
l0 := a.l0
|
||||
l1 := a.l1
|
||||
l2 := a.l2
|
||||
l3 := a.l3
|
||||
l4 := a.l4
|
||||
|
||||
// Squaring works precisely like multiplication above, but thanks to its
|
||||
// symmetry we get to group a few terms together.
|
||||
//
|
||||
// l4 l3 l2 l1 l0 x
|
||||
// l4 l3 l2 l1 l0 =
|
||||
// ------------------------
|
||||
// l4l0 l3l0 l2l0 l1l0 l0l0 +
|
||||
// l4l1 l3l1 l2l1 l1l1 l0l1 +
|
||||
// l4l2 l3l2 l2l2 l1l2 l0l2 +
|
||||
// l4l3 l3l3 l2l3 l1l3 l0l3 +
|
||||
// l4l4 l3l4 l2l4 l1l4 l0l4 =
|
||||
// ----------------------------------------------
|
||||
// r8 r7 r6 r5 r4 r3 r2 r1 r0
|
||||
//
|
||||
// l4l0 l3l0 l2l0 l1l0 l0l0 +
|
||||
// l3l1 l2l1 l1l1 l0l1 19×l4l1 +
|
||||
// l2l2 l1l2 l0l2 19×l4l2 19×l3l2 +
|
||||
// l1l3 l0l3 19×l4l3 19×l3l3 19×l2l3 +
|
||||
// l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4 =
|
||||
// --------------------------------------
|
||||
// r4 r3 r2 r1 r0
|
||||
//
|
||||
// With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with
|
||||
// only three Mul64 and four Add64, instead of five and eight.
|
||||
|
||||
l0_2 := l0 * 2
|
||||
l1_2 := l1 * 2
|
||||
|
||||
l1_38 := l1 * 38
|
||||
l2_38 := l2 * 38
|
||||
l3_38 := l3 * 38
|
||||
|
||||
l3_19 := l3 * 19
|
||||
l4_19 := l4 * 19
|
||||
|
||||
// r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3)
|
||||
r0 := mul64(l0, l0)
|
||||
r0 = addMul64(r0, l1_38, l4)
|
||||
r0 = addMul64(r0, l2_38, l3)
|
||||
|
||||
// r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3
|
||||
r1 := mul64(l0_2, l1)
|
||||
r1 = addMul64(r1, l2_38, l4)
|
||||
r1 = addMul64(r1, l3_19, l3)
|
||||
|
||||
// r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4
|
||||
r2 := mul64(l0_2, l2)
|
||||
r2 = addMul64(r2, l1, l1)
|
||||
r2 = addMul64(r2, l3_38, l4)
|
||||
|
||||
// r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4
|
||||
r3 := mul64(l0_2, l3)
|
||||
r3 = addMul64(r3, l1_2, l2)
|
||||
r3 = addMul64(r3, l4_19, l4)
|
||||
|
||||
// r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2
|
||||
r4 := mul64(l0_2, l4)
|
||||
r4 = addMul64(r4, l1_2, l3)
|
||||
r4 = addMul64(r4, l2, l2)
|
||||
|
||||
c0 := shiftRightBy51(r0)
|
||||
c1 := shiftRightBy51(r1)
|
||||
c2 := shiftRightBy51(r2)
|
||||
c3 := shiftRightBy51(r3)
|
||||
c4 := shiftRightBy51(r4)
|
||||
|
||||
rr0 := r0.lo&maskLow51Bits + c4*19
|
||||
rr1 := r1.lo&maskLow51Bits + c0
|
||||
rr2 := r2.lo&maskLow51Bits + c1
|
||||
rr3 := r3.lo&maskLow51Bits + c2
|
||||
rr4 := r4.lo&maskLow51Bits + c3
|
||||
|
||||
*v = Element{rr0, rr1, rr2, rr3, rr4}
|
||||
v.carryPropagate()
|
||||
}
|
||||
|
||||
// carryPropagate brings the limbs below 52 bits by applying the reduction
|
||||
// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. TODO inline
|
||||
func (v *Element) carryPropagateGeneric() *Element {
|
||||
c0 := v.l0 >> 51
|
||||
c1 := v.l1 >> 51
|
||||
c2 := v.l2 >> 51
|
||||
c3 := v.l3 >> 51
|
||||
c4 := v.l4 >> 51
|
||||
|
||||
v.l0 = v.l0&maskLow51Bits + c4*19
|
||||
v.l1 = v.l1&maskLow51Bits + c0
|
||||
v.l2 = v.l2&maskLow51Bits + c1
|
||||
v.l3 = v.l3&maskLow51Bits + c2
|
||||
v.l4 = v.l4&maskLow51Bits + c3
|
||||
|
||||
return v
|
||||
}
|
||||
@@ -1,558 +0,0 @@
|
||||
// Copyright (c) 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package field
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"math/big"
|
||||
"math/bits"
|
||||
mathrand "math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
)
|
||||
|
||||
func (v Element) String() string {
|
||||
return hex.EncodeToString(v.Bytes())
|
||||
}
|
||||
|
||||
// quickCheckConfig1024 will make each quickcheck test run (1024 * -quickchecks)
|
||||
// times. The default value of -quickchecks is 100.
|
||||
var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10}
|
||||
|
||||
func generateFieldElement(rand *mathrand.Rand) Element {
|
||||
const maskLow52Bits = (1 << 52) - 1
|
||||
return Element{
|
||||
rand.Uint64() & maskLow52Bits,
|
||||
rand.Uint64() & maskLow52Bits,
|
||||
rand.Uint64() & maskLow52Bits,
|
||||
rand.Uint64() & maskLow52Bits,
|
||||
rand.Uint64() & maskLow52Bits,
|
||||
}
|
||||
}
|
||||
|
||||
// weirdLimbs can be combined to generate a range of edge-case field elements.
|
||||
// 0 and -1 are intentionally more weighted, as they combine well.
|
||||
var (
|
||||
weirdLimbs51 = []uint64{
|
||||
0, 0, 0, 0,
|
||||
1,
|
||||
19 - 1,
|
||||
19,
|
||||
0x2aaaaaaaaaaaa,
|
||||
0x5555555555555,
|
||||
(1 << 51) - 20,
|
||||
(1 << 51) - 19,
|
||||
(1 << 51) - 1, (1 << 51) - 1,
|
||||
(1 << 51) - 1, (1 << 51) - 1,
|
||||
}
|
||||
weirdLimbs52 = []uint64{
|
||||
0, 0, 0, 0, 0, 0,
|
||||
1,
|
||||
19 - 1,
|
||||
19,
|
||||
0x2aaaaaaaaaaaa,
|
||||
0x5555555555555,
|
||||
(1 << 51) - 20,
|
||||
(1 << 51) - 19,
|
||||
(1 << 51) - 1, (1 << 51) - 1,
|
||||
(1 << 51) - 1, (1 << 51) - 1,
|
||||
(1 << 51) - 1, (1 << 51) - 1,
|
||||
1 << 51,
|
||||
(1 << 51) + 1,
|
||||
(1 << 52) - 19,
|
||||
(1 << 52) - 1,
|
||||
}
|
||||
)
|
||||
|
||||
func generateWeirdFieldElement(rand *mathrand.Rand) Element {
|
||||
return Element{
|
||||
weirdLimbs52[rand.Intn(len(weirdLimbs52))],
|
||||
weirdLimbs51[rand.Intn(len(weirdLimbs51))],
|
||||
weirdLimbs51[rand.Intn(len(weirdLimbs51))],
|
||||
weirdLimbs51[rand.Intn(len(weirdLimbs51))],
|
||||
weirdLimbs51[rand.Intn(len(weirdLimbs51))],
|
||||
}
|
||||
}
|
||||
|
||||
func (Element) Generate(rand *mathrand.Rand, size int) reflect.Value {
|
||||
if rand.Intn(2) == 0 {
|
||||
return reflect.ValueOf(generateWeirdFieldElement(rand))
|
||||
}
|
||||
return reflect.ValueOf(generateFieldElement(rand))
|
||||
}
|
||||
|
||||
// isInBounds returns whether the element is within the expected bit size bounds
|
||||
// after a light reduction.
|
||||
func isInBounds(x *Element) bool {
|
||||
return bits.Len64(x.l0) <= 52 &&
|
||||
bits.Len64(x.l1) <= 52 &&
|
||||
bits.Len64(x.l2) <= 52 &&
|
||||
bits.Len64(x.l3) <= 52 &&
|
||||
bits.Len64(x.l4) <= 52
|
||||
}
|
||||
|
||||
func TestMultiplyDistributesOverAdd(t *testing.T) {
|
||||
multiplyDistributesOverAdd := func(x, y, z Element) bool {
|
||||
// Compute t1 = (x+y)*z
|
||||
t1 := new(Element)
|
||||
t1.Add(&x, &y)
|
||||
t1.Multiply(t1, &z)
|
||||
|
||||
// Compute t2 = x*z + y*z
|
||||
t2 := new(Element)
|
||||
t3 := new(Element)
|
||||
t2.Multiply(&x, &z)
|
||||
t3.Multiply(&y, &z)
|
||||
t2.Add(t2, t3)
|
||||
|
||||
return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2)
|
||||
}
|
||||
|
||||
if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMul64to128(t *testing.T) {
|
||||
a := uint64(5)
|
||||
b := uint64(5)
|
||||
r := mul64(a, b)
|
||||
if r.lo != 0x19 || r.hi != 0 {
|
||||
t.Errorf("lo-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi)
|
||||
}
|
||||
|
||||
a = uint64(18014398509481983) // 2^54 - 1
|
||||
b = uint64(18014398509481983) // 2^54 - 1
|
||||
r = mul64(a, b)
|
||||
if r.lo != 0xff80000000000001 || r.hi != 0xfffffffffff {
|
||||
t.Errorf("hi-range wide mult failed, got %d + %d*(2**64)", r.lo, r.hi)
|
||||
}
|
||||
|
||||
a = uint64(1125899906842661)
|
||||
b = uint64(2097155)
|
||||
r = mul64(a, b)
|
||||
r = addMul64(r, a, b)
|
||||
r = addMul64(r, a, b)
|
||||
r = addMul64(r, a, b)
|
||||
r = addMul64(r, a, b)
|
||||
if r.lo != 16888498990613035 || r.hi != 640 {
|
||||
t.Errorf("wrong answer: %d + %d*(2**64)", r.lo, r.hi)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetBytesRoundTrip(t *testing.T) {
|
||||
f1 := func(in [32]byte, fe Element) bool {
|
||||
fe.SetBytes(in[:])
|
||||
|
||||
// Mask the most significant bit as it's ignored by SetBytes. (Now
|
||||
// instead of earlier so we check the masking in SetBytes is working.)
|
||||
in[len(in)-1] &= (1 << 7) - 1
|
||||
|
||||
return bytes.Equal(in[:], fe.Bytes()) && isInBounds(&fe)
|
||||
}
|
||||
if err := quick.Check(f1, nil); err != nil {
|
||||
t.Errorf("failed bytes->FE->bytes round-trip: %v", err)
|
||||
}
|
||||
|
||||
f2 := func(fe, r Element) bool {
|
||||
r.SetBytes(fe.Bytes())
|
||||
|
||||
// Intentionally not using Equal not to go through Bytes again.
|
||||
// Calling reduce because both Generate and SetBytes can produce
|
||||
// non-canonical representations.
|
||||
fe.reduce()
|
||||
r.reduce()
|
||||
return fe == r
|
||||
}
|
||||
if err := quick.Check(f2, nil); err != nil {
|
||||
t.Errorf("failed FE->bytes->FE round-trip: %v", err)
|
||||
}
|
||||
|
||||
// Check some fixed vectors from dalek
|
||||
type feRTTest struct {
|
||||
fe Element
|
||||
b []byte
|
||||
}
|
||||
var tests = []feRTTest{
|
||||
{
|
||||
fe: Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676},
|
||||
b: []byte{74, 209, 69, 197, 70, 70, 161, 222, 56, 226, 229, 19, 112, 60, 25, 92, 187, 74, 222, 56, 50, 153, 51, 233, 40, 74, 57, 6, 160, 185, 213, 31},
|
||||
},
|
||||
{
|
||||
fe: Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972},
|
||||
b: []byte{199, 23, 106, 112, 61, 77, 216, 79, 186, 60, 11, 118, 13, 16, 103, 15, 42, 32, 83, 250, 44, 57, 204, 198, 78, 199, 253, 119, 146, 172, 3, 122},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
b := tt.fe.Bytes()
|
||||
if !bytes.Equal(b, tt.b) || new(Element).SetBytes(tt.b).Equal(&tt.fe) != 1 {
|
||||
t.Errorf("Failed fixed roundtrip: %v", tt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func swapEndianness(buf []byte) []byte {
|
||||
for i := 0; i < len(buf)/2; i++ {
|
||||
buf[i], buf[len(buf)-i-1] = buf[len(buf)-i-1], buf[i]
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
func TestBytesBigEquivalence(t *testing.T) {
|
||||
f1 := func(in [32]byte, fe, fe1 Element) bool {
|
||||
fe.SetBytes(in[:])
|
||||
|
||||
in[len(in)-1] &= (1 << 7) - 1 // mask the most significant bit
|
||||
b := new(big.Int).SetBytes(swapEndianness(in[:]))
|
||||
fe1.fromBig(b)
|
||||
|
||||
if fe != fe1 {
|
||||
return false
|
||||
}
|
||||
|
||||
buf := make([]byte, 32) // pad with zeroes
|
||||
copy(buf, swapEndianness(fe1.toBig().Bytes()))
|
||||
|
||||
return bytes.Equal(fe.Bytes(), buf) && isInBounds(&fe) && isInBounds(&fe1)
|
||||
}
|
||||
if err := quick.Check(f1, nil); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// fromBig sets v = n, and returns v. The bit length of n must not exceed 256.
|
||||
func (v *Element) fromBig(n *big.Int) *Element {
|
||||
if n.BitLen() > 32*8 {
|
||||
panic("edwards25519: invalid field element input size")
|
||||
}
|
||||
|
||||
buf := make([]byte, 0, 32)
|
||||
for _, word := range n.Bits() {
|
||||
for i := 0; i < bits.UintSize; i += 8 {
|
||||
if len(buf) >= cap(buf) {
|
||||
break
|
||||
}
|
||||
buf = append(buf, byte(word))
|
||||
word >>= 8
|
||||
}
|
||||
}
|
||||
|
||||
return v.SetBytes(buf[:32])
|
||||
}
|
||||
|
||||
func (v *Element) fromDecimal(s string) *Element {
|
||||
n, ok := new(big.Int).SetString(s, 10)
|
||||
if !ok {
|
||||
panic("not a valid decimal: " + s)
|
||||
}
|
||||
return v.fromBig(n)
|
||||
}
|
||||
|
||||
// toBig returns v as a big.Int.
|
||||
func (v *Element) toBig() *big.Int {
|
||||
buf := v.Bytes()
|
||||
|
||||
words := make([]big.Word, 32*8/bits.UintSize)
|
||||
for n := range words {
|
||||
for i := 0; i < bits.UintSize; i += 8 {
|
||||
if len(buf) == 0 {
|
||||
break
|
||||
}
|
||||
words[n] |= big.Word(buf[0]) << big.Word(i)
|
||||
buf = buf[1:]
|
||||
}
|
||||
}
|
||||
|
||||
return new(big.Int).SetBits(words)
|
||||
}
|
||||
|
||||
func TestDecimalConstants(t *testing.T) {
|
||||
sqrtM1String := "19681161376707505956807079304988542015446066515923890162744021073123829784752"
|
||||
if exp := new(Element).fromDecimal(sqrtM1String); sqrtM1.Equal(exp) != 1 {
|
||||
t.Errorf("sqrtM1 is %v, expected %v", sqrtM1, exp)
|
||||
}
|
||||
// d is in the parent package, and we don't want to expose d or fromDecimal.
|
||||
// dString := "37095705934669439343138083508754565189542113879843219016388785533085940283555"
|
||||
// if exp := new(Element).fromDecimal(dString); d.Equal(exp) != 1 {
|
||||
// t.Errorf("d is %v, expected %v", d, exp)
|
||||
// }
|
||||
}
|
||||
|
||||
func TestSetBytesRoundTripEdgeCases(t *testing.T) {
|
||||
// TODO: values close to 0, close to 2^255-19, between 2^255-19 and 2^255-1,
|
||||
// and between 2^255 and 2^256-1. Test both the documented SetBytes
|
||||
// behavior, and that Bytes reduces them.
|
||||
}
|
||||
|
||||
// Tests self-consistency between Multiply and Square.
|
||||
func TestConsistency(t *testing.T) {
|
||||
var x Element
|
||||
var x2, x2sq Element
|
||||
|
||||
x = Element{1, 1, 1, 1, 1}
|
||||
x2.Multiply(&x, &x)
|
||||
x2sq.Square(&x)
|
||||
|
||||
if x2 != x2sq {
|
||||
t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq)
|
||||
}
|
||||
|
||||
var bytes [32]byte
|
||||
|
||||
_, err := io.ReadFull(rand.Reader, bytes[:])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
x.SetBytes(bytes[:])
|
||||
|
||||
x2.Multiply(&x, &x)
|
||||
x2sq.Square(&x)
|
||||
|
||||
if x2 != x2sq {
|
||||
t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
x := Element{1, 1, 1, 1, 1}
|
||||
y := Element{5, 4, 3, 2, 1}
|
||||
|
||||
eq := x.Equal(&x)
|
||||
if eq != 1 {
|
||||
t.Errorf("wrong about equality")
|
||||
}
|
||||
|
||||
eq = x.Equal(&y)
|
||||
if eq != 0 {
|
||||
t.Errorf("wrong about inequality")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvert(t *testing.T) {
|
||||
x := Element{1, 1, 1, 1, 1}
|
||||
one := Element{1, 0, 0, 0, 0}
|
||||
var xinv, r Element
|
||||
|
||||
xinv.Invert(&x)
|
||||
r.Multiply(&x, &xinv)
|
||||
r.reduce()
|
||||
|
||||
if one != r {
|
||||
t.Errorf("inversion identity failed, got: %x", r)
|
||||
}
|
||||
|
||||
var bytes [32]byte
|
||||
|
||||
_, err := io.ReadFull(rand.Reader, bytes[:])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
x.SetBytes(bytes[:])
|
||||
|
||||
xinv.Invert(&x)
|
||||
r.Multiply(&x, &xinv)
|
||||
r.reduce()
|
||||
|
||||
if one != r {
|
||||
t.Errorf("random inversion identity failed, got: %x for field element %x", r, x)
|
||||
}
|
||||
|
||||
zero := Element{}
|
||||
x.Set(&zero)
|
||||
if xx := xinv.Invert(&x); xx != &xinv {
|
||||
t.Errorf("inverting zero did not return the receiver")
|
||||
} else if xinv.Equal(&zero) != 1 {
|
||||
t.Errorf("inverting zero did not return zero")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectSwap(t *testing.T) {
|
||||
a := Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676}
|
||||
b := Element{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972}
|
||||
|
||||
var c, d Element
|
||||
|
||||
c.Select(&a, &b, 1)
|
||||
d.Select(&a, &b, 0)
|
||||
|
||||
if c.Equal(&a) != 1 || d.Equal(&b) != 1 {
|
||||
t.Errorf("Select failed")
|
||||
}
|
||||
|
||||
c.Swap(&d, 0)
|
||||
|
||||
if c.Equal(&a) != 1 || d.Equal(&b) != 1 {
|
||||
t.Errorf("Swap failed")
|
||||
}
|
||||
|
||||
c.Swap(&d, 1)
|
||||
|
||||
if c.Equal(&b) != 1 || d.Equal(&a) != 1 {
|
||||
t.Errorf("Swap failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMult32(t *testing.T) {
|
||||
mult32EquivalentToMul := func(x Element, y uint32) bool {
|
||||
t1 := new(Element)
|
||||
for i := 0; i < 100; i++ {
|
||||
t1.Mult32(&x, y)
|
||||
}
|
||||
|
||||
ty := new(Element)
|
||||
ty.l0 = uint64(y)
|
||||
|
||||
t2 := new(Element)
|
||||
for i := 0; i < 100; i++ {
|
||||
t2.Multiply(&x, ty)
|
||||
}
|
||||
|
||||
return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2)
|
||||
}
|
||||
|
||||
if err := quick.Check(mult32EquivalentToMul, quickCheckConfig1024); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSqrtRatio(t *testing.T) {
|
||||
// From draft-irtf-cfrg-ristretto255-decaf448-00, Appendix A.4.
|
||||
type test struct {
|
||||
u, v string
|
||||
wasSquare int
|
||||
r string
|
||||
}
|
||||
var tests = []test{
|
||||
// If u is 0, the function is defined to return (0, TRUE), even if v
|
||||
// is zero. Note that where used in this package, the denominator v
|
||||
// is never zero.
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
1, "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
},
|
||||
// 0/1 == 0²
|
||||
{
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
1, "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
},
|
||||
// If u is non-zero and v is zero, defined to return (0, FALSE).
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
0, "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
},
|
||||
// 2/1 is not square in this field.
|
||||
{
|
||||
"0200000000000000000000000000000000000000000000000000000000000000",
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
0, "3c5ff1b5d8e4113b871bd052f9e7bcd0582804c266ffb2d4f4203eb07fdb7c54",
|
||||
},
|
||||
// 4/1 == 2²
|
||||
{
|
||||
"0400000000000000000000000000000000000000000000000000000000000000",
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
1, "0200000000000000000000000000000000000000000000000000000000000000",
|
||||
},
|
||||
// 1/4 == (2⁻¹)² == (2^(p-2))² per Euler's theorem
|
||||
{
|
||||
"0100000000000000000000000000000000000000000000000000000000000000",
|
||||
"0400000000000000000000000000000000000000000000000000000000000000",
|
||||
1, "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
u := new(Element).SetBytes(decodeHex(tt.u))
|
||||
v := new(Element).SetBytes(decodeHex(tt.v))
|
||||
want := new(Element).SetBytes(decodeHex(tt.r))
|
||||
got, wasSquare := new(Element).SqrtRatio(u, v)
|
||||
if got.Equal(want) == 0 || wasSquare != tt.wasSquare {
|
||||
t.Errorf("%d: got (%v, %v), want (%v, %v)", i, got, wasSquare, want, tt.wasSquare)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCarryPropagate(t *testing.T) {
|
||||
asmLikeGeneric := func(a [5]uint64) bool {
|
||||
t1 := &Element{a[0], a[1], a[2], a[3], a[4]}
|
||||
t2 := &Element{a[0], a[1], a[2], a[3], a[4]}
|
||||
|
||||
t1.carryPropagate()
|
||||
t2.carryPropagateGeneric()
|
||||
|
||||
if *t1 != *t2 {
|
||||
t.Logf("got: %#v,\nexpected: %#v", t1, t2)
|
||||
}
|
||||
|
||||
return *t1 == *t2 && isInBounds(t2)
|
||||
}
|
||||
|
||||
if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if !asmLikeGeneric([5]uint64{0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}) {
|
||||
t.Errorf("failed for {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFeSquare(t *testing.T) {
|
||||
asmLikeGeneric := func(a Element) bool {
|
||||
t1 := a
|
||||
t2 := a
|
||||
|
||||
feSquareGeneric(&t1, &t1)
|
||||
feSquare(&t2, &t2)
|
||||
|
||||
if t1 != t2 {
|
||||
t.Logf("got: %#v,\nexpected: %#v", t1, t2)
|
||||
}
|
||||
|
||||
return t1 == t2 && isInBounds(&t2)
|
||||
}
|
||||
|
||||
if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFeMul(t *testing.T) {
|
||||
asmLikeGeneric := func(a, b Element) bool {
|
||||
a1 := a
|
||||
a2 := a
|
||||
b1 := b
|
||||
b2 := b
|
||||
|
||||
feMulGeneric(&a1, &a1, &b1)
|
||||
feMul(&a2, &a2, &b2)
|
||||
|
||||
if a1 != a2 || b1 != b2 {
|
||||
t.Logf("got: %#v,\nexpected: %#v", a1, a2)
|
||||
t.Logf("got: %#v,\nexpected: %#v", b1, b2)
|
||||
}
|
||||
|
||||
return a1 == a2 && isInBounds(&a2) &&
|
||||
b1 == b2 && isInBounds(&b2)
|
||||
}
|
||||
|
||||
if err := quick.Check(asmLikeGeneric, quickCheckConfig1024); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func decodeHex(s string) []byte {
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return b
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
b0c49ae9f59d233526f8934262c5bbbe14d4358d
|
||||
@@ -1,19 +0,0 @@
|
||||
#! /bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
|
||||
STD_PATH=src/crypto/ed25519/internal/edwards25519/field
|
||||
LOCAL_PATH=curve25519/internal/field
|
||||
LAST_SYNC_REF=$(cat $LOCAL_PATH/sync.checkpoint)
|
||||
|
||||
git fetch https://go.googlesource.com/go master
|
||||
|
||||
if git diff --quiet $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH; then
|
||||
echo "No changes."
|
||||
else
|
||||
NEW_REF=$(git rev-parse FETCH_HEAD | tee $LOCAL_PATH/sync.checkpoint)
|
||||
echo "Applying changes from $LAST_SYNC_REF to $NEW_REF..."
|
||||
git diff $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH | \
|
||||
git apply -3 --directory=$LOCAL_PATH
|
||||
fi
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package curve25519
|
||||
package curve25519_test
|
||||
|
||||
// lowOrderPoints from libsodium.
|
||||
// https://github.com/jedisct1/libsodium/blob/65621a1059a37d/src/libsodium/crypto_scalarmult/curve25519/ref10/x25519_ref10.c#L11-L70
|
||||
|
||||
+1
-3
@@ -11,9 +11,7 @@
|
||||
// operations with the same key more efficient. This package refers to the RFC
|
||||
// 8032 private key as the “seed”.
|
||||
//
|
||||
// Beginning with Go 1.13, the functionality of this package was moved to the
|
||||
// standard library as crypto/ed25519. This package only acts as a compatibility
|
||||
// wrapper.
|
||||
// This package is a wrapper around the standard library crypto/ed25519 package.
|
||||
package ed25519
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
module golang.org/x/crypto
|
||||
|
||||
go 1.17
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
golang.org/x/net v0.2.0
|
||||
golang.org/x/sys v0.2.0
|
||||
golang.org/x/term v0.2.0
|
||||
golang.org/x/net v0.21.0 // tagx:ignore
|
||||
golang.org/x/sys v0.23.0
|
||||
golang.org/x/term v0.23.0
|
||||
)
|
||||
|
||||
require golang.org/x/text v0.4.0 // indirect
|
||||
require golang.org/x/text v0.17.0 // indirect
|
||||
|
||||
@@ -1,31 +1,8 @@
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
|
||||
+4
-2
@@ -8,7 +8,7 @@
|
||||
// HKDF is a cryptographic key derivation function (KDF) with the goal of
|
||||
// expanding limited input keying material into one or more cryptographically
|
||||
// strong secret keys.
|
||||
package hkdf // import "golang.org/x/crypto/hkdf"
|
||||
package hkdf
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
@@ -56,7 +56,9 @@ func (f *hkdf) Read(p []byte) (int, error) {
|
||||
|
||||
// Fill the rest of the buffer
|
||||
for len(p) > 0 {
|
||||
f.expander.Reset()
|
||||
if f.counter > 1 {
|
||||
f.expander.Reset()
|
||||
}
|
||||
f.expander.Write(f.prev)
|
||||
f.expander.Write(f.info)
|
||||
f.expander.Write([]byte{f.counter})
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !purego
|
||||
// +build !purego
|
||||
|
||||
// Package alias implements memory aliasing tests.
|
||||
package alias
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build purego
|
||||
// +build purego
|
||||
|
||||
// Package alias implements memory aliasing tests.
|
||||
package alias
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.13
|
||||
// +build !go1.13
|
||||
|
||||
package poly1305
|
||||
|
||||
// Generic fallbacks for the math/bits intrinsics, copied from
|
||||
// src/math/bits/bits.go. They were added in Go 1.12, but Add64 and Sum64 had
|
||||
// variable time fallbacks until Go 1.13.
|
||||
|
||||
func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
|
||||
sum = x + y + carry
|
||||
carryOut = ((x & y) | ((x | y) &^ sum)) >> 63
|
||||
return
|
||||
}
|
||||
|
||||
func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
|
||||
diff = x - y - borrow
|
||||
borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63
|
||||
return
|
||||
}
|
||||
|
||||
func bitsMul64(x, y uint64) (hi, lo uint64) {
|
||||
const mask32 = 1<<32 - 1
|
||||
x0 := x & mask32
|
||||
x1 := x >> 32
|
||||
y0 := y & mask32
|
||||
y1 := y >> 32
|
||||
w0 := x0 * y0
|
||||
t := x1*y0 + w0>>32
|
||||
w1 := t & mask32
|
||||
w2 := t >> 32
|
||||
w1 += x0 * y1
|
||||
hi = x1*y1 + w2 + w1>>32
|
||||
lo = x * y
|
||||
return
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.13
|
||||
// +build go1.13
|
||||
|
||||
package poly1305
|
||||
|
||||
import "math/bits"
|
||||
|
||||
func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
|
||||
return bits.Add64(x, y, carry)
|
||||
}
|
||||
|
||||
func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
|
||||
return bits.Sub64(x, y, borrow)
|
||||
}
|
||||
|
||||
func bitsMul64(x, y uint64) (hi, lo uint64) {
|
||||
return bits.Mul64(x, y)
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (!amd64 && !ppc64le && !s390x) || !gc || purego
|
||||
// +build !amd64,!ppc64le,!s390x !gc purego
|
||||
|
||||
package poly1305
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
package poly1305
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
|
||||
package poly1305
|
||||
|
||||
import "encoding/binary"
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag
|
||||
// for a 64 bytes message is approximately
|
||||
@@ -114,13 +117,13 @@ type uint128 struct {
|
||||
}
|
||||
|
||||
func mul64(a, b uint64) uint128 {
|
||||
hi, lo := bitsMul64(a, b)
|
||||
hi, lo := bits.Mul64(a, b)
|
||||
return uint128{lo, hi}
|
||||
}
|
||||
|
||||
func add128(a, b uint128) uint128 {
|
||||
lo, c := bitsAdd64(a.lo, b.lo, 0)
|
||||
hi, c := bitsAdd64(a.hi, b.hi, c)
|
||||
lo, c := bits.Add64(a.lo, b.lo, 0)
|
||||
hi, c := bits.Add64(a.hi, b.hi, c)
|
||||
if c != 0 {
|
||||
panic("poly1305: unexpected overflow")
|
||||
}
|
||||
@@ -155,8 +158,8 @@ func updateGeneric(state *macState, msg []byte) {
|
||||
// hide leading zeroes. For full chunks, that's 1 << 128, so we can just
|
||||
// add 1 to the most significant (2¹²⁸) limb, h2.
|
||||
if len(msg) >= TagSize {
|
||||
h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0)
|
||||
h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(msg[8:16]), c)
|
||||
h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0)
|
||||
h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(msg[8:16]), c)
|
||||
h2 += c + 1
|
||||
|
||||
msg = msg[TagSize:]
|
||||
@@ -165,8 +168,8 @@ func updateGeneric(state *macState, msg []byte) {
|
||||
copy(buf[:], msg)
|
||||
buf[len(msg)] = 1
|
||||
|
||||
h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0)
|
||||
h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(buf[8:16]), c)
|
||||
h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0)
|
||||
h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(buf[8:16]), c)
|
||||
h2 += c
|
||||
|
||||
msg = nil
|
||||
@@ -219,9 +222,9 @@ func updateGeneric(state *macState, msg []byte) {
|
||||
m3 := h2r1
|
||||
|
||||
t0 := m0.lo
|
||||
t1, c := bitsAdd64(m1.lo, m0.hi, 0)
|
||||
t2, c := bitsAdd64(m2.lo, m1.hi, c)
|
||||
t3, _ := bitsAdd64(m3.lo, m2.hi, c)
|
||||
t1, c := bits.Add64(m1.lo, m0.hi, 0)
|
||||
t2, c := bits.Add64(m2.lo, m1.hi, c)
|
||||
t3, _ := bits.Add64(m3.lo, m2.hi, c)
|
||||
|
||||
// Now we have the result as 4 64-bit limbs, and we need to reduce it
|
||||
// modulo 2¹³⁰ - 5. The special shape of this Crandall prime lets us do
|
||||
@@ -243,14 +246,14 @@ func updateGeneric(state *macState, msg []byte) {
|
||||
|
||||
// To add c * 5 to h, we first add cc = c * 4, and then add (cc >> 2) = c.
|
||||
|
||||
h0, c = bitsAdd64(h0, cc.lo, 0)
|
||||
h1, c = bitsAdd64(h1, cc.hi, c)
|
||||
h0, c = bits.Add64(h0, cc.lo, 0)
|
||||
h1, c = bits.Add64(h1, cc.hi, c)
|
||||
h2 += c
|
||||
|
||||
cc = shiftRightBy2(cc)
|
||||
|
||||
h0, c = bitsAdd64(h0, cc.lo, 0)
|
||||
h1, c = bitsAdd64(h1, cc.hi, c)
|
||||
h0, c = bits.Add64(h0, cc.lo, 0)
|
||||
h1, c = bits.Add64(h1, cc.hi, c)
|
||||
h2 += c
|
||||
|
||||
// h2 is at most 3 + 1 + 1 = 5, making the whole of h at most
|
||||
@@ -287,9 +290,9 @@ func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
|
||||
// in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the
|
||||
// result if the subtraction underflows, and t otherwise.
|
||||
|
||||
hMinusP0, b := bitsSub64(h0, p0, 0)
|
||||
hMinusP1, b := bitsSub64(h1, p1, b)
|
||||
_, b = bitsSub64(h2, p2, b)
|
||||
hMinusP0, b := bits.Sub64(h0, p0, 0)
|
||||
hMinusP1, b := bits.Sub64(h1, p1, b)
|
||||
_, b = bits.Sub64(h2, p2, b)
|
||||
|
||||
// h = h if h < p else h - p
|
||||
h0 = select64(b, h0, hMinusP0)
|
||||
@@ -301,8 +304,8 @@ func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
|
||||
//
|
||||
// by just doing a wide addition with the 128 low bits of h and discarding
|
||||
// the overflow.
|
||||
h0, c := bitsAdd64(h0, s[0], 0)
|
||||
h1, _ = bitsAdd64(h1, s[1], c)
|
||||
h0, c := bits.Add64(h0, s[0], 0)
|
||||
h1, _ = bits.Add64(h1, s[1], c)
|
||||
|
||||
binary.LittleEndian.PutUint64(out[0:8], h0)
|
||||
binary.LittleEndian.PutUint64(out[8:16], h1)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
package poly1305
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
@@ -20,15 +19,14 @@
|
||||
|
||||
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \
|
||||
MULLD r0, h0, t0; \
|
||||
MULLD r0, h1, t4; \
|
||||
MULHDU r0, h0, t1; \
|
||||
MULLD r0, h1, t4; \
|
||||
MULHDU r0, h1, t5; \
|
||||
ADDC t4, t1, t1; \
|
||||
MULLD r0, h2, t2; \
|
||||
ADDZE t5; \
|
||||
MULHDU r1, h0, t4; \
|
||||
MULLD r1, h0, h0; \
|
||||
ADD t5, t2, t2; \
|
||||
ADDE t5, t2, t2; \
|
||||
ADDC h0, t1, t1; \
|
||||
MULLD h2, r1, t3; \
|
||||
ADDZE t4, h0; \
|
||||
@@ -38,13 +36,11 @@
|
||||
ADDE t5, t3, t3; \
|
||||
ADDC h0, t2, t2; \
|
||||
MOVD $-4, t4; \
|
||||
MOVD t0, h0; \
|
||||
MOVD t1, h1; \
|
||||
ADDZE t3; \
|
||||
ANDCC $3, t2, h2; \
|
||||
AND t2, t4, t0; \
|
||||
RLDICL $0, t2, $62, h2; \
|
||||
AND t2, t4, h0; \
|
||||
ADDC t0, h0, h0; \
|
||||
ADDE t3, h1, h1; \
|
||||
ADDE t3, t1, h1; \
|
||||
SLD $62, t3, t4; \
|
||||
SRD $2, t2; \
|
||||
ADDZE h2; \
|
||||
@@ -76,6 +72,7 @@ TEXT ·update(SB), $0-32
|
||||
loop:
|
||||
POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22)
|
||||
|
||||
PCALIGN $16
|
||||
multiply:
|
||||
POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21)
|
||||
ADD $-16, R5
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
package poly1305
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gc && !purego
|
||||
// +build gc,!purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package testenv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CommandContext is like exec.CommandContext, but:
|
||||
// - skips t if the platform does not support os/exec,
|
||||
// - sends SIGQUIT (if supported by the platform) instead of SIGKILL
|
||||
// in its Cancel function
|
||||
// - if the test has a deadline, adds a Context timeout and WaitDelay
|
||||
// for an arbitrary grace period before the test's deadline expires,
|
||||
// - fails the test if the command does not complete before the test's deadline, and
|
||||
// - sets a Cleanup function that verifies that the test did not leak a subprocess.
|
||||
func CommandContext(t testing.TB, ctx context.Context, name string, args ...string) *exec.Cmd {
|
||||
t.Helper()
|
||||
|
||||
var (
|
||||
cancelCtx context.CancelFunc
|
||||
gracePeriod time.Duration // unlimited unless the test has a deadline (to allow for interactive debugging)
|
||||
)
|
||||
|
||||
if t, ok := t.(interface {
|
||||
testing.TB
|
||||
Deadline() (time.Time, bool)
|
||||
}); ok {
|
||||
if td, ok := t.Deadline(); ok {
|
||||
// Start with a minimum grace period, just long enough to consume the
|
||||
// output of a reasonable program after it terminates.
|
||||
gracePeriod = 100 * time.Millisecond
|
||||
if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" {
|
||||
scale, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
t.Fatalf("invalid GO_TEST_TIMEOUT_SCALE: %v", err)
|
||||
}
|
||||
gracePeriod *= time.Duration(scale)
|
||||
}
|
||||
|
||||
// If time allows, increase the termination grace period to 5% of the
|
||||
// test's remaining time.
|
||||
testTimeout := time.Until(td)
|
||||
if gp := testTimeout / 20; gp > gracePeriod {
|
||||
gracePeriod = gp
|
||||
}
|
||||
|
||||
// When we run commands that execute subprocesses, we want to reserve two
|
||||
// grace periods to clean up: one for the delay between the first
|
||||
// termination signal being sent (via the Cancel callback when the Context
|
||||
// expires) and the process being forcibly terminated (via the WaitDelay
|
||||
// field), and a second one for the delay between the process being
|
||||
// terminated and the test logging its output for debugging.
|
||||
//
|
||||
// (We want to ensure that the test process itself has enough time to
|
||||
// log the output before it is also terminated.)
|
||||
cmdTimeout := testTimeout - 2*gracePeriod
|
||||
|
||||
if cd, ok := ctx.Deadline(); !ok || time.Until(cd) > cmdTimeout {
|
||||
// Either ctx doesn't have a deadline, or its deadline would expire
|
||||
// after (or too close before) the test has already timed out.
|
||||
// Add a shorter timeout so that the test will produce useful output.
|
||||
ctx, cancelCtx = context.WithTimeout(ctx, cmdTimeout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, name, args...)
|
||||
// Set the Cancel and WaitDelay fields only if present (go 1.20 and later).
|
||||
// TODO: When Go 1.19 is no longer supported, remove this use of reflection
|
||||
// and instead set the fields directly.
|
||||
if cmdCancel := reflect.ValueOf(cmd).Elem().FieldByName("Cancel"); cmdCancel.IsValid() {
|
||||
cmdCancel.Set(reflect.ValueOf(func() error {
|
||||
if cancelCtx != nil && ctx.Err() == context.DeadlineExceeded {
|
||||
// The command timed out due to running too close to the test's deadline.
|
||||
// There is no way the test did that intentionally — it's too close to the
|
||||
// wire! — so mark it as a test failure. That way, if the test expects the
|
||||
// command to fail for some other reason, it doesn't have to distinguish
|
||||
// between that reason and a timeout.
|
||||
t.Errorf("test timed out while running command: %v", cmd)
|
||||
} else {
|
||||
// The command is being terminated due to ctx being canceled, but
|
||||
// apparently not due to an explicit test deadline that we added.
|
||||
// Log that information in case it is useful for diagnosing a failure,
|
||||
// but don't actually fail the test because of it.
|
||||
t.Logf("%v: terminating command: %v", ctx.Err(), cmd)
|
||||
}
|
||||
return cmd.Process.Signal(Sigquit)
|
||||
}))
|
||||
}
|
||||
if cmdWaitDelay := reflect.ValueOf(cmd).Elem().FieldByName("WaitDelay"); cmdWaitDelay.IsValid() {
|
||||
cmdWaitDelay.Set(reflect.ValueOf(gracePeriod))
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
if cancelCtx != nil {
|
||||
cancelCtx()
|
||||
}
|
||||
if cmd.Process != nil && cmd.ProcessState == nil {
|
||||
t.Errorf("command was started, but test did not wait for it to complete: %v", cmd)
|
||||
}
|
||||
})
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Command is like exec.Command, but applies the same changes as
|
||||
// testenv.CommandContext (with a default Context).
|
||||
func Command(t testing.TB, name string, args ...string) *exec.Cmd {
|
||||
t.Helper()
|
||||
return CommandContext(t, context.Background(), name, args...)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build windows || plan9 || (js && wasm) || wasip1
|
||||
|
||||
package testenv
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Sigquit is the signal to send to kill a hanging subprocess.
|
||||
// On Unix we send SIGQUIT, but on non-Unix we only have os.Kill.
|
||||
var Sigquit = os.Kill
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build unix
|
||||
|
||||
package testenv
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Sigquit is the signal to send to kill a hanging subprocess.
|
||||
// Send SIGQUIT to get a stack trace.
|
||||
var Sigquit = syscall.SIGQUIT
|
||||
@@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.20
|
||||
|
||||
package wycheproof
|
||||
|
||||
import (
|
||||
|
||||
@@ -6,7 +6,11 @@ package wycheproof
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
"golang.org/x/crypto/cryptobyte/asn1"
|
||||
)
|
||||
|
||||
func TestECDSA(t *testing.T) {
|
||||
@@ -76,9 +80,25 @@ func TestECDSA(t *testing.T) {
|
||||
h.Reset()
|
||||
h.Write(decodeHex(sig.Msg))
|
||||
hashed := h.Sum(nil)
|
||||
got := ecdsa.VerifyASN1(pub, hashed, decodeHex(sig.Sig))
|
||||
sigBytes := decodeHex(sig.Sig)
|
||||
got := ecdsa.VerifyASN1(pub, hashed, sigBytes)
|
||||
if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want {
|
||||
t.Errorf("tcid: %d, type: %s, comment: %q, wanted success: %t", sig.TcID, sig.Result, sig.Comment, want)
|
||||
t.Errorf("tcid: %d, type: %s, comment: %q, VerifyASN1 wanted success: %t", sig.TcID, sig.Result, sig.Comment, want)
|
||||
}
|
||||
|
||||
var r, s big.Int
|
||||
var inner cryptobyte.String
|
||||
input := cryptobyte.String(sigBytes)
|
||||
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
|
||||
!input.Empty() ||
|
||||
!inner.ReadASN1Integer(&r) ||
|
||||
!inner.ReadASN1Integer(&s) ||
|
||||
!inner.Empty() {
|
||||
continue
|
||||
}
|
||||
got = ecdsa.Verify(pub, hashed, &r, &s)
|
||||
if want := shouldPass(sig.Result, sig.Flags, flagsShouldPass); got != want {
|
||||
t.Errorf("tcid: %d, type: %s, comment: %q, Verify wanted success: %t", sig.TcID, sig.Result, sig.Comment, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.13
|
||||
// +build go1.13
|
||||
|
||||
package wycheproof
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
func TestEddsa(t *testing.T) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@@ -28,6 +29,11 @@ const wycheproofModVer = "v0.0.0-20191219022705-2196000605e4"
|
||||
var wycheproofTestVectorsDir string
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
if flag.Lookup("test.short").Value.(flag.Getter).Get().(bool) {
|
||||
log.Println("skipping test that downloads testdata via 'go mod download' in short mode")
|
||||
os.Exit(0)
|
||||
}
|
||||
if _, err := exec.LookPath("go"); err != nil {
|
||||
log.Printf("skipping test because 'go' command is unavailable: %v", err)
|
||||
os.Exit(0)
|
||||
@@ -42,8 +48,6 @@ func TestMain(m *testing.M) {
|
||||
// can be used in the following tests.
|
||||
path := "github.com/google/wycheproof@" + wycheproofModVer
|
||||
cmd := exec.Command("go", "mod", "download", "-json", path)
|
||||
// TODO: enable the sumdb once the Trybots proxy supports it.
|
||||
cmd.Env = append(os.Environ(), "GONOSUMDB=*")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to run `go mod download -json %s`, output: %s", path, output)
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@
|
||||
|
||||
// Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
|
||||
//
|
||||
// Deprecated: MD4 is cryptographically broken and should should only be used
|
||||
// Deprecated: MD4 is cryptographically broken and should only be used
|
||||
// where compatibility with legacy systems, not security, is the goal. Instead,
|
||||
// use a secure hash like SHA-256 (from crypto/sha256).
|
||||
package md4 // import "golang.org/x/crypto/md4"
|
||||
package md4
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ Anonymous sealing/opening is an extension of NaCl defined by and interoperable
|
||||
with libsodium:
|
||||
https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes.
|
||||
*/
|
||||
package box // import "golang.org/x/crypto/nacl/box"
|
||||
package box
|
||||
|
||||
import (
|
||||
cryptorand "crypto/rand"
|
||||
|
||||
@@ -32,7 +32,7 @@ chunk size.
|
||||
|
||||
This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html.
|
||||
*/
|
||||
package secretbox // import "golang.org/x/crypto/nacl/secretbox"
|
||||
package secretbox
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/internal/alias"
|
||||
|
||||
+1
-1
@@ -21,9 +21,9 @@
|
||||
package sign
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
"golang.org/x/crypto/internal/alias"
|
||||
)
|
||||
|
||||
|
||||
+8
-7
@@ -5,7 +5,7 @@
|
||||
// Package ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
|
||||
// are signed messages attesting to the validity of a certificate for a small
|
||||
// period of time. This is used to manage revocation for X.509 certificates.
|
||||
package ocsp // import "golang.org/x/crypto/ocsp"
|
||||
package ocsp
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
@@ -279,21 +279,22 @@ func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier {
|
||||
|
||||
// This is the exposed reflection of the internal OCSP structures.
|
||||
|
||||
// The status values that can be expressed in OCSP. See RFC 6960.
|
||||
// The status values that can be expressed in OCSP. See RFC 6960.
|
||||
// These are used for the Response.Status field.
|
||||
const (
|
||||
// Good means that the certificate is valid.
|
||||
Good = iota
|
||||
Good = 0
|
||||
// Revoked means that the certificate has been deliberately revoked.
|
||||
Revoked
|
||||
Revoked = 1
|
||||
// Unknown means that the OCSP responder doesn't know about the certificate.
|
||||
Unknown
|
||||
Unknown = 2
|
||||
// ServerFailed is unused and was never used (see
|
||||
// https://go-review.googlesource.com/#/c/18944). ParseResponse will
|
||||
// return a ResponseError when an error response is parsed.
|
||||
ServerFailed
|
||||
ServerFailed = 3
|
||||
)
|
||||
|
||||
// The enumerated reasons for revoking a certificate. See RFC 5280.
|
||||
// The enumerated reasons for revoking a certificate. See RFC 5280.
|
||||
const (
|
||||
Unspecified = 0
|
||||
KeyCompromise = 1
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.7
|
||||
// +build go1.7
|
||||
|
||||
package ocsp
|
||||
|
||||
import (
|
||||
|
||||
@@ -10,14 +10,15 @@
|
||||
// for their specific task. If you are required to interoperate with OpenPGP
|
||||
// systems and need a maintained package, consider a community fork.
|
||||
// See https://golang.org/issue/44226.
|
||||
package armor // import "golang.org/x/crypto/openpgp/armor"
|
||||
package armor
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/openpgp/errors"
|
||||
)
|
||||
|
||||
// A Block represents an OpenPGP armored structure.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// for their specific task. If you are required to interoperate with OpenPGP
|
||||
// systems and need a maintained package, consider a community fork.
|
||||
// See https://golang.org/issue/44226.
|
||||
package clearsign // import "golang.org/x/crypto/openpgp/clearsign"
|
||||
package clearsign
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
// https://golang.org/issue/44226), and ElGamal in the OpenPGP ecosystem has
|
||||
// compatibility and security issues (see https://eprint.iacr.org/2021/923).
|
||||
// Moreover, this package doesn't protect against side-channel attacks.
|
||||
package elgamal // import "golang.org/x/crypto/openpgp/elgamal"
|
||||
package elgamal
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// for their specific task. If you are required to interoperate with OpenPGP
|
||||
// systems and need a maintained package, consider a community fork.
|
||||
// See https://golang.org/issue/44226.
|
||||
package errors // import "golang.org/x/crypto/openpgp/errors"
|
||||
package errors
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
+2
-2
@@ -61,7 +61,7 @@ type Key struct {
|
||||
type KeyRing interface {
|
||||
// KeysById returns the set of keys that have the given key id.
|
||||
KeysById(id uint64) []Key
|
||||
// KeysByIdAndUsage returns the set of keys with the given id
|
||||
// KeysByIdUsage returns the set of keys with the given id
|
||||
// that also meet the key usage given by requiredUsage.
|
||||
// The requiredUsage is expressed as the bitwise-OR of
|
||||
// packet.KeyFlag* values.
|
||||
@@ -183,7 +183,7 @@ func (el EntityList) KeysById(id uint64) (keys []Key) {
|
||||
return
|
||||
}
|
||||
|
||||
// KeysByIdAndUsage returns the set of keys with the given id that also meet
|
||||
// KeysByIdUsage returns the set of keys with the given id that also meet
|
||||
// the key usage given by requiredUsage. The requiredUsage is expressed as
|
||||
// the bitwise-OR of packet.KeyFlag* values.
|
||||
func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
|
||||
|
||||
@@ -132,7 +132,7 @@ func TestRevokedUserID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestExternallyRevokableKey attempts to load and parse a key with a third party revocation permission.
|
||||
// TestExternallyRevocableKey attempts to load and parse a key with a third party revocation permission.
|
||||
func TestExternallyRevocableKey(t *testing.T) {
|
||||
kring, err := ReadKeyRing(readerFromHex(subkeyUsageHex))
|
||||
if err != nil {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user