Commit Graph

29 Commits

Author SHA1 Message Date
Eng Zer Jun f6db0fe0a3
test: use `T.TempDir` to create temporary test directory (#5930)
Use the T.TempDir method from the testing package to create temporary
directories for tests. Directories created by T.TempDir are automatically
removed when tests complete.
2022-02-07 12:41:28 -08:00
Aaron Gable 305ef9cce9
Improve error checking paradigm (#5920)
We have decided that we don't like the if err := call(); err != nil
syntax, because it creates confusing scopes, but we have not cleaned up
all existing instances of that syntax. However, we have now found a
case where that syntax enables a bug: It caused readers to believe that
a later err = call() statement was assigning to an already-declared err
in the local scope, when in fact it was assigning to an
already-declared err in the parent scope of a closure. This caused our
ineffassign and staticcheck linters to be unable to analyze the
lifetime of the err variable, and so they did not complain when we
never checked the actual value of that error.

This change standardizes on the two-line error checking syntax
everywhere, so that we can more easily ensure that our linters are
correctly analyzing all error assignments.
2022-02-01 14:42:43 -07:00
Jacob Hoffman-Andrews ad75295f51
Add benchmark for fermat factorization. (#5854) 2021-12-22 14:54:21 -08:00
Aaron Gable 89000bd61c
Add close-primes detection via Fermat's factorization (#5853)
Add a new check to GoodKey which attempts to factor the public modulus
of the presented key using Fermat's factorization method. This method
will succeed if and only if the prime factors are very close to each
other -- i.e. almost certainly were not selected independently from a
random uniform distribution, but were instead calculated via some other
less secure method.

To support this new feature, add a new config flag to the RA, CA, and
WFE, which all use the GoodKey checks. As part of adding this new config
value, refactor the GoodKey config items into their own config struct
which can be re-used across all services.

If the new `FermatRounds` config value has not been set, it will default
to zero, causing no factorization to be attempted.

Fixes #5850
Part of #5851
2021-12-14 09:19:33 -08:00
Aaron Gable bab688b98f
Remove sa-wrappers.go (#5663)
Remove the last of the gRPC wrapper files. In order to do so:

- Remove the `core.StorageGetter` interface. Replace it with a new
  interface (whose methods include the `...grpc.CallOption` arg)
  inside the `sa/proto/` package.
- Remove the `core.StorageAdder` interface. There's no real use-case
  for having a write-only interface.
- Remove the `core.StorageAuthority` interface, as it is now redundant
  with the autogenerated `sapb.StorageAuthorityClient` interface.
- Replace the `certificateStorage` interface (which appears in two
  different places) with a single unified interface also in `sa/proto/`.
- Update all test mocks to include the `_ ...grpc.CallOption` arg in
  their method signatures so they match the gRPC client interface.
- Delete many methods from mocks which are no longer necessary (mostly
  because they're mocking old authz1 methods that no longer exist).
- Move the two `test/inmem/` wrappers into their own sub-packages to
  avoid an import cycle.
- Simplify the `satest` package to satisfy one of its TODOs and to
  avoid an import cycle.
- Add many methods to the `test/inmem/sa/` wrapper, to accommodate all
  of the methods which are called in unittests.

Fixes #5600
2021-09-27 13:25:41 -07:00
Aaron Gable 294d1c31d7
Use error wrapping for berrors and tests (#5169)
This change adds two new test assertion helpers, `AssertErrorIs`
and `AssertErrorWraps`. The former is a wrapper around `errors.Is`,
and asserts that the error's wrapping chain contains a specific (i.e.
singleton) error. The latter is a wrapper around `errors.As`, and
asserts that the error's wrapping chain contains any error which is
of the given type; it also has the same unwrapping side effect as
`errors.As`, which can be useful for further assertions about the
contents of the error.

It also makes two small changes to our `berrors` package, namely
making `berrors.ErrorType` itself an error rather than just an int,
and giving `berrors.BoulderError` an `Unwrap()` method which
exposes that inner `ErrorType`. This allows us to use the two new
helpers above to make assertions about berrors, rather than
having to hand-roll equality assertions about their types.

Finally, it takes advantage of the two changes above to greatly
simplify many of the assertions in our tests, removing conditional
checks and replacing them with simple assertions.
2020-11-06 13:17:11 -08:00
Jacob Hoffman-Andrews 8dd386b6bc
SA: Update RPC interface to proto3 (#5043)
One slightly surprising / interesting thing: Since core types like
Order and Registration are still proto2 and have pointer fields,
there are actually some places in this PR where I had to add
a `*` rather than delete an `&`, because I was taking a pointer
field from one of those core types and passing it as a field in
an SA RPC request.

Fixes #5037.
2020-08-25 10:28:41 -07:00
Jacob Hoffman-Andrews baf2a5be6e
sa: remove nil checks for zero-able fields. (#5034)
As part of the migration to proto3, any fields in requests that may be
zero should also be allowed to be nil. That's because proto3 will
represent those fields as absent when they have their zero value.

This is based on a manual review of the wrappers for the SA, plus
a pair of integration test runs. For the integration test runs I took these
steps:

1. Copy sa/proto to sa/proto2
2. Change sa/proto to use proto3 and regenerate.
3. In sa/*.go and cmd/boulder-sa/main.go, update the imports to use the
    proto2 version.
4. Split grpc/sa-wrappers.go into sa-server-wrappers.go and sa-wrappers.go
    (containing the client code)
5. In sa-server-wrappers.go, change the import to use sa/proto2.
6. In sa-server-wrappers.go, make a local copy of the core.StorageAuthority
    interface that uses the sa/proto2 types. This was necessary as
    a temporary kludge because of how the server wrapper internally
    uses the core.StorageAuthority interface.
7. Fix all the pointer-vs-value build errors in every other package.
8. Run integration tests.

I also performed those steps with proto2 and proto3 swapped, to confirm the
behavior when a proto2 client talks to a proto3 SA.
2020-08-18 16:20:07 -07:00
Aaron Gable 4a85abf25a
Fix error types emitted by good_key.go (#4932)
The `KeyPolicy.GoodKey` method is used to validate both public keys
used to sign JWK messages, and public keys contained inside CSR
messages.

According to RFC8555 section 6.7, validation failure in the former
case should result in `badPublicKey`, while validation failure in
the latter case should result in `badCSR`. In either case, a failure
due to reasons other than the key itself should result in
`serverInternal`.

However, the GoodKey method returns a variety of different errors
which are not all applicable depending on the context in which it is
called. In addition, the `csr.VerifyCSR` method passes these errors
through verbatim, resulting in ACME clients receiving confusing and
incorrect error message types.

This change causes the GoodKey method to always return either a
generic error or a KeyError. Calling methods should treat a `KeyError`
as either a `badPublicKey` or a `badCSR` depending on their context,
and may treat a generic error however they choose (though likely as a
serverInternal error).

Fixes #4930
2020-07-06 10:06:10 -07:00
Alexander Scheel a505ff80bb
Use GCD to check RSA moduli for small primes (#4883)
The existing checkSmallPrimes function maintains a table of primes,
converts them to an array of *big.Int and uses the resulting values
for comparing against a RSA modulus as follows:

    for _, prime := range smallPrimes {
        if modulus % prime != 0 {
            return invalid
        }
    }
    return valid

This incurs substantial overhead as each prime is checked individually,
invoking QuoRem(...) each time. By multiplying the primes together into
a single *big.Int, we can utilize a single library call, GCD(...), and
check all the values at once. While a single GCD invocation is slower
than a single QuoRem, 133 such invocations of QuoRem are together
slower than the single GCD.

BenchmarkSmallPrimeGCD
BenchmarkSmallPrimeGCD-4                       72759             16240 ns/op
BenchmarkSmallPrimeIndividualMods
BenchmarkSmallPrimeIndividualMods-4             8866            165265 ns/op

This gives us room to later increase the number of smallPrimes, if
desired, while keeping the same timing profile. Currently the product
of the 133 primes in smallPrimes fits within 1040 bits.

Signed-off-by: Alexander Scheel <alexander.m.scheel@gmail.com>
2020-06-24 13:05:47 -07:00
Roland Bracewell Shoemaker 56898e8953
Log RSA key sizes in WFE/WFE2 and add feature to restrict them (#4839)
Currently 99.99% of RSA keys we see in certificates at Let's Encrypt are
either 2048, 3072, or 4096 bits, but we support every 8 bit increment
between 2048 and 4096. Supporting these uncommon key sizes opens us up to
having to block much larger ranges of keys when dealing with something
like the Debian weak keys incident. Instead we should just reduce the
set of key sizes we support down to what people actually use.

Fixes #4835.
2020-06-08 11:23:27 -07:00
alexzorin 97147d81dd
goodkey: early rejection of unsupported key types (#4809)
This prevents a confusing error being emitted by blockedKeys.blocked.

Fixes #4728
2020-05-18 17:02:00 -07:00
Roland Bracewell Shoemaker 9df97cbf06
Add a blocked keys table, and use it (#4773)
Fixes #4712 and fixes #4711.
2020-04-15 13:42:51 -07:00
Roland Bracewell Shoemaker 7cc5f64a48
Reject RSA keys with non-standard exponent (#4769)
Only allow the RSA exponent 65537, which is the defacto standard (only 3 unexpired certificates issued by Let's Encrypt use a different exponent).
2020-04-13 15:29:32 -07:00
Jacob Hoffman-Andrews 0db7d9ff89
Block keys using hex(sha256(spki)). (#4745)
In addition to base64(sha256(spki)).

As part of that, change KeyDigest to return [32]byte, and add KeyDigestB64 which provides the base64-encoded output that KeyDigest used to provide. Also update all call sites.
2020-04-09 09:41:33 -07:00
Roland Bracewell Shoemaker 324d92d7c5
goodkey cleanups (#4754)
Fixes #4748 and fixes #4740.
2020-04-08 17:57:23 -07:00
Jacob Hoffman-Andrews 49043a4156 Clarify public key blocklist documentation. (#4523)
Previously, we referred to "DER encoded PKIX public keys", but PKIX (RFC 5280)
doesn't define a standalone "public key" type. Instead, it defines
SubjectPublicKeyInfo, containing an algorithm and a BIT STRING. As a
result, SPKI and SPKI hash are more commonly used terms, and we're more
likely to get reports based on those. We should mirror that terminology
in our documentation.
2019-11-04 09:10:36 -05:00
Daniel McCarney f02e9da38f
Support admin. blocking public keys. (#4419)
We occasionally have reason to block public keys from being used in CSRs
or for JWKs. This work adds support for loading a YAML blocked keys list
to the WFE, the RA and the CA (all the components already using the
`goodekey` package).

The list is loaded in-memory and is intended to be used sparingly and
not for more complicated mass blocking scenarios. This augments the
existing debian weak key checking which is specific to RSA keys and
operates on a truncated hash of the key modulus. In comparison the
admin. blocked keys are identified by the Base64 encoding of a SHA256
hash over the DER encoding of the public key expressed as a PKIX subject
public key. For ECDSA keys in particular we believe a more thorough
solution would have to consider inverted curve points but to start we're
calling this approach "Good Enough".

A utility program (`block-a-key`) is provided that can read a PEM
formatted x509 certificate or a JSON formatted JWK and emit lines to be
added to the blocked keys YAML to block the related public key.

A test blocked keys YAML file is included
(`test/example-blocked-keys.yml`), initially populated with a few of the
keys from the `test/` directory. We may want to do a more through pass
through Boulder's source code and add a block entry for every test
private key.

Resolves https://github.com/letsencrypt/boulder/issues/4404
2019-09-06 16:54:26 -04:00
alexzorin bc200cbedc Use %T in GoodKey error fmt to handle nil keys (#4138)
* Use %T in GoodKey error fmt to handle nil keys

This is to prevent nil keys from generating format errors such as:
    unknown key type %!s(\u003cnil\u003e)

* Add GoodKey test for nil keys

The fmt package says:
>All errors begin with the string "%!" followed sometimes by a single character (the verb) and end with a parenthesized description.

This test ensures an error is generated and that '%!' marker is not
present.
2019-04-02 08:20:54 -04:00
Jacob Hoffman-Andrews b3f5c0f6e5
Speed up goodkey test. (#3733)
This is one of our slowest unittests, clocking in at 23 seconds in a recent run.
This was largely due to generating keys. Note that performance is significantly
worse under the race detector.
2018-05-23 16:11:46 -07:00
Jacob Hoffman-Andrews cd49316493 Do ROCAChecks by default. (#3283)
This feature flag has been enabled in prod, and we don't expect to want to
turn it off any time soon.
2017-12-15 13:44:39 -08:00
Jacob Hoffman-Andrews 5df083a57e Add ROCA weak key checking (#3189)
Thanks to @titanous for the library!
2017-11-02 08:42:59 -04:00
Roland Bracewell Shoemaker 2d3fc8c4b4 Add tool to search for certificates containing debian weak keys (#3077)
Fixes #3074.
2017-09-13 10:59:58 -07:00
Daniel McCarney 2a84bc2495 Replace go-jose v1 with go-jose v2. (#2899)
This commit replaces the Boulder dependency on
gopkg.in/square/go-jose.v1 with gopkg.in/square/go-jose.v2. This is
necessary both to stay in front of bitrot and because the ACME v2 work
will require a feature from go-jose.v2 for JWS validation.

The largest part of this diff is cosmetic changes:

Changing import paths
jose.JsonWebKey -> jose.JSONWebKey
jose.JsonWebSignature -> jose.JSONWebSignature
jose.JoseHeader -> jose.Header
Some more significant changes were caused by updates in the API for
for creating new jose.Signer instances. Previously we constructed
these with jose.NewSigner(algorithm, key). Now these are created with
jose.NewSigner(jose.SigningKey{},jose.SignerOptions{}). At present all
signers specify EmbedJWK: true but this will likely change with
follow-up ACME V2 work.

Another change was the removal of the jose.LoadPrivateKey function
that the wfe tests relied on. The jose v2 API removed these functions,
moving them to a cmd's main package where we can't easily import them.
This function was reimplemented in the WFE's test code & updated to fail
fast rather than return errors.

Per CONTRIBUTING.md I have verified the go-jose.v2 tests at the imported
commit pass:

ok      gopkg.in/square/go-jose.v2      14.771s
ok      gopkg.in/square/go-jose.v2/cipher       0.025s
?       gopkg.in/square/go-jose.v2/jose-util    [no test files]
ok      gopkg.in/square/go-jose.v2/json 1.230s
ok      gopkg.in/square/go-jose.v2/jwt  0.073s

Resolves #2880
2017-07-26 10:55:14 -07:00
Roland Bracewell Shoemaker 7c6183b3b4 Fix debian weak key testing (#2884)
Initial implementation constructed the hash input incorrectly. New test uses a key modulus that is actually on the openssl weak key list instead of a random placeholder.
2017-07-20 12:25:32 -07:00
Roland Bracewell Shoemaker 8ce2f8b432 Basic RSA known weak key checking (#2765)
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](https://wiki.debian.org/SSLkeys).

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.
2017-05-25 09:33:58 -07:00
Roland Bracewell Shoemaker e2b2511898 Overhaul internal error usage (#2583)
This patch removes all usages of the `core.XXXError` and almost all usages of `probs` outside of the WFE and VA and replaces them with a unified internal error type. Since the VA uses `probs.ProblemDetails` quite extensively in challenges, and currently stores them in the DB I've saved this change for another change (it'll also require a migration). Since `ProblemDetails` should only ever be exposed to end-users all of its related logic should be moved into the `WFE` but since it still needs to be exposed to the VA and SA I've left it in place for now.

The new internal `errors` package offers the same convenience functions as `probs` does as well as a new simpler type testing method. A few small changes have also been made to error messages, mainly adding the library and function name to internal server errors for easier debugging (i.e. where a number of functions return the exact same errors and there is no other way to distinguish which method threw the error).

Also adds proper encoding of internal errors transferred over gRPC (the current encoding scheme is kept for `core` and `probs` errors since it'll be ideally be removed after we deploy this and follow-up changes) using `grpc/metadata` instead of the gRPC status codes.

Fixes #2507. Updates #2254 and #2505.
2017-03-22 23:27:31 -07:00
Ben Irving b587d4e663 Simplify KeyPolicy code (#2092)
This PR, removes the allowedSigningAlgos configuration struct and hard codes a key policy.

Fixes #1844
2016-07-30 16:15:19 -07:00
Jacob Hoffman-Andrews 9a4b979397 Move goodkey and nonce out of core (#1869) 2016-06-02 11:29:58 -07:00