"errors"
"io"
"math/big"
+
+ "golang.org/x/crypto/cryptobyte"
+ "golang.org/x/crypto/cryptobyte/asn1"
)
+import (
+ "crypto/internal/boring"
+ "unsafe"
+)
+
// A invertible implements fast inverse mod Curve.Params().N
type invertible interface {
// Inverse returns the inverse of k in GF(P)
type PublicKey struct {
elliptic.Curve
X, Y *big.Int
+
+ boring unsafe.Pointer
}
+ // Equal reports whether pub and x have the same value.
+ //
+ // Two keys are only considered to have the same value if they have the same Curve value.
+ // Note that for example elliptic.P256() and elliptic.P256().Params() are different
+ // values, as the latter is a generic not constant time implementation.
+ func (pub *PublicKey) Equal(x crypto.PublicKey) bool {
+ xx, ok := x.(*PublicKey)
+ if !ok {
+ return false
+ }
+ return pub.X.Cmp(xx.X) == 0 && pub.Y.Cmp(xx.Y) == 0 &&
+ // Standard library Curve implementations are singletons, so this check
+ // will work for those. Other Curves might be equivalent even if not
+ // singletons, but there is no definitive way to check for that, and
+ // better to err on the side of safety.
+ pub.Curve == xx.Curve
+ }
+
// PrivateKey represents an ECDSA private key.
type PrivateKey struct {
PublicKey
D *big.Int
+
+ boring unsafe.Pointer
}
- type ecdsaSignature struct {
- R, S *big.Int
- }
-
// Public returns the public key corresponding to priv.
func (priv *PrivateKey) Public() crypto.PublicKey {
return &priv.PublicKey
"math/big"
)
+import "crypto/internal/boring"
+
+ // Per RFC 8017, Section 9.1
+ //
+ // EM = MGF1 xor DB || H( 8*0x00 || mHash || salt ) || 0xbc
+ //
+ // where
+ //
+ // DB = PS || 0x01 || salt
+ //
+ // and PS can be empty so
+ //
+ // emLen = dbLen + hLen + 1 = psLen + sLen + hLen + 2
+ //
+
func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) {
- // See [1], section 9.1.1
+ // See RFC 8017, Section 9.1.1.
+
hLen := hash.Size()
sLen := len(salt)
emLen := (emBits + 7) / 8
saltLength = hash.Size()
}
- if opts != nil && opts.Hash != 0 {
- hash = opts.Hash
- }
-
+ if boring.Enabled && rand == boring.RandReader {
+ bkey, err := boringPrivateKey(priv)
+ if err != nil {
+ return nil, err
+ }
- return boring.SignRSAPSS(bkey, hash, hashed, saltLength)
++ return boring.SignRSAPSS(bkey, hash, digest, saltLength)
+ }
+
salt := make([]byte, saltLength)
if _, err := io.ReadFull(rand, salt); err != nil {
return nil, err
}
// VerifyPSS verifies a PSS signature.
- // hashed is the result of hashing the input message using the given hash
- // function and sig is the signature. A valid signature is indicated by
- // returning a nil error. The opts argument may be nil, in which case sensible
- // defaults are used.
- func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts *PSSOptions) error {
- return verifyPSS(pub, hash, hashed, sig, opts.saltLength())
- }
-
- // verifyPSS verifies a PSS signature with the given salt length.
- func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error {
+ //
+ // A valid signature is indicated by returning a nil error. digest must be the
+ // result of hashing the input message using the given hash function. The opts
+ // argument may be nil, in which case sensible defaults are used. opts.Hash is
+ // ignored.
+ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error {
+ if boring.Enabled {
+ bkey, err := boringPublicKey(pub)
+ if err != nil {
+ return err
+ }
- if err := boring.VerifyRSAPSS(bkey, hash, hashed, sig, saltLen); err != nil {
++ if err := boring.VerifyRSAPSS(bkey, hash, digest, sig, opts.saltLength()); err != nil {
+ return ErrVerification
+ }
+ return nil
+ }
- nBits := pub.N.BitLen()
- if len(sig) != (nBits+7)/8 {
+ if len(sig) != pub.Size() {
return ErrVerification
}
s := new(big.Int).SetBytes(sig)
// TestSupportedSignatureAlgorithms checks that all supportedSignatureAlgorithms
// have valid type and hash information.
func TestSupportedSignatureAlgorithms(t *testing.T) {
- for _, sigAlg := range supportedSignatureAlgorithms {
+ for _, sigAlg := range supportedSignatureAlgorithms() {
sigType, hash, err := typeAndHashFromSignatureScheme(sigAlg)
if err != nil {
- t.Errorf("%#04x: unexpected error: %v", sigAlg, err)
+ t.Errorf("%v: unexpected error: %v", sigAlg, err)
}
if sigType == 0 {
- t.Errorf("%#04x: missing signature type", sigAlg)
+ t.Errorf("%v: missing signature type", sigAlg)
}
if hash == 0 && sigAlg != Ed25519 {
- t.Errorf("%#04x: missing hash", sigAlg)
+ t.Errorf("%v: missing hash", sigAlg)
}
}
}