lime
Lime is a C++ library implementing Open Whisper System Signal protocol
Enumerations | Functions | Variables
lime::double_ratchet_protocol Namespace Reference

Group in this namespace all the functions related to building or parsing double ratchet packets. More...

Enumerations

enum  DR_message_type : uint8_t { DR_message_type::X3DH_init_flag = 0x01, DR_message_type::payload_direct_encryption_flag = 0x02, DR_message_type::KEM_pk_index = 0x04 }
 DR message type byte bit mapping. More...
 
enum  DR_X3DH_OPk_flag : uint8_t { DR_X3DH_OPk_flag::withoutOPk =0x00, DR_X3DH_OPk_flag::withOPk =0x01 }
 haveOPk byte from X3DH init message mapping More...
 

Functions

template<typename Curve >
void buildMessage_X3DHinit (std::vector< uint8_t > &message, const DSA< Curve, lime::DSAtype::publicKey > &Ik, const X< Curve, lime::Xtype::publicKey > &Ek, const uint32_t SPk_id, const uint32_t OPk_id, const bool OPk_flag) noexcept
 build an X3DH init message to insert in DR header EC only version More...
 
template<typename Curve >
void buildMessage_X3DHinit (std::vector< uint8_t > &message, const DSA< typename Curve::EC, lime::DSAtype::publicKey > &Ik, const X< typename Curve::EC, lime::Xtype::publicKey > &Ek, const K< typename Curve::KEM, lime::Ktype::cipherText > &Ct, const uint32_t SPk_id, const uint32_t OPk_id, const bool OPk_flag) noexcept
 build an X3DH init message to insert in DR header EC and KEM version More...
 
template<typename Curve >
void parseMessage_X3DHinit (const std::vector< uint8_t >message, DSA< Curve, lime::DSAtype::publicKey > &Ik, X< Curve, lime::Xtype::publicKey > &Ek, uint32_t &SPk_id, uint32_t &OPk_id, bool &OPk_flag) noexcept
 Parse the X3DH init message and extract peer Ik, peer Ek, self SPk id and seld OPk id if present This is for EC only version. More...
 
template<typename Curve >
void parseMessage_X3DHinit (const std::vector< uint8_t >message, DSA< typename Curve::EC, lime::DSAtype::publicKey > &Ik, X< typename Curve::EC, lime::Xtype::publicKey > &Ek, K< typename Curve::KEM, lime::Ktype::cipherText > &Ct, uint32_t &SPk_id, uint32_t &OPk_id, bool &OPk_flag) noexcept
 Parse the X3DH init message and extract peer Ik, peer Ek, self SPk id and seld OPk id if present This is for EC and KEM version. More...
 
template<typename Curve >
bool parseMessage_get_X3DHinit (const std::vector< uint8_t > &message, std::vector< uint8_t > &X3DH_initMessage) noexcept
 check the message for presence of X3DH init in the header, extract it if there is one More...
 
template<typename Curve >
constexpr size_t headerSize (uint8_t messageType) noexcept
 return the size of the double ratchet packet header More...
 
template<typename Curve >
constexpr size_t X3DHinitSize (bool haveOPk, typename std::enable_if_t<!std::is_base_of_v< genericKEM, Curve >, bool >=true) noexcept
 return the size of the X3DH init packet included in the double ratchet packet header More...
 
template<typename Algo >
constexpr size_t X3DHinitSize (bool haveOPk, typename std::enable_if_t< std::is_base_of_v< genericKEM, Algo >, bool >=true) noexcept
 return the size of the X3DH init packet included in the double ratchet packet header More...
 
template<typename Algo >
void buildMessage_X3DHinit (std::vector< uint8_t > &message, const DSA< typename Algo::EC, lime::DSAtype::publicKey > &Ik, const X< typename Algo::EC, lime::Xtype::publicKey > &Ek, const K< typename Algo::KEM, lime::Ktype::cipherText > &Ct, const uint32_t SPk_id, const uint32_t OPk_id, const bool OPk_flag) noexcept
 
template<typename Algo >
void parseMessage_X3DHinit (const std::vector< uint8_t >message, DSA< typename Algo::EC, lime::DSAtype::publicKey > &Ik, X< typename Algo::EC, lime::Xtype::publicKey > &Ek, K< typename Algo::KEM, lime::Ktype::cipherText > &Ct, uint32_t &SPk_id, uint32_t &OPk_id, bool &OPk_flag) noexcept
 

Variables

constexpr uint8_t DR_v01 =0x01
 

Detailed Description

Group in this namespace all the functions related to building or parsing double ratchet packets.

Implemented version of the DR session protocol (provide a way to handle future/alternative packets formats/crypto algorithm) Supported version description :

Version 0x01:

DRHeader is: Protocol Version Number<1 byte> || Message Type <1 byte> || curveId <1 byte> || [X3DH Init message < variable >] || Ns<2 bytes> || PN<2 bytes> || [ DHs<...> or DHrIndex<12 bytes> || DHsIndex<12 bytes> ]

Message is : DRheader<...> || cipherMessageKeyK<32 bytes> || Key auth tag<16 bytes> || cipherText<...> || Message auth tag<16 bytes>

Associated Data are transmitted separately: ADk for the Key auth tag, and ADm for the Message auth tag

Message AEAD on : (ADm, message plain text) keyed by message Key(include IV)

Key AEAD on : (ADk || Message auth tag || header, Message Key) keyed by Double Ratchet generated key/IV

ADm is : source GRUU<...> || recipient sip-uri(can be a group uri)<...>

ADk is : source GRUU<...> || recipient GRUU<...>

Note
: ADk is used with session stored AD provided by X3DH at session creation which is HKDF(initiator Ik || receiver Ik || initiator device Id || receiver device Id)

Diffie-Hellman support: X25519 or X448 (not mixed, specified by X3DH server and client setting which must match)

Packets types are : regular or x3dhinit

Enumeration Type Documentation

DR message type byte bit mapping.

1 | 7 6 5 4 3 2 1 0 |
2 | < Unused > KEM Pk Flag Payload_Direct_Encryption_Flag X3DH_Init_Flag |

KEM Pk index Flag (bit 2):

  • set : This header holds two KEM Pk indexes (local and peer one
  • unset : This header holds a KEM public key Payload_Direct_Encryptiun Flag (bit 1):
  • set : the Double Ratchet packet encrypts the user plaintext
  • unset: the Double Ratchet packet encrypts a random seed used to encrypt the user plaintext X3DH_Init_Flag (bit 0):
  • set : the Double Ratchet Packet header contains a X3DH Init message
  • unset: the Double Ratcher Packet header does not contain a X3DH Init message
Enumerator
X3DH_init_flag 

bit 0

payload_direct_encryption_flag 

bit 1

KEM_pk_index 

bit 2

haveOPk byte from X3DH init message mapping

Enumerator
withoutOPk 

0x00

withOPk 

0x01

Function Documentation

template<typename Curve >
void lime::double_ratchet_protocol::buildMessage_X3DHinit ( std::vector< uint8_t > &  message,
const DSA< Curve, lime::DSAtype::publicKey > &  Ik,
const X< Curve, lime::Xtype::publicKey > &  Ek,
const uint32_t  SPk_id,
const uint32_t  OPk_id,
const bool  OPk_flag 
)
noexcept

build an X3DH init message to insert in DR header EC only version

haveOPk <flag 1 byte> ||
self Ik < DSA<Curve, lime::DSAtype::publicKey>::ssize() bytes > ||
Ek < X<Curve, lime::Xtype::publicKey>::keyLenght() bytes> ||
peer SPk id < 4 bytes > ||
[peer OPk id(if flag is set)<4bytes>]

Parameters
[out]messagethe X3DH init message
[in]Ikself public identity key
[in]Ekself public ephemeral key
[in]SPk_idid of peer signed prekey used
[in]OPk_idid of peer OneTime prekey used(if any)
[in]OPk_flagdo we used an OPk?
template<typename Algo >
void lime::double_ratchet_protocol::buildMessage_X3DHinit ( std::vector< uint8_t > &  message,
const DSA< typename Algo::EC, lime::DSAtype::publicKey > &  Ik,
const X< typename Algo::EC, lime::Xtype::publicKey > &  Ek,
const K< typename Algo::KEM, lime::Ktype::cipherText > &  Ct,
const uint32_t  SPk_id,
const uint32_t  OPk_id,
const bool  OPk_flag 
)
noexcept
template<typename Curve >
void lime::double_ratchet_protocol::buildMessage_X3DHinit ( std::vector< uint8_t > &  message,
const DSA< typename Curve::EC, lime::DSAtype::publicKey > &  Ik,
const X< typename Curve::EC, lime::Xtype::publicKey > &  Ek,
const K< typename Curve::KEM, lime::Ktype::cipherText > &  Ct,
const uint32_t  SPk_id,
const uint32_t  OPk_id,
const bool  OPk_flag 
)
noexcept

build an X3DH init message to insert in DR header EC and KEM version

haveOPk <flag 1 byte> ||
self Ik < DSA<Curve, lime::DSAtype::publicKey>::ssize() bytes > ||
Ek < X<Curve, lime::Xtype::publicKey>::keyLenght() bytes> ||
Ct < K<Curve, lime::Ktype::cipherText>::keyLenght() bytes> ||
peer SPk id < 4 bytes > ||
[peer OPk id(if flag is set)<4bytes>]

Parameters
[out]messagethe X3DH init message
[in]Ikself public identity key
[in]Ekself public ephemeral key
[in]Ctciphertext encaspsulated to OPk if any or SPk otherwise
[in]SPk_idid of peer signed prekey used
[in]OPk_idid of peer OneTime prekey used(if any)
[in]OPk_flagdo we used an OPk?
template<typename Curve >
constexpr size_t lime::double_ratchet_protocol::headerSize ( uint8_t  messageType)
noexcept

return the size of the double ratchet packet header

header is: Protocol Version Number<1 byte> || Message Type <1 byte> || curveId <1 byte> || [X3DH Init message < variable >] || Ns<2 bytes> || PN<2 bytes> || DHs< DH public key size >

Returns
the header size without optionnal X3DH init packet
template<typename Curve >
bool lime::double_ratchet_protocol::parseMessage_get_X3DHinit ( const std::vector< uint8_t > &  message,
std::vector< uint8_t > &  X3DH_initMessage 
)
noexcept

check the message for presence of X3DH init in the header, extract it if there is one

Parameters
[in]messageA buffer holding the message, it shall be DR header || DR message. If there is a X3DH init message it is in the DR header
[out]X3DH_initMessageA buffer holding the X3DH input message
Returns
true if a X3DH init message was found, false otherwise (also in case of invalid packet)
template<typename Algo >
void lime::double_ratchet_protocol::parseMessage_X3DHinit ( const std::vector< uint8_t >  message,
DSA< typename Algo::EC, lime::DSAtype::publicKey > &  Ik,
X< typename Algo::EC, lime::Xtype::publicKey > &  Ek,
K< typename Algo::KEM, lime::Ktype::cipherText > &  Ct,
uint32_t &  SPk_id,
uint32_t &  OPk_id,
bool &  OPk_flag 
)
noexcept
template<typename Curve >
void lime::double_ratchet_protocol::parseMessage_X3DHinit ( const std::vector< uint8_t >  message,
DSA< Curve, lime::DSAtype::publicKey > &  Ik,
X< Curve, lime::Xtype::publicKey > &  Ek,
uint32_t &  SPk_id,
uint32_t &  OPk_id,
bool &  OPk_flag 
)
noexcept

Parse the X3DH init message and extract peer Ik, peer Ek, self SPk id and seld OPk id if present This is for EC only version.

usedOPk < flag on one byte > ||
peer Ik ||
peer Ek ||
self SPk id ||
self OPk id(if flag is set)

When this function is called, we already parsed the DR message to extract the X3DH_initMessage all checks were already performed by the Double Ratchet packet parser, just grab the data

Parameters
[in]messagethe message to parse
[out]Ikpeer public Identity key
[out]Ekpeer public Ephemeral key
[out]SPk_idself Signed prekey id
[out]OPk_idself One Time prekey id(if used, 0 otherwise)
[out]OPk_flagtrue if an OPk flag was present in the message
template<typename Curve >
void lime::double_ratchet_protocol::parseMessage_X3DHinit ( const std::vector< uint8_t >  message,
DSA< typename Curve::EC, lime::DSAtype::publicKey > &  Ik,
X< typename Curve::EC, lime::Xtype::publicKey > &  Ek,
K< typename Curve::KEM, lime::Ktype::cipherText > &  Ct,
uint32_t &  SPk_id,
uint32_t &  OPk_id,
bool &  OPk_flag 
)
noexcept

Parse the X3DH init message and extract peer Ik, peer Ek, self SPk id and seld OPk id if present This is for EC and KEM version.

usedOPk < flag on one byte > ||
peer Ik ||
peer Ek ||
peer Ct ||
Cipher text encapsulated with OPk if present, SPk otherwise self SPk id ||
self OPk id(if flag is set)

When this function is called, we already parsed the DR message to extract the X3DH_initMessage all checks were already performed by the Double Ratchet packet parser, just grab the data

Parameters
[in]messagethe message to parse
[out]Ikpeer public Identity key
[out]Ekpeer public Ephemeral key
[out]Ctpeer Cipher text - encaspsulated either to OPk if any or SPk if not
[out]SPk_idself Signed prekey id
[out]OPk_idself One Time prekey id(if used, 0 otherwise)
[out]OPk_flagtrue if an OPk flag was present in the message
template<typename Curve >
constexpr size_t lime::double_ratchet_protocol::X3DHinitSize ( bool  haveOPk,
typename std::enable_if_t<!std::is_base_of_v< genericKEM, Curve >, bool >  = true 
)
noexcept

return the size of the X3DH init packet included in the double ratchet packet header

For EC only version X3DH init packet is : OPk flag<1 byte> || Ik < DSA public key size > || Ek < DH public key size > || SPk Id <4 bytes> || [OPk Id <4 bytes>]

Returns
the header size without optionnal X3DH init packet
template<typename Algo >
constexpr size_t lime::double_ratchet_protocol::X3DHinitSize ( bool  haveOPk,
typename std::enable_if_t< std::is_base_of_v< genericKEM, Algo >, bool >  = true 
)
noexcept

return the size of the X3DH init packet included in the double ratchet packet header

For EC/KEM version X3DH init packet is : OPk flag<1 byte> || Ik < DSA public key size > || Ek < DH public key size > || Ct < KEM cipher text size > || SPk Id <4 bytes> || [OPk Id <4 bytes>]

Returns
the header size without optionnal X3DH init packet

Variable Documentation

constexpr uint8_t lime::double_ratchet_protocol::DR_v01 =0x01

Double ratchet protocol version number