From d92c34cc214a08f60950e997db7e4edf98ecfead Mon Sep 17 00:00:00 2001 From: qmuntal Date: Tue, 24 Oct 2023 15:07:30 +0200 Subject: [PATCH] verify DSA key sizes --- cng/dsa.go | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/cng/dsa.go b/cng/dsa.go index 09b43e6..2c9d62d 100644 --- a/cng/dsa.go +++ b/cng/dsa.go @@ -22,12 +22,17 @@ import ( const maxGroupSize = 32 type dsaAlgorithm struct { - handle bcrypt.ALG_HANDLE + handle bcrypt.ALG_HANDLE + allowedKeyLengths bcrypt.KEY_LENGTHS_STRUCT } func loadDSA() (h dsaAlgorithm, err error) { v, err := loadOrStoreAlg(bcrypt.DSA_ALGORITHM, bcrypt.ALG_NONE_FLAG, "", func(h bcrypt.ALG_HANDLE) (interface{}, error) { - return dsaAlgorithm{h}, nil + lengths, err := getKeyLengths(bcrypt.HANDLE(h)) + if err != nil { + return nil, err + } + return dsaAlgorithm{h, lengths}, nil }) if err != nil { return dsaAlgorithm{}, err @@ -40,6 +45,14 @@ type DSAParameters struct { P, Q, G BigInt } +func (p DSAParameters) keySize() uint32 { + return uint32(len(p.P)) +} + +func (p DSAParameters) groupSize() uint32 { + return uint32(len(p.Q)) +} + // GenerateDSAParameters generates a set of DSA parameters for a key of size L bytes. // If L is less than or equal to 1024, the parameters are generated according to FIPS 186-2. // If L is greater than 1024, the parameters are generated according to FIPS 186-3. @@ -49,6 +62,9 @@ func GenerateDSAParameters(L int) (params DSAParameters, X, Y BigInt, err error) if err != nil { return DSAParameters{}, nil, nil, err } + if !keyIsAllowed(h.allowedKeyLengths, uint32(L)) { + return DSAParameters{}, nil, nil, errors.New("crypto/dsa: invalid key size") + } // To generate the parameters, we need to generate a key pair and then export the public key. // The public key contains the parameters. We then discard the key pair. var hkey bcrypt.KEY_HANDLE @@ -107,8 +123,12 @@ func GenerateKeyDSA(params DSAParameters) (*PrivateKeyDSA, error) { if err != nil { return nil, err } + keySize := params.keySize() + if !keyIsAllowed(h.allowedKeyLengths, keySize*8) { + return nil, errors.New("crypto/dsa: invalid key size") + } var hkey bcrypt.KEY_HANDLE - if err := bcrypt.GenerateKeyPair(h.handle, &hkey, uint32(len(params.P))*8, 0); err != nil { + if err := bcrypt.GenerateKeyPair(h.handle, &hkey, keySize*8, 0); err != nil { return nil, err } if err := setDSAParameter(hkey, params); err != nil { @@ -130,6 +150,10 @@ func NewPrivateKeyDSA(params DSAParameters, X, Y BigInt) (*PrivateKeyDSA, error) if err != nil { return nil, err } + keySize := params.keySize() + if !keyIsAllowed(h.allowedKeyLengths, keySize*8) { + return nil, errors.New("crypto/dsa: invalid key size") + } hkey, err := encodeDSAKey(h.handle, params, X, Y) if err != nil { return nil, err @@ -145,6 +169,10 @@ func NewPublicKeyDSA(params DSAParameters, Y BigInt) (*PublicKeyDSA, error) { if err != nil { return nil, err } + keySize := params.keySize() + if !keyIsAllowed(h.allowedKeyLengths, keySize*8) { + return nil, errors.New("crypto/dsa: invalid key size") + } hkey, err := encodeDSAKey(h.handle, params, nil, Y) if err != nil { return nil, err @@ -212,8 +240,8 @@ func VerifyDSA(pub *PublicKeyDSA, hashed []byte, r, s BigInt) bool { } func encodeDSAKey(h bcrypt.ALG_HANDLE, params DSAParameters, X, Y BigInt) (bcrypt.KEY_HANDLE, error) { - keySize := uint32(len(params.P)) - groupSize := uint32(len(params.Q)) + keySize := params.keySize() + groupSize := params.groupSize() private := X != nil var blob []byte var idx int @@ -355,8 +383,8 @@ func decodeDSAKey(hkey bcrypt.KEY_HANDLE, private bool) (params DSAParameters, X // setDSAParameter sets the DSA parameters for the given key. func setDSAParameter(hkey bcrypt.KEY_HANDLE, params DSAParameters) error { - keySize := uint32(len(params.P)) - groupSize := uint32(len(params.Q)) + keySize := params.keySize() + groupSize := params.groupSize() var blob []byte var idx int appendBigInt := func(b BigInt) { @@ -410,7 +438,7 @@ func dsaAdjustHashSize(hkey bcrypt.KEY_HANDLE, hashed []byte, buf []byte) ([]byt if err != nil { return nil, err } - groupSize := len(params.Q) + groupSize := int(params.groupSize()) if groupSize > len(buf) { panic("output buffer too small") }