| 1 | /* |
|---|
| 2 | The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack. |
|---|
| 3 | Copyright (C) 2011 Belledonne Communications |
|---|
| 4 | |
|---|
| 5 | This library is free software; you can redistribute it and/or |
|---|
| 6 | modify it under the terms of the GNU Lesser General Public |
|---|
| 7 | License as published by the Free Software Foundation; either |
|---|
| 8 | version 2.1 of the License, or (at your option) any later version. |
|---|
| 9 | |
|---|
| 10 | This library 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 GNU |
|---|
| 13 | Lesser General Public License for more details. |
|---|
| 14 | |
|---|
| 15 | You should have received a copy of the GNU Lesser General Public |
|---|
| 16 | License along with this library; if not, write to the Free Software |
|---|
| 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 18 | */ |
|---|
| 19 | |
|---|
| 20 | #if defined(_MSC_VER) && (defined(WIN32) || defined(_WIN32_WCE)) |
|---|
| 21 | #include "ortp-config-win32.h" |
|---|
| 22 | #elif HAVE_CONFIG_H |
|---|
| 23 | #include "ortp-config.h" |
|---|
| 24 | #endif |
|---|
| 25 | |
|---|
| 26 | #include "ortp/ortp.h" |
|---|
| 27 | #include "rtpsession_priv.h" |
|---|
| 28 | |
|---|
| 29 | #include "ortp/zrtp.h" |
|---|
| 30 | |
|---|
| 31 | #ifdef WIN32 |
|---|
| 32 | #include <malloc.h> |
|---|
| 33 | #endif |
|---|
| 34 | |
|---|
| 35 | #ifdef HAVE_zrtp |
|---|
| 36 | |
|---|
| 37 | |
|---|
| 38 | // Minimum packet length is 3 + 3 (HelloAck) + 1 = 7 uint_32t |
|---|
| 39 | #define ZRTP_MIN_MSG_LENGTH 28 |
|---|
| 40 | |
|---|
| 41 | // ZRTP message is prefixed by RTP header |
|---|
| 42 | #define ZRTP_MESSAGE_OFFSET 12 |
|---|
| 43 | |
|---|
| 44 | #define SRTP_PAD_BYTES (SRTP_MAX_TRAILER_LEN + 4) |
|---|
| 45 | // 1234567890123456 |
|---|
| 46 | static const char userAgentStr[] = "LINPHONE-ZRTPCPP"; // 16 chars max. |
|---|
| 47 | |
|---|
| 48 | struct _OrtpZrtpContext{ |
|---|
| 49 | ortp_mutex_t mutex; |
|---|
| 50 | RtpSession *session; |
|---|
| 51 | uint32_t timerWillTriggerAt; |
|---|
| 52 | uint16_t last_recv_zrtp_seq_number; |
|---|
| 53 | uint16_t last_sent_zrtp_seq_number; |
|---|
| 54 | srtp_t srtpSend; |
|---|
| 55 | srtp_t srtpRecv; |
|---|
| 56 | zrtp_Callbacks zrtp_cb; |
|---|
| 57 | ZrtpContext *zrtpContext; // back link |
|---|
| 58 | RtpTransport rtpt; |
|---|
| 59 | RtpTransport rtcpt; |
|---|
| 60 | }; |
|---|
| 61 | |
|---|
| 62 | typedef enum { |
|---|
| 63 | rtp_stream, |
|---|
| 64 | rtcp_stream |
|---|
| 65 | } stream_type; |
|---|
| 66 | |
|---|
| 67 | |
|---|
| 68 | |
|---|
| 69 | // Helper functions |
|---|
| 70 | static inline OrtpZrtpContext* user_data(ZrtpContext *c) { |
|---|
| 71 | return (OrtpZrtpContext*) c->userData; |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | static inline uint64_t convert_timeval_to_millis(struct timeval *t) { |
|---|
| 75 | uint32_t ret=(1000LL*t->tv_sec)+(t->tv_usec/1000LL); |
|---|
| 76 | return ret; |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | static void check_timer(ZrtpContext *zrtpContext, OrtpZrtpContext *c) { |
|---|
| 80 | if (c->timerWillTriggerAt != 0) { |
|---|
| 81 | struct timeval t; |
|---|
| 82 | gettimeofday(&t,NULL); |
|---|
| 83 | uint64_t now=convert_timeval_to_millis(&t); |
|---|
| 84 | if (now > c->timerWillTriggerAt) { |
|---|
| 85 | c->timerWillTriggerAt=0; |
|---|
| 86 | zrtp_processTimeout(zrtpContext); |
|---|
| 87 | } |
|---|
| 88 | } |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | static void parseZrtpMessageType(char *messageType, const uint8_t* data) { |
|---|
| 92 | memcpy(messageType, data+4,8); |
|---|
| 93 | messageType[8]=0; |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | /* Structure of ZRTP packet (taken from the RFC) |
|---|
| 97 | 0 1 2 3 |
|---|
| 98 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
|---|
| 99 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|---|
| 100 | |0 0 0 1|Not Used (set to zero) | Sequence Number | |
|---|
| 101 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|---|
| 102 | | Magic Cookie 'ZRTP' (0x5a525450) | |
|---|
| 103 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|---|
| 104 | | Source Identifier | |
|---|
| 105 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|---|
| 106 | | | |
|---|
| 107 | | ZRTP Message (length depends on Message Type) | |
|---|
| 108 | | . . . | |
|---|
| 109 | | | |
|---|
| 110 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|---|
| 111 | | CRC (1 word) | |
|---|
| 112 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|---|
| 113 | Figure 2: ZRTP Packet Format |
|---|
| 114 | */ |
|---|
| 115 | |
|---|
| 116 | /* Structure of ZRTP Message (taken from RFC) |
|---|
| 117 | 0 1 2 3 |
|---|
| 118 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
|---|
| 119 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|---|
| 120 | |0 1 0 1 0 0 0 0 0 1 0 1 1 0 1 0| length | |
|---|
| 121 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|---|
| 122 | | Message Type Block="the type" (2 words) | |
|---|
| 123 | | | |
|---|
| 124 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
|---|
| 125 | */ |
|---|
| 126 | static inline uint16_t get_rtp_seqnumber(const uint8_t *rtp) { |
|---|
| 127 | return ntohs(*(uint16_t*)(rtp+2)); |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | static inline uint16_t get_zrtp_message_length(const uint8_t *zrtp_message){ |
|---|
| 131 | return ntohs(*(uint16_t*)(zrtp_message+2)); |
|---|
| 132 | } |
|---|
| 133 | |
|---|
| 134 | static inline uint32_t get_zrtp_packet_crc(const uint32_t *zrtp_packet, uint16_t zrtp_message_length) { |
|---|
| 135 | return ntohl(*(zrtp_packet + ZRTP_MESSAGE_OFFSET/4 + zrtp_message_length)); |
|---|
| 136 | } |
|---|
| 137 | |
|---|
| 138 | static const char *zrtpErrorType="Error "; |
|---|
| 139 | static void print_zrtp_packet(const char *info, const uint8_t *rtp) { |
|---|
| 140 | const uint8_t *zmessage=rtp+ZRTP_MESSAGE_OFFSET; |
|---|
| 141 | uint16_t zmessage_seq=get_rtp_seqnumber(rtp); |
|---|
| 142 | |
|---|
| 143 | char msgType[9]; |
|---|
| 144 | parseZrtpMessageType(msgType, zmessage); |
|---|
| 145 | |
|---|
| 146 | /* uint16_t zmessage_length = get_zrtp_message_length(zmessage); |
|---|
| 147 | uint32_t crc = get_zrtp_packet_crc((uint32_t*) rtp, zmessage_length); |
|---|
| 148 | |
|---|
| 149 | ortp_message("%s ZRTP seq=%u type=%s CRC=%u, ln=%u", |
|---|
| 150 | info, zmessage_seq, msgType, crc, zmessage_length); |
|---|
| 151 | */ |
|---|
| 152 | |
|---|
| 153 | if (strcmp(zrtpErrorType, msgType) == 0) { |
|---|
| 154 | uint32_t *msg32=(uint32_t*)zmessage; |
|---|
| 155 | uint32_t errcode=ntohl(msg32[3]); |
|---|
| 156 | ortp_error("%s ZRTP %s 0x%x %u", info, msgType, errcode, zmessage_seq); |
|---|
| 157 | } else { |
|---|
| 158 | ortp_message("%s ZRTP %s %u", info, msgType, zmessage_seq); |
|---|
| 159 | } |
|---|
| 160 | |
|---|
| 161 | /* uint32_t *msg32=(uint32_t*)zmessage; |
|---|
| 162 | int i=0; |
|---|
| 163 | for (; i<zmessage_length; i++) { |
|---|
| 164 | ortp_message("%u", ntohl(msg32[i])); |
|---|
| 165 | }*/ |
|---|
| 166 | } |
|---|
| 167 | |
|---|
| 168 | |
|---|
| 169 | |
|---|
| 170 | /* ZRTP library Callbacks implementation */ |
|---|
| 171 | |
|---|
| 172 | /** |
|---|
| 173 | * Send a ZRTP packet via RTP. |
|---|
| 174 | * |
|---|
| 175 | * ZRTP calls this method to send a ZRTP packet via the RTP session. |
|---|
| 176 | * |
|---|
| 177 | * @param ctx |
|---|
| 178 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 179 | * @param data |
|---|
| 180 | * Points to ZRTP message to send. |
|---|
| 181 | * @param length |
|---|
| 182 | * The length in bytes of the data |
|---|
| 183 | * @return |
|---|
| 184 | * zero if sending failed, one if packet was sent |
|---|
| 185 | */ |
|---|
| 186 | static int32_t ozrtp_sendDataZRTP (ZrtpContext* ctx, const uint8_t* data, const int32_t length ){ |
|---|
| 187 | OrtpZrtpContext *userData = user_data(ctx); |
|---|
| 188 | RtpSession *session = userData->session; |
|---|
| 189 | struct sockaddr *destaddr=(struct sockaddr*)&session->rtp.rem_addr; |
|---|
| 190 | socklen_t destlen=session->rtp.rem_addrlen; |
|---|
| 191 | ortp_socket_t sockfd=session->rtp.socket; |
|---|
| 192 | |
|---|
| 193 | // Create ZRTP packet |
|---|
| 194 | |
|---|
| 195 | int32_t newlength = length + 3*4; // strangely, given length includes CRC size !!!! |
|---|
| 196 | uint32_t* buffer32 = alloca(newlength); |
|---|
| 197 | uint8_t *buffer8=(uint8_t*)buffer32; |
|---|
| 198 | uint16_t *buffer16=(uint16_t*)buffer32; |
|---|
| 199 | |
|---|
| 200 | uint16_t seqNumber=userData->last_sent_zrtp_seq_number++; |
|---|
| 201 | |
|---|
| 202 | *buffer8 = 0x10; |
|---|
| 203 | buffer8[1]=0; |
|---|
| 204 | buffer16[1] = htons(seqNumber); |
|---|
| 205 | buffer32[1] = htonl(ZRTP_MAGIC); |
|---|
| 206 | buffer32[2] = htonl(session->snd.ssrc); |
|---|
| 207 | memcpy(buffer32+3, data, length); |
|---|
| 208 | uint32_t cks=zrtp_EndCksum(zrtp_GenerateCksum(buffer8, newlength-CRC_SIZE)); |
|---|
| 209 | buffer32[newlength/4-1] = htonl(cks); |
|---|
| 210 | |
|---|
| 211 | print_zrtp_packet("sent", buffer8); |
|---|
| 212 | |
|---|
| 213 | // Send packet |
|---|
| 214 | ssize_t bytesSent = sendto(sockfd, (void*)buffer8, newlength,0,destaddr,destlen); |
|---|
| 215 | if (bytesSent == -1 || bytesSent < length) { |
|---|
| 216 | ortp_error("zrtp_sendDataZRTP: sent only %d bytes out of %d", (int)bytesSent, length); |
|---|
| 217 | return 0; |
|---|
| 218 | } else { |
|---|
| 219 | return 1; |
|---|
| 220 | } |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | |
|---|
| 224 | /** |
|---|
| 225 | * Activate timer. |
|---|
| 226 | * |
|---|
| 227 | * @param ctx |
|---|
| 228 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 229 | * @param time |
|---|
| 230 | * The time in ms for the timer |
|---|
| 231 | * @return |
|---|
| 232 | * zero if activation failed, one if timer was activated |
|---|
| 233 | */ |
|---|
| 234 | static int32_t ozrtp_activateTimer (ZrtpContext* ctx, int32_t time ) { |
|---|
| 235 | if (user_data(ctx)->timerWillTriggerAt != 0) { |
|---|
| 236 | ortp_error("zrtp_activateTimer while another timer already active"); |
|---|
| 237 | return 0; |
|---|
| 238 | } |
|---|
| 239 | struct timeval t; |
|---|
| 240 | gettimeofday(&t,NULL); |
|---|
| 241 | user_data(ctx)->timerWillTriggerAt=time+convert_timeval_to_millis(&t); |
|---|
| 242 | return 1; |
|---|
| 243 | } |
|---|
| 244 | |
|---|
| 245 | /** |
|---|
| 246 | * Cancel the active timer. |
|---|
| 247 | * |
|---|
| 248 | * @param ctx |
|---|
| 249 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 250 | * @return |
|---|
| 251 | * zero if cancel action failed, one if timer was canceled |
|---|
| 252 | */ |
|---|
| 253 | static int32_t ozrtp_cancelTimer(ZrtpContext* ctx) { |
|---|
| 254 | user_data(ctx)->timerWillTriggerAt=0; |
|---|
| 255 | return 1; |
|---|
| 256 | } |
|---|
| 257 | |
|---|
| 258 | /** |
|---|
| 259 | * Send information messages to the hosting environment. |
|---|
| 260 | * |
|---|
| 261 | * The ZRTP implementation uses this method to send information |
|---|
| 262 | * messages to the host. Along with the message ZRTP provides a |
|---|
| 263 | * severity indicator that defines: Info, Warning, Error, |
|---|
| 264 | * Alert. Refer to the <code>MessageSeverity</code> enum above. |
|---|
| 265 | * |
|---|
| 266 | * @param ctx |
|---|
| 267 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 268 | * @param severity |
|---|
| 269 | * This defines the message's severity |
|---|
| 270 | * @param subCode |
|---|
| 271 | * The subcode identifying the reason. |
|---|
| 272 | * @see ZrtpCodes#MessageSeverity |
|---|
| 273 | */ |
|---|
| 274 | static void ozrtp_sendInfo (ZrtpContext* ctx, int32_t severity, int32_t subCode ) { |
|---|
| 275 | const char* submsg; |
|---|
| 276 | switch (subCode) { |
|---|
| 277 | case zrtp_InfoHelloReceived: |
|---|
| 278 | /*!< Hello received, preparing a Commit */ |
|---|
| 279 | submsg="zrtp_InfoHelloReceived"; |
|---|
| 280 | break; |
|---|
| 281 | case zrtp_InfoCommitDHGenerated: |
|---|
| 282 | /*!< Commit: Generated a public DH key */ |
|---|
| 283 | submsg="zrtp_InfoCommitDHGenerated"; |
|---|
| 284 | break; |
|---|
| 285 | case zrtp_InfoRespCommitReceived: |
|---|
| 286 | /*!< Responder: Commit received, preparing DHPart1 */ |
|---|
| 287 | submsg="zrtp_InfoRespCommitReceived"; |
|---|
| 288 | break; |
|---|
| 289 | case zrtp_InfoDH1DHGenerated: |
|---|
| 290 | /*!< DH1Part: Generated a public DH key */ |
|---|
| 291 | submsg="zrtp_InfoDH1DHGenerated"; |
|---|
| 292 | break; |
|---|
| 293 | case zrtp_InfoInitDH1Received: |
|---|
| 294 | /*!< Initiator: DHPart1 received, preparing DHPart2 */ |
|---|
| 295 | submsg="zrtp_InfoInitDH1Received"; |
|---|
| 296 | break; |
|---|
| 297 | case zrtp_InfoRespDH2Received: |
|---|
| 298 | /*!< Responder: DHPart2 received, preparing Confirm1 */ |
|---|
| 299 | submsg="zrtp_InfoRespDH2Received"; |
|---|
| 300 | break; |
|---|
| 301 | case zrtp_InfoInitConf1Received: |
|---|
| 302 | /*!< Initiator: Confirm1 received, preparing Confirm2 */ |
|---|
| 303 | submsg="zrtp_InfoInitConf1Received"; |
|---|
| 304 | break; |
|---|
| 305 | case zrtp_InfoRespConf2Received: |
|---|
| 306 | /*!< Responder: Confirm2 received, preparing Conf2Ack */ |
|---|
| 307 | submsg="zrtp_InfoRespConf2Received"; |
|---|
| 308 | break; |
|---|
| 309 | case zrtp_InfoRSMatchFound: |
|---|
| 310 | /*!< At least one retained secrets matches - security OK */ |
|---|
| 311 | submsg="zrtp_InfoRSMatchFound"; |
|---|
| 312 | break; |
|---|
| 313 | case zrtp_InfoSecureStateOn: |
|---|
| 314 | /*!< Entered secure state */ |
|---|
| 315 | submsg="zrtp_InfoSecureStateOn"; |
|---|
| 316 | break; |
|---|
| 317 | case zrtp_InfoSecureStateOff: |
|---|
| 318 | /*!< No more security for this session */ |
|---|
| 319 | submsg="zrtp_InfoSecureStateOff"; |
|---|
| 320 | break; |
|---|
| 321 | default: |
|---|
| 322 | submsg="unkwown"; |
|---|
| 323 | break; |
|---|
| 324 | } |
|---|
| 325 | |
|---|
| 326 | switch (severity) { |
|---|
| 327 | case zrtp_Info: |
|---|
| 328 | ortp_message("ZRTP INFO %s",submsg); |
|---|
| 329 | break; |
|---|
| 330 | case zrtp_Warning: /*!< A Warning message - security can be established */ |
|---|
| 331 | ortp_warning("ZRTP %s",submsg); |
|---|
| 332 | break; |
|---|
| 333 | case zrtp_Severe:/*!< Severe error, security will not be established */ |
|---|
| 334 | ortp_error("ZRTP SEVERE %s",submsg); |
|---|
| 335 | break; |
|---|
| 336 | case zrtp_ZrtpError: |
|---|
| 337 | ortp_error("ZRTP ERROR %s",submsg); |
|---|
| 338 | break; |
|---|
| 339 | default: |
|---|
| 340 | ortp_error("ZRTP UNKNOWN ERROR %s",submsg); |
|---|
| 341 | break; |
|---|
| 342 | } |
|---|
| 343 | |
|---|
| 344 | |
|---|
| 345 | if (subCode == zrtp_InfoSecureStateOn || subCode == zrtp_InfoSecureStateOff) { |
|---|
| 346 | OrtpEventData *eventData; |
|---|
| 347 | OrtpEvent *ev; |
|---|
| 348 | ev=ortp_event_new(ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED); |
|---|
| 349 | eventData=ortp_event_get_data(ev); |
|---|
| 350 | eventData->info.zrtp_stream_encrypted=(subCode == zrtp_InfoSecureStateOn); |
|---|
| 351 | rtp_session_dispatch_event(user_data(ctx)->session, ev); |
|---|
| 352 | } |
|---|
| 353 | } |
|---|
| 354 | |
|---|
| 355 | |
|---|
| 356 | /** returned key need to be fred.*/ |
|---|
| 357 | static uint8_t *key_with_salt(C_SrtpSecret_t* s, int32_t role) { |
|---|
| 358 | uint8_t *saltedKey; |
|---|
| 359 | const int pad=128; |
|---|
| 360 | if (role == Initiator) { |
|---|
| 361 | saltedKey=ortp_malloc0((s->initKeyLen + s->initSaltLen + pad)/8); |
|---|
| 362 | memcpy(saltedKey, s->keyInitiator, s->initKeyLen/8); |
|---|
| 363 | memcpy(saltedKey + s->initKeyLen/8, s->saltInitiator, s->initSaltLen/8); |
|---|
| 364 | } else { |
|---|
| 365 | saltedKey=ortp_malloc0((s->respKeyLen + s->respSaltLen + pad)/8); |
|---|
| 366 | memcpy(saltedKey, s->keyResponder, s->respKeyLen/8); |
|---|
| 367 | memcpy(saltedKey + s->respKeyLen/8, s->saltResponder, s->respSaltLen/8); |
|---|
| 368 | } |
|---|
| 369 | return saltedKey; |
|---|
| 370 | } |
|---|
| 371 | |
|---|
| 372 | |
|---|
| 373 | /** |
|---|
| 374 | * SRTP crypto data ready for the sender or receiver. |
|---|
| 375 | * |
|---|
| 376 | * The ZRTP implementation calls this method right after all SRTP |
|---|
| 377 | * secrets are computed and ready to be used. The parameter points |
|---|
| 378 | * to a structure that contains pointers to the SRTP secrets and a |
|---|
| 379 | * <code>enum Role</code>. The called method (the implementation |
|---|
| 380 | * of this abstract method) must either copy the pointers to the SRTP |
|---|
| 381 | * data or the SRTP data itself to a save place. The SrtpSecret_t |
|---|
| 382 | * structure is destroyed after the callback method returns to the |
|---|
| 383 | * ZRTP implementation. |
|---|
| 384 | * |
|---|
| 385 | * The SRTP data themselves are obtained in the ZRtp object and are |
|---|
| 386 | * valid as long as the ZRtp object is active. TheZRtp's |
|---|
| 387 | * destructor clears the secrets. Thus the called method needs to |
|---|
| 388 | * save the pointers only, ZRtp takes care of the data. |
|---|
| 389 | * |
|---|
| 390 | * The implementing class may enable SRTP processing in this |
|---|
| 391 | * method or delay it to srtpSecertsOn(). |
|---|
| 392 | * |
|---|
| 393 | * @param ctx |
|---|
| 394 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 395 | * @param secrets A pointer to a SrtpSecret_t structure that |
|---|
| 396 | * contains all necessary data. |
|---|
| 397 | * |
|---|
| 398 | * @param part for which part (Sender or Receiver) this data is |
|---|
| 399 | * valid. |
|---|
| 400 | * |
|---|
| 401 | * @return Returns false if something went wrong during |
|---|
| 402 | * initialization of SRTP context, for example memory shortage. |
|---|
| 403 | */ |
|---|
| 404 | static int32_t ozrtp_srtpSecretsReady (ZrtpContext* ctx, C_SrtpSecret_t* secrets, int32_t part ) { |
|---|
| 405 | srtp_policy_t policy; |
|---|
| 406 | err_status_t srtpCreateStatus; |
|---|
| 407 | err_status_t addStreamStatus; |
|---|
| 408 | OrtpZrtpContext *userData = user_data(ctx); |
|---|
| 409 | |
|---|
| 410 | ortp_message("ZRTP secrets for %s are ready; auth tag len is %i", |
|---|
| 411 | (part == ForSender) ? "sender" : "receiver",secrets->srtpAuthTagLen); |
|---|
| 412 | |
|---|
| 413 | // Get authentication and cipher algorithms in srtp format |
|---|
| 414 | if (secrets->authAlgorithm != zrtp_Sha1) { |
|---|
| 415 | ortp_fatal("unsupported authentication algorithm by srtp"); |
|---|
| 416 | } |
|---|
| 417 | |
|---|
| 418 | if (secrets->symEncAlgorithm != zrtp_Aes) { |
|---|
| 419 | ortp_fatal("unsupported cipher algorithm by srtp"); |
|---|
| 420 | } |
|---|
| 421 | |
|---|
| 422 | /* |
|---|
| 423 | * Don't use crypto_policy_set_from_profile_for_rtp(), it is totally buggy. |
|---|
| 424 | */ |
|---|
| 425 | memset(&policy,0,sizeof(policy)); |
|---|
| 426 | |
|---|
| 427 | if (secrets->srtpAuthTagLen == 32){ |
|---|
| 428 | crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); |
|---|
| 429 | crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtcp); |
|---|
| 430 | }else if (secrets->srtpAuthTagLen == 80){ |
|---|
| 431 | crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); |
|---|
| 432 | crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); |
|---|
| 433 | }else{ |
|---|
| 434 | ortp_fatal("unsupported auth tag len"); |
|---|
| 435 | } |
|---|
| 436 | |
|---|
| 437 | if (part == ForSender) { |
|---|
| 438 | srtpCreateStatus=srtp_create(&userData->srtpSend, NULL); |
|---|
| 439 | policy.ssrc.type=ssrc_specific; |
|---|
| 440 | policy.ssrc.value=userData->session->snd.ssrc; // us |
|---|
| 441 | policy.key=key_with_salt(secrets, secrets->role); |
|---|
| 442 | addStreamStatus=srtp_add_stream(userData->srtpSend, &policy); |
|---|
| 443 | } else { //if (part == ForReceiver) |
|---|
| 444 | srtpCreateStatus=srtp_create(&userData->srtpRecv, NULL); |
|---|
| 445 | policy.ssrc.type = ssrc_any_inbound; /*we don't know the incoming ssrc will be */ |
|---|
| 446 | int32_t peerRole=secrets->role == Initiator ? Responder : Initiator; |
|---|
| 447 | policy.key=key_with_salt(secrets,peerRole); |
|---|
| 448 | addStreamStatus=srtp_add_stream(userData->srtpRecv, &policy); |
|---|
| 449 | } |
|---|
| 450 | |
|---|
| 451 | ortp_free(policy.key); |
|---|
| 452 | |
|---|
| 453 | if (srtpCreateStatus != err_status_ok) { |
|---|
| 454 | ortp_error("ZRTP Error %u during creation of SRTP context for %s", |
|---|
| 455 | srtpCreateStatus, (part == ForSender) ? "sender" : "receiver"); |
|---|
| 456 | return 0; |
|---|
| 457 | } |
|---|
| 458 | if (addStreamStatus != err_status_ok) { |
|---|
| 459 | ortp_error("ZRTP Error %u during addition of SRTP stream for %s", |
|---|
| 460 | addStreamStatus, (part == ForSender) ? "sender" : "receiver"); |
|---|
| 461 | return 0; |
|---|
| 462 | } |
|---|
| 463 | return 1; |
|---|
| 464 | } |
|---|
| 465 | |
|---|
| 466 | |
|---|
| 467 | |
|---|
| 468 | |
|---|
| 469 | /** |
|---|
| 470 | * Switch off the security for the defined part. |
|---|
| 471 | * |
|---|
| 472 | * @param ctx |
|---|
| 473 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 474 | * @param part Defines for which part (sender or receiver) to |
|---|
| 475 | * switch off security |
|---|
| 476 | */ |
|---|
| 477 | static void ozrtp_srtpSecretsOff (ZrtpContext* ctx, int32_t part ) { |
|---|
| 478 | OrtpZrtpContext *userData = user_data(ctx); |
|---|
| 479 | |
|---|
| 480 | if (userData->srtpRecv != NULL) { |
|---|
| 481 | srtp_dealloc(userData->srtpRecv); |
|---|
| 482 | userData->srtpRecv=NULL; |
|---|
| 483 | } |
|---|
| 484 | |
|---|
| 485 | if (userData->srtpSend != NULL) { |
|---|
| 486 | srtp_dealloc(userData->srtpSend); |
|---|
| 487 | userData->srtpSend=NULL; |
|---|
| 488 | } |
|---|
| 489 | |
|---|
| 490 | ortp_message("ZRTP secrets off"); |
|---|
| 491 | } |
|---|
| 492 | |
|---|
| 493 | /** |
|---|
| 494 | * Switch on the security. |
|---|
| 495 | * |
|---|
| 496 | * ZRTP calls this method after it has computed the SAS and check |
|---|
| 497 | * if it is verified or not. In addition ZRTP provides information |
|---|
| 498 | * about the cipher algorithm and key length for the SRTP session. |
|---|
| 499 | * |
|---|
| 500 | * This method must enable SRTP processing if it was not enabled |
|---|
| 501 | * during sertSecretsReady(). |
|---|
| 502 | * |
|---|
| 503 | * @param ctx |
|---|
| 504 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 505 | * @param c The name of the used cipher algorithm and mode, or |
|---|
| 506 | * NULL |
|---|
| 507 | * |
|---|
| 508 | * @param s The SAS string |
|---|
| 509 | * |
|---|
| 510 | * @param verified if <code>verified</code> is true then SAS was |
|---|
| 511 | * verified by both parties during a previous call. |
|---|
| 512 | */ |
|---|
| 513 | static void ozrtp_rtpSecretsOn (ZrtpContext* ctx, char* c, char* s, int32_t verified ){ |
|---|
| 514 | // OrtpZrtpContext *userData = user_data(ctx); |
|---|
| 515 | |
|---|
| 516 | // srtp processing is enabled in SecretsReady fuction when receiver secrets are ready |
|---|
| 517 | // Indeed, the secrets on is called before both parts are given to secretsReady. |
|---|
| 518 | |
|---|
| 519 | OrtpEventData *eventData; |
|---|
| 520 | OrtpEvent *ev; |
|---|
| 521 | ev=ortp_event_new(ORTP_EVENT_ZRTP_SAS_READY); |
|---|
| 522 | eventData=ortp_event_get_data(ev); |
|---|
| 523 | memcpy(eventData->info.zrtp_sas.sas,s,4); |
|---|
| 524 | eventData->info.zrtp_sas.sas[4]=0; |
|---|
| 525 | eventData->info.zrtp_sas.verified=(verified != 0) ? TRUE : FALSE; |
|---|
| 526 | rtp_session_dispatch_event(user_data(ctx)->session, ev); |
|---|
| 527 | ortp_message("ZRTP secrets on: SAS is %s previously verified %s - algo %s", s, verified == 0 ? "no" : "yes", c); |
|---|
| 528 | } |
|---|
| 529 | |
|---|
| 530 | |
|---|
| 531 | /** |
|---|
| 532 | * |
|---|
| 533 | * According to the ZRTP specification the user must be informed about |
|---|
| 534 | * a GoClear request because the ZRTP implementation switches off security |
|---|
| 535 | * if it could authenticate the GoClear packet. |
|---|
| 536 | * |
|---|
| 537 | * <b>Note:</b> GoClear is not yet implemented in GNU ZRTP. |
|---|
| 538 | * |
|---|
| 539 | * @param ctx |
|---|
| 540 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 541 | */ |
|---|
| 542 | static void ozrtp_handleGoClear(ZrtpContext* ctx) { |
|---|
| 543 | ortp_fatal("not implemented"); |
|---|
| 544 | } |
|---|
| 545 | |
|---|
| 546 | /** |
|---|
| 547 | * Handle ZRTP negotiation failed. |
|---|
| 548 | * |
|---|
| 549 | * ZRTP calls this method in case ZRTP negotiation failed. The |
|---|
| 550 | * parameters show the severity as well as the reason. |
|---|
| 551 | * |
|---|
| 552 | * @param ctx |
|---|
| 553 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 554 | * @param severity |
|---|
| 555 | * This defines the message's severity |
|---|
| 556 | * @param subCode |
|---|
| 557 | * The subcode identifying the reason. |
|---|
| 558 | * @see ZrtpCodes#MessageSeverity |
|---|
| 559 | */ |
|---|
| 560 | static void ozrtp_zrtpNegotiationFailed (ZrtpContext* ctx, int32_t severity, int32_t subCode ){ |
|---|
| 561 | ozrtp_sendInfo(ctx, severity, subCode); |
|---|
| 562 | // FIXME: necessary? |
|---|
| 563 | } |
|---|
| 564 | |
|---|
| 565 | /** |
|---|
| 566 | * ZRTP calls this method if the other side does not support ZRTP. |
|---|
| 567 | * |
|---|
| 568 | * @param ctx |
|---|
| 569 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 570 | * If the other side does not answer the ZRTP <em>Hello</em> packets then |
|---|
| 571 | * ZRTP calls this method, |
|---|
| 572 | * |
|---|
| 573 | */ |
|---|
| 574 | static void ozrtp_zrtpNotSuppOther(ZrtpContext* ctx) { |
|---|
| 575 | // FIXME: do nothing |
|---|
| 576 | } |
|---|
| 577 | |
|---|
| 578 | /** |
|---|
| 579 | * Enter synchronization mutex. |
|---|
| 580 | * |
|---|
| 581 | * GNU ZRTP requires one mutex to synchronize its |
|---|
| 582 | * processing. Because mutex implementations depend on the |
|---|
| 583 | * underlying infrastructure, for example operating system or |
|---|
| 584 | * thread implementation, GNU ZRTP delegates mutex handling to the |
|---|
| 585 | * specific part of its implementation. |
|---|
| 586 | * |
|---|
| 587 | * @param ctx |
|---|
| 588 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 589 | */ |
|---|
| 590 | static void ozrtp_synchEnter(ZrtpContext* ctx){ |
|---|
| 591 | ortp_mutex_lock(&user_data(ctx)->mutex); |
|---|
| 592 | } |
|---|
| 593 | |
|---|
| 594 | /** |
|---|
| 595 | * Leave synchronization mutex. |
|---|
| 596 | * |
|---|
| 597 | * @param ctx |
|---|
| 598 | * Pointer to the opaque ZrtpContext structure. |
|---|
| 599 | */ |
|---|
| 600 | static void ozrtp_synchLeave(ZrtpContext* ctx){ |
|---|
| 601 | ortp_mutex_unlock(&user_data(ctx)->mutex); |
|---|
| 602 | } |
|---|
| 603 | |
|---|
| 604 | |
|---|
| 605 | static inline uint32_t get_rtcp_ssrc(uint8_t *rtp) { |
|---|
| 606 | return ntohl(*(uint32_t*)(rtp+4)); |
|---|
| 607 | |
|---|
| 608 | } |
|---|
| 609 | static int ozrtp_generic_sendto(stream_type stream, RtpTransport *t, mblk_t *m, int flags, const struct sockaddr *to, socklen_t tolen){ |
|---|
| 610 | int slen; |
|---|
| 611 | err_status_t err; |
|---|
| 612 | ortp_socket_t socket; |
|---|
| 613 | |
|---|
| 614 | ZrtpContext *zrtpContext = (ZrtpContext*) t->data; |
|---|
| 615 | OrtpZrtpContext *userData = (OrtpZrtpContext*) zrtpContext->userData; |
|---|
| 616 | |
|---|
| 617 | |
|---|
| 618 | if (stream == rtp_stream) { |
|---|
| 619 | socket= t->session->rtp.socket; |
|---|
| 620 | } else { |
|---|
| 621 | socket= t->session->rtcp.socket; |
|---|
| 622 | } |
|---|
| 623 | |
|---|
| 624 | if (userData->srtpSend == NULL || !zrtp_inState(zrtpContext, SecureState)) { |
|---|
| 625 | int size; |
|---|
| 626 | msgpullup(m,-1); |
|---|
| 627 | size=msgdsize(m); |
|---|
| 628 | return sendto(socket,(void*)m->b_rptr,size,flags,to,tolen); |
|---|
| 629 | } |
|---|
| 630 | slen=msgdsize(m); |
|---|
| 631 | // Protect with srtp |
|---|
| 632 | /* enlarge the buffer for srtp to write its data */ |
|---|
| 633 | msgpullup(m,msgdsize(m)+SRTP_PAD_BYTES); |
|---|
| 634 | if (stream == rtp_stream) { |
|---|
| 635 | err=srtp_protect(userData->srtpSend,m->b_rptr,&slen); |
|---|
| 636 | } else { |
|---|
| 637 | err=srtp_protect_rtcp(userData->srtpSend,m->b_rptr,&slen); |
|---|
| 638 | } |
|---|
| 639 | if (err==err_status_ok){ |
|---|
| 640 | return sendto(socket,(void*)m->b_rptr,slen,flags,to,tolen); |
|---|
| 641 | } else { |
|---|
| 642 | ortp_error("srtp_protect() failed with status %d", err); |
|---|
| 643 | } |
|---|
| 644 | return -1; |
|---|
| 645 | } |
|---|
| 646 | |
|---|
| 647 | static int ozrtp_rtcp_sendto(RtpTransport *t, mblk_t *m, int flags, const struct sockaddr *to, socklen_t tolen){ |
|---|
| 648 | return ozrtp_generic_sendto(rtcp_stream,t,m,flags,to,tolen); |
|---|
| 649 | } |
|---|
| 650 | |
|---|
| 651 | static int ozrtp_rtp_sendto(RtpTransport *t, mblk_t *m, int flags, const struct sockaddr *to, socklen_t tolen){ |
|---|
| 652 | return ozrtp_generic_sendto(rtp_stream,t,m,flags,to,tolen); |
|---|
| 653 | } |
|---|
| 654 | |
|---|
| 655 | |
|---|
| 656 | static int ozrtp_rtp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){ |
|---|
| 657 | int rlen; |
|---|
| 658 | |
|---|
| 659 | ZrtpContext *zrtpContext = (ZrtpContext*) t->data; |
|---|
| 660 | OrtpZrtpContext *userData = (OrtpZrtpContext*) zrtpContext->userData; |
|---|
| 661 | |
|---|
| 662 | |
|---|
| 663 | // Do extra stuff first |
|---|
| 664 | check_timer(zrtpContext, userData); |
|---|
| 665 | |
|---|
| 666 | |
|---|
| 667 | // Check if something to receive |
|---|
| 668 | rlen=rtp_session_rtp_recv_abstract(t->session->rtp.socket,m,flags,from,fromlen); |
|---|
| 669 | if (rlen<=0) { |
|---|
| 670 | // nothing was received or error: pass the information to caller |
|---|
| 671 | return rlen; |
|---|
| 672 | } |
|---|
| 673 | |
|---|
| 674 | uint8_t* rtp = m->b_rptr; |
|---|
| 675 | int rtpVersion = ((rtp_header_t*)rtp)->version; |
|---|
| 676 | |
|---|
| 677 | // If plain or secured RTP |
|---|
| 678 | if (rtpVersion == 2) { |
|---|
| 679 | if (userData->srtpRecv != NULL && zrtp_inState(zrtpContext, SecureState)) { |
|---|
| 680 | // probably srtp packet, unprotect |
|---|
| 681 | err_status_t err = srtp_unprotect(userData->srtpRecv,m->b_wptr,&rlen); |
|---|
| 682 | if (err != err_status_ok) { |
|---|
| 683 | ortp_warning("srtp_unprotect failed; packet may be plain RTP"); |
|---|
| 684 | } |
|---|
| 685 | } |
|---|
| 686 | // in both cases (RTP plain and deciphered srtp) |
|---|
| 687 | return rlen; |
|---|
| 688 | } |
|---|
| 689 | |
|---|
| 690 | |
|---|
| 691 | // if ZRTP packet, send to engine |
|---|
| 692 | uint32_t *magicField=(uint32_t *)(rtp + 4); |
|---|
| 693 | if (rlen >= ZRTP_MIN_MSG_LENGTH && rtpVersion==0 && ntohl(*magicField) == ZRTP_MAGIC) { |
|---|
| 694 | print_zrtp_packet("received", rtp); |
|---|
| 695 | uint8_t *ext_header = rtp+ZRTP_MESSAGE_OFFSET; |
|---|
| 696 | uint16_t ext_length = get_zrtp_message_length(ext_header); |
|---|
| 697 | char messageType[9]; |
|---|
| 698 | parseZrtpMessageType(messageType, ext_header); |
|---|
| 699 | |
|---|
| 700 | // Check max length |
|---|
| 701 | if (rlen < 12 + ext_length + 4) { |
|---|
| 702 | ortp_warning("Received malformed ZRTP-like packet: size %d (expected %d)", rlen, 12 + ext_length + 4); |
|---|
| 703 | return 0; |
|---|
| 704 | } |
|---|
| 705 | |
|---|
| 706 | // Check sequence number |
|---|
| 707 | uint16_t seq_number = get_rtp_seqnumber(rtp); |
|---|
| 708 | if (userData->last_recv_zrtp_seq_number != 0 && seq_number <= userData->last_recv_zrtp_seq_number) { |
|---|
| 709 | // Discard out of order ZRTP packet |
|---|
| 710 | ortp_message("Discarding received out of order zrtp packet: %d (expected >%d)", |
|---|
| 711 | seq_number, userData->last_recv_zrtp_seq_number); |
|---|
| 712 | return 0; |
|---|
| 713 | } |
|---|
| 714 | |
|---|
| 715 | |
|---|
| 716 | // Check packet checksum |
|---|
| 717 | uint32_t rcv_crc = get_zrtp_packet_crc((uint32_t*)rtp, ext_length); |
|---|
| 718 | uint32_t zrtp_total_packet_length = ZRTP_MESSAGE_OFFSET + 4*ext_length + 4; |
|---|
| 719 | if (!zrtp_CheckCksum(rtp, zrtp_total_packet_length-CRC_SIZE, rcv_crc)) { |
|---|
| 720 | ortp_warning("Bad ZRTP packet checksum %u total %u", rcv_crc, zrtp_total_packet_length); |
|---|
| 721 | return 0; |
|---|
| 722 | } |
|---|
| 723 | |
|---|
| 724 | uint32_t peerssrc = ntohl(*(uint32_t*)(rtp+8)); |
|---|
| 725 | zrtp_processZrtpMessage(zrtpContext, ext_header, peerssrc); |
|---|
| 726 | userData->last_recv_zrtp_seq_number=seq_number; |
|---|
| 727 | return 0; |
|---|
| 728 | } |
|---|
| 729 | else { |
|---|
| 730 | // Not a ZRTP packet, accept it |
|---|
| 731 | return rlen; |
|---|
| 732 | } |
|---|
| 733 | } |
|---|
| 734 | |
|---|
| 735 | |
|---|
| 736 | |
|---|
| 737 | static int ozrtp_rtcp_recvfrom(RtpTransport *t, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen){ |
|---|
| 738 | ZrtpContext *zrtpContext = (ZrtpContext*) t->data; |
|---|
| 739 | OrtpZrtpContext *userData = (OrtpZrtpContext*) zrtpContext->userData; |
|---|
| 740 | |
|---|
| 741 | int rlen = rtp_session_rtp_recv_abstract(t->session->rtcp.socket,m,flags,from,fromlen); |
|---|
| 742 | if (rlen<=0) { |
|---|
| 743 | // nothing was received or error: pass the information to caller |
|---|
| 744 | return rlen; |
|---|
| 745 | } |
|---|
| 746 | |
|---|
| 747 | uint8_t *rtcp = m->b_wptr; |
|---|
| 748 | int version = ((rtcp_common_header_t *)rtcp)->version; |
|---|
| 749 | if (version == 2 && userData->srtpRecv != NULL && zrtp_inState(zrtpContext, SecureState)) { |
|---|
| 750 | err_status_t err = srtp_unprotect_rtcp(userData->srtpRecv,m->b_wptr,&rlen); |
|---|
| 751 | if (err != err_status_ok) { |
|---|
| 752 | ortp_error("srtp_unprotect failed %d ; packet discarded (may be plain RTCP)", err); |
|---|
| 753 | return 0; |
|---|
| 754 | } |
|---|
| 755 | } |
|---|
| 756 | |
|---|
| 757 | return rlen; |
|---|
| 758 | } |
|---|
| 759 | |
|---|
| 760 | |
|---|
| 761 | static ortp_socket_t ozrtp_rtp_getsocket(RtpTransport *t){ |
|---|
| 762 | return t->session->rtp.socket; |
|---|
| 763 | } |
|---|
| 764 | |
|---|
| 765 | static ortp_socket_t ozrtp_rtcp_getsocket(RtpTransport *t){ |
|---|
| 766 | return t->session->rtcp.socket; |
|---|
| 767 | } |
|---|
| 768 | |
|---|
| 769 | static OrtpZrtpContext* createUserData(ZrtpContext *context) { |
|---|
| 770 | OrtpZrtpContext *userData=ortp_new0(OrtpZrtpContext,1); |
|---|
| 771 | userData->zrtpContext=context; |
|---|
| 772 | userData->timerWillTriggerAt=0; |
|---|
| 773 | userData->last_recv_zrtp_seq_number=0; |
|---|
| 774 | userData->last_sent_zrtp_seq_number=rand()+1; // INT_MAX+1 (signed) |
|---|
| 775 | |
|---|
| 776 | userData->srtpRecv=NULL; |
|---|
| 777 | userData->srtpSend=NULL; |
|---|
| 778 | ortp_mutex_init(&userData->mutex,NULL); |
|---|
| 779 | |
|---|
| 780 | memset(&userData->zrtp_cb,0,sizeof(userData->zrtp_cb)); |
|---|
| 781 | userData->zrtp_cb.zrtp_activateTimer=&ozrtp_activateTimer; |
|---|
| 782 | userData->zrtp_cb.zrtp_cancelTimer=&ozrtp_cancelTimer; |
|---|
| 783 | userData->zrtp_cb.zrtp_handleGoClear=&ozrtp_handleGoClear; |
|---|
| 784 | userData->zrtp_cb.zrtp_rtpSecretsOn=&ozrtp_rtpSecretsOn; |
|---|
| 785 | userData->zrtp_cb.zrtp_sendDataZRTP=&ozrtp_sendDataZRTP; |
|---|
| 786 | userData->zrtp_cb.zrtp_sendInfo=&ozrtp_sendInfo; |
|---|
| 787 | userData->zrtp_cb.zrtp_srtpSecretsOff=&ozrtp_srtpSecretsOff; |
|---|
| 788 | userData->zrtp_cb.zrtp_srtpSecretsReady=&ozrtp_srtpSecretsReady; |
|---|
| 789 | userData->zrtp_cb.zrtp_synchEnter=&ozrtp_synchEnter; |
|---|
| 790 | userData->zrtp_cb.zrtp_synchLeave=&ozrtp_synchLeave; |
|---|
| 791 | userData->zrtp_cb.zrtp_zrtpNegotiationFailed=&ozrtp_zrtpNegotiationFailed; |
|---|
| 792 | userData->zrtp_cb.zrtp_zrtpNotSuppOther=&ozrtp_zrtpNotSuppOther; |
|---|
| 793 | |
|---|
| 794 | return userData; |
|---|
| 795 | } |
|---|
| 796 | |
|---|
| 797 | //static void initContext() { |
|---|
| 798 | // Configure algorithms |
|---|
| 799 | //zrtp_confClear(context); |
|---|
| 800 | /* FIXMe use default ones as these methods require some unknown char* |
|---|
| 801 | zrtp_addAlgo(context,zrtp_CipherAlgorithm,zrtp_Aes); |
|---|
| 802 | zrtp_addAlgo(context,zrtp_HashAlgorithm,zrtp_Sha1);*/ |
|---|
| 803 | // CF zrtp_InitializeConfig |
|---|
| 804 | //} |
|---|
| 805 | |
|---|
| 806 | static void ortp_zrtp_configure(ZrtpContext *context){ |
|---|
| 807 | zrtp_InitializeConfig(context); |
|---|
| 808 | zrtp_setMandatoryOnly(context); |
|---|
| 809 | zrtp_setTrustedMitM(context,FALSE);//because it is uninitialized in zrtpcpp. |
|---|
| 810 | zrtp_setSasSignature(context,FALSE);//because it is uninitialized in zrtpcpp. |
|---|
| 811 | } |
|---|
| 812 | |
|---|
| 813 | static OrtpZrtpContext* ortp_zrtp_configure_context(OrtpZrtpContext *userData, RtpSession *s, OrtpZrtpParams *params) { |
|---|
| 814 | ZrtpContext *context=userData->zrtpContext; |
|---|
| 815 | |
|---|
| 816 | |
|---|
| 817 | if (s->rtp.tr || s->rtcp.tr) |
|---|
| 818 | ortp_warning("Overwriting rtp or rtcp transport with ZRTP one"); |
|---|
| 819 | |
|---|
| 820 | userData->rtpt.data=context; |
|---|
| 821 | userData->rtpt.t_getsocket=ozrtp_rtp_getsocket; |
|---|
| 822 | userData->rtpt.t_sendto=ozrtp_rtp_sendto; |
|---|
| 823 | userData->rtpt.t_recvfrom=ozrtp_rtp_recvfrom; |
|---|
| 824 | |
|---|
| 825 | userData->rtcpt.data=context; |
|---|
| 826 | userData->rtcpt.t_getsocket=ozrtp_rtcp_getsocket; |
|---|
| 827 | userData->rtcpt.t_sendto=ozrtp_rtcp_sendto; |
|---|
| 828 | userData->rtcpt.t_recvfrom=ozrtp_rtcp_recvfrom; |
|---|
| 829 | |
|---|
| 830 | rtp_session_set_transports(s, &userData->rtpt, &userData->rtcpt); |
|---|
| 831 | |
|---|
| 832 | ortp_message("Starting ZRTP engine"); |
|---|
| 833 | zrtp_setEnrollmentMode(context,FALSE);//because it is uninitialized in zrtpcpp. |
|---|
| 834 | |
|---|
| 835 | zrtp_startZrtpEngine(context); |
|---|
| 836 | |
|---|
| 837 | return userData; |
|---|
| 838 | } |
|---|
| 839 | |
|---|
| 840 | OrtpZrtpContext* ortp_zrtp_context_new(RtpSession *s, OrtpZrtpParams *params){ |
|---|
| 841 | ZrtpContext *context = zrtp_CreateWrapper(); |
|---|
| 842 | OrtpZrtpContext *userData=createUserData(context); |
|---|
| 843 | userData->session=s; |
|---|
| 844 | ortp_zrtp_configure(context); |
|---|
| 845 | ortp_message("Initialized ZRTP context"); |
|---|
| 846 | zrtp_initializeZrtpEngine(context, &userData->zrtp_cb, userAgentStr, params->zid_file, userData, 0); |
|---|
| 847 | return ortp_zrtp_configure_context(userData,s,params); |
|---|
| 848 | } |
|---|
| 849 | |
|---|
| 850 | OrtpZrtpContext* ortp_zrtp_multistream_new(OrtpZrtpContext* activeContext, RtpSession *s, OrtpZrtpParams *params) { |
|---|
| 851 | int32_t length; |
|---|
| 852 | char *multiparams=NULL; |
|---|
| 853 | int i=0; |
|---|
| 854 | |
|---|
| 855 | if (!zrtp_isMultiStreamAvailable(activeContext->zrtpContext)) { |
|---|
| 856 | ortp_warning("could't add stream: mutlistream not supported by peer"); |
|---|
| 857 | } |
|---|
| 858 | |
|---|
| 859 | if (zrtp_isMultiStream(activeContext->zrtpContext)) { |
|---|
| 860 | ortp_fatal("Error: should derive multistream from DH or preshared modes only"); |
|---|
| 861 | } |
|---|
| 862 | |
|---|
| 863 | multiparams=zrtp_getMultiStrParams(activeContext->zrtpContext, &length); |
|---|
| 864 | |
|---|
| 865 | ortp_message("ZRTP multiparams length is %d", length); |
|---|
| 866 | for (;i<length;i++) { |
|---|
| 867 | ortp_message("%d", multiparams[i]); |
|---|
| 868 | } |
|---|
| 869 | |
|---|
| 870 | ortp_message("Initializing ZRTP context"); |
|---|
| 871 | ZrtpContext *context = zrtp_CreateWrapper(); |
|---|
| 872 | OrtpZrtpContext *userData=createUserData(context); |
|---|
| 873 | userData->session=s; |
|---|
| 874 | ortp_zrtp_configure(context); |
|---|
| 875 | |
|---|
| 876 | zrtp_initializeZrtpEngine(context, &userData->zrtp_cb, userAgentStr, params->zid_file, userData, 0); |
|---|
| 877 | |
|---|
| 878 | ortp_message("setting zrtp_setMultiStrParams"); |
|---|
| 879 | zrtp_setMultiStrParams(context,multiparams,length); |
|---|
| 880 | |
|---|
| 881 | return ortp_zrtp_configure_context(userData,s,params); |
|---|
| 882 | } |
|---|
| 883 | |
|---|
| 884 | bool_t ortp_zrtp_available(){return TRUE;} |
|---|
| 885 | |
|---|
| 886 | |
|---|
| 887 | |
|---|
| 888 | void ortp_zrtp_sas_verified(OrtpZrtpContext* ctx){ |
|---|
| 889 | zrtp_SASVerified(ctx->zrtpContext); |
|---|
| 890 | } |
|---|
| 891 | |
|---|
| 892 | void ortp_zrtp_sas_reset_verified(OrtpZrtpContext* ctx){ |
|---|
| 893 | zrtp_resetSASVerified(ctx->zrtpContext); |
|---|
| 894 | } |
|---|
| 895 | |
|---|
| 896 | void ortp_zrtp_context_destroy(OrtpZrtpContext *ctx) { |
|---|
| 897 | ortp_message("Stopping ZRTP context"); |
|---|
| 898 | zrtp_stopZrtpEngine(ctx->zrtpContext); |
|---|
| 899 | |
|---|
| 900 | ortp_message("Destroying ZRTP wrapper"); |
|---|
| 901 | zrtp_DestroyWrapper(ctx->zrtpContext); |
|---|
| 902 | |
|---|
| 903 | ortp_message("Destroying ORTP-ZRTP mutex"); |
|---|
| 904 | ortp_mutex_destroy(&ctx->mutex); |
|---|
| 905 | |
|---|
| 906 | ortp_message("Destroying SRTP contexts"); |
|---|
| 907 | if (ctx->srtpSend != NULL) srtp_dealloc(ctx->srtpSend); |
|---|
| 908 | if (ctx->srtpRecv != NULL) srtp_dealloc(ctx->srtpRecv); |
|---|
| 909 | |
|---|
| 910 | ortp_message("ORTP-ZRTP context destroyed"); |
|---|
| 911 | } |
|---|
| 912 | |
|---|
| 913 | |
|---|
| 914 | |
|---|
| 915 | #else |
|---|
| 916 | |
|---|
| 917 | |
|---|
| 918 | OrtpZrtpContext* ortp_zrtp_context_new(RtpSession *s, OrtpZrtpParams *params){ |
|---|
| 919 | ortp_message("ZRTP is disabled - not implemented yet"); |
|---|
| 920 | return NULL; |
|---|
| 921 | } |
|---|
| 922 | |
|---|
| 923 | OrtpZrtpContext* ortp_zrtp_multistream_new(OrtpZrtpContext* activeContext, RtpSession *s, OrtpZrtpParams *params) { |
|---|
| 924 | ortp_message("ZRTP is disabled - not implemented yet - not adding stream"); |
|---|
| 925 | return NULL; |
|---|
| 926 | } |
|---|
| 927 | |
|---|
| 928 | bool_t ortp_zrtp_available(){return FALSE;} |
|---|
| 929 | void ortp_zrtp_sas_verified(OrtpZrtpContext* ctx){} |
|---|
| 930 | void ortp_zrtp_sas_reset_verified(OrtpZrtpContext* ctx){} |
|---|
| 931 | void ortp_zrtp_context_destroy(OrtpZrtpContext *ctx){} |
|---|
| 932 | |
|---|
| 933 | #endif |
|---|
| 934 | |
|---|
| 935 | |
|---|