return signature
}
-func signGeneric(signature, privateKey, message []byte) {
+func sign(signature, privateKey, message []byte) {
if l := len(privateKey); l != PrivateKeySize {
panic("ed25519: bad private key length: " + strconv.Itoa(l))
}
// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
- return verify(publicKey, message, sig)
-}
-
-func verifyGeneric(publicKey PublicKey, message, sig []byte) bool {
if l := len(publicKey); l != PublicKeySize {
panic("ed25519: bad public key length: " + strconv.Itoa(l))
}
+++ /dev/null
-// Copyright 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.
-
-// +build !s390x
-
-package ed25519
-
-func sign(signature, privateKey, message []byte) {
- signGeneric(signature, privateKey, message)
-}
-
-func verify(publicKey PublicKey, message, sig []byte) bool {
- return verifyGeneric(publicKey, message, sig)
-}
+++ /dev/null
-// Copyright 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.
-
-package ed25519
-
-import (
- "internal/cpu"
- "strconv"
-)
-
-//go:noescape
-func kdsaSign(message, signature, privateKey []byte) bool
-
-//go:noescape
-func kdsaVerify(message, signature, publicKey []byte) bool
-
-// sign does a check to see if hardware has Edwards Curve instruction available.
-// If it does, use the hardware implementation. Otherwise, use the generic version.
-func sign(signature, privateKey, message []byte) {
- if cpu.S390X.HasEDDSA {
- if l := len(privateKey); l != PrivateKeySize {
- panic("ed25519: bad private key length: " + strconv.Itoa(l))
- }
-
- ret := kdsaSign(message, signature, privateKey[:32])
- if !ret {
- panic("ed25519: kdsa sign has a failure")
- }
- return
- }
- signGeneric(signature, privateKey, message)
-}
-
-// verify does a check to see if hardware has Edwards Curve instruction available.
-// If it does, use the hardware implementation for eddsa verfication. Otherwise, the generic
-// version is used
-func verify(publicKey PublicKey, message, sig []byte) bool {
- if cpu.S390X.HasEDDSA {
- if l := len(publicKey); l != PublicKeySize {
- panic("ed25519: bad public key length: " + strconv.Itoa(l))
- }
-
- if len(sig) != SignatureSize || sig[63]&224 != 0 {
- return false
- }
-
- return kdsaVerify(message, sig, publicKey)
- }
- return verifyGeneric(publicKey, message, sig)
-}
+++ /dev/null
-// Copyright 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.
-
-#include "textflag.h"
-
-// func kdsaSign(message, signature, privateKey []byte) bool
-TEXT ·kdsaSign(SB), $4096-73
- // The kdsa instruction takes function code,
- // buffer's location, message's location and message len
- // as parameters. Out of those, the function code and buffer's location
- // should be placed in R0 and R1 respectively. The message's location
- // and message length should be placed in an even-odd register pair. (e.g: R2 and R3)
-
- // The content of parameter block(buffer) looks like the following:
- // Signature R, Signature S and Private Key all take 32 bytes.
- // In the signing case, the signatures(R and S) will be generated by
- // the signing instruction and get placed in the locations shown in the parameter block.
- // 0 +---------------+
- // | Signature(R) |
- // 32 +---------------+
- // | Signature(S) |
- // 64 +---------------+
- // | Private Key |
- // 96 +---------------+
- // | Reserved |
- // 112+---------------+
- // | |
- // | ... |
- // | |
- // 4088 +---------------+
-
- // The following code section setups the buffer from stack:
- // Get the address of the buffer stack variable.
- MOVD $buffer-4096(SP), R1
-
- // Zero the buffer.
- MOVD R1, R2
- MOVD $(4096/256), R0 // number of 256 byte chunks to clear
-
-clear:
- XC $256, (R2), (R2)
- MOVD $256(R2), R2
- BRCTG R0, clear
-
- MOVD $40, R0 // EDDSA-25519 sign has a function code of 40
- LMG message+0(FP), R2, R3 // R2=base R3=len
- LMG signature+24(FP), R4, R5 // R4=base R5=len
- LMG privateKey+48(FP), R6, R7 // R6=base R7=len
-
- // Checks the length of signature and private key
- CMPBNE R5, $64, panic
- CMPBNE R7, $32, panic
-
- // The instruction uses RFC 8032's private key, which is the first 32 bytes
- // of the private key in this package. So we copy that into the buffer.
- MVC $32, (R6), 64(R1)
-
-loop:
- WORD $0xB93A0002 // The KDSA instruction
- BVS loop // The instruction is exectued by hardware and can be interrupted. This does a retry when that happens.
- BNE error
-
-success:
- // The signatures generated are in big-endian form, so we
- // need to reverse the bytes of Signature(R) and Signature(S) in the buffers to transform
- // them from big-endian to little-endian.
-
- // Transform Signature(R) from big endian to little endian and copy into the signature
- MVCIN $32, 31(R1), (R4)
-
- // Transform Signature(S) from big endian to little endian and copy into the signature
- MVCIN $32, 63(R1), 32(R4)
-
- MOVB $1, ret+72(FP)
- RET
-
-error:
- // return false
- MOVB $0, ret+72(FP)
- RET
-
-panic:
- UNDEF
-
-// func kdsaVerify(message, signature, publicKey []byte) bool
-TEXT ·kdsaVerify(SB), $4096-73
- // The kdsa instruction takes function code,
- // buffer's location, message's location and message len
- // as parameters. Out of those, the function code and buffer's location
- // should be placed in R0 and R1 respectively. The message's location
- // and message length should be placed in an even-odd register pair. (e.g: R2 and R3)
-
- // The parameter block(buffer) is similar to that of signing, except that
- // we use public key for verification, and Signatures(R and S) are provided
- // as input parameters to the parameter block.
- // 0 +---------------+
- // | Signature(R) |
- // 32 +---------------+
- // | Signature(S) |
- // 64 +---------------+
- // | Public Key |
- // 96 +---------------+
- // | Reserved |
- // 112+---------------+
- // | |
- // | ... |
- // | |
- // 4088 +---------------+
-
- // The following code section setups the buffer from stack:
- // Get the address of the buffer stack variable.
- MOVD $buffer-4096(SP), R1
-
- // Zero the buffer.
- MOVD R1, R2
- MOVD $(4096/256), R0 // number of 256 byte chunks to clear
-
-clear:
- XC $256, (R2), (R2)
- MOVD $256(R2), R2
- BRCTG R0, clear
-
- MOVD $32, R0 // EDDSA-25519 verify has a function code of 32
- LMG message+0(FP), R2, R3 // R2=base R3=len
- LMG signature+24(FP), R4, R5 // R4=base R5=len
- LMG publicKey+48(FP), R6, R7 // R6=base R7=len
-
- // Checks the length of public key and signature
- CMPBNE R5, $64, panic
- CMPBNE R7, $32, panic
-
-verify:
- // The instruction needs Signature(R), Signature(S) and public key
- // to be in big-endian form during computation. Therefore,
- // we do the transformation (from little endian to big endian) and copy those into the buffer.
-
- // Transform Signature(R) from little endian to big endian and copy into the buffer
- MVCIN $32, 31(R4), (R1)
-
- // Transform Signature(S) from little endian to big endian and copy into the buffer
- MVCIN $32, 63(R4), 32(R1)
-
- // Transform Public Key from little endian to big endian and copy into the buffer
- MVCIN $32, 31(R6), 64(R1)
-
-verifyLoop:
- WORD $0xB93A0002 // KDSA instruction
- BVS verifyLoop // Retry upon hardware interrupt
- BNE error
-
-success:
- MOVB $1, ret+72(FP)
- RET
-
-error:
- MOVB $0, ret+72(FP)
- RET
-
-panic:
- UNDEF
return len(buf), nil
}
-// signGenericWrapper is identical to Sign except that it unconditionally calls signGeneric directly
-// rather than going through the sign function that might call assembly code.
-func signGenericWrapper(privateKey PrivateKey, msg []byte) []byte {
- sig := make([]byte, SignatureSize)
- signGeneric(sig, privateKey, msg)
- return sig
-}
-
func TestUnmarshalMarshal(t *testing.T) {
pub, _, _ := GenerateKey(rand.Reader)
}
func TestSignVerify(t *testing.T) {
- t.Run("Generic", func(t *testing.T) { testSignVerify(t, signGenericWrapper, verifyGeneric) })
- t.Run("Native", func(t *testing.T) { testSignVerify(t, Sign, Verify) })
-}
-
-func testSignVerify(t *testing.T, signImpl func(privateKey PrivateKey, message []byte) []byte,
- verifyImpl func(publicKey PublicKey, message, sig []byte) bool) {
var zero zeroReader
public, private, _ := GenerateKey(zero)
message := []byte("test message")
- sig := signImpl(private, message)
- if !verifyImpl(public, message, sig) {
+ sig := Sign(private, message)
+ if !Verify(public, message, sig) {
t.Errorf("valid signature rejected")
}
wrongMessage := []byte("wrong message")
- if verifyImpl(public, wrongMessage, sig) {
+ if Verify(public, wrongMessage, sig) {
t.Errorf("signature of different message accepted")
}
}
func TestCryptoSigner(t *testing.T) {
- t.Run("Generic", func(t *testing.T) { testCryptoSigner(t, verifyGeneric) })
- t.Run("Native", func(t *testing.T) { testCryptoSigner(t, Verify) })
-}
-
-func testCryptoSigner(t *testing.T, verifyImpl func(publicKey PublicKey, message, sig []byte) bool) {
var zero zeroReader
public, private, _ := GenerateKey(zero)
t.Fatalf("error from Sign(): %s", err)
}
- if !verifyImpl(public, message, signature) {
+ if !Verify(public, message, signature) {
t.Errorf("Verify failed on signature from Sign()")
}
}
}
func TestGolden(t *testing.T) {
- t.Run("Generic", func(t *testing.T) { testGolden(t, signGenericWrapper, verifyGeneric) })
- t.Run("Native", func(t *testing.T) { testGolden(t, Sign, Verify) })
-}
-
-func testGolden(t *testing.T, signImpl func(privateKey PrivateKey, message []byte) []byte,
- verifyImpl func(publicKey PublicKey, message, sig []byte) bool) {
// sign.input.gz is a selection of test cases from
// https://ed25519.cr.yp.to/python/sign.input
testDataZ, err := os.Open("testdata/sign.input.gz")
copy(priv[:], privBytes)
copy(priv[32:], pubKey)
- sig2 := signImpl(priv[:], msg)
+ sig2 := Sign(priv[:], msg)
if !bytes.Equal(sig, sig2[:]) {
t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
}
- if !verifyImpl(pubKey, msg, sig2) {
+ if !Verify(pubKey, msg, sig2) {
t.Errorf("signature failed to verify on line %d", lineNo)
}
}
func TestMalleability(t *testing.T) {
- t.Run("Generic", func(t *testing.T) { testMalleability(t, verifyGeneric) })
- t.Run("Native", func(t *testing.T) { testMalleability(t, Verify) })
-}
-
-func testMalleability(t *testing.T, verifyImpl func(publicKey PublicKey, message, sig []byte) bool) {
// https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test
// that s be in [0, order). This prevents someone from adding a multiple of
// order to s and obtaining a second valid signature for the same message.
0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa,
}
- if verifyImpl(publicKey, msg, sig) {
+ if Verify(publicKey, msg, sig) {
t.Fatal("non-canonical signature accepted")
}
}