\documentclass[a4paper,11pt]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{hyperref}
\usepackage[table]{xcolor}
\usepackage{amsmath}
\usepackage{algpseudocode}
\usepackage[margin=1.25in]{geometry}
\usepackage{placeins}
\usepackage[skip=-10pt,font=small,font=bf,labelformat=empty,justification=RaggedRight]{caption}
\usepackage{msc}
\usepackage{textcomp}
\usepackage[nottoc,numbib]{tocbibind}

% New definitions Switch/case
\algnewcommand\algorithmicswitch{\textbf{switch}}
\algnewcommand\algorithmiccase{\textbf{case}}
\algnewcommand\algorithmicassert{\texttt{assert}}
\algnewcommand\Assert[1]{\State \algorithmicassert(#1)}%
% New "environments" Switch/case
\algdef{SE}[SWITCH]{Switch}{EndSwitch}[1]{\algorithmicswitch\ #1\ \algorithmicdo}{\algorithmicend\ \algorithmicswitch}%
\algdef{SE}[CASE]{Case}{EndCase}[1]{\algorithmiccase\ #1}{\algorithmicend\ \algorithmiccase}%
\algtext*{EndSwitch}%
\algtext*{EndCase}%

\let\oldtabular\tabular 
\renewcommand{\tabular}{\footnotesize\oldtabular}

\makeatletter
\newcommand{\StatexIndent}[1][3]{%
  \setlength\@tempdima{\algorithmicindent}%
  \Statex\hskip\dimexpr#1\@tempdima\relax}
\algdef{S}[WHILE]{WhileNoDo}[1]{\algorithmicwhile\ #1}%
\makeatother

\hypersetup{colorlinks=true, linkcolor=black, citecolor=black, urlcolor=olive}

\title{Linphone Instant Message Encryption v2.0 (Lime v2.0)}
\date{\today\\Version 1.0}
\author{Johan Pascal}

\begin{document}

\maketitle
\tableofcontents
\newpage

\section{Introduction}
\paragraph{}Linphone Instant Message Encryption (Lime) v2.0 implements the Signal protocol allowing users to privately and asynchronously exchange messages. Detailed specification of the Signal protocol can be found on the \href{https://signal.org/docs/}{Signal website}. Lime supports multiple devices per user and multiple users per device.
\paragraph{}Lime is designed to be used with \href{https://linphone.org}{Linphone}, an open source SIP phone. Lime establishes encrypted sessions and encrypts messages but relies on Linphone to acquire the unique identification string of peer devices and route the messages to their recipients. The use of Lime with other message delivery software is possible but is out of the scope of this document.
\paragraph*{}Lime is written in C\nolinebreak\hspace{-.05em}\raisebox{.4ex}{\tiny\bf +}\nolinebreak\hspace{-.10em}\raisebox{.4ex}{\tiny\bf +}11 and the library uses templates to provide support for Curve25519- and Curve448-based cryptographic algorithms. The library supports one or both curves according to build settings.\\*A users network (all clients and keys server) must commit to using either Curve25519 or Curve448, but a device may host several users communicating on separate users' networks; using different curves.
\paragraph{Note:} Lime v1.0 was based on \href{https://en.wikipedia.org/wiki/Silent_Circle_Instant_Messaging_Protocol}{SCIMP}. This document presents Lime v2.0, which is neither related to nor compatible with Lime v1.0. In this document the use of the term Lime refers to Lime v2.0.

\newpage
\section{Notations}
\paragraph{}$A\Arrowvert B$ denotes the concatenation of byte sequences $A$ and $B$
\paragraph{}$A\langle value\rangle$ the bytes sequence $A$ size is $value$. For example, $key\langle 32bytes\rangle $ denotes a 32 bytes long buffer called $key$. Several values may be included in a comma-separated list, indicating that several sizes are possible.
\paragraph{}$element\{ instances\}$ denotes the number of occurrences of a given $element$. $Instances$ may be a number, a range or a comma-separated list of possible values. For example, $key\{ 4\}$ means 4 $keys$, $key\{ 0,1\}$ means either 0 or 1 $key$.
\paragraph{}$element[values]$: element value can be one of the values given in a comma-separated list. For example, $type[1,2,3]$ means $type$ equals either 1, 2, or 3.

\newpage
\section{Brief introduction to Signal protocol specification documents}
  \subsection{The Double Ratchet Algorithm}
    \paragraph{}\textquotedblleft \textit{The Double Ratchet algorithm\cite{doubleRatchet} is used by two parties to exchange encrypted
messages based on a shared secret key. Typically the parties will use some
key agreement protocol (such as X3DH\cite{x3dh}) to agree on the shared secret key.
Following this, the parties will use the Double Ratchet to send and receive
encrypted messages.
    \paragraph{}The parties derive new keys for every Double Ratchet message so that earlier keys
cannot be calculated from later ones. The parties also send Diffie-Hellman public
values attached to their messages. The results of Diffie-Hellman calculations
are mixed into the derived keys so that later keys cannot be calculated from
earlier ones. These properties give some protection to earlier or later encrypted
messages in case of a compromise of a party’s keys.}\textquotedblright 
  
  \subsection{The X3DH Key Agreement Protocol}
    \paragraph{}\textquotedblleft \textit{\textquotesingle X3DH\textquotesingle   (or  \textquotesingle Extended Triple Diffie-Hellman\textquotesingle  )\cite{x3dh} key
agreement protocol establishes a shared secret key between two parties
who mutually authenticate each other based on public keys. X3DH provides
forward secrecy and cryptographic deniability.
    \paragraph{}X3DH is designed for asynchronous settings where one user (\textquotesingle Bob\textquotesingle ) is offline
but has published some information to a server. Another user (\textquotesingle Alice\textquotesingle ) wants to
use that information to send encrypted data to Bob and also to establish a shared
secret key for future communication.}\textquotedblright 

  \subsection{The Sesame Algorithm}
    \paragraph{}\textquotedblleft \textit{The Sesame algorithm\cite{sesame} manages message encryption
sessions in an asynchronous and multi-device setting.
Sesame was designed to manage Double Ratchet sessions\cite{doubleRatchet} created with a X3DH
key agreement\cite{x3dh}. However, Sesame is a generic algorithm that works with
any session-based message encryption algorithm that meets certain conditions.}\textquotedblright 

\newpage
\section{Major discrepancies between Lime v2.0 and Signal protocol}
\paragraph{}This section will not go into the details of the Signal protocol specification but will focus only on the points where the Lime v2.0 implementation does not follow the Signal specification documentation\cite{doubleRatchet}\cite{x3dh}\cite{sesame}. A prior knowledge of these specs is essential to understand the possible effects of such discrepancies.

  \subsection{Double Ratchet}
  \subsubsection{Group chat management}
    \label{subsubsec:groupchat}
    \paragraph*{}The group chat mechanism implemented by Whisper Systems in \href{https://github.com/WhisperSystems/libsignal-protocol-c}{libsignal-protocol-c}\cite{libsignal} uses an unspecified (at least in Double Ratchet document\cite{doubleRatchet}) feature, the sender key, which:
    \begin{enumerate}
      \item When accepting membership, a group member creates its sender key and distributes it to all other members using pairwise Double Ratchet sessions; then
      \item Members use their sender key to encrypt messages to the group, deriving it by using a simple symmetric ratcheting.
    \end{enumerate}
    This mechanism allows an efficient server-side fan-out but loses the break-in recovery property provided by the Double Ratchet mechanism.
    
    \paragraph*{}Operating in a multi device environment, Lime provides the following mechanism to save bandwith when sending message to multiple devices:
    \begin{enumerate}
      \item Generate a random key and use it to encrypt the message.
      \item Use Double Ratchet sessions to encrypt the random key.
      \item Send to server a bundle of:
        \begin{center}
          \textit{DR encrypted random key\{one for each recipient device\}\\*$\Arrowvert$ Message encrypted using the random key}
        \end{center}
      \item Server fans out the messages to recipients mailboxes posting only the appropriate double ratchet encrypted random key and encrypted message.
    \end{enumerate}
    \paragraph{}This mechanism is optional and the default behavior of the library is to use it when it saves upload bandwidth, using a regular encryption in the Double Ratchet message otherwise.
    \paragraph{}The bandwidth and computational power consumption is greater than the Whisper System implementation but all the exchanges are protected by an actual Double Ratchet; maintaining the break-in recovery property.
    \paragraph{}Silent members/devices (lost devices and users quitting the network are good candidates) may result in weakness in the break-in recovery as no Diffie-Hellman ratchet step is ever performed. This is mitigated by setting a limit to the sending chain length. The sending device would create a new Double Ratchet session fetching keys from X3DH key server if the limit is reached.
    \paragraph{Note}: The actual implementation generates a 32 bytes random seed derived through HKDF\cite{rfc5869} into a 32 bytes key and a 16 bytes nonce. The DR session encrypts the 32 bytes random seed using AES256-GCM (with 16 bytes authentication tag); producing a 48 bytes output to transmit the key.
  
  \subsubsection{AEAD encryption scheme: AES256-GCM}
  \paragraph{}The Double Ratchet specification \cite[section 5.2]{doubleRatchet} recommends the use of a SIV based AEAD encryption scheme.
  \paragraph{}The Lime implementation of the Double Ratchet Chain Key derivation is described in \ref{subsubsec:kdfck} of this document. The message key$\langle 32 bytes\rangle$ and initialisation vector $\langle 16 bytes\rangle $ are generated, used and destroyed during the encryption process. The direct use of an AES256-GCM as the AEAD encryption scheme is assumed to be secure as the key and IV are not reused.

  \subsection{X3DH Identity Key signature}
    \label{subsec:x3dhIk}
    \paragraph{}The X3DH specification uses ECDH keys only in combination with XEdDSA\cite{xeddsa} to provide an EdDSA-compatible signature using its Identity key (Ik) formatted for X25519 or X448 ECDH functions.
    \paragraph{}Lime performs the same signature and ECDH operations but the identity key (Ik) is generated, stored and transmitted in its EdDSA format and then converted into X25519 or X448 format when an ECDH computation is performed on it.
    \paragraph{}The X3DH $Encode(PK)$ function recommends the usage of a single byte constant to represent the type of curve followed by the encoding specified in \cite{rfc7748}. Lime uses direct encoding specified in \cite{rfc7748} for its ECDH public keys and \cite{rfc8032} for its EdDSA keys but the type of curve is present in the messages header.

  \subsection{Authentication}
  \paragraph*{}X3DH specification mentions \cite[section 4.1]{x3dh} the necessity of an identity authentication mechanism and libsignal\cite{libsignal} implements a key fingerprints comparison to provide it. Lime makes use of a ZRTP\cite{zrtp} call with an oral SAS verification to provide mutual identity authentication. See implementation details in section \ref{subsec:mutualauthentication}
  \subsection{Optional features not implemented}
    \begin{itemize}
      \item Double ratchet with header encryption as in \cite[section 4]{doubleRatchet}
      \item Retry request as in \cite[section 4.1]{sesame}
      \item Session expiration as in \cite[section 4.2]{sesame} but a related mechanism is implemented: A Double Ratchet session expires after encrypting a certain number of messages without performing any Diffie-Hellman ratchet step.
    \end{itemize}

\newpage
\section{Implementation details}
  \subsection{Preliminaries}
    \paragraph{}For clarity, the different terms used in this document are defined here:
    \begin{itemize}
      \item device Id: a unique string associated to a device, provided to Lime by Linphone. It shall be the GRUU\cite{rfc5627}
      \item user Id: a unique string defining a user or a group of users, provided to Lime by Linphone. It shall be the sip URI.
      \item source: the device generating and encrypting a message.
      \item recipient: the parties targeted to receive and decrypt the message. Multiple devices can be associated to the it so any mention of recipient must specify user Id or device Id to clarify the intent.
    \end{itemize}

  \subsection{HKDF}
      The HKDF function, as described in RFC5869 \cite{rfc5869} is used in both X3DH and Double Ratchet. Lime uses an implementation of HKDF based on SHA512. Its prototype in the pseudo-code is as follow, all inputs and output have variable size. $salt$ is optionnal and the function may be used without(set to $null$ in the pseudo-code). The size of the generated output key material, $okm$, is arbitrary and depends only on request not on input or hash algorithm used.
      \begin{algorithmic}
        \Statex
        \Function{HKDFSha512}{$salt, ikm, info$}
          \State \Return {$okm$}
        \EndFunction
      \end{algorithmic}
  \subsection{Double Ratchet}
    \subsubsection{Diffie-Hellman}
      \paragraph{}The ECDH function can be either X448 or X25519 as described in \cite{rfc7748}.
    \subsubsection{KDF\_RK}
      \paragraph{}As recommended in \cite[section 5.2]{doubleRatchet}, this function uses HKDF\cite{rfc5869} based on SHA512. The $salt$ is RK and $ikm$ is the output of ECDH(\textit{DH\_out}). The info string is "\textit{DR Root Chain Key Derivation}". \textit{DH\_out} size depends on ECDH function used, X25519 produces a 32 bytes output, X448 a 56 bytes output.

      \begin{algorithmic}
        \Function{KDF\_RK}{RK$\langle 32bytes\rangle, DH\_out\langle 32,56bytes\rangle  $}
          \State $info \gets \textit{"DR Root Chain Key Derivation"}$
          \State $RK\langle 32bytes\rangle\Arrowvert CK\langle 32bytes\rangle \gets \Call{HKDFSha512}{RK, DH\_out, info}$
          \State \Return $RK\langle 32bytes\rangle , CK\langle 32bytes\rangle$
        \EndFunction
      \end{algorithmic}
    \subsubsection{KDF\_CK}
      \label{subsubsec:kdfck}
      Implemented as described in \cite[section 5.2]{doubleRatchet}. Message key derivation outputs 48 bytes as it generates the message key ($MK\langle 32bytes\rangle$) and the AEAD nonce ($IV\langle 16 bytes\rangle$) as suggested in \cite[section 3.1 - ENCRYPT]{doubleRatchet}.
      \begin{algorithmic}
        \Function{KDF\_CK}{CK$\langle 32bytes\rangle $}
          \State $MK\Arrowvert IV \gets \Call{HmacSha512}{ChainKey, 0x01}$
          \State $CK \gets \Call{HmacSha512}{ChainKey, 0x02}$
          \State \Return $CK\langle 32bytes\rangle ,MK\langle 32bytes\rangle ,IV\langle 16 bytes\rangle $
        \EndFunction
      \end{algorithmic}

    \subsubsection{RatchetEncrypt}
      \paragraph{}The RatchetEncrypt function described in \cite[section 3.4]{doubleRatchet} is not directly used to encrypt the message. Instead, to provide the group chat (see section \ref{subsubsec:groupchat}) capabilities, an encryption request must include a list of recipient devices (can contain one or more elements).\\*
      Each recipient in the list is composed of:
        \begin{algorithmic}
          \State $recipientDeviceId$: the recipient device Id
          \State $DRsession$: an active Double Ratchet session with the recipient device
          \State $DRmessage$: encryption output ($Double\ Ratchet\ Message$) for this recipient device
          \State $peerDeviceStatus$: an ouput giving a status on the recipient: unknown(till now thus), untrusted or trusted
        \end{algorithmic}
      \paragraph{}The ouput may be completed by a $Cipher\ Message$ holding the encrypted plain text according to the selected encryption policy,
      \paragraph{}The message is sent from the sender device to one recipient user (with one user Id and one or more associated device Id) but also distributed to other devices registered to the same sender user. Recipient devices in the list must all be linked to this, unique, recipient user Id or to the sender user Id. For example:
      \begin{itemize}
        \item $Alice$, $Bob$ and $Claire$ are users Id. Each of them have several ($nA, nB, nC$) associated devices with devices Id $Alice.1$, $Alice.2$, .., $Alice.nA$
        \item $Alice$, $Bob$ and $Claire$ are members of a group with user Id $Group$
        \item If $Alice.1$ sends a message to $Bob$, the inputs for the RatchetEncrypt function must include $Bob$ as recipient user and $Bob.1$, .., $Bob.nB$, $Alice.2$, .., $Alice.nA$ as list of recipient devices.
        \item If $Alice.1$ sends a message to $Group$, the inputs for the RatchetEncrypt function must include $Group$ as recipient user and $Bob.1$, .., $Bob.nB$, $Alice.2$, .., $Alice.nA$, $Claire.1$, .., $Claire.nC$ as list of recipient devices.
        \item The Lime library does not perform any check on the link between user Id and device Id and will not generate any error if the RatchetEncrypt arguments are $Bob$ as recipient user and $Bob.1$, .., $Bob.nB$, $Alice.2$, .., $Alice.nA$, $Claire.1$ as list of recipient devices. The error would instead be detected by $Claire.1$ during decryption. See \ref{subsubsec:associatedData} for details on the use of Associated Data to detect mismatching association of user Id and device Id.
        
      \end{itemize}
      \paragraph*{Encryption policy}: As stated in section \ref{subsubsec:groupchat}, the plain message can be:
      \label{encryptionPolicyMSC}
      \begin{itemize}
        \item encrypted directly in the Double Ratchet messages.\textit{(Double Ratchet Message encryption policy)}
        \item encrypted by a random key in a common cipher message, the random key being encrypted into the Double Ratchet messages.\textit{(Cipher Message encryption policy)}
      \end{itemize}
      The two policies are represented on the following diagrams. It is assumed that the server will dispatch only the requested parts to recipients and not the whole upload. Double Ratchet sessions establishment are not shown on the diagram but are assumed to be already completed between all participants. All participants have one device only.\\\newline
      \begin{msc}{Double Ratchet Message encryption policy}
        \setlength{\instdist}{3.8cm}
        \setlength{\instwidth}{1.9cm}
        \setlength{\actionwidth}{1.7cm}
        \setlength{\envinstdist}{1.7cm}
        \declinst{alice}{}{Alice}
        \declinst{SIP}{}{SIP server}
        \declinst{bob}{}{Bob}
        \declinst{claire}{}{Claire}
        \action{encrypt}{alice}
        \nextlevel[3]
        \mess{Bob DR msg$\Arrowvert $Claire DR msg}{alice}{SIP}
        \nextlevel[2]
        \mess{Bob DR msg}{SIP}{bob}
        \nextlevel
        \mess{Claire DR msg}{SIP}{claire}
      \end{msc}
      \\\newline
      \begin{msc}{Cipher Message encryption policy}
        \setlength{\instdist}{3.8cm}
        \setlength{\instwidth}{1.9cm}
        \setlength{\actionwidth}{1.7cm}
        \setlength{\envinstdist}{1.9cm}
        \declinst{alice}{}{Alice}
        \declinst{SIP}{}{SIP server}
        \declinst{bob}{}{Bob}
        \declinst{claire}{}{Claire}
        \action{encrypt}{alice}
        \nextlevel[3]
        \mess{Bob DR msg$\Arrowvert $Claire DR msg$\Arrowvert $cipher Message}{alice}{SIP}
        \nextlevel[2]
        \mess{Bob DR msg$\Arrowvert $cipher Message}{SIP}{bob}
        \nextlevel
        \mess{Claire DR msg$\Arrowvert $cipher Message}{SIP}{claire}
      \end{msc}
      
      \paragraph*{}Selection of the encryption policy according to policy parameter, recipientLists and plain text characteristics. The policy parameter is given at runtime by caller and default to $optimize\ Upload\ Size$ if omitted. Possible values of this parameter are:
        \begin{itemize}
          \item $Double\ Ratchet\ Message$: the plain text is encrypted and embeded in the Double Ratchet message.
          \item $cipher\ Message$: the plain text is encrypted in a cipher message with a random key, itself encrypted in the DR message.
          \item $optimize\ Upload\ Size$: for each message, select the mode which minimize the upload size. This is the default policy.
          \item $optimize\ Global\ Bandwidth$: for each message, select the mode which minimize upload + download size.
        \end{itemize}
        \paragraph*{Note}: the optimize modes do not take in consideration the multipart boundary added by the presence of an extra part holding the cipher Message.
        \label{messageEncrypt}
        
        \begin{algorithmic}
          \Statex
          \Function{MessageEncrypt}{$recipientList, plain, sourceDeviceId, recipientUserId, policy$}
            \Switch{$policy$}
              \Case{$Double Rachet Message$}
                \State $\Call{DRMessageEncrypt}{recipientList, plain, sourceDeviceId, recipientUserId}$
              \EndCase
              \Case{$cipher Message$}
                \State $\Call{cipherMessageEncrypt}{recipientList, plain, sourceDeviceId, recipientUserId}$
              \EndCase
              \Case{$optimize\ Upload\ Size$}
                \State $n \gets number\ of\ recipients\ in\ the\ recipientList$
                \State $DRMessageSize \gets n \times plain\ size$
                \State $cipherMessageSize \gets (plain\ size + authTag\ size) + n\times(randomSeed\ size)$
                \If{$DRmessageSize \leq cipherMessageSize$}
                  \State $\Call{DRMessageEncrypt}{recipientList, plain, sourceDeviceId, recipientUserId}$
                \Else
                  \State $\Call{cipherMessageEncrypt}{recipientList, plain, sourceDeviceId, recipientUserId}$
                \EndIf
              \EndCase
              \Case{$optimize\ Global\ Bandwidth$}
                \State $n \gets number\ of\ recipients\ in\ the\ recipientList$
                \State $DRMessageSize \gets 2\times n \times plain\ size$
                \State $cipherMessageSize \gets (plain\ size + authTag\ size)$
                \StatexIndent[9]$+ n\times(2\times randomSeed\ size+plain\ size+authTag\ size)$
                \If{$DRmessageSize \leq cipherMessageSize$}
                  \State $\Call{DRMessageEncrypt}{recipientList, plain, sourceDeviceId, recipientUserId}$
                \Else
                  \State $\Call{cipherMessageEncrypt}{recipientList, plain, sourceDeviceId, recipientUserId}$
                \EndIf
              \EndCase

            \EndSwitch
          \EndFunction
        \end{algorithmic}
        \paragraph*{}with following functions definitions:
        
        \begin{algorithmic}
          \Statex
          \Function{DRMessageEncrypt}{$recipientList, plain, sourceDeviceId, recipientUserId$}
            \Comment{Encrypts the plain in the Double Ratchet message}
            \ForAll{$r \in recipientList$}
              \State $AD \gets recipientUserId\Arrowvert sourceDeviceId\Arrowvert r.recipientDeviceId$
              \State $r.DRmessage \gets \Call{RatchetEncrypt}{r.session, plain, AD}$
            \EndFor
            \State\Return $recipientList$
          \EndFunction
        \end{algorithmic}
        

        \begin{algorithmic}
          \Statex
          \Function{cipherMessageEncrypt}{$recipientList, plain, sourceDeviceId, recipientUserId$}
            \Comment{Generate a random key and nonce to encrypt the plain}
            \State $randomSeed\langle 32bytes\rangle \gets \Call{RandomSource}{}$
            \State $info \gets \textit{"DR Message Key Derivation"}$
            \State $key\langle 32bytes\rangle\Arrowvert IV\langle 16bytes\rangle \gets \Call{HKDFSha512}{null, randomSeed, info}$
            \State $cipherMessage \langle plain size + 16bytes\rangle  \gets\Call{Encrypt}{key, IV, plain, sourceDeviceId \Arrowvert recipientUserId}$
            \Statex
            \Statex
            \Comment{Use Double Ratchet sessions to encrypt the random seed used to encrypt the plain}
            \ForAll{$r \in recipientList$}
              \State $AD \gets tag\Arrowvert sourceDeviceId\Arrowvert r.recipientDeviceId$
              \State $r.DRmessage \gets \Call{RatchetEncrypt}{r.session, randomSeed, AD}$
            \EndFor
            \State\Return $recipientList,cipherMessage$
          \EndFunction
        \end{algorithmic}
        
        \begin{algorithmic}
          \Statex
          \Function{RatchetEncrypt}{$DRsession, plaintext, AD$}
            \State \textit{\ as described in \cite[section 3.4]{doubleRatchet}:}
            \State $CKs,mK,IV \gets \Call{KDF\_CK}{CKs}$
            \State $header \gets \Call{header}{DHs, PN, Ns}$
            \State $Ns += 1$
            \State\Call{UpdateDRsessionInLocalStorage}{DRsession}
            \State\Return $header\Arrowvert \Call{Encrypt}{mK, IV, plaintext, AD\Arrowvert X3DH$ $provided$ $AD\Arrowvert header$}
          \EndFunction
          \Statex
        \end{algorithmic}
        
        \begin{algorithmic}
          \Statex
          \Function{Encrypt}{$key\langle 32 bytes\rangle , IV\langle 16 bytes\rangle , plain, associatedData$}
            \State\Return AES256-GCM output$\Arrowvert$Auth tag (on plain and associatedData)$\langle 16 bytes\rangle $
          \EndFunction
        \end{algorithmic}
        
      \paragraph{}Header function is specified in section \ref{subsubsec:protocol_doubleratchet_header}
        
    \subsubsection{RatchetDecrypt}
      \paragraph{}The decryption function described in \cite[section 3.5]{doubleRatchet} is not directly used to decrypt the message. Lime first assess the presence of a cipher message and depending on it use directly the Double Ratchet or perform the two steps of encryption: first decrypt the Double Ratchet message to retrieve the random Key and IV, then decrypt the message itself.
      \paragraph{}The receiving process described in Sesame specifications \cite[section 3.4]{sesame} is partly implemented in the Double Ratchet decryption process: the message decrypt function accepts a list of Double Ratchet sessions and tries them all until one decrypts correctly the message (or all fail).
      \paragraph{}The decryption returns the peer device's status(unknown, unsafe, untrusted or trusted) in case of success or fail in case of failure.
        \begin{algorithmic}
          \Statex
          \Function{MessageDecrypt}{$sourceDeviceId,$
            \StatexIndent[9] $recipientDeviceId, recipientUserId,$
            \StatexIndent[9] $DRsessionList, DRmessage, cipherMessage$}
          
            \If{$cipherMessage\exists$}
              \State \Return \Call{cipherMessageDecrypt}{$sourceDeviceId,recipientDeviceId,$
                \StatexIndent[9] $recipientDeviceId, recipientUserId$
                \StatexIndent[9] $DRsessionList, DRmessage, cipherMessage$}
            \Else
              \State \Return \Call{DRMessageDecrypt}{$sourceDeviceId,recipientDeviceId,$
                \StatexIndent[9] $recipientDeviceId, recipientUserId$
                \StatexIndent[9] $DRsessionList, DRmessage$}
            \EndIf
          \EndFunction
        \end{algorithmic}
          
        \begin{algorithmic}
          \Statex
          \Function{DRMessageDecrypt}{$sourceDeviceId,$
          \StatexIndent[9] $recipientDeviceId, recipientUserId,$
          \StatexIndent[9] $DRsessionList, DRmessage$}
          \Statex
          \State $AD \gets recipientUserId\Arrowvert sourceDeviceId\Arrowvert recipientDeviceId$
          \ForAll{$DRsession \in DRsessionList$}
            \If{$plain \gets\Call{RatchetDecrypt}{DRsession, DRmessage, AD}}$
              \State \Return $plain$
            \EndIf
          \EndFor
          \State \Return \textbf{fail}
          \EndFunction      
      \end{algorithmic}

      \begin{algorithmic}
          \Statex
          \Function{cipherMessageDecrypt}{$sourceDeviceId,$
          \StatexIndent[9] $recipientDeviceId, recipientUserId,$
          \StatexIndent[9] $DRsessionList, DRmessage, cipherMessage}$
          \Statex
          \State $AD \gets tag\Arrowvert sourceDeviceId\Arrowvert recipientDeviceId$
          \ForAll{$DRsession \in DRsessionList$}
            \If{$randomSeed \gets\Call{RatchetDecrypt}{DRsession, DRmessage, AD}}$
              \State $info \gets \textit{"DR Message Key Derivation"}$
              \State $key\langle 32bytes\rangle\Arrowvert IV\langle 16bytes\rangle \gets \Call{HKDFSha512}{null, randomSeed\langle 32bytes\rangle, info$}
              \State \Return $\Call{AEADDecrypt\&auth}{key, IV, cipher, tag, sourceDeviceId\Arrowvert recipientUserId}$
            \EndIf
          \EndFor
          \State \Return \textbf{fail}
          \EndFunction
      \end{algorithmic}
      
      \begin{algorithmic}      
          \Function{RatchetDecrypt}{$DRsession, header\Arrowvert payload\Arrowvert tag, AD$}
            \State\textit{As described in \cite[section 3.5]{doubleRatchet}}
            \State\textit{Associated Data given to AEAD is $AD\Arrowvert X3DH provided AD\Arrowvert header$}
            \If{Success}
              \State\Call{UpdateDRsessionInLocalStorage}{DRsession}
            \EndIf
          \EndFunction
        \end{algorithmic}

    \subsubsection{Associated Data}
     \label{subsubsec:associatedData}
     \paragraph{}The double ratchet encryption and decryption AEAD scheme uses Associated Data as recommended by X3DH and Double Ratchet specifications\cite[section 3.3]{x3dh}, \cite[section 3.4]{doubleRatchet}. The Associated Data authenticated is composed of:
     \paragraph*{Cipher Message encryption policy}
     \begin{algorithmic}
          \State $Message\ Tag\langle 16bytes\rangle \Arrowvert Source\ deviceId \Arrowvert Recipient\ deviceId \Arrowvert X3DH AD\langle 32bytes\rangle \Arrowvert DR\ Header$
     \end{algorithmic}
     \paragraph*{Double Ratchet Message encryption policy}
     \begin{algorithmic}
          \State $Recipient\ UserId \Arrowvert Source\ deviceId \Arrowvert Recipient\ deviceId \Arrowvert X3DH AD\langle 32bytes\rangle \Arrowvert DR\ Header$
     \end{algorithmic}

     \begin{itemize}
      \item $Message\ Tag$: AEAD authentication tag computed on plaintext and the associated data given to AEAD in cipher Message mode: $Source\ deviceId\Arrowvert Recipient\ UserId$.
      \item $Recipient\ UserId$: The inclusion of $Recipient\ UserId$ allows the recipient device to verify the original intended recipient user. The $Recipient\ UserId$ is provided to the recipient device along the message by the routing protocol as it may not be the $UserId$ linked to the recipient device but a group user Id.
      \item $Source\ deviceId$ and $Recipient\ deviceId$: Enforce identification of source and recipient device.
      \item $X3DH\ AD$: Associated data computed at session creation by the X3DH protocol, based on both parties Identity keys and devices Id. See \ref{subsubsec:X3DHAD} for details. It is present in the device local storage from the X3DH initialisation completion.
      \item $DR\ Header$: as specified in \cite[section 3.4]{doubleRatchet}. See \ref{subsubsec:protocol_doubleratchet_header} for details.
     \end{itemize}


  \subsection{X3DH}
    \paragraph*{}As stated in section \ref{subsec:x3dhIk}, Lime does not use XEdDSA but manipulates two key formats: the identity key is stored in EdDSA format (as defined in \cite{rfc8032}); while all the other keys are stored in ECDH format (as defined is \cite{rfc7748}).
    \subsubsection{DH}
      \paragraph*{}Available Diffie-Hellman algorithms are X25519 and X448, the DH computations performed strictly follow the X3DH specifications.
    \subsubsection{Sig}
      \paragraph*{}The signature/verify operation performed is an EdDSA (both EdDSA25519 and EdDSA448 are available). The identity key used is stored in EdDSA format so there is no need to use XEdDSA contrary to the X3DH specifications \cite[section 2.2]{x3dh}.
    \subsubsection{Shared Secrets generation}
      \paragraph{SK}is computed as specified in \cite[section 3.3 and 2.2]{x3dh}. The salt used for the HKDF function is a zero filled buffer the size of the hash function used, the \textit{info} parameter is "\textit{Lime}".
          \begin{algorithmic}
            \State $ZeroBuffer\langle SHA512 output size(64bytes)\rangle \gets 0$
            \State $SK\langle 32bytes\rangle  \gets \Call{HKDFSha512}{ZeroBuffer, F\langle 32,57bytes\rangle \Arrowvert DH1\Arrowvert DH2\Arrowvert DH3\Arrowvert DH4, $\textit{"Lime"}}
          \end{algorithmic}
        F is a 32 (when using curve25519) or 57 (when using curve448) bytes 0xFF filled buffer.

      \label{subsubsec:X3DHAD}
      \paragraph{Associated Data} is computed from identity keys and devices Id as specified in \cite[section 3.3]{x3dh}. For implementation convenience, the actual AD used by the Double Ratchet session is derived from these inputs by the HKDF function producing a fixed size buffer as following:
          \begin{algorithmic}
            \State $ZeroBuffer\langle SHA512 output size(64bytes)\rangle \gets 0$
            \State $ADinput \gets initiatorIk\Arrowvert receiverIk\Arrowvert initiatorDeviceId\Arrowvert receiverDeviceId$
            \State $AD\langle 32bytes\rangle  \gets \Call{HKDFSha512}{ZeroBuffer, ADinput, $\textit{"X3DH Associated Data"}}
          \end{algorithmic}
          \textit{initiator} being the device who initiates the session (Alice in the X3DH spec) by fetching a keys bundle on the X3DH server and \textit{receiver} being the recipient device of the first message (Bob in the X3DH spec).
    \subsubsection{X3DH test server}
      \paragraph*{Nodejs}: An X3DH test server running on nodejs is provided with the Lime library source code. This server is not meant to be used in production and its purpose is for testing only. This server lacks user authentication layer, which in real use case is provided by the linphone ecosystem.
  \subsection{Sesame}
    \paragraph{}The Sesame requirements are fulfilled as follow:
    \begin{itemize}
      \item Lime is operating in per-device identity keys mode.
      \item Providing an updated list of Devices Id to match the intended recipients (and sender user other devices) is performed by the linphone ecosystem (SIP and conference server). So the loop between client and server during encryption described in the Sesame spec\cite{sesame} is not relevant. Lime relies on the SIP or conference server to provide an updated list of recipient devices before the message encryption.
      \item Encrypt message to multiple recipient device is performed by the Lime Double Ratchet $messageEncrypt$ function (see section \ref{messageEncrypt}).
      \item Support for multiple sessions between devices is performed by Lime Double Ratchet $messageDecrypt$ trying multiples sessions, if present, to find one able to decrypt the incoming message.
      \item User and device identifications are provided by the linphone ecosystem: a user Id is its sip:uri, also used to identify groups. A device Id is its GRUU\cite{rfc5627}. The connection to the X3DH server is performed over HTTPS and uses the user authentication associated to the SIP user account.
      \item Mailboxes and message routing are provided by the linphone ecosystem
    \end{itemize}
   
    \newpage
    \subsubsection{Scenario 1: first encryption, multiple devices}
    \paragraph{}Alice1 encrypts a message to Bob for the first time. Alice1 must establish Double Ratchet sessions and, for that, requests key bundles. It is assumed that Alice2 is known to Alice1; so there is no request for an Alice2 key bundle. The cipher message encryption policy is used.\\\newline
    \begin{msc}{Alice1 encrypts to Bob for the first time}
    \setlength{\instdist}{2.9cm}
    \setlength{\envinstdist}{0.95cm}
    \declinst{aliced1}{}{Alice1}
    \declinst{aliced2}{}{Alice2}
    \declinst{SIP}{}{SIP s.}
    \declinst{X3DH}{}{X3DH s.}
    \declinst{bobd1}{}{Bob1}
    \declinst{bobd2}{}{Bob2}
    \mess{get Bob device's GRUU}{aliced1}{SIP}
    \nextlevel
    \mess{Alice2, Bob1, Bob2}{SIP}{aliced1}
    \nextlevel[2]
    \mess{get Bob1, Bob2 keys bundles}{aliced1}{X3DH}
    \nextlevel
    \mess{get Alice user credentials}{X3DH}{SIP}
    \nextlevel
    \mess{auth challenge}{X3DH}{aliced1}
    \nextlevel
    \mess{Alice user credentials}{SIP}{X3DH}
    \nextlevel
    \mess{auth challenge response}{aliced1}{X3DH}
    \nextlevel
    \action*{Check credentials}{X3DH}
    \nextlevel[2]
    \mess{Bob1, Bob2 keys bundles}{X3DH}{aliced1}
    \nextlevel
    \action{encrypt}{aliced1}
    \nextlevel[3]
    \mess{Alice2, Bob1, Bob2 DR msg$\Arrowvert $cipher Message}{aliced1}{SIP}
    \nextlevel[2]
    \mess{Alice2 DR msg$\Arrowvert $cipher Message}{SIP}{aliced2}
    \nextlevel
    \mess{Bob1 DR msg$\Arrowvert $cipher Message}{SIP}{bobd1}
    \nextlevel
    \mess{Bob2 DR msg$\Arrowvert $cipher Message}{SIP}{bobd2}
    \end{msc}
    
    \newpage
    \subsubsection{Scenario 2: group chat}
    \paragraph*{}Alice sends a first message to a group called Friends composed of Alice, Bob and Carol. Alice's message is dispatched and then Carol posts a message to the group. Carol's message is dispatched and finally Bob sends a message to the group. It is assumed that users did not exchanged any message prior and that they have one device each. User authentication messages to and from X3DH server are not shown for better readability but the users authentication by X3DH server and X3DH server authentication by users must take place. The cipher message encryption policy is used.\\\newline
    \begin{msc}{Group chat establishment, $Friends$ is composed of Alice, Bob and Carol}
    \setlength{\instdist}{2.9cm}
    \setlength{\envinstdist}{1cm}
    \declinst{alice}{}{Alice}
    \declinst{bob}{}{Bob}
    \declinst{carol}{}{Carol}
    \declinst{SIP}{}{SIP s.}
    \declinst{X3DH}{}{X3DH s.}
    \mess{get \textit{Friends} device's GRUU}{alice}{SIP}
    \nextlevel
    \mess{Bob, Carol}{SIP}{alice}
    \nextlevel[2]
    \mess{get Bob, Carol keys bundles}{alice}{X3DH}
    \nextlevel
    \mess{Bob, Carol keys bundles}{X3DH}{alice}
    \nextlevel
    \action{encrypt}{alice}
    \nextlevel[2]
    \mess{Bob, Carol DR msg$\Arrowvert $cipher Message}{alice}{SIP}
    \nextlevel
    \mess{Bob DR msg$\Arrowvert $cipher Message}{SIP}{bob}
    \nextlevel
    \mess{Carol DR msg$\Arrowvert $cipher Message}{SIP}{carol}
    \nextlevel[2]
    \mess{get \textit{Friends} device's GRUU}{carol}{SIP}
    \nextlevel
    \mess{Alice, Bob}{SIP}{carol}
    \nextlevel[2]
    \mess{get Bob keys bundles}{carol}{X3DH}
    \nextlevel
    \mess{Bob keys bundles}{X3DH}{carol}
    \nextlevel
    \action{encrypt}{carol}
    \nextlevel[3]
    \mess{Alice, Bob DR msg$\Arrowvert $cipher Message}{carol}{SIP}
    \nextlevel
    \mess{Alice DR msg$\Arrowvert $cipher Message}{SIP}{alice}
    \nextlevel
    \mess{Bob DR msg$\Arrowvert $cipher Message}{SIP}{bob}
    \nextlevel[2]
    \mess{get \textit{Friends} device's GRUU}{bob}{SIP}
    \nextlevel
    \mess{Alice, Carol}{SIP}{bob}
    \nextlevel
    \action{encrypt}{bob}
    \nextlevel[3]
    \mess{Alice, Carol DR msg$\Arrowvert $cipher Message}{bob}{SIP}
    \nextlevel
    \mess{Alice DR msg$\Arrowvert $cipher Message}{SIP}{alice}
    \nextlevel
    \mess{Carol DR msg$\Arrowvert $cipher Message}{SIP}{carol}
    \end{msc}
    
  \subsection{Mutual authentication and peer device status}
    \label{subsec:mutualauthentication}
    \paragraph{}As stated in \cite[section 4.1]{x3dh}, the parties shall compare their identity public keys otherwise they receive no cryptographic guarantee as to whom they are communicating with. Each peer device has a status available after any encryption or decryption operation which can be:
   \begin{itemize}
      \item $unknown$: we had no information about this device in the local storage(before the last encryption or decryption), this status spots a newly encountered device and shall be clearly made available to the end user.
      \item $untrusted$: it's is not the first interaction with this device, but we never established mutual authentication
      \item $trusted$: we already performed the mutual authentication ritual with this peer device.
      \item $unsafe$: we know this device, it has been tagged as unsafe by the application(Linphone).
   \end{itemize}
    \paragraph{}Lime provides an API to set/get peer devices identity keys and trust level indexed by its device Id. Linphone uses a ZRTP\cite{zrtp} audio call leveraging the MiTM detection offered by the ZRTP short authentication string to authenticate the peer identity key. ZRTP auxiliary secret is used to compare both parties' identity public keys in the following way:
    \begin{itemize}
      \item parties exchange their identity public keys in the signaling channel at call establishment;
      \item parties use $caller\ Ik \Arrowvert receiver\ Ik$ as ZRTP auxiliary secret;
      \item when ZRTP key exchange is complete, parties check that the auxiliary secret is matching and perform a vocal SAS comparison (if not performed before); and
      \item if the verification succeeds, each party sets the peer Ik status as $trusted$ in the Lime local storage. If the peer key is already present in the Lime local storage, Lime verifies that it matches the one obtained through the ZRTP channel.
    \end{itemize}
    
    \paragraph{}In the following diagram $alice\ Ik$ and $bob\ Ik$ refer to the identity public key associated to the particular devices used by Alice and Bob to perform the ZRTP audio call.\\\newline
    \begin{msc}{Mutual Authentication}
    \setlength{\instdist}{9cm}
    \setlength{\envinstdist}{2.5cm}
    \declinst{alice}{}{Alice}
    \declinst{bob}{}{Bob}
    \mess{SIP INVITE with $alice\ Ik$}{alice}{bob}
    \nextlevel
    \mess{SIP 200 Ok with $bob\ Ik$}{bob}{alice}
    \nextlevel
    \action*{%
      \begin{minipage}{4cm}\centering
        set $alice\ Ik\Arrowvert bob\ Ik$\\
        as ZRTP auxsecret
      \end{minipage}%
      }{alice}
    \action*{%
      \begin{minipage}{4cm}\centering
        set $alice\ Ik\Arrowvert bob\ Ik$\\
        as ZRTP auxsecret
      \end{minipage}%
      }{bob}
    \nextlevel[3]
    \mess{ZRTP exchange}{alice}{bob}
    \mess{}{bob}{alice}
    \nextlevel
    \condition{ZRTP SAS verified, auxiliary secret match}{alice,bob}
    \nextlevel[2]
    \action*{%
      \begin{minipage}{4cm}\centering
        set $bob\ Ik$ as trusted\\
        in Lime local storage
      \end{minipage}%
      }{alice}
    \action*{%
      \begin{minipage}{4cm}\centering
        set $alice\ Ik$ as trusted\\
        in Lime local storage
      \end{minipage}%
      }{bob}
    \nextlevel[3]
    \end{msc}

  \subsection{Keys and sessions management}
    \paragraph{}Key lifetime management is the responsibility of the client device; the X3DH server is not involved in their management. On a regular schedule (once a day is recommended), the device must run the $update$ function to check keys validity, renew and delete outdated ones. Several settings are involved in the $update$ operation and are all defined in \textit{lime\_settings.hpp}.
    
    \subsubsection{Identity Key}
      \paragraph{}Is valid for the lifetime of a device.
    
    \subsubsection{Signed Pre-key}
      \paragraph*{SPK\_lifeTime\_days}is a constant (7 days default) defining the key validity period. Once a key is outdated, a new one is generated, signed and uploaded on the X3DH server. Old keys are kept in storage with an $invalid$ status so valid but delayed X3DH initiation messages using this signed pre-key can still be processed.
      \paragraph*{SPK\_limboTime\_days}is a constant (30 days default) defining the period invalid keys are kept by the device.
       
    \subsubsection{One-time Pre-key}
      \paragraph{}These can be used only once, so any use implies immediate deletion:
      \begin{itemize}
      \item when the server delivers a One-time Pre-key, it immediately deletes it; and
      \item when a client makes use of one of its One-time Pre-key (upon reception from peer of an X3DH init message using that key), it immediately deletes it.
      \end{itemize}
      \paragraph*{}During $update$, a device requests from the X3DH server the list of its own OPk available on the server. The device can upload more keys if there are not enough online and track which keys where delivered by the server but not yet used by comparing the server's OPk list and the OPk actually in local storage.
      \paragraph{}The three following constants can be overridden at runtime by parameters passed to the $update$ or $create\_user$ functions:
      \paragraph{OPK\_serverLowLimit}is a constant (100 default) defining the lower bound of keys count present on server. During an update, if there are fewer occurrences of keys on the X3DH server, the client will generate and upload a batch of One-time Pre-keys.
      \paragraph{OPK\_batchSize} is a constant (25 default) defining the number of keys generated and uploaded to the server if an upload is needed.
      \paragraph{OPK\_initialBatchSize}is a constant (100 default) defining the number of keys generated and uploaded to the server at the registration of a new user device.
      \paragraph{}During $update$, the client will update the status of One-time Pre-keys in local storage to reflect the information provided by the server. Any key still in local storage but no longer on the server is assigned the $dispatched$ status.
      \paragraph{}During $update$, the device deletes One-time Pre-keys having the $dispatched$ status for a longer than pre-determined period of time.
      \paragraph{OPK\_limboTime\_days} is a constant (37 days default) defining the period dispatched One-time Pre-keys are kept by the device.

    \subsubsection{Double Ratchet Sessions}
      \paragraph{}More than one double ratchet session may exist between two devices but only one shall be active. The encryption is always performed by the active session and, on reception, the session successfully decrypting the message becomes the active session. Stalled sessions are kept for a pre-determined period of time to allow decrypting of delayed or unordered messages:
      \paragraph{DRSession\_limboTime\_days}is a constant (30 days default) defining the period stalled sessions are kept by the device.
      \paragraph{}In case a peer device is silent, the double ratchet session will never perform a Diffie-Hellman ratchet but only symmetric ratchet steps. To mitigate this problem, a pre-defined limit on the number of messages encrypted without performing Diffie-Hellman is set (effectively being a limit on the length of the sending chain, each Diffie-Hellman ratchet reset the sending chain counter):
      \paragraph{maxSendingChain}is a constant (1000 default) defining the maximum length of a sending chain. When reached, the Double Ratchet session status is stalled, forcing the sender device to create a new session; fetching a new key bundle from the X3DH server in order to keep on sending messages.
    
    \subsubsection{Skipped message keys}
      \paragraph{}As messages may be out of order on reception, Double Ratchet specifies how skipped intermediate messages keys, generated to decrypt a received message, shall be stored to allow the decryption of out-of-order messages. After a pre-determined number of messages successfully decrypted by a double ratchet session, skipped messages are considered lost and their stored message keys are deleted from local storage:
      \paragraph{maxMessagesReceivedAfterSkip} is a constant (128 default) linked to a double ratchet receiving chain (a new chain is started within the session each time a Diffie-Hellman ratchet is performed). Each time a skipped message key is stored in this chain, the counter is reset. Each time a message is decrypted by the session, all skipped message key chain counters are increase by one. When the counter reaches $maxMessagesReceivedAfterSkip$, the skipped message key chain is deleted.
    

  \subsection{Local Storage}
    The local storage is provided by an sqlite3 database accessed using the \href{https://github.com/SOCI/soci}{SOCI library} \cite{libsoci}.
    \subsubsection{Devices tables}
    \paragraph*{lime\_LocalUsers} stores data relative to local devices.
    \begin{itemize}
      \item $Uid$: integer primary key.
      \item $UserId$: the device Id provided by linphone, it shall be the GRUU.
      \item $Ik$: Identity key, an EdDSA key stored as public key $\Arrowvert $ private key.
      \item $server$: the X3DH server URL to be used by this user.
      \item $curveId$: An unsigned integer, mapped as following:
        \begin{itemize}
          \item LSB(bit 7 to 0) stores the curve id mapped to integers: 0x01 for Curve 25519 or 0x02 for Curve 448. This value must match the X3DH server setting.
          \item bit 8 is the active flag : 0 for active user, 1 for inactive user
        \end{itemize}
    \end{itemize}
    
    \paragraph*{lime\_PeerDevices}
    \textit{Note:} Records in this table are not linked to a local user but shared among local users in order to avoid storing multiple records containing the same information.
    \begin{itemize}
      \item $Did$: integer primary key.
      \item $DeviceId$: the peer device Id, it shall be its GRUU.
      \item $Ik$: the peer's public EdDSA identity key.
      \item $Status$: status flag:
        \begin{itemize}
          \item 0 for untrusted: peer's identity is not verified(default value)
          \item 1 for trusted: peer's identity was already verified
          \item 2 for unsafe: peer's device has been flagged as unsafe
        \end{itemize}
        see this document section \ref{subsec:mutualauthentication} for usage.
    \end{itemize}
    
    \subsubsection{X3DH tables}
    The X3DH dedicated tables store local users' Signed Pre-keys and One-time Pre-keys, records are linked to a local user through a foreign key: $Uid$.
    \paragraph*{X3DH\_SPK}
    \textit{Note:} signature is computed and uploaded to the server at key generation but is then not needed, so not stored locally.
    \begin{itemize}
      \item $SPKid$: a random Id (unsigned integer on 31 bits) to identify the key. This value being public, it is not a sequence but a random number.
      \item $SPK$: an ECDH key (stored as public key$\Arrowvert $private key).
      \item $timeStamp$: is set to current time when the key status is set to invalid.
      \item $Status$: set to valid (1) at creation and then to invalid (0) when a new key is generated.
      \item $Uid$: link to $lime\_LocalUsers$: identifies which local user owns this record.
    \end{itemize}
  
  \paragraph*{X3DH\_OPK}
    \begin{itemize}
      \item $OPKid$: a random Id (unsigned integer on 31 bits) to identify the key. This value being public, it is not a sequence but a random number.
      \item $OPK$: an ECDH key (stored as public key$\Arrowvert $private key).
      \item $timeStamp$: is set to current time when the key status is set to dispatched.
      \item $Status$: set to online (1) at key generation and then to dispatched (0) when the key is not found anymore on the X3DH server by the $update$ request.
      \item $Uid$: link to $lime\_LocalUsers$: identify which local user owns this record.
    \end{itemize}
              
    \subsubsection{Double ratchet tables}
    The Double Ratchet tables store all material needed for the Double Ratchet session, including dedicated tables for skipped keys. Records are linked to local and peer devices through foreign keys: Uid and Did.
    \paragraph*{DR\_sessions}
    \begin{itemize}
      \item $Did$: link to $lime\_PeerDevices$: identify peer device for this session.
      \item $Uid$: link to $lime\_LocalUsers$: identify local device for this session.
      \item $sessionId$: integer primary key.
      \item $Ns$: index of current sending chain.
      \item $Nr$: index of current receiving chain.
      \item $PN$: index of previous sending chain.
      \item $DHr$: peer's ECDH public key.
      \item $DHs$: self ECDH key (public$\Arrowvert $private).
      \item $RK$: Diffie-Hellman Ratchet Root key.
      \item $CKr$: Symmetric Ratchet receiver chain key.
      \item $CKs$: Symmetric Ratchet sender chain key.
      \item $AD$: session Associated Data (provided at session creation by X3DH).
      \item $Status$: active (1) or stale (0), only one session can be active between two devices.
      \item $timeStamp$: is set to current time when the status is set switched from active to stale.
      \item $X3DHInit$: holds the X3DH init message while it is requested to insert it in message header.
    \end{itemize}
    
    \paragraph*{}The two following tables store the skipped message keys, indexed by peer's ECDH public key and receiving chain index:
    \paragraph*{DR\_MSk\_DHr} stores key chain information: peer's ECDH public keys.
    \begin{itemize}
      \item $DHid$: integer primary key
      \item $sessionId$: link to $DR\_sessions$: identifies to which session this chain of skipped message keys belongs.
      \item $DHr$: peer's ECDH public key associated to this message key chain.
      \item $received$: counts the messages successfully decrypted after the last insertion of a skipped message key in this chain. Is used to delete old message keys.
    \end{itemize}

    \paragraph*{DR\_MSk\_MK} is the actual storage of message keys.
    \begin{itemize}
      \item $DHid$: link to $DR\_MSk\_DHr$: identifies to which receiving chain this message key belongs.
      \item $Nr$: index of the skipped message in the receiving chain.
      \item $MK$: the message key$\langle 32bytes\rangle  \Arrowvert $initial vector$\langle 16bytes\rangle $.
    \end{itemize}
  

    
  \subsection{Summary of cryptographic algorithms used}
    \subsubsection{Double Ratchet}
      \begin{itemize}
        \item Diffie-Hellman using either X25519 or X448
        \item KDF are HKDF\cite{rfc5869} based on Sha512
        \item ENCRYPT is AES256-GCM with a 128bits authentication tag
      \end{itemize}
    \subsubsection{X3DH}
      \begin{itemize}
        \item Diffie-Hellman using either X25519 or X448
        \item HKDF uses Sha512
        \item Signature uses EdDSA25519 or EdDSA448
        \item EdDSA keys are converted to ECDH keys to perform classic ECDH
      \end{itemize}
  
  \subsubsection{Cryptographic libraries}
    \paragraph{}Elliptic curves operations are provided by decaf library\cite{libdecaf}, version 0.9.4 or above: X25519, X448, EdDSA25519, EdDSA448 and conversion function from EdDSA key to ECDH key format.
    \paragraph{}Hash (HmacSha512) and encryption (AES256-GCM) are provided by mbedtls library\cite{libmbedtls}. Version 2.1 or above.
    \paragraph{Note}: These libraries are not accessed directly but through the bctoolbox abstraction library.

\newpage
\section{Protocol specification}
  This section describes the details of messages structures.
  \paragraph*{Notes}: Keys are intended as public keys and their size depends on the selected curve indicated in the messages header. The following sizes apply:
  \begin{itemize}
    \item Curve 25519 ECDH: 32 bytes
    \item Curve 25519 EdDSA: 32 bytes
    \item Curve 25519 Signature: 64 bytes
    \item Curve 448 ECDH: 56 bytes
    \item Curve 448 EdDSA: 57 bytes
    \item Curve 448 Signature: 114 bytes
  \end{itemize}
  Keys are stored and distributed in the formats described in \cite{rfc7748} and \cite{rfc8032}.\\*
  Others numeric values (counts, Ids, counters) are unsigned integers in big endian.
  
  \subsection{Double Ratchet message}
    \paragraph*{}These messages are exchanged among devices. The system runs in asynchronous mode, and messages are sent to and stored by a server and are fetched by final recipients when online. The server in charge of storing/routing the messages shall fan-out to the respective recipients not all the incoming message but only the part addressed to them.

    \paragraph*{}Double Ratchet messages are composed of header and payload. The payload is the AEAD output (cipher text and authentication tag) of either a random seed used to encrypt the plain message or the plain message itself according to selected encryption policy. The sender produces one Double Ratchet message per recipient device.\\
      Definitions:
      \begin{itemize}
      \item Protocol Version: 0x01.
      \item Message Type is a byte with following bit mapping:
        \begin{itemize}
          \item bit 7 to 2: not used.
          \item bit 1: Payload encryption flag:
            \begin{itemize}
              \item 1: payload in the DR message
              \item 0: payload in a cipher message, DR holds the random seed
            \end{itemize}
          \item bit 0: X3DH init flag:
            \begin{itemize}
              \item 1: (X3DH init in the header)
              \item 0: (no X3DH init in the header)
            \end{itemize}
        \end{itemize}
      \item Curve Id: [0x01 (curve 25519), 0x02 (curve 448)]
      \end{itemize}

      \subsubsection{Header}
      \label{subsubsec:protocol_doubleratchet_header}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        Protocol Version [0x01] & Message type & Curve Id [0x01,0x02] & \\
        \cline{1-3}
        \multicolumn{4}{|c|}{X3DH Init $\langle $variable size$\rangle $\{0,1\}}\\
        \multicolumn{4}{|c|}{This part is present only if Message type X3DH init flag is set}\\
        \hline
        \multicolumn{2}{|c}{Ns}&\multicolumn{2}{|c|}{PN}\\
        \hline
        \multicolumn{4}{|c|}{DHs$\langle 32,56 bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
      \end{tabular}
      \end{center}

      \subsubsection{Payload in cipher message encryption policy}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        \multicolumn{4}{|c|}{Random Seed encrypted using DR session$\langle 32bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{Double Ratchet AEAD authentication tag$\langle 16bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
      \end{tabular}
      \end{center}
      
      \subsubsection{Payload in Double Ratchet message encryption policy}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        \multicolumn{4}{|c|}{plaintext encrypted using DR session$\langle variable\ size,\ same\ as\ plaintext\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{Double Ratchet AEAD authentication tag$\langle 16bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
      \end{tabular}
      \end{center}

      \subsubsection{X3DH init}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        OPk flag [0x00,0x01]&\multicolumn{3}{|c|}{}\\
        \cline{1-1}
        \multicolumn{4}{|c|}{EdDSA Identity Key$\langle 32,57bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{ ECDH Ephemeral Key$\langle 32,56bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{Signed Pre-key Id}\\
        \hline
        \multicolumn{4}{|c|}{One Time Pre-key Id\{0,1\} only if OPk flag = 0x01}\\
        \hline
      \end{tabular}
      \end{center}
      
  \subsection{Cipher Message}. The cipher message is produced only when selecting the cipher message encryption policy. The sender produces one cipher message common to all recipients. When present, the cipher message is dispatched along the Double Ratchet messages.(see \ref{encryptionPolicyMSC} for details)
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        \multicolumn{4}{|c|}{Cipher text produced by AEAD using a derivative of Random Seed <variable size>}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{AEAD authentication tag$\langle 16bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
      \end{tabular}
      \end{center}
  \subsection{X3DH message}
    \paragraph{}Theses messages are exchanged between devices and the X3DH key server.
    \paragraph*{}The messages are sent to the server using the HTTPS protocol. Clients identify themselves to the server by setting their device Id (GRUU) in the HTTPS packet \textit{From} field. Server challenges the client with a nonce and expects a digest of the password of their user account on the SIP server. X3DH server must have access to the SIP register server database to be able to authenticate clients. Communications between clients and X3DH server are assumed to be secure and the details of this assumption are out of the scope of this document.
    \paragraph*{}X3DH messages are composed of a header and the content:\\*
    Protocol Version$\langle 1byte\rangle \Arrowvert $ Message Type $\langle 1byte\rangle \Arrowvert $ Curve Id $\langle 1byte\rangle \Arrowvert $ Message content.
    Definitions:
      \begin{itemize}
      \item Protocol Version: 0x01.
      \item Message Type:
        \begin{itemize}
          \item \textit{0x01: deprecated register User}: a device registers its Id and Identity key on X3DH server, this message holds the Ik only and shall be supported for retro-compatibility with old clients only.
          \item \textit{0x02: delete User}: a device deletes its Id and Identity key from X3DH server.
          \item \textit{0x03: post Signed Pre-key}: a device publishes a Signed Pre-key on X3DH server.
          \item \textit{0x04: post One-time Pre-keys}: a device publishes a batch of One-time Pre-keys on X3DH server.
          \item \textit{0x05: get peers key bundles}: a device requests key bundles for a list of peer devices.
          \item \textit{0x06: peers key bundles}: X3DH server responds to device with the list of requested key bundles.
          \item \textit{0x07: get self One-time Pre-keys}: ask server for self One-time Pre-keys Ids available.
          \item \textit{0x08: self One-time Pre-keys}: server response with a count and list of all One-time Pre-keys Ids available.          
          \item \textit{0x09: register User}: a device registers its Id and Identity key, Signed Pre-key and a batch of One-time Pre-keys on X3DH server.
          \item \textit{0xFF: error}: something went wrong on server side during processing of client message, server respond with details on failure.
        \end{itemize}
      \item Curve Id: [0x01 (curve 25519), 0x02 (curve 448)]
      \end{itemize}
    
    To device generated messages \textit{(deprecated) register User, delete User, post Signed Pre-key} and \textit{post One-time Pre-key}, on success, the X3DH server responds with the original message header:\\*
    Protocol Version $\Arrowvert $ Message type $\Arrowvert $ Curve Id
    \subsubsection{Register User Message}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        Protocol Version [0x01] & Message type [0x09] & Curve Id [0x01,0x02] &\\
        \cline{1-3}
        \multicolumn{4}{|c|}{EdDSA Identity Key$\langle 32,57bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{ECDH Signed Pre-key$\langle 32,56bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{ECDH Signed Pre-key Signature$\langle 64,114bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{Signed Pre-key Id}\\
        \hline
        \multicolumn{2}{|c}{keys Count} & \multicolumn{2}{|c|}{One-time Pre-key bundle$\langle 36,60bytes\rangle $\{keys Count\}}\\
        \cline{1-2}
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{c}{}\\
        \multicolumn{4}{c}{with One-time Pre-key bundle:}\\
        \hline
        \cellcolor[gray]{0.95} byte 0 & \cellcolor[gray]{0.95} byte 1 & \cellcolor[gray]{0.95} byte 2 & \cellcolor[gray]{0.95}byte 3\\
        \hline
        \multicolumn{4}{|c|}{ECDH One-Time Pre-key$\langle 32,56bytes\rangle$}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{One-Time Pre-key Id}\\
        \hline
      \end{tabular}
      \end{center}
    
    \subsubsection{Delete User Message}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        Protocol Version [0x01] & Message type [0x02] & Curve Id [0x01,0x02] & \\
        \hline
      \end{tabular}
      \end{center}

    \subsubsection{post Signed Pre-key Message}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        Protocol Version [0x01] & Message type [0x03] & Curve Id [0x01,0x02] & \\
        \cline{1-3}
        \multicolumn{4}{|c|}{ECDH Signed Pre-key$\langle 32,56bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{ECDH Signed Pre-key Signature$\langle 64,114bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{Signed Pre-key Id}\\
        \hline
      \end{tabular}
      \end{center}
    
    \subsubsection{post One-time Pre-key Message}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        Protocol Version [0x01] & Message type [0x04] & Curve Id [0x01,0x02] & keys Count MSB\\
        \hline
        keys Count LSB & \multicolumn{3}{c|}{One-time Pre-key bundle$\langle 36,60bytes\rangle $\{keys Count\}}\\
        \cline{1-1}
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{c}{}\\
        \multicolumn{4}{c}{with One-time Pre-key bundle:}\\
        \hline
        \cellcolor[gray]{0.95} byte 0 & \cellcolor[gray]{0.95} byte 1 & \cellcolor[gray]{0.95} byte 2 & \cellcolor[gray]{0.95}byte 3\\
        \hline
        \multicolumn{4}{|c|}{ECDH One-Time Pre-key$\langle 32,56bytes\rangle$}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{One-Time Pre-key Id}\\
        \hline
      \end{tabular}
      \end{center}
     
    \subsubsection{get peers key bundles Message}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        Protocol Version [0x01] & Message type [0x05] & Curve Id [0x01,0x02] & request Count MSB\\
        \hline
        request Count LSB & \multicolumn{3}{c|}{request\{request Count\}}\\
        \cline{1-1}
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{c}{}\\
        \multicolumn{4}{c}{with request:}\\
        \hline
        \cellcolor[gray]{0.95} byte 0 & \cellcolor[gray]{0.95} byte 1 & \cellcolor[gray]{0.95} byte 2 & \cellcolor[gray]{0.95}byte 3\\
        \hline
        \multicolumn{2}{|c}{Device Id size}&\multicolumn{2}{|c|}{Device Id$\langle$variable size$\rangle$...}\\
        \hline
        \multicolumn{4}{|c|}{...Device Id$\langle$variable size$\rangle$}\\
        \hline
      \end{tabular}
      \end{center}
    
    \subsubsection{peers key bundles Message}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        Protocol Version [0x01] & Message type [0x06] & Curve Id [0x01,0x02] & bundles Count MSB\\
        \hline
        bundles Count LSB & \multicolumn{3}{c|}{key Bundle\{bundles Count\}}\\
        \cline{1-1}
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{c}{}\\
        \multicolumn{4}{c}{with key Bundle(if a the device has published keys on the server):}\\
        \hline
        \cellcolor[gray]{0.95} byte 0 & \cellcolor[gray]{0.95} byte 1 & \cellcolor[gray]{0.95} byte 2 & \cellcolor[gray]{0.95}byte 3\\
        \hline
        \multicolumn{2}{|c|}{Device Id size}&\multicolumn{2}{c|}{Device Id$\langle$variable size$\rangle$...}\\
        \hline
        \multicolumn{4}{|c|}{...Device Id$\langle$variable size$\rangle$}\\
        \hline
        bundle flag [0x00,0x01] & \multicolumn{3}{c|}{}\\
        \cline{1-1}
        \multicolumn{4}{|c|}{EdDSA Identity Key$\langle 32,57bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{ECDH Signed Pre-key$\langle 32,56bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{Signed Pre-key Id}\\
        \hline
        \multicolumn{4}{|c|}{ECDH Signed Pre-key Signature$\langle 64,114bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{ECDH One-Time Pre-key$\langle 32,56bytes\rangle $\{0,1\} only if bundle flag = 0x01}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
        \multicolumn{4}{|c|}{One-Time Pre-key Id\{0,1\} only if bundle flag = 0x01}\\
        \hline
        \multicolumn{4}{c}{}\\
        \multicolumn{4}{c}{or key Bundle(if a the device has not published keys on the server):}\\
        \hline
        \cellcolor[gray]{0.95} byte 0 & \cellcolor[gray]{0.95} byte 1 & \cellcolor[gray]{0.95} byte 2 & \cellcolor[gray]{0.95}byte 3\\
        \hline
        \multicolumn{2}{|c|}{Device Id size}&\multicolumn{2}{c|}{Device Id$\langle$variable size$\rangle$...}\\
        \hline
        \multicolumn{4}{|c|}{...Device Id$\langle$variable size$\rangle$}\\
        \hline
        bundle flag [0x02]\\
        \cline{1-1}
      \end{tabular}
      \end{center}
      
    \subsubsection{get Self OPks Message}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        Protocol Version [0x01] & Message type [0x07] & Curve Id [0x01,0x02] & \\
        \hline
      \end{tabular}
      \end{center}

    \subsubsection{self OPks Message}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        Protocol Version [0x01] & Message type [0x08] & Curve Id [0x01,0x02] & OPk Count MSB\\
        \hline
        OPk Count LSB & \multicolumn{3}{c|}{OPk Id$\langle 4bytes\rangle $\{OPk Count\}}\\
        \cline{1-1}
        \multicolumn{4}{|c|}{...}\\
        \hline
      \end{tabular}
      \end{center}

    \subsubsection{Error Message}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        Protocol Version [0x01] & Message type [0xFF] & Curve Id [0x01,0x02] & Error Code[0x00-0x08]\\
        \hline
        \multicolumn{4}{|c|}{Optional error message of variable size}\\
        \multicolumn{4}{|c|}{Null terminated ASCII string}\\
        \multicolumn{4}{|c|}{...}\\
        \hline        
      \end{tabular}
      \end{center}

    With Error codes in:
    \begin{itemize}
      \item 0x00: \textbf{bad content type}: HTTPS packet \textit{content-type} is not "x3dh/octet-stream"
      \item 0x01: \textbf{bad curve}: client and server curve mismatch.
      \item 0x02: \textbf{missing Sender Id}: HTTPS packet \textit{from} is not set.
      \item 0x03: \textbf{bad protocol version}: client and server X3DH protocol version number mismatch.
      \item 0x04: \textbf{bad size}: the size of received Message is not the expected one
      \item 0x05: \textbf{user already in}: trying to register a user on X3DH server but it is already in the database
      \item 0x06: \textbf{user not found}: an operation concerning a user could not be performed because the user was not found in server database.
      \item 0x07: \textbf{db error}: server encountered problem with its database.
      \item 0x08: \textbf{bad request}: malformed peer bundle request.
    \end{itemize}

    \subsubsection{Deprecated Register User Message}
      \begin{center}
      \begin{tabular}{ | p{1.4in} | p{1.4in} | p{1.4in} | p{1.4in} |}
        \hline
        \cellcolor[gray]{0.85} byte 0 & \cellcolor[gray]{0.85} byte 1 & \cellcolor[gray]{0.85} byte 2 & \cellcolor[gray]{0.85}byte 3\\
        \hline
        Protocol Version [0x01] & Message type [0x01] & Curve Id [0x01,0x02] &\\
        \cline{1-3}
        \multicolumn{4}{|c|}{EdDSA Identity Key$\langle 32,57bytes\rangle $}\\
        \multicolumn{4}{|c|}{...}\\
        \hline
      \end{tabular}
      \end{center}

\newpage
\section{IPR}
  \paragraph*{}Copyright\textcopyright 2018 Belledonne Communications.  All rights reserved.

\newpage
\begin{thebibliography}{99}

\bibitem{doubleRatchet}
  Moxie Marlinspike, Trevor Perrin (editor)
  \textit{\: "The Double Ratchet Algorithm"},
  Revision 1,
  2016-11-20.
  \href{https://signal.org/docs/specifications/doubleratchet/}{https://signal.org/docs/specifications/doubleratchet/}

\bibitem{x3dh}
  Moxie Marlinspike, Trevor Perrin (editor)
  \textit{\: "The X3DH Key Agreement Protocol"},
  Revision 1,
  2016-11-04.
  \href{https://signal.org/docs/specifications/x3dh/}{https://signal.org/docs/specifications/x3dh/} 

\bibitem{sesame}
  Moxie Marlinspike, Trevor Perrin (editor)
  \textit{\: "The Sesame Algorithm: Session Management for Asynchronous Message Encryption"},
  Revision 2,
  2017-04-14.
  \href{https://signal.org/docs/specifications/sesame/}{https://signal.org/docs/specifications/sesame/}

\bibitem{xeddsa}
  Trevor Perrin (editor)
  \textit{\: "The XEdDSA and VXEdDSA Signature Schemes"},
  Revision 1,
  2016-10-20.
  \href{https://signal.org/docs/specifications/xeddsa/}{https://signal.org/docs/specifications/xeddsa/}

\bibitem{rfc7748}
  A. Langley, M. Hamburg, and S. Turner,
  \textit{\: "Elliptic Curves for Security."},
  Internet Engineering Task Force; RFC 7748 (Informational); IETF, Jan-2016.
  \href{http://www.ietf.org/rfc/rfc7748.txt}{http://www.ietf.org/rfc/rfc7748.txt}
  
\bibitem{rfc8032}
  S. Josefsson and I. Liusvaara
  \textit{\: "Edwards-Curve Digital Signature Algorithm (EdDSA)"},
  Internet Engineering Task Force; RFC 8032 (Informational); IETF, Jan-2017.
  \href{https://tools.ietf.org/html/rfc8032}{https://tools.ietf.org/html/rfc8032}

\bibitem{rfc5627}
  J. Rosenberg
  \textit{\:"Obtaining and Using Globally Routable User Agent URIs (GRUUs) in the Session Initiation Protocol (SIP)"},
  Internet Engineering Task Force; RFC 5627 (Standards Track); IETF, Oct-2009.
  \href{https://tools.ietf.org/html/rfc5627}{https://tools.ietf.org/html/rfc5627}
  
\bibitem{rfc5869}
  H. Krawczyk and P. Eronen
  \textit{\:"HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"},
  Internet Engineering Task Force; RFC 5869 (Informational); IETF, May-2010.
  \href{https://tools.ietf.org/html/rfc5869}{https://tools.ietf.org/html/rfc5869}
  
\bibitem{zrtp}
  P. Zimmermann, A. Johnston and J. Callas
  \textit{\:"ZRTP: Media Path Key Agreement for Unicast Secure RTP"},
  Internet Engineering Task Force; RFC 6189 (Informational); IETF, April-2011.
  \href{https://tools.ietf.org/html/rfc6189}{https://tools.ietf.org/html/rfc6189}

\bibitem{libsignal}
  Whisper Systems
  \textit{\:"Signal Protocol C Library"},
  \href{https://github.com/WhisperSystems/libsignal-protocol-c}{https://github.com/WhisperSystems/libsignal-protocol-c}

\bibitem{libdecaf}
  Mike Hamburg
  \textit{\:"Ed448-Goldilocks"},
  \href{https://sourceforge.net/projects/ed448goldilocks/}{https://sourceforge.net/projects/ed448goldilocks/}
  
\bibitem{libmbedtls}
  ARM mbed
  \textit{\:"mbed TLS"},
  \href{https://tls.mbed.org/}{https://tls.mbed.org/}
  
\bibitem{libsoci}
  SOCI
  \textit{\:"SOCI - The C++ Database Access Library."},
  \href{https://github.com/SOCI/soci}{https://github.com/SOCI/soci}
\end{thebibliography}

\end{document}
