Skip to content

_GSoC 2019 E2EE final evaluation

Alexey Andreyev edited this page Aug 25, 2019 · 12 revisions

Google Summer of Code 2019

Matrix project final evaluation: end-to-end encryption

*libQMatrixClient was renamed to libQuotient

Name: Alexey Andreyev

E-mail: yetanotherandreyev@gmail.com

Matrix: @aa13q:matrix.org

Idea: Adding end-to-end encryption to more clients

GSoC project page: link

Mentors: Alexey Rusakov, Hubert Chathi

Contribution: libQuotient GSoC E2EE PRs list

The work done

The project aimed at adding end-to-end encryption to libQuotient for future support in Qt/libQuotient-based client like Quaternion and Spectal, or even Telepathy IM.

Regarding my initial proposal, I’ve completed tasks enough for message receiving, and not finished tasks related to message sending.

Focused on libQuotient, I've also added changes to Quaternion client to support the proposed API and test the results. I've reused libQtOlm, which is a Qt wrapper to the matrix olm library and contributed to provide better compatibility during its building and deployment. This also required to dive into the olm library itself and provide minor patch for the olm CMake files too.

So, the basic structure of the project changed a bit, libQtOlm was added as a dependency to support libolm:

                              +--------------------------------------------+
                              |   Quaternion/Spectral/Telepathy|Tank/etc   |
+------------------+          +--------------------------------------------+
|      CS API      |  <---->  |                  libQuotient               |
+------------------+          +-------------------------------+------------+
|Synapse homeserver|          |               Qt              |  libQtOlm  |
+------------------+          +--------------------------------------------+
                                                              |   libolm   |
                                                              +------------+

During the coding period, I've resorted to the specification, the guide and the last year GSoC python implementation actively. And added minor fix for the documentation about names constants at the documentation examples.

Keys and room initialization tasks

After sorting it out with the additional dependencies, I've focused on receiving m.room.encryption event properly to detect additional megolm properties such as rotation criteria: rotation_period_msgs and rotation_period_ms. After the contribution, I've got full EncryptionEvent support.

The next thing that was introduced is the EncryptionManager class, which provides methods to work with the olm account. EncryptionManager gives access to QtOlm::Account field from the QtOlm wrapper of the olm library. EncryptionManager was also implemented to handle all the device-specific initialization, such as handling targetKeysNumber and methods like uploading device and one-time keys, olm session decryption. To support saving olm account after application restarts, additional option AccountSettings::encryptionAccountPickle was introduced.

Next task was uploading device keys and one-time keys using EncryptionManager, which required attention to the request structure and fields. After that, it was possible to upload identity and one-time keys during successfull connection to the server.

The result of the iteration was provided as pull request for a review. Quotient and Spectral clients successfully uploaded device keys, while one-time keys required additional fixes during actual decryption later.

The note at This Week In Matrix were also provided.

Receiving encrypted messages

Next step was to implement EncryptedEvent support. After the additional changes to the libQtOlm and olm to support in-tree building, I've dived into the documentation to support encrypted messages, found minor issue at the example and fixed it at the docs and the library.

@kitsune provided recommendations on how to organize messages decryption on-the-go without storing them decrypted to avoid security and architecture problems. The EncryptedEvent event type is used when sending encrypted events. It can be used either within a room (in which case it will have all of the Room Event fields), or as a to-device event. The encrypted payload can contain any message event. However, for most of the cases, the message event is the room message event. And even for the to-device events, the context is for the room. So, to simplify integration to the timeline, EncryptedEvent is a RoomEvent inheritor. Strictly speaking though, it's not always a RoomEvent, but an Event in general. It's possible because RoomEvent interface is similar to Event's one and doesn't add new restrictions, just provides additional features. This was also referenced at the code implementation.

The iteration with draft EncryptedEvents implementation was provided as a PR. @kitsune introduced new logging categories and fixed memory leaks and dangling pointers after that.

Looking at python implementation as a reference and implementing similar logic, I've started to realize better how the things work, how olm session is used to share the keys and initialize the megolm session at the room. And realized what parts are missing to implement receiving of the encrypted messages.

During the debugging, I've fixed EncryptionManager initialization place, implemented RoomKeyEvent to support olm session initialization, added handling of the to-device messages and fixed megolm inbound session decryption logic. As a result, I've provided actual working code for receiving messages that could be reused at the project. I've also provided missing Arch Linux packages for the community to test it with my native environment too.

The result were introduced as final PR.

Additional contribution were provided to test results with Quaternion: aa13q-e2ee branch

Demonstration

Imgur

Future work

Talking about future work, I'm going to sync it with the libQuotient project board. Next steps are:

  • Managing devices list for users in the room
  • Sending encrypted messages

While olm account management architecture and device_one_time_keys_count sync data handling is here, such tasks as session management after a restart and device verification still requires additional efforts. After that encrypted attachments support and key backups could also be added.

Conclusion

To take part in the Google Summer of Code project was my dream. I'm very happy I've managed to took part this year, since it was the last year of my study, while I'm probably not very satisfied with my personal results.

From the beginning of the project, I've realized I'm very lucky since I've got all the chances to provide perfect results. @Kaffeine helped me a lot with my TelepathyIM contribution. He helped me to evolve my CMake, git and Qt/C++ skills and that's how I've started contributing to the libQuotient before GSoC. After that, it turns out that I've accepted and received even two mentors. @uhoreg from the Matrix team, who helped me with End-to-End Encryption logic and olm/megolm understanding. And @kitsune from the Quotient project, who helped me a lot with the code review, with the architecture decisions and the library logic, and even with the time management (he was the one who watched carefully about my results). The last year GSoC python implementation and guide from @Zil0 were also here, and it turns out that Spectral developer @BHat provided QtOlm wrapper right before GSoC stated. However, time management was my weak point, where I've made key mistakes, such as poor combination with my regular part-time job. I definitely should have reserved a small vacation at least for the final period of the project to handle tasks better. In the end, I've managed to debug the mistakes and provided encrypted messages receiving that could already be used at the clients. Also, I evolved my skills and dived into the megolm E2EE subject. I'm willing to continue my contribution to develop libQuotient as full-featured Qt-based Matrix library.

In general, I am not disappointed. I'm wishing luck to all the future students who are reading this. I'm happy to receive support and contribute to an international open project not only for myself, but also for the other developers and users.

Clone this wiki locally