lime
Lime is a C++ library implementing Open Whisper System Signal protocol
lime_x3dh_protocol.hpp
Go to the documentation of this file.
1 /*
2  lime_x3dh_protocol.hpp
3  @author Johan Pascal
4  @copyright Copyright (C) 2017 Belledonne Communications SARL
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef lime_x3dh_protocol_hpp
21 #define lime_x3dh_protocol_hpp
22 
24 #include "lime_x3dh.hpp"
25 #include "lime_log.hpp"
26 #include <iostream> // ostreamstring to generate incoming/outgoing messages debug trace
27 #include <iomanip>
28 
29 namespace lime {
30 
35  enum class X3DHKeyBundleFlag : uint8_t {
36  noOPk=0,
37  OPk=1,
38  noBundle=2};
43  template <typename Curve>
44  struct X3DH_peerBundle {
46  const std::string deviceId;
60  X3DH_peerBundle(std::string &&deviceId, const std::vector<uint8_t>::const_iterator bundle, bool haveOPk, std::ostringstream &message_trace) :
61  deviceId{deviceId},
62  Ik{bundle},
65  // add Ik to message trace
66  message_trace << " Ik: "<<std::hex << std::setfill('0');
67  hexStr(message_trace, Ik.data(), DSA<Curve, lime::DSAtype::publicKey>::ssize());
68  // add SPk Id, SPk and SPk signature to the trace
69  SPk.dump(message_trace);
70  if (haveOPk) {
71  OPk = OneTimePreKey<Curve>(bundle + DSA<Curve, lime::DSAtype::publicKey>::ssize() + SignedPreKey<Curve>::serializedPublicSize());
72  OPk.dump(message_trace); // add OPk Id and OPk to the trace
73  }
74  };
79  X3DH_peerBundle(std::string &&deviceId) :
80  deviceId{deviceId}, Ik{}, SPk{}, OPk{}, bundleFlag{lime::X3DHKeyBundleFlag::noBundle} {};
81  };
82 
83  namespace x3dh_protocol {
88  enum class x3dh_message_type : uint8_t{
89  deprecated_registerUser=0x01, // The usage of this value is deprecated, but kept in the define so it is not recycled.
90  deleteUser=0x02,
91  postSPk=0x03,
92  postOPks=0x04,
93  getPeerBundle=0x05,
94  peerBundle=0x06,
95  getSelfOPks=0x07,
96  selfOPks=0x08,
97  registerUser=0x09,
98  error=0xff};
99 
104  enum class x3dh_error_code : uint8_t{
105  bad_content_type=0x00,
106  bad_curve=0x01,
107  missing_senderId=0x02,
109  bad_size=0x04,
110  user_already_in=0x05,
111  user_not_found=0x06,
112  db_error=0x07,
113  bad_request=0x08,
114  server_failure=0x09,
116  unknown_error_code=0xfe,
117  unset_error_code=0xff};
118 
119  template <typename Curve>
120  void buildMessage_registerUser(std::vector<uint8_t> &message, const DSA<typename Curve::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<Curve> &SPk, const std::vector<OneTimePreKey<Curve>> &OPks) noexcept;
121 
122  template <typename Curve>
123  void buildMessage_deleteUser(std::vector<uint8_t> &message) noexcept;
124 
125  template <typename Curve>
126  void buildMessage_publishSPk(std::vector<uint8_t> &message, const SignedPreKey<Curve> &SPk) noexcept;
127 
128  template <typename Curve>
129  void buildMessage_publishOPks(std::vector<uint8_t> &message, const std::vector<OneTimePreKey<Curve>> &OPks) noexcept;
130 
131  template <typename Curve>
132  void buildMessage_getPeerBundles(std::vector<uint8_t> &message, std::vector<std::string> &peer_device_ids) noexcept;
133 
134  template <typename Curve>
135  void buildMessage_getSelfOPks(std::vector<uint8_t> &message) noexcept;
136 
137  template <typename Curve>
138  bool parseMessage_getType(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept;
139 
140  template <typename Curve>
141  bool parseMessage_getPeerBundles(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<Curve>> &peersBundle) noexcept;
142 
143  template <typename Curve>
144  bool parseMessage_selfOPks(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept;
145 
146  /* this templates are intanciated in lime_x3dh_procotocol.cpp, do not re-instanciate it anywhere else */
147 #ifdef EC25519_ENABLED
148  extern template void buildMessage_registerUser<C255>(std::vector<uint8_t> &message, const DSA<C255::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<C255> &SPk, const std::vector<OneTimePreKey<C255>> &OPks) noexcept;
149  extern template void buildMessage_deleteUser<C255>(std::vector<uint8_t> &message) noexcept;
150  extern template void buildMessage_publishSPk<C255>(std::vector<uint8_t> &message, const SignedPreKey<C255> &SPk) noexcept;
151  extern template void buildMessage_publishOPks<C255>(std::vector<uint8_t> &message, const std::vector<OneTimePreKey<C255>> &OPks) noexcept;
152  extern template void buildMessage_getPeerBundles<C255>(std::vector<uint8_t> &message, std::vector<std::string> &peer_device_ids) noexcept;
153  extern template void buildMessage_getSelfOPks<C255>(std::vector<uint8_t> &message) noexcept;
154  extern template bool parseMessage_getType<C255>(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept;
155  extern template bool parseMessage_getPeerBundles<C255>(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<C255>> &peersBundle) noexcept;
156  extern template bool parseMessage_selfOPks<C255>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept;
157 #endif
158 
159 #ifdef EC448_ENABLED
160  extern template void buildMessage_registerUser<C448>(std::vector<uint8_t> &message, const DSA<C448::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<C448> &SPk, const std::vector<OneTimePreKey<C448>> &OPks) noexcept;
161  extern template void buildMessage_deleteUser<C448>(std::vector<uint8_t> &message) noexcept;
162  extern template void buildMessage_publishSPk<C448>(std::vector<uint8_t> &message, const SignedPreKey<C448> &SPk) noexcept;
163  extern template void buildMessage_publishOPks<C448>(std::vector<uint8_t> &message, const std::vector<OneTimePreKey<C448>> &OPks) noexcept;
164  extern template void buildMessage_getPeerBundles<C448>(std::vector<uint8_t> &message, std::vector<std::string> &peer_device_ids) noexcept;
165  extern template void buildMessage_getSelfOPks<C448>(std::vector<uint8_t> &message) noexcept;
166  extern template bool parseMessage_getType<C448>(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept;
167  extern template bool parseMessage_getPeerBundles<C448>(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<C448>> &peersBundle) noexcept;
168  extern template bool parseMessage_selfOPks<C448>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept;
169 #endif
170 
171 #ifdef HAVE_BCTBXPQ
172 #ifdef EC25519_ENABLED
173  // C25519/Kyber512
174  extern template void buildMessage_registerUser<C255K512>(std::vector<uint8_t> &message, const DSA<C255K512::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<C255K512> &SPk, const std::vector<OneTimePreKey<C255K512>> &OPks) noexcept;
175  extern template void buildMessage_deleteUser<C255K512>(std::vector<uint8_t> &message) noexcept;
176  extern template void buildMessage_publishSPk<C255K512>(std::vector<uint8_t> &message, const SignedPreKey<C255K512> &SPk) noexcept;
177  extern template void buildMessage_publishOPks<C255K512>(std::vector<uint8_t> &message, const std::vector<OneTimePreKey<C255K512>> &OPks) noexcept;
178  extern template void buildMessage_getPeerBundles<C255K512>(std::vector<uint8_t> &message, std::vector<std::string> &peer_device_ids) noexcept;
179  extern template void buildMessage_getSelfOPks<C255K512>(std::vector<uint8_t> &message) noexcept;
180  extern template bool parseMessage_getType<C255K512>(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept;
181  extern template bool parseMessage_getPeerBundles<C255K512>(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<C255K512>> &peersBundle) noexcept;
182  extern template bool parseMessage_selfOPks<C255K512>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept;
183  // C25519/MLKem512
184  extern template void buildMessage_registerUser<C255MLK512>(std::vector<uint8_t> &message, const DSA<C255MLK512::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<C255MLK512> &SPk, const std::vector<OneTimePreKey<C255MLK512>> &OPks) noexcept;
185  extern template void buildMessage_deleteUser<C255MLK512>(std::vector<uint8_t> &message) noexcept;
186  extern template void buildMessage_publishSPk<C255MLK512>(std::vector<uint8_t> &message, const SignedPreKey<C255MLK512> &SPk) noexcept;
187  extern template void buildMessage_publishOPks<C255MLK512>(std::vector<uint8_t> &message, const std::vector<OneTimePreKey<C255MLK512>> &OPks) noexcept;
188  extern template void buildMessage_getPeerBundles<C255MLK512>(std::vector<uint8_t> &message, std::vector<std::string> &peer_device_ids) noexcept;
189  extern template void buildMessage_getSelfOPks<C255MLK512>(std::vector<uint8_t> &message) noexcept;
190  extern template bool parseMessage_getType<C255MLK512>(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept;
191  extern template bool parseMessage_getPeerBundles<C255MLK512>(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<C255MLK512>> &peersBundle) noexcept;
192  extern template bool parseMessage_selfOPks<C255MLK512>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept;
193 #endif
194 #ifdef EC448_ENABLED
195  // C448/MLKem1024
196  extern template void buildMessage_registerUser<C448MLK1024>(std::vector<uint8_t> &message, const DSA<C448MLK1024::EC, lime::DSAtype::publicKey> &Ik, const SignedPreKey<C448MLK1024> &SPk, const std::vector<OneTimePreKey<C448MLK1024>> &OPks) noexcept;
197  extern template void buildMessage_deleteUser<C448MLK1024>(std::vector<uint8_t> &message) noexcept;
198  extern template void buildMessage_publishSPk<C448MLK1024>(std::vector<uint8_t> &message, const SignedPreKey<C448MLK1024> &SPk) noexcept;
199  extern template void buildMessage_publishOPks<C448MLK1024>(std::vector<uint8_t> &message, const std::vector<OneTimePreKey<C448MLK1024>> &OPks) noexcept;
200  extern template void buildMessage_getPeerBundles<C448MLK1024>(std::vector<uint8_t> &message, std::vector<std::string> &peer_device_ids) noexcept;
201  extern template void buildMessage_getSelfOPks<C448MLK1024>(std::vector<uint8_t> &message) noexcept;
202  extern template bool parseMessage_getType<C448MLK1024>(const std::vector<uint8_t> &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr<limeCallback> callback) noexcept;
203  extern template bool parseMessage_getPeerBundles<C448MLK1024>(const std::vector<uint8_t> &body, std::vector<X3DH_peerBundle<C448MLK1024>> &peersBundle) noexcept;
204  extern template bool parseMessage_selfOPks<C448MLK1024>(const std::vector<uint8_t> &body, std::vector<uint32_t> &selfOPkIds) noexcept;
205 #endif
206 #endif // HAVE_BCTBXPQ
207  } // namespace x3dh_protocol
208 } // namespace lime
209 
210 #endif /* lime_x3dh_protocol_hpp */
const DSA< typename Curve::EC, lime::DSAtype::publicKey > Ik
Definition: lime_x3dh_protocol.hpp:47
X3DHKeyBundleFlag
Set possible values for a flag in the keyBundle X3DH packet.
Definition: lime_x3dh_protocol.hpp:35
void buildMessage_deleteUser(std::vector< uint8_t > &message) noexcept
build a deleteUser message
Definition: lime_x3dh_protocol.cpp:192
const std::string deviceId
Definition: lime_x3dh_protocol.hpp:45
Holds everything found in a key bundle received from X3DH server.
Definition: lime_x3dh_protocol.hpp:44
bool parseMessage_getType(const std::vector< uint8_t > &body, x3dh_message_type &message_type, x3dh_error_code &error_code, const std::shared_ptr< limeCallback > callback) noexcept
Definition: lime_x3dh_protocol.cpp:337
x3dh_message_type
the x3dh message type exchanged with the X3DH server
Definition: lime_x3dh_protocol.hpp:88
void buildMessage_publishSPk(std::vector< uint8_t > &message, const SignedPreKey< Curve > &SPk) noexcept
build a postSPk message
Definition: lime_x3dh_protocol.cpp:209
void buildMessage_publishOPks(std::vector< uint8_t > &message, const std::vector< OneTimePreKey< Curve >> &OPks) noexcept
build a postOPks message
Definition: lime_x3dh_protocol.cpp:234
OneTimePreKey< Curve > OPk
Definition: lime_x3dh_protocol.hpp:49
X3DH_peerBundle(std::string &&deviceId)
Definition: lime_x3dh_protocol.hpp:79
std::function< void(const lime::CallbackReturn status, const std::string message)> limeCallback
Callback use to give a status on asynchronous operation.
Definition: lime.hpp:103
Definition: lime_x3dh.hpp:218
bool parseMessage_getPeerBundles(const std::vector< uint8_t > &body, std::vector< X3DH_peerBundle< Curve >> &peersBundle) noexcept
Parse a peerBundles message and populate a vector of peerBundles.
Definition: lime_x3dh_protocol.cpp:494
X3DH_peerBundle(std::string &&deviceId, const std::vector< uint8_t >::const_iterator bundle, bool haveOPk, std::ostringstream &message_trace)
Definition: lime_x3dh_protocol.hpp:60
static constexpr size_t ssize(void)
provide a static size function to be able to call the function not on an object
Definition: lime_crypto_primitives.hpp:151
void buildMessage_getPeerBundles(std::vector< uint8_t > &message, std::vector< std::string > &peer_device_ids) noexcept
build a getPeerBundle message
Definition: lime_x3dh_protocol.cpp:277
void buildMessage_getSelfOPks(std::vector< uint8_t > &message) noexcept
build a getSelfOPks message
Definition: lime_x3dh_protocol.cpp:320
Definition: lime.cpp:33
static constexpr size_t ssize(bool haveOPk)
Definition: lime_x3dh_protocol.hpp:45
const SignedPreKey< Curve > SPk
Definition: lime_x3dh_protocol.hpp:48
void buildMessage_registerUser(std::vector< uint8_t > &message, const DSA< typename Curve::EC, lime::DSAtype::publicKey > &Ik, const SignedPreKey< Curve > &SPk, const std::vector< OneTimePreKey< Curve >> &OPks) noexcept
build a registerUser message : Identity Key
Definition: lime_x3dh_protocol.cpp:146
Definition: lime_x3dh.hpp:32
x3dh_error_code
the error codes included in the x3dh error message received from the X3DH server
Definition: lime_x3dh_protocol.hpp:104
const lime::X3DHKeyBundleFlag bundleFlag
Definition: lime_x3dh_protocol.hpp:50
bool parseMessage_selfOPks(const std::vector< uint8_t > &body, std::vector< uint32_t > &selfOPkIds) noexcept
Parse a selfOPk message and populate a self OPk ids.
Definition: lime_x3dh_protocol.cpp:598
void hexStr(std::ostringstream &os, const uint8_t *data, size_t len, size_t digest)
Definition: lime_log.cpp:30