Browse Source

Initial commit of spec template and key reset spec draft (incomplete).

Initial commit of interim spec template and mostly-but-not-entirely-finished key reset specification draft. N.B.: Key reset spec is intended to give an example for future specs of *as-yet-unimplemented* protocols, since there was some disagreement on what is necessary. Since it has already been implemented, there will be several sections missing that are in the initial template.

Start from the initial template, and use what you need! Each specification is different. Necessary, though, are the problem framing, examples and the requirements they drive, and the response to those examples in the protocol description section.

Anyway, not complete. Just archived for now.
darthmama 11 months ago
committed by Krista Bennett
2 changed files with 856 additions and 0 deletions
  1. +708
  2. +148

+ 708
- 0 View File

@ -0,0 +1,708 @@
# Key Reset
## Front matter
<tr><td> Title: </td><td> Key Reset Specification </td></tr>
<tr><td> Author: </td><td> Krista Bennett </td></tr>
<tr><td> Team: </td><td> Engine Team </td></tr>
<tr><td> Reviewer(s): </td><td> TBD </td></tr>
<tr><td> Created: </td><td> 2020-11-02 </td></tr>
<tr><td> Last updated: </td><td> 2020-11-09 </td></tr>
<tr><td> Ticket reference: </td><td> ENGINE-842 </td></tr>
*Style note: the author has chosen to use the singular 'they' throughout the
document to refer to unspecified users and communications partners in examples. Efforts have
been made to ensure the singular/plural context is clear.*
## Introduction
One of p≡p's challenges as an encryption product which automates as
much of the key management and trust process as possible is that when there are
key related issues - e.g. compromise, revocation, or simply needing to use a
different default key for a partner - the software must be able to provide both
internal and user access to the ability to change these default keys without actually
exposing the concept of keys, which goes against p≡p's "Pretty Easy" principle,
or the details of trust management.
This document describes the **Key Reset** protocol, which is implemented primarily in
the engine and allows applications to provide simple high level functionality to users
needing to perform some of the aforementioned functions while still ensuring that
the appropriate low-level changes in keyrings and trust management are handled
consistently, and that communication of these changes to active partners (where necessary)
happens seamlessly, without explicit action on the part of the user.
Additionally, the protocol provides important lower-level *internal* functionality to other internal
protocols (e.g. **KeySync**).
### Glossary
The following are terms used in the document which may not be familiar to developers new to the system, and are defined
upfront for easy reference.
<dt><a name="address"> Address </a></dt>
<dd> A specific endpoint messages can be routed to (e.g. an email address). Can belong to one or more <i>users</i>. </dd>
<dt><a name="default_key"> Default key </a></dt>
<dd> The key which is, for an identity or user, marked as the key to be used to encrypt to
(in the case of communications partners) or to sign with (in the case of the own user).</dd>
<dt><a name="device_group"> Device group </a></dt>
<dd> A set of devices controlled by one p≡p user which synchronise selected identity information
(including chosen private keys) across the group. (See the **KeySync** protocol.)</dd>
<dt><a name="identity"> Identity </a></dt>
<dd> A binding between a <i>user</i> and an <i>address</i>. Each identity is uniquely identified
by this binding. Identities contain a number of different pieces of information, often including,
but not limited to:
<!-- html because markdown screams at the indent -->
<li> the user id </li>
<li> the address </li>
<li> a default key </li>
<li> a username </li>
<li> a preferred encryption format </li>
<li> information about whether this is an own identity </li>
<li> ... </li>
<dt><a name="keysync"> KeySync </a></dt>
<dd> A synchronisation protocol for sharing and maintaining private keys across a user's p≡p installations </dd>
<dt><a name="own_ident"> Own identity </a></dt>
<dd> An identity corresponding to one of the own user's addresses. </dd>
<dt><a name="own_key"> Own key </a></dt>
<dd> A public/private keypair corresponding to one of the user's own identities. </dd>
<dt><a name="trustwords"> Trustwords </a></dt>
<dd> A set of words generated from the combined key fingerprints of a communications pair,
used for verification and establishment of trust (for the respective keys and partners).</dd>
<dt><a name="user"> User </a></dt>
<dd> An individual entity using p≡p. A user will have one or more <i>identities</i>. </dd>
<dt><a name="user_id"> User ID </a></dt>
<dd> The unique identifier for a given <i>user</i>. </dd>
### Problem Description
#### Context: p≡p and default keys
p≡p has, for every [identity](#identity) (where possible), a [default key](#default_key) used for encryption and signing of messages (or their
For the individual p≡p [user](#user) and corresponding [address](#address), their own default key is
the key they use to sign messages to others, to decrypt messages from communications
partners, and to encrypt messages to themselves.
Additionally, however, for every identity that this user communicates with, there is (where available) a default key
belonging to the communications partner which is used to encrypt messages to that identity and to verify messages signed by
that identity.
A user may have several identities, and each of those identities may have a distinct default
These defaults generally stay stable unless a key becomes invalid or unusable. However,
there are times when a user or an internal protocol needs to *reset* these defaults and
replace them with new ones. Additionally, when a user begins using a new default key,
they may need to communicate this change of desired defaults to communications partners.
Or an automated internal protocol may, for example, have a reason to invalidate one or more
of a user's own keys
Within the p≡p environment, there are several circumstances under which we might need
to reset the default key that p≡p would ordinarily use as the default key either for
the user themselves to sign messages and data, or for a communications partner in
order to encrypt it. A user may need to revoke one or more of their own keys due to compromise or accidental
creation of a new key. And internally, there are protocols, such as [KeySync](#keysync), which, as part of automated
key management, may need to securely force removal and regeneration of default keys across devices.
#### Problem summary
The big picture problem comes in two parts:
1. Users who have had their devices/systems compromised need a fast and easy way to ensure that their own default keys are revoked and replaced,
that these changes are communicated to partners as seamlessly as possible, and that their partners are able to start
using the correct key with little or no interaction.
2. In the case that a partner is using a key which is either not the user's real key or is a key that the user no longer has access to, there needs
to be a way for that user to contact the partner on a second channel to tell them to stop using that key for their address.
Because we want to abstract the idea of keys away from the user, having them only focus on their contacts and
the expression of trust with these contacts as applied to the sending and receipt of messages, p≡p must
provide a way for apps to create this abstraction without needing to retain information about specific keys, especially
since we want to avoid users interacting with the idea of keys at all costs.
Thus, we need a way for the engine to provide this functionality for both the reset of own keys belonging to an own identity
as well as such a reset for partner keys belonging to a partner identity which does not require any information
about keys from the application or external protocol layer, while still ensuring the the appropriate low-level
(keyring and management database) actions can occur appropriately.
We also need to be able to ensure that partners a user who has reset their own key(s) contacts regularly can be notified
and informed that they should use the new key (and stop using the old one) corresponding to the specific user address
they have been communicating with without the need for the user to inform partners explicitly while still ensuring
some verification that this information actually came from the user.
The **Key Reset** protocol aims to solve this problem of providing an abstraction to the adapter/application layer as well as
providing both opportunistic and situation-based automated communication of changes to partners without compromising
the trust system and minimising man-in-the-middle attacks. It does this by providing API functions which operate
at both the user and identity levels for both own users and partners, using the engine to both map identity information to keys
and to do all key manipulation and management database functions, as well as to automate the partner-notification process.
Implementation of this protocol impacts engine development, the adapter team (which must wrap the API functions for applications),
and the application layer, where apps must decide where and how they call these functions and build the necessary
user abstractions to execute the protocol (e.g. a "Reset User" button in the UI which contextually requests that keys are
reset for the current user being displayed).
This document is intended for developers at these three levels.
### Background
Early implementations of p≡p lacked an easy means for high-level key revocation of own keys, for partners to
stop using a key at the request of the user, and for notification of default key changes through revocation to communications
partners. This made it very difficult to clear [default key](#default_key) data when desired without forcing applications to keep track
of default key information, and partners would continue encrypting messages to the older default key. There was no means
for applications to simply tell the engine, "please reset all key data for this identity", or to automatically tell partners
they were using a revoked key and to start using a new one.
Key reset provides this functionality, which can be used both by applications and by internal protocols to provide
these functions under a variety of circumstances.
### Goals, Product, and Technical Requirements
#### Overall requirements driven by user examples
This section uses key use cases to create a list of requirements the key reset protocol must fulfill. This is
central to designing a solution.
One preexisting requirement, however, that impacts all of the examples is this, and is driven by one of the principles
of the system, which is that users should neither need to know or care about the concept of "keys":
1. Default key removal and/or replacements must be possible from the application or external protocol level
*without* the application or external protocol having to have knowledge of the specific default key, only the identity or user.
The engine must use this information to determine which keys to reset.
##### <a name="req_ex_1"> Example 1: Own single key replacement with new key </a>
A p≡p user decides, for any reason, that they want to replace their current default key for one of their identities[^1].
([^1]: This is current generally not expressed at the application later for reasons to be explained in section TODO; however,
it remains possible from the engine level) The key should not be used by communication partners in the future, and they want
to ensure the old key is invalid for future use by communications partners or adversaries.
This creates the following additional requirements in addition to 1. above:
2. The protocol must provide a mechanism at the cryptographic engine level (i.e. within the keyring) for the revocation
of the own default key associated with this identity.
3. The protocol must provide a mechanism for the generation of a new keypair corresponding to this identity and to
assign this key as the identity default.
4. If the key being replaced was also the user default, the new key generated by 3) must replace the first key in
the management database as the user default key.
5. Communications partners must be informed, at latest at the first reply to a message encrypted to the now-revoked key,
of the revocation of the first key and its replacement with the second.
6. The notification in 5. requires communication of both the revocation in 2 via a revocation certificate (signed by
the now-revoked key) and the public part of the new keypair.
7. The notification in 5. must, at the very least, contain some artifact that requires the private key of
the now-revoked key to produce (e.g. a revocation certificate).
8. The notification in 5. must, at a minimum, be signed with the private key of the new keypair.[^signing_w_revoked]
([^signing_w_revoked]: This is because once revoked, we cannot sign with the old private key.)
##### <a name="req_ex_2"> Example 2: Device compromise - simple case (single device) </a>
A p≡p user is forced to unlock and give up their phone at the border[^2]. ([^2]: The "device compromise" use case can happen
in other ways, but we want to initially provide the simplest case, where the user recovers the same device after compromise.
Dealing with device compromise from another device is handled later).
They want to ensure that the keys on that phone are no longer valid for use in order to prevent unauthorised parties from
decrypting their future communications or posing as an imposter, sending mails which can be falsely "verified" as them.
This creates the following requirements:
9. Expanding on 2 above, the protocol must provide a mechanism for the revocation of *all* own keys
at the cryptographic engine level (i.e. within the keyring) associated with:
1. the user, and
2. all of the user's identities
10. Expanding on 3 above, the protocol must provide a mechanism for the generation of new keys corresponding to *each impacted identity* and to
assign them as new default keys for that corresponding identity.
11. The user default key must be replaced with one of the new default keys of the impacted identities.
12. For each newly-revoked key, communications partners must be informed *from the corresponding identity they have corresponded with* of the
revocation of the first key and replacement of the second according to requirements 5, 6, 7, and 8.
##### <a name="req_ex_3"> Example 3: Encryption to a revoked p≡p partner key </a>
A p≡p user, Alice, has the public key of another p≡p user, Bob. Bob has done a key reset of his own key, but Alice is not among the people
he has yet notified of this change. Because Alice does not know that Bob has a new key,
the public key she uses to encrypt to him corresponds to a key he
has already revoked and does not want others to use. While the initial encryption to Bob using this key cannot be stopped, as Alice is unaware of
its invalidity, Bob needs to be certain that on the next round of communication originating from Alice, she uses the correct new key to
encrypt to him, replacing the older key as its default in the corresponding Bob identity in her database.
That said, if Alice and Bob have exchanged Trustwords and Bob's old key was trusted (creating a "green" channel in the
parlance of the applications), Bob's new key should *not* retain this trust; rather, Alice and Bob should have to
exchange trustwords again to establish trust for this particular new key, while still maintaining other communications
channel information, such as whether or not Bob is a p≡p user.
This creates the following additional requirements:
13. The protocol must detect when a message has been sent to an own key that is revoked
14. If such a message was sent by a p≡p user, then the protocol must, as a response, generate and send a notification
to the relevant partner as specified in requirements 5 through 8.
The p≡p communications partner must have the means to process and validate such a notification. This creates the following
relevant requirements:
15. The protocol must provide the means for processing and validating notifications as specified in requirements 5 through 8. This
requires 16-21:
16. The protocol must verify that the notification contains at least one artifact signed by the now-revoked previous key.
17. The protocol must process the revocation certificate of the sender, recording the revocation with the cryptographic engine
and mistrusting the revoked key in the management database. This certificate fulfills the requirement in a. above.
18. The protocol must verify that this revoked key corresponds to the extant default key of the user.
19. The protocol must verify that the replacement key is attached to the message and corresponds to the key information
given in the received key reset message
20. The protocol must set the received key as the default key for the communications partner
21. The protocol must ensure that any trusted status gained by the previous exchange of Trustwords with the sending partner
is removed; trusted status can only be set with the new key upon a new exchange of Trustwords.
##### <a name="req_ex_4"> Example 4: Manually changing use of an incorrect partner key </a>
A p≡p user has a key set as default for a communications partner that this partner does not want used for communication for
a particular address (and, thus, in p≡p terms, a particular identity). However, that
partner is not using, and may not have access to, the key reset mechanism for that key. This could happen if the partner
is an OpenPGP partner, if the partner only had their private key on one device which is now inaccessible to them, or if the
partner does not intend to revoke that key, they simply do not want it used for the address associated with the identity
in question.
p≡p needs to provide a mechanism for the user to manually indicate that this key should not be used as the
This creates the following requirement:
22. The protocol must provide a means for the user to manually remove the default key for a partner identity.
(Note that if there is a compromise indicated, the p≡p protocol itself provides the means for users to mistrust keys
of their contacts, and that this is not an explicit part of manual key reset of partner keys.)
##### <a name="req_ex_5"> Example 5: Removing trust or mistrust from a communications partner key </a>
A p≡p user may have exchanged Trustwords with a partner and accidentally or intentionally confirmed them and want to
rescind that decision. Alternately, a p≡p user may have mistrusted a partner key and want to rescind that decision.
These two possibilities imply the following requirements:
23. The protocol must provide a means for users to reset trusted or mistrusted status for default communications partner keys.
##### <a name="req_ex_6"> Example 6: KeySync: Reset own keys </a>
*N.B. This example requires understanding of the KeySync protocol, which is out of scope for this document. Minimal key
terms are defined in the glossary.*
KeySync is a protocol which allows several of a user's different devices running p≡p to synchronise and use the same private keys
for synchronised own identities. This group of devices is called a *device group*.
A user may decide to reset one or more keys associated with identities marked for synchronisation. The request for reset
is done on a single device, but must be propagated to the other devices. Because this is an automated reset of
*own private keys* initiated externally for the other devices, it has some additional special requirements for security
reasons, in addition to requirements 9-12:
24. The protocol must provide the means for notifying own devices of the reset of shared keys
25. The protocol must provide the means for the initiating device to communicate key reset information in a message
signed by one of the keys to be reset, which will still be valid from the recipient device point of view upon
26. The protocol must provide the means for the initiating device to fulfill requirements 9-12 while still fulfilling
requirement 25.
27. The protocol must provide the means for communicating the following additional key reset information to
non-initiating devices within the device group:
1. Identities impacted
2. New public/private key material for the respective replacement default keys and their binding
3. Mapping of old defaults keys to new keys
28. The protocol must provide the means for receipt and verification of this reset communcation by non-initiating
devices in the device group, including ensuring signature by an own, extant key from one the synchronised identities
in the device group
29. The protocol must provide the means for the import and setting of these replacement keys according to their respective,
identities, along with local revocation of the default keys being replaced, according to requirements 2 and 4 for
each respective identity, as well as enabling communications corresponding to requirements 5-8 when in receipt
of messages to a revoked key
30. If initial opportunistic notification of recent contact partners is desired as part of the implementation, then
the initiating device will perform the unsolicitied notification to contact partners according to requirement 12.
[comment]: <> (### Non-Goals or Out of Scope)
[comment]: <> (### Future Goals)
[comment]: <> (### Assumptions)
[comment]: <> (- Conditions and resources that need to be present and accessible for the solution to work as described.)
## Proposed solution
### Status quo
This specification is being written *a posteriori*; thus, there already exists an implementation which
fulfills these requirements.
### Proposed Solution / Design
#### Overview of solution
The **Key Reset** protocol provides a high-level API to the adapter/application level which allows the reset, according
to the requirements above, of either all of a user's default keys in the database, or of the default key associated
with a specific identity. These functions are opaque to the upper layers; any necessary communications will be dropped
into the applications message queue directly by the protocol, and all underlying database manipulation, key generation,
etc, is done in the engine without further interaction with the application.
The engine is responsible for evaluating the input identity or identities (if only a user is specified to the engine),
determining whether it is an own identity or a partner identity, and processing the reset appropriately according
to the requirements, including management database manipulation, default key setting, and, where appropriate,
key revocation, key generation, and sending of any initial key reset notification messages.
It is also responsible for receiving and processing key reset messages both from partner identities and from own
identities, and for interacting with them in accordance with the requirements above.
An additional component of the solution, though not strictly required (as seen above), is that we provide a mechanism
for opportunistic notification of recently contacted partners (where "recently contacted" indicates contact originating
from the user, not received communications) at the time an own key reset is made. This is not strictly necessary,
as we will notify on the first receipt of a message encrypted with a revoked key, but it does speed up the process
of appropriate key usage by frequent communications partners.
The applications, on the other hand, are responsible for giving the users an interface to these functions as required
[^user_caveat]. ([^user_caveat]: At the moment, under some circumstances, applications are only required to provide
users with the option to reset an entire user. This should be discussed in more detail in a later version of the
document, as the author may have gotten this partially wrong.) How this works will depend on how much of the
user/identity model is exposed in their interfaces and the context from which the reset is called.
**FIXME:** Ask Huss/Thomas/Andreas for more input here. I don't know what they do. - KB
#### External components that the solution will interact with and that it will alter
For the most part, the solution is an interaction triggered by the application, through the adapter, and serviced
by the engine. At the end of processing, the old default key should be reset according to the requirements, given
the input identity or user. Applications will need to implement context-dependent mechanisms to allow users to call
the API functions. And, as with **KeySync**, **Key Reset**, at the engine level, will interact with the
application's/adapter's message queue for this session, if present, putting **Key Reset** notifications into the
queue for certain kinds of calls (specifically, own resets of various kinds).
The applications, then, are responsible for processing the message queue and ensuring sending and receipt of messages,
as is normal.
#### Solution logic and protocols
##### API information
The engine must implement and deliver the following API:
1. ```key_reset_identity(p≡p_SESSION session, p≡p_identity* ident, const char* fpr)``` <br/><br/>
This function resets the default management database status for the identity / keypair
provided by removing the fingerprint ```fpr``` as a default key for this identity, and removing
any trusted or mistrusted status from the trust database for this key and this identity's user.
If this corresponds to an own identity and a private key, it will also revoke the key,
generate a new one, and communicate the reset to recently contacted p≡p partners for this identity.
If the fingerprint ```fpr``` is ```NULL```, then whatever key is set as the default for this identity
is treated as above. Note that if the key reset by this function is the default for any other user
or identity, it will be removed as the default for that identity.
Currently, this also removes a partner key from the keyring, where applicable[^key_election].
([^key_election]: This will change with the integration of key election removal.)<br/><br/>
2. ```key_reset_user(p≡p_SESSION session, const char* user_id, const char* fpr)``` <br/><br/>
This function effectively applies ```key_reset_identity()``` to a series of identities corresponding
to the user as indicated by ```user_id```, as follows:
1. if the user is a communications partner rather than the own user:
1. if the fingerprint ```fpr``` is present, apply ```key_reset_identity()``` for each of the partner's
identities containing ```fpr``` as the default key.
2. otherwise, perform ```key_reset_identity()``` on ALL of the partner's identities corresponding
to their ```user_id``` with a ```NULL fpr``` as above.
2. if the ```user_id``` indicates the own user, however, ```fpr``` **must not** be ```NULL```. The appropriate
function in that case is ```key_reset_all_own_keys()```. If ```fpr``` *is* present, then the functionality
is as with the communications partner case.<br/><br/>
As above, reset keys are removed as defaults for all users and identities.<br/><br/>
3. ```key_reset_all_own_keys(p≡p_SESSION session)```<br/> <br/>
This function will revoke and mistrust all own keys, generate new keys for all
own identities, and opportunistically communicate key reset information to people we have recently
contacted. This is effectively ```key_reset_identity()``` for every own identity and own default key.
Note that if any identities share one of these own default keys as a default, they will each have different
(separate) new default keys after completion.<br/> <br/>
4. <a name="reset_own_grouped"></a>```key_reset_own_grouped_keys(p≡p_SESSION session)```<br/> <br/>
This function is, on the surface, like ```key_reset_all_own_keys()```, only it is only applied to the default
keys for identities that are marked for synchronisation as part of a **KeySync** device group.
However, because of the fact that these are synchronised identities, this function has additional functionality.
This function must create a special **Key Reset** message to be used *internally* in order to communicate to
each grouped device the following information:
1. The identity whose default key is to be revoked
2. The default key for each corresponding identity to revoke
3. The new default key which will replace each default key (for each corresponding identity)
4. The public/private keypair for each corresponding replacement key<br/><br/>
This whole message is encrypted to and, more importantly, signed by one of the device group's *current valid* keys at
the time the reset function is called. This function must wait until it produces and signs this message before, on the caller device,
performing the revocation functionality associated with **Key Reset** of own keys and replacing with the new defaults
it generated and sent to the other devices in the key reset message.
The device on which this function is called is the sole device responsible for communicating any opportunistic
key reset messages to partners as described in Requirements 123123-12312312.
##### Additional required internal logic as a result of API calls
1. Processing the results of ```key_reset_identity()``` and ```key_reset_user()``` from a communications partner<br/><br/>
Practically speaking, from the receiver point of view, this will only involve individual messages from
For any given message, the recipient must verify that:
1. there is an extant matching identity,
2. they have the key being reset in their keyring,
3. if the key is present, that they have imported a revocation (which implies an object signed by the known
private key of the sender)
4. that the public part of the replacement key indicated in the key reset message is attached and imported<br/><br>
If all of these things are true, then the recipient will replace the new key as the default for this identity in their
database and mistrust the revoked key.<br/><br/>
Note that if the reset key is *not* the default key for this identity, the database will not change, but the
revocation certificate will be imported as well as the new key. This means that if another identity contains
the to-be-replaced key as a default key, it will not be valid; however, it will not be removed as the default key
for that identity until the engine tries to use it, and it will not be replaced by the newly-sent key unless a
specific key reset message is received for that identity indicating it should do so.<br/><br/>
2. <a href="proc_own_grouped"></a> Processing the results of ```key_reset_own_grouped_keys()```<br/><br/>
This is perhaps the most security-critical part of the protocol from the user's perspective, as it is processed
automatically, it changes the user's default private keys, and it revokes their extant private keys.
When receiving an own_grouped_keys reset message, the user *must* verify that the key used to sign the message
corresponds to the default own identity it was sent from, that the corresponding key is still valid, and that
it contains a private key. Note that because ```key_reset_own_grouped_keys()``` *does not send* revocation certificates,
but rather references to these keys to devices in the device group indicating which keys to replace and revoke locally,
this key will still be valid if it is an actionable and correct own grouped key reset message.
Should this be the case, for every transmitted identity and replacement key pair, the
recipient device will revoke the old key for that identity and replace it with the indicated
new key (instead of generating a new key). Recipient devices *do not* send out key reset notifications
to partners, as this was handled by the device that generated the reset message.
These new keys are then trusted as new keys and operation can continue as normal.
##### DDL impacts
Implementation requires the following features, many of which were present before **Key Reset** was implemented:
1. A ```social_graph``` table, binding partner identities with the addresses the user has contacted them from.
This is to avoid exposing own user aliases to the partner when sending key reset messages and ensures there is a
match between the address the reset is for and the identity the partner associates with the key to be reset
on the recipient end. Note that only identities the user as proactively contacted themselves are contained in this
table, an important note for 2).
2. Timestamps on identities indicating recent access or update. This is used to filter which partners to opportunistically
contact. Note that only identities which the user has intentionally communicated with (rather than just receiving
a message from) will be sent these opportunistic messages; this is to prevent spammers from receiving key reset messages.
Other tables and fields (e.g. ```main_key_fpr`` for identity default keys, etc) are already integral to the system and
are used here, but their DDL semantics remain unaltered.
**FIXME**: This should probably, in fact, indicate these fields and tables, but it depends on how deep we intend
the spec to go, and this is dragging on as an example.
##### Protocol descriptions, with examples
In this section, we take the indicated use cases from the
[requirements](#goals-product-and-technical-requirements) section and show how the protocol operates.
###### Example 1: Own single key replacement with new key
Recall that the p≡p user, [in this example](#req_ex_1), wants to replace one default key
from one identity.
The application must provide a way for the user to select the identity (presumably by address)
they wish to reset. Since the application does not keep track of the default key for that address,
but *does* (either in the application or through the adapter) have a constant representation
of the own ```user_id```, it will call ```key_reset_identity``` with the ```session``` argument,
the appropriate own identity, and a ```NULL fpr```.
The engine then:
1. retrieves the own identity, including the default key fingerprint, and
2. if it is not already revoked and contains a private key:
1. tells the cryptographic engine to revoke the private key,
2. asks the cryptographic engine to generate a new public/private keypair,
3. records the binding of the revoked key and its replacement in the key management database,
4. sets the new key as the identity default,
5. replaces the user default key with the new one if the identity default key and the user default key were the same,
6. mistrusts the old key in the management database,
7. repeats ii-vi for any other own identity for which this key was the default,
8. searches the identity database for any identities in the social graph which have been
actively contacted by this identity and whose identities have been updated in the last two weeks,
9. generates key reset messages as described in [requirements 5-8](#req_ex_1") for each of those
identities from the reset identity, and
10. places those messages into the adapter/application message queue, which is sent in
at session initialisation (if there is no message queue present, no messages are sent).<br/><br/>
###### Example 2: Device compromise - simple case (single device)
This [example](#req_ex_2) featured a p≡p user which wanted to reset all of their own keys on their
single, ungrouped device and wished to invalidate their keys for future use.
In this case, the application provides a mechanism for the user to simply reset all own keys.
This will call ``key_reset_all_own_keys()`` with the current session as the argument.
The engine will then use its knowledge of its own ```user_id``` to fetch all own identities, and then,
for each own identity, proceed as in step 2 of Example 1 above.
###### Example 3: Encryption to a revoked p≡p partner key
In this [example](#req_ex_3), a p≡p user, Alice, only has an outdated key from her p≡p communications
partner, Bob. Bob has revoked the key, but Alice is unaware of it, and so sends Bob
a message encrypted to the key he has revoked.
Bob, who still has the revoked key in his keyring and can decrypt with it, decrypts and verifies
Alice's message as usual. However, in ```decrypt_message()```, the engine notes that Alice is
using one of Bob's revoked, mistrusted keys.
The engine looks up the revoked key in the database. If its replacement key is his current default,
it creates a key reset message for alice containing the revocation certificate of the old key
(this can be done by just sending the revoked key, which contains the revocation certificate),
his new key along with the specified key reset information.
If, however, the engine notes that the key that replaced his revoked key is also revoked, it follows
the chain of replacements until it finds the current valid default key and uses this in
the key reset message.
Alice then receives Bob's message. On decrypting his message, the engine will import both the
new key and the revocation certificate. On processing the key reset message, the engine will, if it
notes that the old key is now revoked in her keyring and the message is signed by the new key,
mistrust Bob's old default key and replace the default key for Bob's respective
identity with the new key; however, *no trust status* will carry over to the new
If Alice wishes to trust Bob's new key, she will contact Bob on a side channel and exchange
Trustwords for their combined public keys and set the trust for the new keypair if
she can verify them.
###### Example 4: Manually changing use of an incorrect partner key
There are two likely scenarios which generate [this use case](#req_ex_4): Bob is an OpenPGP user with several
keys, and Alice's p≡p installation has chosen to make the wrong one the default, or perhaps
Bob is a p≡p user who has reinstalled his client several times without resetting keys, and thus
has partners who have an unusable (for Bob) public key for him.
In either event, Bob contacts Alice and says, "Hey, I need you to stop using that public key" in
the first case, or in the second, "Hey, I can't decrypt the mails you sent me."
In both cases, the application provides the means for Alice to either reset an identity
or reset the user (note that in engine parlance this is resetting the *key* of the identity
or user, but the application does not keep track of keys). Presuming the application allows
resets at the identity level of granularity (e.g. contact address rather than contact),
it will call ```key_reset_identity()``` with Bob's identity and a ```NULL fpr```.
The engine will then see that this is a partner identity and remove the current default key
as the default *as well as resetting its trust status in the database*.
This will leave an empty default [^key_deletion].
([^key_deletion]: **IMPORTANT NOTE**: In the current implementation,
we remove Bob's reset key from the keyring entirely. This is to ensure that key election
does not, next time Bob's identity is updated, simply reselect the reset key. See * for more
details on this and this will change in the near future).
If, on the other hand, only the user (e.g. the user's keys) is available as a reset option
in the application UI, the application will call ```key_reset_user``` with Bob's ```user_id```
and a ```NULL fpr```. This will repeat the process above for individual identities for each
of Bob's known identities.
Bob should then mail Alice again. If he is mailing from a p≡p client, he will automatically
attach his new key and it should be selected as the default on receipt (again, see *). If
it was a full user reset, he will at some point need to mail from all impacted accounts in order to ensure
Alice has keys for each. If Alice and Bob wish to trust these keys, they must exchange
Trustwords (possibly again) for each impacted identity.
If Bob is mailing from an OpenPGP client, he should simply attach his key to a message and mail
Alice at his earliest convenience.
###### Example 5: Removing trust or mistrust from a communications partner key
[Recall](#req_ex_5) that this involves a user wanting to reset the trusted or mistrusted status of a
communications partner identity.
The application must provide the means for the user to select an identity whose trust should
be reset. This functionality should call ```key_reset_identity()``` or ```key_reset_user()``` as in
example 4 and will take the same steps with the same remedy.
###### Example 6: KeySync: Reset own keys
In this [example](#req_ex_6), the user wishes to reset the synchronised keys in a device group
using **[KeySync](#keysync)**.
There are a couple of examples where this could happen - a grouped device is reset with
```reset_all_own_keys()```, and some of the identities corresponding to some keys are
marked for synchonisation, or as an internal function, a device leaves a [device group](#device_group)
and the remaining member devices need to revoke old keys and set new ones.
####### Manual reset of grouped keys
In the first case, ```reset_all_own_keys()``` separates out the identities which are
synchronised identities and which ones are non-synchronised identities. Non-synchronised identities
are subjected to the same treatment as examples 1/2. The remaining identities are
processed with ```key_reset_own_grouped_keys()```; through this function, the engine collects
all identities which are marked for synchronisation and proceeds as specified in
[```key_reset_own_grouped_keys()```](#reset_own_grouped) (from the initiating device) and
the [processing description](#proc_own_grouped) for key reset messages generated by
```key_reset_own_grouped_keys()``` (for the recipient devices).
####### Leaving a device group
In the case where the user decides to take a device out of a device group, this part of the
protocol becomes more complicated. We divide the actors, at first, into two groups: the leaver,
and the remaining group.
When the leaving device calls ```leave_device_group()``` within the **KeySync** protocol, two
sets of events are triggered, one set for the leaving device, and one for the remaining group.
The leaving device notifies the group it is leaving, unmarks all of its identities for
synchronisation, and then resets all of them locally via ```key_reset_user()``` and proceeds as with Example 2.
The group, on the other hand, chooses a leader. This leader calls ```key_reset_own_grouped_keys()```
and both the leader, as the initiating device, and the rest of the group, as recipient
devices, proceed as under manual reset of grouped keys above in this example.
##### Limitations and caveats
See section security.
#### Service requirements
Suggested logging additions, at a minimum, would be the fingerprints of reset default keys and their replacements
as well as the event that triggered their reset, or, alternately/additionally, reasons for failure.
#### Deployment and release plan
**Key Reset** has been deployed for some time and involves heavy implementation in the engine as well as
access at the application and UI level. This was achieved some time ago.
Should there be API changes or radical changes in behaviour, the engine team will file tickets with the appropriate
stakeholders (adapter for API changes, adapter and applications for semantic and functionality changes).
#### Security and privacy considerations
* MITM to partner, mitigation
* Unknown resets
#### Known issues, with possible solutions and mitigation
* Key election removal
### Open questions
Does P = NP?

+ 148
- 0 View File

@ -0,0 +1,148 @@
# Specification Template
## Front matter
- Title
- Author(s)
- Team
- Reviewer(s)
- Created
- Last updated
- Ticket reference link (where applicable)
## Introduction
This is a rough template for something like a technical specification. There are
so many different levels this can be done at that I wanted to give a framework with
emphasis on the parts that we don't do well, that are poorly understood, and that
are challenging. There is room for all of the rest, and this is only a template.
You will note that there is less specific emphasis on exactly how solutions should be
laid out when the technical area arrives, because that is highly dependent on
the problem and solution. One of the most serious drawbacks of government-style requirements
engineering specifications is that the format tends to overwhelm form and get in
the way of communicating the actual information.
At the same time, our current ad-hoc process is completely insufficient - "here are some states we have or some message
types that will be sent" is so low-information that it is unactionable.
Having done systems engineering level formal specifications for government contractors, I want to avoid the
process-for-the-sake-of-process rigidity of those specifications (because they are time consuming and often impede results) and recognise the limited nature of our resources to make the best use of them.
This is a *tool*. Extended discussions about formal requirements language are out-of-scope
here; if you plan to write a spec, you do what you need to do. This reflects a superset of
what *I*, as a team lead and developer, would expect to see and be able to work with.
### Overview, Problem Description, Summary, or Abstract
Motivation for what you are proposing. **If you feed the specification consumer a plan and they don't know why you're doing it, it's not really
a plan for anything.**
We're all technical, and tend to think the technical parts showing the bits and pieces
of our solution are the most important thing, but this section
is actually the **cornerstone** of your document, and it will be the hardest to write.
It is not *sufficient*, but it is absolutely *necessary*.
This section should contain at least the following:
1. Context for the problem what you are specifying will solve. You **must** situate what you are proposing.
2. Summary of the problem.
- *Try to view this from highest stakeholder viewpoint this impacts. If it is a user problem, explain the user problem. If it causes issues for application developers without impacting actual users, explain it from this view. If its impacts are only engine-internal, then
give the summary from this viewpoint. You have ample opportunity to clarify low-level impacts deeper within the document*
3. Suggested solution
- *This is where you give a high-level explanation. No state machines, no protocols. This is a description - a placeholder for later details,*
4. The stakeholders
- *Define those involved in the problem and the solution, and make sure you clarify for whom this document is intended*
### Glossary
### Background
This should contain information such as the origin of the problem and why it
is worth solving, who the problem impacts, how it impacts them, and how the problem
interacts with and impacts other parts of the system.
### Goals or Product and Technical Requirements
- Overall requirements driven by user examples - these can be used again and drawn through the document as illustration if need be
- Technical requirements
### Non-Goals or Out of Scope
### Future Goals
### Assumptions
- Conditions and resources that need to be present and accessible for the solution to work as described.
## Proposed solution
### Status quo
Discussion of how this problem may currently be being handled, or, if it is not,
why the current system cannot handle it, and the pros and cons of leaving things
*as they are now*
### Proposed Solution / Design
#### Overview of solution
*This is very high level. What, if you had five minutes to explain the solution to
someone who does not know all the details of the system, would you say to someone
to give them an idea of what the solution does or involves. Presume an ill-informed
audience who is not going to pay attention to the details YOU care about - that comes
#### External components that the solution will interact with and that it will alter
*This is important to be able to frame who needs the document as well as guiding you,
as the writer, to the perspectives you need to present in the solution*
#### Dependencies
#### Pros and cons of the proposed solution
#### Solution logic and protocols
This needs to be described in terms of each part of the system it impacts.
This should include the following, where applicable, and in an order that makes sense:
- API information and changes
- DDL information and changes
- Protocol descriptions, *including examples*
- Pseudocode, state machines, flowcharts
- Error and failure states, and how those should be handled internally and externally
- Limitations and caveats
#### Service requirements
This should make it clear what needs to be incorporated into the solution
so that service can give appropriate feedback. This includes tools, logging, and
other infrastructure that may need to be developed or modified.
#### Deployment and release plan
- Notification to other teams who may need to modify systems
- Coordination of how impacted systems will deploy or release in concert with
- Plan for communicating changes, warnings, caveats for new behaviour to affected stakeholders
#### Impacts and follow-on requirements
- Which teams will be impacted by this solution, and how can that impact be measured
and minimised?
- What impacts does this solution have on stakeholders? What will it require of them?
- What requirements does this solution generate now and in the future?
#### Alternatives, Risks
#### Security and privacy considerations
#### Known issues, with possible solutions and mitigation
### Open questions