| <!-- Copyright 2018 Google LLC |
| |
| Use of this source code is governed by an MIT-style |
| license that can be found in the LICENSE file or at |
| https://opensource.org/licenses/MIT. --> |
| |
| # Contributing |
| |
| ## Cloning |
| |
| ```shell |
| git clone --recursive https://fuchsia.googlesource.com/mundane |
| ``` |
| |
| Development occurs at https://fuchsia.googlesource.com/mundane, with the GitHub |
| repository as a read-only mirror. See [Code reviews](#code-reviews) for details |
| on how to submit changes. |
| |
| Mundane depends on BoringSSL, which is in a Git submodule. When cloning this |
| repository, make sure to pass the `--recursive` flag to Git to also download |
| this submodule. |
| |
| ## Code Guidelines |
| |
| ### Unsafe |
| |
| `unsafe` is not allowed, except for in the `boringssl` module. We |
| `#[forbid(unsafe)]` in all other modules, so code that uses `unsafe` outside of |
| that module should fail to compile. For details on how to use `unsafe` in the |
| `boringssl` module, see the doc comment on that module. |
| |
| ### `#[must_use]` |
| |
| The `#[must_use]` directive causes the compiler to emit a warning if code calls |
| a function but does not use its return value. It is a very useful lint against |
| failing to properly act on the result of cryptographic operations. A |
| `#[must_use]` directive should go on: |
| - All functions/methods (including in trait definitions) which return a value |
| and are visible outside of the crate |
| - In the `boringssl` module: |
| - All functions/methods (including in trait definitions) which return a value |
| and are visible outside of the `boringssl` module or are exported from the |
| `raw` or `wrapper` modules to the top-level `boringssl` module |
| |
| `#[must_use]` may also be used on types, but should be evaluated on a |
| case-by-case basis. A few things to keep in mind: |
| - All functions defined in Mundane which return values have `#[must_use]` on |
| them, so the case of a type returned by a function defined in Mundane is |
| already covered. |
| - Unlike on functions, `#[must_use]` on types affects code other than the |
| immediate caller since code outside of this crate may return types which are |
| defined in this crate. |
| |
| Thus, `#[must_use]` should only be used on a type when it's desired for |
| functions defined outside of this crate which return the type to have |
| `#[must_use]` behavior. |
| |
| As a general rule of thumb, this should be restricted to types which could be |
| used to make security decisions. For example, digests and signatures should have |
| `#[must_use]`, while keys should not have it. |
| |
| *TODO(joshlf): Re-evaluate this policy? Maybe we want to put `#[must_use]` on |
| more types?* |
| |
| ### Insecure |
| |
| Some clients require access to insecure operations in order to interoperate with |
| legacy applications. While we provide these operations, we do so with a few |
| caveats: |
| - We only provide the bare minimum required. For example, while we provide |
| HMAC-SHA1, we do not provide SHA-1 on its own, as it is not needed. |
| - We attempt to make it as difficult as possible for somebody to use an insecure |
| operation unintentionally, as detailed in the next section. |
| |
| #### Adding Insecure Operations |
| |
| We use a number of mechanisms to make it less likely for somebody to use an |
| insecure operation unintentionally or without understanding the implications. |
| They are: |
| - Use of Rust's `#[deprecated]` attribute so that code which uses insecure |
| operations will produce a compiler warning |
| - Naming of insecure types, functions, and methods with an "insecure" prefix so |
| that their use will stand out in code, and their insecurity will stand out |
| when reading their documentation |
| - Documentation comments that stress the operation's insecurity |
| - Placing all insecure operations in their own `insecure` module so that users |
| are unlikely to accidentally come across an insecure operation while browsing |
| other documentation |
| - Placing the `insecure` module behind a feature flag which is disabled by |
| default |
| |
| The whole is also more than the sum of the parts. Taken together, these |
| mechanisms serve to give an appropriate air of gravitas to insecure operations. |
| Users should feel uneasy - like they're wading into dangerous and subtle |
| territory (because they are!). They should be made to feel the gravity of the |
| situation, and to appreciate the importance of carefully considering whether |
| using an insecure operation is appropriate. |
| |
| ##### Deprecation |
| |
| Rust provides the `#[deprecated]` |
| [attribute](https://doc.rust-lang.org/reference/attributes.html) which can be |
| placed on items including modules, types, functions, methods, and traits. If a |
| deprecated item is imported or used, it will cause a compiler warning (two, |
| actually - one for the import, and one for the use in code). |
| |
| In Mundane, all insecure operations must be marked with a `#[deprecated]` |
| attribute with an appropriate message. This includes all items that a user could |
| ever interact with - types, functions, methods, etc. If it has a `pub` in front |
| of it, it needs a deprecation attribute. For example: |
| |
| ```rust |
| #[deprecated(note = "Foo is considered insecure")] |
| pub struct InsecureFooResult; |
| |
| impl InsecureFooResult { |
| #[deprecated(note = "Foo is considered insecure")] |
| pub fn insecure_frobnicate(&self) { ... } |
| } |
| |
| #[deprecated(note = "Foo is considered insecure")] |
| pub fn insecure_foo() -> InsecureFooResult { ... } |
| ``` |
| |
| ##### Naming |
| |
| Every user-facing Rust item associated with an insecure operation carries an |
| "insecure" prefix on its name. For types and traits, this is of the form |
| `Insecure`, while for functions, methods, and modules, it's of the form |
| `insecure_`. See the example from the previous section for a demonstration of |
| this naming. |
| |
| The justification for this is twofold. First, it makes it so that, while reading |
| documentation, it's unlikely for even a casual reader to miss that what they're |
| reading about is a special case that should be carefully considered. Second, it |
| makes it very obvious when reading or reviewing code that makes use of insecure |
| operations. |
| |
| ##### Documentation |
| |
| Every documentation comment on an insecure operation should have the following |
| structure: |
| |
| ```rust |
| /// INSECURE: <summary of operation> |
| /// |
| /// # Security |
| /// |
| /// <operation> is considered insecure, and should only be used for compatibility |
| /// with legacy applications. |
| /// |
| /// <further documentation if necessary> |
| ``` |
| |
| As with naming, this serves to lessen the likelihood that a user will use an |
| insecure operation without realizing what they're doing. |
| |
| ##### Module Isolation |
| |
| All insecure operations are exposed through a top-level `insecure` module, which |
| is itself marked with a deprecation attribute, and carries appropriate |
| module-level documentation. |
| |
| Unfortunately, due to Rust's visibility rules, making this work involves a bit |
| of a dance. For reasons of practicality, insecure operations are defined |
| alongside their secure counterparts. For example, the `InsecureHmacSha1` type is |
| defined in the `hmac` module, and the `InsecureSha1Digest` type is defined in |
| the `hash` module. A programmer's first inclination might be to mark these as |
| `pub(crate)` and attempt to re-export them from the `insecure` module. |
| Unfortunately, Rust forbids this. |
| |
| Instead, we take the somewhat circuitous approach of putting an insecure |
| operation inside of its own `pub(crate)` module (e.g., `hmac::insecure_hmac`). |
| Inside of this module, the insecure operation can be `pub` rather than |
| `pub(crate)`. This, in turn, allows the `insecure` module to re-export the item |
| without running afoul of the compiler. It's an awkward dance, but it makes it so |
| that insecure operations can only be accessed through the `insecure` module, |
| which is a big win. |
| |
| ##### Feature Gating |
| |
| By default, the `insecure` module is not present. The user must explicitly |
| enable the `insecure` feature in order to enable the module. |
| |
| ## Contributor License Agreement |
| |
| Contributions to this project must be accompanied by a Contributor License |
| Agreement. You (or your employer) retain the copyright to your contribution; |
| this simply gives us permission to use and redistribute your contributions as |
| part of the project. Head over to <https://cla.developers.google.com/> to see |
| your current agreements on file or to sign a new one. |
| |
| You generally only need to submit a CLA once, so if you've already submitted one |
| (even if it was for a different project), you probably don't need to do it |
| again. |
| |
| ## Code reviews |
| |
| All submissions, including submissions by project members, require review. We |
| use [Gerrit](https://fuchsia-review.googlesource.com/admin/repos/mundane) for |
| this purpose. |
| |
| ### Setup |
| If you have not done so on this machine, you will need to set up a password for |
| Gerrit. Sign in with a Google account, visit [this |
| link](https://fuchsia.googlesource.com/), and click the "Generate Password" link |
| in the top right. You will also need to prepare your checkout to [add |
| Change-Ids](https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html) |
| on commit. In the repository, run: |
| |
| ``` |
| curl -Lo .git/hooks/commit-msg https://fuchsia-review.googlesource.com/tools/hooks/commit-msg |
| chmod u+x .git/hooks/commit-msg |
| ``` |
| |
| ### Uploading changes |
| To upload a change, push it to the special `refs/for/master` target: |
| |
| ``` |
| git push origin HEAD:refs/for/master |
| ``` |
| |
| Alternatively, to configure the repository so that all pushes go to this target |
| (`git push` on its becomes equivalent to the above): |
| |
| ``` |
| git config remote.origin.push HEAD:refs/for/master |
| ``` |
| |
| The output of `git push` will then give you a link to the change. Add |
| `joshlf@google.com` as a reviewer. |
| |
| Pushing a commit with the same Change-Id as an existing change will upload a new |
| version of it. (Use the `git rebase` or `git commit --amend` commands.) |
| |
| For more detailed instructions, see the [Gerrit User |
| Guide](https://gerrit-review.googlesource.com/Documentation/intro-user.html). |
| |
| ## Community Guidelines |
| |
| This project follows [Google's Open Source Community |
| Guidelines](https://opensource.google.com/conduct/). |