Skip to content

Basic RSA known weak key checking#2765

Merged
jsha merged 9 commits intomasterfrom
new-weak-test
May 25, 2017
Merged

Basic RSA known weak key checking#2765
jsha merged 9 commits intomasterfrom
new-weak-test

Conversation

@rolandshoemaker
Copy link
Copy Markdown
Contributor

Adds a basic truncated modulus hash check for RSA keys that can be used to check keys against the Debian {openssl,openssh,openvpn}-blacklist lists of weak keys generated during the Debian weak key incident.

Testing is gated on adding a new configuration key to the WFE, RA, and CA configs which contains the path to a directory which should contain the weak key lists.

Fixes #157.

@rolandshoemaker rolandshoemaker requested review from cpu and jsha May 15, 2017 21:36
Copy link
Copy Markdown
Contributor

@jsha jsha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend performing a one-time transform of the input into something simpler to parse, like a JSON list.

Also, I think the WFE doesn't need to check for weak keys, so we can leave out the config for it, and somewhat simplify the instantiation. The main reason we call into goodkey in the WFE is to avoid trying to verify JWS signed by large RSA keys.

Comment thread goodkey/weak.go

func (wk *weakKeys) addSuffix(str string) error {
var suffix [10]byte
decoded, err := hex.DecodeString(str)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we assume these are all exactly 10 bytes decoded, we should check that here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment thread goodkey/weak.go
@@ -0,0 +1,59 @@
package goodkey
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a file-level comment describing what this is for.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Copy Markdown
Contributor

@cpu cpu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few small nits but otherwise looking good! Thanks @rolandshoemaker

Comment thread cmd/weak-key-flatten/main.go Outdated
for k := range flattened {
list = append(list, k)
}
jsonList, err := json.Marshal(list)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should err be checked before calling ioutil.WriteFile? It seems like if marshalling fails the jsonList will be written anyway.

Comment thread goodkey/good_key.go Outdated
return berrors.MalformedError("RSA keys are not allowed")
}
if policy.weakRSAList != nil {
if policy.weakRSAList.Known(key.N.Bytes()) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you collapse these two if blocks into one with the condition policy.weakRSAList != nil && policy.weakRSAList.Known(key.N.Bytes()) ?

Comment thread goodkey/weak_test.go Outdated

wk, err := loadSuffixes(tempPath)
test.AssertNotError(t, err, "Failed to load suffixes from directory")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: unnecessary whitespace

Comment thread goodkey/weak.go Outdated
package goodkey

// This file defines a basic method for testing if a given RSA public key is on one of
// the Debian weak key lists and is therefore considered easily enumerable. Instead of
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"...and the private key is therefore considered compromised" insead of "easily enumerable"

Comment thread cmd/boulder-ra/main.go Outdated

// WeakKeyDirectory is the path to a directory containing truncated RSA modulus
// hashes of known easily enumerable keys.
WeakKeyDirectory string
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now a file, not a directory.

Comment thread cmd/weak-key-flatten/main.go Outdated
)

func main() {
inputs := flag.String("inputs", "", "comma separated list of files to flatten")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Describe where to find this list of inputs?

Comment thread cmd/weak-key-flatten/main.go Outdated
}
}

list := []string{}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var list []string

Comment thread cmd/weak-key-flatten/main.go Outdated
}
jsonList, err := json.Marshal(list)
cmd.FailOnError(err, "failed to marshal list")
err = ioutil.WriteFile(*output, jsonList, os.ModePerm)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ModePerm is not right here; let's do 0640 instead.

Comment thread cmd/weak-key-flatten/main.go Outdated
list = append(list, k)
}
jsonList, err := json.Marshal(list)
cmd.FailOnError(err, "failed to marshal list")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For FailOnError I've been trying to move to a style that eliminates the "failed", since it already logs that there is an error. E.g. cmd.FailOnError(err, "marshalling list")

Comment thread goodkey/weak.go Outdated
return nil, err
}

suffixList := []string{}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var suffixList []string

Comment thread goodkey/weak.go Outdated
)

type weakKeys struct {
suffixes map[[10]byte]struct{}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's define a type for [10]byte, e.g. type truncatedHash [10]byte

Comment thread cmd/weak-key-flatten/main.go Outdated
for k := range flattened {
list = append(list, k)
}
jsonList, err := json.Marshal(list)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use MarshalIndent here so we get an entry per line.

Comment thread goodkey/good_key.go Outdated
// NewKeyPolicy returns a KeyPolicy that allows RSA, ECDSA256 and ECDSA384.
func NewKeyPolicy() KeyPolicy {
return KeyPolicy{
func NewKeyPolicy(weakKeyDir string) (KeyPolicy, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*weakKeyFile. Also, please add to the function comment describing the param, and the behavior when it's empty.

Comment thread goodkey/weak.go Outdated
return nil
}

func (wk *weakKeys) Known(modulus []byte) bool {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: It's a little nicer for this to take an *rsa.PublicKey, and abstract away the fact that it really wants .N.Bytes(), which is an implementation detail.

Comment thread test/example-weak-keys.json Outdated
@@ -0,0 +1 @@
["0002a4226a4043426396","00008be7025d9f1a9088","0001313db46d8945bba0","00015b6662ff95aefa3f","000169a60c9eb82a558b","000220bb2bcbc060b8da","00024ac71844e42b0fa6","0002beb9288f6c0140cf","00008f7e6a29aea0b430","00026532237f74a48943","00006aa0ce2cd60e6660","00015e77627966ce16e7","00029956ea9997f257e1","0002a4ba3cf408927759"] No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you regenerate this with MarshalIndent so it's easier to read?

Copy link
Copy Markdown
Contributor

@cpu cpu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks @rolandshoemaker

Only the strong keys survive!
💪 🔑 💪

@jsha jsha merged commit 8ce2f8b into master May 25, 2017
@jsha jsha deleted the new-weak-test branch May 25, 2017 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants