1 /*
2 linphone
3 Copyright (C) 2015  Belledonne Communications SARL
4 
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 */
19 
20 #ifndef LIME_H
21 #define LIME_H
22 
23 #define LIME_INVALID_CACHE	0x1001
24 #define LIME_UNABLE_TO_DERIVE_KEY 0x1002
25 #define LIME_UNABLE_TO_ENCRYPT_MESSAGE 0x1004
26 #define LIME_UNABLE_TO_DECRYPT_MESSAGE 0x1008
27 #define LIME_NO_VALID_KEY_FOUND_FOR_PEER	0x1010
28 #define LIME_INVALID_ENCRYPTED_MESSAGE 0x1020
29 #define LIME_PEER_KEY_HAS_EXPIRED	0x1040
30 #define LIME_NOT_ENABLED 0x1100
31 
32 /* this define the maximum key derivation number allowed to get the caches back in sync in case of missed messages */
33 #define MAX_DERIVATION_NUMBER 100
34 
35 #define LIME_SENDER	0x01
36 #define LIME_RECEIVER 0x02
37 #include <stdint.h>
38 #include <libxml/tree.h>
39 #include <libxml/parser.h>
40 #include <libxml/xmlwriter.h>
41 
42 #include "linphone/core.h"
43 #include <mediastreamer2/mscommon.h>
44 
45 /**
46  * @brief Structure holding all needed material to encrypt/decrypt Messages */
47 typedef struct limeKey_struct  {
48 	int zuid; /**< the internal cache id for this key, zuid is a binding on local uri and zid <-> peer uri and zid */
49 	uint8_t key[32]; /**< a 256 bit key used to encrypt/decrypt message */
50 	uint8_t sessionId[32]; /**< a session id used to derive key */
51 	uint32_t sessionIndex; /**< an index to count number of derivation */
52 	uint8_t peerZID[12]; /**< the ZID associated to this key */
53 } limeKey_t;
54 
55 /**
56  * @brief Store the differents keys associated to a sipURI */
57 typedef struct limeURIKeys_struct {
58 	limeKey_t 	**peerKeys; /**< an array of all the key material associated to each ZID matching the specified URI */
59 	uint16_t	associatedZIDNumber; /**< previous array length */
60 	char 		*peerURI; /**< the peer sip URI associated to all the keys, must be a null terminated string */
61 	char  		*selfURI; /**< the local sip URI used to send messages, must be a null terminated string */
62 } limeURIKeys_t;
63 
64 /**
65  * @brief Get from cache all the senders keys associated to the given URI
66  * peerKeys field from associatedKeys param must be NULL when calling this function.
67  * Structure content must then be freed using lime_freeKeys function
68  *
69  * @param[in]		cachedb		Pointer to the sqlite3 DB
70  * @param[in,out]	associatedKeys	Structure containing the self and peer URI. After this call contains all key material associated to the given URI. Must be then freed through lime_freeKeys function
71  *
72  * @return 0 on success(at least one valid key found), error code otherwise
73  */
74 LINPHONE_PUBLIC int lime_getCachedSndKeysByURI(void *cachedb, limeURIKeys_t *associatedKeys);
75 
76 /**
77  * @brief Get the receiver key associated to the ZID given in the associatedKey parameter
78  *
79  * @param[in]		cachedb			Pointer to the sqlite3 DB
80  * @param[in,out]	associatedKey		Structure containing the peerZID and will store the retrieved key
81  * @param[in]		selfURI			The source URI
82  * @param[in]		peerURI			The destination URI
83  *
84  * @return 0 on success, error code otherwise
85  */
86 LINPHONE_PUBLIC int lime_getCachedRcvKeyByZid(void *cachedb, limeKey_t *associatedKey, const char *selfURI, const char *peerURI);
87 
88 /**
89  * @brief Set in cache the given key material, association is made by ZID contained in the associatedKey parameter
90  *
91  * @param[in/out]	cachedb		Pointer to the sqlite3 DB
92  * @param[in,out]	associatedKey		Structure containing the key and ZID to identify the peer node to be updated
93  * @param[in]		role			Can be LIME_SENDER or LIME_RECEIVER, specify which key we want to update
94  * @param[in]		validityTimeSpan	If not 0, set the <valid> tag to now+validityTimeSpan (in seconds)
95  *
96  * @return 0 on success, error code otherwise
97  */
98 LINPHONE_PUBLIC int lime_setCachedKey(void *cachedb, limeKey_t *associatedKey, uint8_t role, uint64_t validityTimeSpan);
99 
100 /**
101  * @brief Free all allocated data in the associated keys structure
102  * Note, this will also free the peerURI string which then must have been allocated
103  * This does not free the memory area pointed by associatedKeys.
104  *
105  * @param[in,out]	associatedKeys	The structure to be cleaned
106  *
107  */
108 LINPHONE_PUBLIC void lime_freeKeys(limeURIKeys_t *associatedKeys);
109 
110 /**
111  * @brief encrypt a message with the given key
112  *
113  * @param[in]	key					Key to use: first 192 bits are used as key, last 64 bits as init vector
114  * @param[in]	plainMessage		The string to be encrypted
115  * @param[in]	messageLength		The length in bytes of the message to be encrypted
116  * @param[in]	selfZID				The self ZID is use in authentication tag computation
117  * @param[out]	encryptedMessage	A buffer to hold the output, ouput length is input's one + 16 for the authentication tag
118  * 									Authentication tag is set at the begining of the encrypted Message
119  *
120  * @return 0 on success, error code otherwise
121  *
122  */
123 LINPHONE_PUBLIC int lime_encryptMessage(limeKey_t *key, const uint8_t *plainMessage, uint32_t messageLength, uint8_t selfZID[12], uint8_t *encryptedMessage);
124 
125 /**
126  * @brief Encrypt a file before transfering it to the server, encryption is done in several call, first one will be done with cryptoContext null, last one with length = 0
127  *
128  * @param[in,out]	cryptoContext		The context used to encrypt the file using AES-GCM. Is created at first call(if null)
129  * @param[in]		key					256 bits : 192 bits of key || 64 bits of Initial Vector
130  * @param[in]		length				Length of data to be encrypted, if 0 it will conclude the encryption
131  * @param[in]		plain				Plain data to be encrypted (length bytes)
132  * @param[out]		cipher				Output to a buffer allocated by caller, at least length bytes available
133  *
134  * @return 0 on success, error code otherwise
135  *
136  */
137 LINPHONE_PUBLIC int lime_encryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher);
138 
139 /**
140  * @brief Decrypt a file retrieved from server, decryption is done in several call, first one will be done with cryptoContext null, last one with length = 0
141  *
142  * @param[in,out]	cryptoContext		The context used to decrypt the file using AES-GCM. Is created at first call(if null)
143  * @param[in]		key					256 bits : 192 bits of key || 64 bits of Initial Vector
144  * @param[in]		length				Length of data to be decrypted, if 0 it will conclude the decryption
145  * @param[out]		plain				Output to a buffer allocated by caller, at least length bytes available
146  * @param[in]		cipher				Cipher text to be decrypted(length bytes)
147  *
148  * @return 0 on success, error code otherwise
149  *
150  */
151 LINPHONE_PUBLIC int lime_decryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher);
152 
153 /**
154  * @brief decrypt and authentify a message with the given key
155  *
156  * @param[in]	key					Key to use: first 192 bits are used as key, last 64 bits as init vector
157  * @param[in]	encryptedMessage	The string to be decrypted
158  * @param[in]	messageLength		The length in bytes of the message to be decrypted (this include the 16 bytes tag at the begining of the message)
159  * @param[in]	selfZID				The self ZID is use in authentication tag computation
160  * @param[out]	plainMessage		A buffer to hold the output, ouput length is input's one - 16 for the authentication tag + 1 for null termination char
161  * 									Authentication tag is retrieved at the begining of the encrypted Message
162  *
163  * @return 0 on success, error code otherwise
164  *
165  */
166 
167 LINPHONE_PUBLIC int lime_decryptMessage(limeKey_t *key, uint8_t *encryptedMessage, uint32_t messageLength, uint8_t selfZID[12], uint8_t *plainMessage);
168 
169 /**
170  * @brief create the encrypted multipart xml message from plain text and destination URI
171  * Retrieve in cache the needed keys which are then updated. Output buffer is allocated and must be freed by caller
172  *
173  * @param[in,out]	cachedb			Pointer to the sqlite DB holding zrtp/lime cache, get the keys and selfZID from it, updated by this function with derivated keys
174  * @param[in]		content_type		The content type of the message to encrypt
175  * @param[in]		message			The message content to be encrypted
176  * @param[in]		selfURI			The source URI
177  * @param[in]		peerURI			The destination URI, associated keys will be found in cache
178  * @param[out]		output			The output buffer, allocated and set with the encrypted message xml body(null terminated string). Must be freed by caller
179  *
180  * @return 	0 on success, error code otherwise
181  */
182 LINPHONE_PUBLIC int lime_createMultipartMessage(void *cachedb, const char *contentType, uint8_t *message, const char *selfURI, const char *peerURI, uint8_t **output);
183 
184 /**
185  * @brief decrypt a multipart xml message
186  * Retrieve in cache the needed key which is then updated. Output buffer is allocated and must be freed by caller
187  *
188  * @param[in,out]	cachedb			Pointer to the sqlite DB holding zrtp/lime cache, get the keys and selfZID from it, updated by this function with derivated keys
189  * @param[in]		message			The multipart message, contain one or several part identified by destination ZID, one shall match the self ZID retrieved from cache
190  * @param[in]		selfURI			The source URI
191  * @param[in]		peerURI			The destination URI, associated keys will be found in cache
192  * @param[out]		output			The output buffer, allocated and set with the decrypted message(null terminated string). Must be freed by caller
193  * @param[out]		content_type	The content type of the decrypted message
194  * @param[in]		validityTimeSpan	If not 0, update the <valid> tag associated to sender to now+validityTimeSpan (in seconds)
195  * @return 	0 on success, error code otherwise
196  */
197 LINPHONE_PUBLIC int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *selfURI, const char *peerURI, uint8_t **output, char **content_type, uint64_t validityTimeSpan);
198 
199 /**
200  * @brief given a readable version of error code generated by Lime functions
201  * @param[in]	errorCode	The error code
202  * @return a string containing the error description
203  */
204 LINPHONE_PUBLIC char *lime_error_code_to_string(int errorCode);
205 
206 /**
207  * @brief Check if Lime was enabled at build time
208  *
209  * @return TRUE if Lime is available, FALSE if not
210  */
211 LINPHONE_PUBLIC bool_t lime_is_available(void);
212 
213 int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg);
214 
215 int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg);
216 
217 int lime_im_encryption_engine_process_downloading_file_cb(LinphoneImEncryptionEngine *engine, LinphoneChatMessage *msg, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decrypted_buffer);
218 
219 int lime_im_encryption_engine_process_uploading_file_cb(LinphoneImEncryptionEngine *engine, LinphoneChatMessage *msg, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encrypted_buffer);
220 
221 bool_t lime_im_encryption_engine_is_file_encryption_enabled_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room);
222 
223 void lime_im_encryption_engine_generate_file_transfer_key_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg);
224 
225 #endif /* LIME_H */
226