Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
wtls.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * wtls.c: WTLS server-side implementation
59  *
60  * Nick Clarey <nclarey@3glab.com>
61  * Nikos Balkanas, InAccess Networks (2009)
62  */
63 
64 
65 #include "gwlib/gwlib.h"
66 
67 #ifdef HAVE_WTLS_OPENSSL
68 
69 #include "wtls.h"
70 #include "timers.h"
71 #include "wap_events.h"
72 #include "wtls_pdu.h"
73 #include "wtls_statesupport.h"
74 #include "wtls_pdusupport.h"
75 #include "gw/msg.h"
76 
77 #include "wap.h"
78 #include "wtp.h"
79 
80 #define WTLS_CONNECTIONLESS_PORT 9202
81 /***********************************************************************
82  * Internal data structures.
83  *
84  * List of WTLS Server machines.
85  */
86 static List *wtls_machines = NULL;
87 
88 /*
89  * Counter for WTLS Server machine id numbers, to make sure they are unique.
90  */
91 static Counter *wtls_machine_id_counter = NULL;
92 
93 /*
94  * Give the status of wtls server layer:
95  * limbo - not running at all
96  * running - operating normally
97  * terminating - waiting for operations to terminate, returning to limbo
98  */
99 static enum { limbo, running, terminating } wtls_run_status = limbo;
100 
101 /*
102  * Queue of events to be handled by WTLS Server machines.
103  */
104 static List *wtls_queue = NULL;
105 
106 /*****************************************************************************
107  *
108  * Prototypes of internal functions:
109  */
110 
111 static wtls_dispatch_func_t *dispatch_resp_to_bb;
112 
113 /*
114  * Create and destroy an uninitialized wtls server state machine.
115  */
116 
117 static WTLSMachine *wtls_machine_create(WAPAddrTuple * tuple);
118 static void wtls_machine_destroy(void *p);
119 
120 /*
121  * Checks whether the list of wlts server machines includes a specific machine.
122  *
123  * The machine in question is identified with with source and destination
124  * address and port. If the machine does not exist and the event is either;
125  * - A SEC-Create-Request.req or
126  * - A T-Unitdata.ind containing a ClientHello packet or
127  * - A T-Unitdata.ind containing an Alert(no_renegotiation) packet
128  * a new machine is created and added in the machines data structure.
129  *
130  * See WTLS 7.2 for details of this check.
131  */
132 static WTLSMachine *wtls_machine_find_or_create(WAPEvent * event);
133 
134 /*
135  * Feed an event to a WTLS Server state machine. Handle all errors by
136  * itself, do not report them to the caller.
137  */
138 static void wtls_event_handle(WTLSMachine * machine, WAPEvent * event);
139 
140 /*
141  * Find a WTLS Server machine from the global list of wtls server
142  * structures that corresponds to the four-tuple of source and destination
143  * addresses and ports. Return a pointer to the machine, or NULL if not found.
144  */
145 static WTLSMachine *wtls_machine_find(WAPAddrTuple * tuple, long mid);
146 
147 /* Function prototypes */
148 static void main_thread(void *);
149 static WTLSMachine *find_wtls_machine_using_mid(long mid);
150 static void add_wtls_address(Msg * msg, WTLSMachine * wtls_machine);
151 static void add_pdu(WTLSMachine * wtls_machine, wtls_PDU * pduToAdd);
152 static void send_queuedpdus(WTLSMachine * wtls_machine);
153 void send_alert(WAPEvent * event, WTLSMachine * wtls_machine);
154 char *stateName(int s);
155 
156 /* The match* functions are used for searches through lists */
157 static int match_handshake_type(void *item, void *pattern);
158 static int match_pdu_type(void *item, void *pattern);
159 
160 extern void write_to_bearerbox(Msg * pmsg);
161 extern Octstr *wtls_get_certificate(void);
162 
163 /*static WAPEvent *create_tr_invoke_ind(WTPRespMachine *sm, Octstr *user_data);
164 static WAPEvent *create_tr_abort_ind(WTPRespMachine *sm, long abort_reason);
165 static WAPEvent *create_tr_result_cnf(WTPRespMachine *sm); */
166 
167 /******************************************************************************
168  *
169  * EXTERNAL FUNCTIONS:
170  *
171  */
173 {
174  WAPEvent *unitdataIndEvent;
175  List *wtlsPayloadList;
176 
177  /* Dump the Msg */
178  msg_dump(msg, 0);
179 
180  /* Then, stuff it into a T_Unitdata_Ind Event */
181  unitdataIndEvent = wap_event_create(T_Unitdata_Ind);
182  info(0, "Event created");
183 
184  /* Firstly, the address */
185  unitdataIndEvent->u.T_Unitdata_Ind.addr_tuple =
186  wap_addr_tuple_create(msg->wdp_datagram.source_address,
187  msg->wdp_datagram.source_port,
188  msg->wdp_datagram.destination_address,
189  msg->wdp_datagram.destination_port);
190  info(0, "Set address and stuff");
191 
192  /* Attempt to stuff this baby into a list-of-WTLS-PDUs */
193  wtlsPayloadList = wtls_unpack_payloadlist(msg->wdp_datagram.user_data);
194  info(0, "Datagram unpacked!");
195 
196  /* Then, the pdu material */
197  unitdataIndEvent->u.T_Unitdata_Ind.pdu_list = wtlsPayloadList;
198 
199  /* And return the event */
200  return unitdataIndEvent;
201 }
202 
203 void wtls_init(wtls_dispatch_func_t *responder_dispatch)
204 {
205  /* Initialise our various lists and counters */
206  wtls_machines = gwlist_create();
207  wtls_machine_id_counter = counter_create();
208 
209  wtls_queue = gwlist_create();
210  gwlist_add_producer(wtls_queue);
211  dispatch_resp_to_bb = responder_dispatch;
212 
213  /* Idiot check - ensure that we are able to start running */
214  gw_assert(wtls_run_status == limbo);
215  wtls_run_status = running;
217 }
218 
219 void wtls_shutdown(void)
220 {
221  /* Make sure that we're actually running; if so, then
222  prepare for termination */
223  gw_assert(wtls_run_status == running);
224  wtls_run_status = terminating;
225  gwlist_remove_producer(wtls_queue);
227 
228  /* Print out a friendly message stating that we're going to die */
229  debug("wap.wtls", 0, "wtls_shutdown: %ld wtls machines left",
230  gwlist_len(wtls_machines));
231 
232  /* And clean up nicely after ourselves */
233  gwlist_destroy(wtls_machines, wtls_machine_destroy);
235  counter_destroy(wtls_machine_id_counter);
236 }
237 
238 void wtls_dispatch_event(WAPEvent * event)
239 {
240  /* Stick the event on the incoming events queue */
241  gwlist_produce(wtls_queue, event);
242 }
243 
244 void wtls_dispatch_resp(WAPEvent * dgram)
245 {
246  WAPAddrTuple *tuple;
247  WTLSMachine *wtls_machine;
248 
249  tuple = dgram->u.T_DUnitdata_Req.addr_tuple;
250  if ((wtls_machine = wtls_machine_find(tuple, -1))) {
251  wtls_PDU *respPDU;
252 
253  debug("wtls", 0,
254  "wtls_dispatch_resp ~> Dispatching datagram to bearerbox");
255  respPDU = wtls_pdu_create(Application_PDU);
256  respPDU->cipher = 1;
257  respPDU->snMode = wtls_machine->sequence_number_mode ? 1 : 0;
258  respPDU->rlen = 1;
259  respPDU->u.application.data =
260  dgram->u.T_DUnitdata_Req.user_data;
261  debug("wtls", 0, "Sending Response PDU:");
262  wtls_pdu_dump(respPDU, 0);
263  add_pdu(wtls_machine, respPDU);
264  wtls_pdu_destroy(respPDU);
265  send_queuedpdus(wtls_machine);
266  dgram->u.T_DUnitdata_Req.user_data = NULL;
267  } else error(0, "wtls_dispatch_event: Unable to find state machine. "
268  "Dropping datagram.");
269 }
270 
271 int wtls_get_address_tuple(long mid, WAPAddrTuple ** tuple)
272 {
273  WTLSMachine *sm;
274 
275  sm = find_wtls_machine_using_mid(mid);
276  if (sm == NULL)
277  return -1;
278 
279  *tuple = wap_addr_tuple_duplicate(sm->addr_tuple);
280  return 0;
281 }
282 
283 void send_alert(WAPEvent * event, WTLSMachine * wtls_machine)
284 {
285  wtls_PDU *alertPDU;
286 
287  alertPDU = (wtls_PDU *) wtls_pdu_create(Alert_PDU);
288  alertPDU->rlen = 1;
289  alertPDU->snMode = wtls_machine->sequence_number_mode ? 1 : 0;
290  alertPDU->u.alert.level = event->u.SEC_Terminate_Req.alert_level;
291  alertPDU->u.alert.desc = event->u.SEC_Terminate_Req.alert_desc;
292 
293  /* Here's where we should get the current checksum from the wtls_machine */
294  alertPDU->u.alert.chksum = octstr_create("0000");
295 
296  add_pdu(wtls_machine, alertPDU);
297  wtls_pdu_destroy(alertPDU);
298  send_queuedpdus(wtls_machine);
299 }
300 
301 static void add_pdu(WTLSMachine * wtls_machine, wtls_PDU * pduToAdd)
302 {
303  int currentLength;
304  wtls_Payload *payloadToAdd;
305  Octstr *packedPDU;
306 
307  /* Update sequence number before encryption */
308  wtls_machine->server_seq_num++;
309 
310  /* Pack and encrypt the pdu */
311  if (!(payloadToAdd = wtls_pdu_pack(pduToAdd, wtls_machine))) {
312  wtls_machine->server_seq_num--;
313  return;
314  }
315  if (!payloadToAdd->data) {
316  wtls_machine->server_seq_num--;
317  wtls_payload_destroy(payloadToAdd);
318  return;
319  }
320 
321  /* Check to see if we've already allocated some memory for the list */
322  if (!wtls_machine->packet_to_send)
323  wtls_machine->packet_to_send = octstr_create("");
324 
325  /* If the pdu is a Handshake pdu, append the Octstr to our wtls_machine's
326  exchanged_handshakes Octstr */
327  packedPDU =
328  wtls_payload_pack(payloadToAdd, wtls_machine->server_seq_num);
329  if (pduToAdd->type == ChangeCipher_PDU)
330  wtls_machine->server_seq_num = -1;
331 
332  /* Add it to our list */
333  currentLength = octstr_len(wtls_machine->packet_to_send);
334  octstr_insert(wtls_machine->packet_to_send, packedPDU, currentLength);
335  wtls_payload_destroy(payloadToAdd);
336  octstr_destroy(packedPDU);
337 }
338 
339 /*
340  * Send the pdu_to_send list to the destination specified by the address in the machine
341  * structure. Don't return anything, handle all errors internally.
342  */
343 static void send_queuedpdus(WTLSMachine * wtls_machine)
344 {
345  Msg *msg = NULL;
346 
347  gw_assert(wtls_machine->packet_to_send != NULL);
348  if (!wtls_machine->packet_to_send)
349  return;
350 
351  /* Pack the PDU */
352  msg = msg_create(wdp_datagram);
353  add_wtls_address(msg, wtls_machine);
354  msg->wdp_datagram.user_data =
355  octstr_duplicate(wtls_machine->packet_to_send);
356 
357  /* Send it off */
358  dispatch_resp_to_bb(msg);
359 
360  /* Destroy our copy of the sent string */
361  octstr_destroy(wtls_machine->packet_to_send);
362  wtls_machine->packet_to_send = NULL;
363 }
364 
365 /*
366  * Add address from state machine.
367  */
368 void add_wtls_address(Msg * msg, WTLSMachine * wtls_machine)
369 {
370 
371  debug("wap.wtls", 0, "adding address");
372  msg->wdp_datagram.source_address =
373  octstr_duplicate(wtls_machine->addr_tuple->local->address);
374  msg->wdp_datagram.source_port = wtls_machine->addr_tuple->local->port;
375  msg->wdp_datagram.destination_address =
376  octstr_duplicate(wtls_machine->addr_tuple->remote->address);
377  msg->wdp_datagram.destination_port =
378  wtls_machine->addr_tuple->remote->port;
379 }
380 
381 /*****************************************************************************
382  *
383  * INTERNAL FUNCTIONS:
384  *
385  */
386 
387 static void main_thread(void *arg)
388 {
389  WTLSMachine *sm;
390  WAPEvent *e;
391 
392  while (wtls_run_status == running && (e = gwlist_consume(wtls_queue))) {
393  sm = wtls_machine_find_or_create(e);
394  if (sm == NULL)
396  else
397  wtls_event_handle(sm, e);
398  }
399 }
400 
401 /*
402  * Give the name of a WTLS Server state in a readable form.
403  */
404 char *stateName(int s)
405 {
406  switch (s) {
407 #define STATE_NAME(state) case state: return #state;
408 #define ROW(state, event, condition, action, new_state)
409 #include "wtls_state-decl.h"
410  default:
411  return "unknown state";
412  }
413 }
414 
415 static void fatalAlert(WAPEvent * event, int description)
416 {
417  WAPEvent *abort;
418 
420  abort->u.SEC_Terminate_Req.addr_tuple = wap_addr_tuple_duplicate
421  (event->u.T_Unitdata_Ind.addr_tuple);
422  abort->u.SEC_Terminate_Req.alert_level = fatal_alert;
423  abort->u.SEC_Terminate_Req.alert_desc = description;
424  wtls_dispatch_event(abort);
425 }
426 
427 static void clientHello(WAPEvent * event, WTLSMachine * wtls_machine)
428 {
429  /* The Wap event we have to dispatch */
430  WAPEvent *res;
431  wtls_Payload *tempPayload;
432  wtls_PDU *clientHelloPDU;
433  CipherSuite *ciphersuite;
434  int randomCounter, algo;
435 
436  tempPayload =
437  (wtls_Payload *) gwlist_search(event->u.T_Unitdata_Ind.pdu_list,
438  (void *)client_hello,
439  match_handshake_type);
440  if (!tempPayload) {
441  error(0, "Illegal PDU while waiting for a ClientHello");
442  fatalAlert(event, unexpected_message);
443  return;
444  }
445  clientHelloPDU = wtls_pdu_unpack(tempPayload, wtls_machine);
446 
447  /* Store the client's random value - use pack for simplicity */
448  wtls_machine->client_random = octstr_create("");
449  randomCounter = pack_int32(wtls_machine->client_random, 0,
450  clientHelloPDU->u.handshake.client_hello->
452  octstr_insert(wtls_machine->client_random,
453  clientHelloPDU->u.handshake.client_hello->random->
454  random_bytes, randomCounter);
455 
456  /* Select the ciphersuite from the supplied list */
457  ciphersuite =
459  ciphersuites);
460  if (!ciphersuite) {
461  error(0, "Couldn't agree on encryption cipher. Aborting");
462  wtls_pdu_destroy(clientHelloPDU);
463  fatalAlert(event, handshake_failure);
464  return;
465  }
466  /* Set the relevant values in the wtls_machine and PDU structure */
467  wtls_machine->bulk_cipher_algorithm = ciphersuite->bulk_cipher_algo;
468  wtls_machine->mac_algorithm = ciphersuite->mac_algo;
469 
470  /* Generate a SEC_Create_Res event, and pass it back into the queue */
471  res = wap_event_create(SEC_Create_Res);
472  res->u.SEC_Create_Res.addr_tuple =
473  wap_addr_tuple_duplicate(event->u.T_Unitdata_Ind.addr_tuple);
474  res->u.SEC_Create_Res.bulk_cipher_algo = ciphersuite->bulk_cipher_algo;
475  res->u.SEC_Create_Res.mac_algo = ciphersuite->mac_algo;
476  res->u.SEC_Create_Res.client_key_id = wtls_choose_clientkeyid
477  (clientHelloPDU->u.handshake.client_hello->client_key_ids, &algo);
478  if (!res->u.SEC_Create_Res.client_key_id) {
479  error(0, "Couldn't agree on key exchange protocol. Aborting");
480  wtls_pdu_destroy(clientHelloPDU);
481  wap_event_destroy(res);
482  fatalAlert(event, unknown_key_id);
483  return;
484  }
485  wtls_machine->key_algorithm = algo;
486 
487  /* Set the sequence number mode in both the machine and the outgoing packet */
488  res->u.SEC_Create_Res.snmode =
489  wtls_choose_snmode(clientHelloPDU->u.handshake.client_hello->
490  snmode);
491  wtls_machine->sequence_number_mode = res->u.SEC_Create_Res.snmode;
492 
493  /* Set the key refresh mode in both the machine and the outgoing packet */
494  res->u.SEC_Create_Res.krefresh =
495  clientHelloPDU->u.handshake.client_hello->krefresh;
496  wtls_machine->key_refresh = res->u.SEC_Create_Res.krefresh;
497  /* Global refresh variable */
498  debug("wtls", 0, "clientHello ~> Accepted refresh = %d, refresh_rate = "
499  "%d", wtls_machine->key_refresh, 1 << wtls_machine->key_refresh);
500 
501  /* Keep the data so we can send it back in EXCHANGE
502  * temporary - needs to delete old one if exists !
503  * wtls_machine->handshake_data = octstr_create("");
504  */
505  if (wtls_machine->handshake_data)
506  octstr_destroy(wtls_machine->handshake_data);
507  wtls_machine->handshake_data = octstr_create("");
508  octstr_append(wtls_machine->handshake_data, tempPayload->data);
509 
510  debug("wtls", 0, "clientHello ~> Dispatching SEC_Create_Res event");
511  wtls_pdu_destroy(clientHelloPDU);
512  wtls_dispatch_event(res);
513 }
514 
515 static void serverHello(WAPEvent * event, WTLSMachine * wtls_machine)
516 {
517  WAPEvent *req;
518  wtls_PDU *serverHelloPDU;
519 // wtls_PDU* certificatePDU;
520  Random *tempRandom;
521 /* List *certList;
522  Certificate *cert;
523 */ int randomCounter = 0;
524 
525  /* Our serverHello */
526  serverHelloPDU = wtls_pdu_create(Handshake_PDU);
527  serverHelloPDU->rlen = 1;
528  serverHelloPDU->snMode = wtls_machine->sequence_number_mode ? 1 : 0;
529  serverHelloPDU->u.handshake.msg_type = server_hello;
530  serverHelloPDU->u.handshake.server_hello =
531  (ServerHello *) gw_malloc(sizeof(ServerHello));
532 
533  /* Set our server version */
534  serverHelloPDU->u.handshake.server_hello->serverversion = 1;
535 
536  /* Get a suitably random number - store it in both the machine structure and outgoing PDU */
537  tempRandom = wtls_get_random();
538  wtls_machine->server_random = octstr_create("");
539  randomCounter =
540  pack_int32(wtls_machine->server_random, 0,
541  tempRandom->gmt_unix_time);
542  octstr_insert(wtls_machine->server_random, tempRandom->random_bytes,
543  octstr_len(wtls_machine->server_random));
544 
545  serverHelloPDU->u.handshake.server_hello->random = tempRandom;
546 
547  /* At the moment, we don't support session caching, so tell them to forget about caching us */
548  serverHelloPDU->u.handshake.server_hello->session_id =
549  octstr_format("%llu", wtls_machine->mid);
550 
551  /* We need to select an appropriate mechanism here from the ones listed */
552  serverHelloPDU->u.handshake.server_hello->client_key_id =
553  event->u.SEC_Create_Res.client_key_id;
554 
555  /* Get our ciphersuite details */
556  serverHelloPDU->u.handshake.server_hello->ciphersuite = (CipherSuite *)
557  gw_malloc(sizeof(CipherSuite));
559  = event->u.SEC_Create_Res.bulk_cipher_algo;
560  serverHelloPDU->u.handshake.server_hello->ciphersuite->mac_algo =
561  event->u.SEC_Create_Res.mac_algo;
562  serverHelloPDU->u.handshake.server_hello->comp_method = null_comp;
563 
564  /* We need to confirm the client's choice, or if they haven't
565  * specified one, select one ourselves
566  */
567  serverHelloPDU->u.handshake.server_hello->snmode =
568  event->u.SEC_Create_Res.snmode;
569 
570  /* We need to either confirm the client's choice of key refresh rate, or choose a lower rate */
571  serverHelloPDU->u.handshake.server_hello->krefresh =
572  event->u.SEC_Create_Res.krefresh;
573 
574  /* Add the PDUsto the server's outgoing list */
575  add_pdu(wtls_machine, serverHelloPDU);
576  wtls_pdu_destroy(serverHelloPDU);
577 
578  /* Generate and dispatch a SEC_Exchange_Req or maybe a SEC_Commit_Req */
580  req->u.SEC_Exchange_Req.addr_tuple =
581  wap_addr_tuple_duplicate(event->u.T_Unitdata_Ind.addr_tuple);
582  wtls_dispatch_event(req);
583  debug("wtls", 0, "serverHello ~> Dispatching SEC_Exchange_Req event");
584 }
585 
586 static void exchange_keys(WAPEvent * event, WTLSMachine * wtls_machine)
587 {
588  RSAPublicKey *public_key = NULL;
589  Octstr *checking_data = NULL;
590 
591  /* The Wap PDUs we have to dispatch */
592  wtls_PDU *changeCipherSpecPDU;
593  wtls_PDU *finishedPDU;
594 
595  /* The PDUs we have to process */
596  wtls_Payload *tempPayload;
597  wtls_PDU *clientKeyXchgPDU;
598  wtls_PDU *changeCipherSpec_incoming_PDU;
599  wtls_PDU *finished_incoming_PDU;
600 
601  /* For decrypting/encrypting data */
602  Octstr *concatenatedRandoms = NULL;
603  Octstr *encryptedData = NULL;
604  Octstr *decryptedData = NULL;
605  Octstr *labelVerify = NULL;
606  Octstr *labelMaster = NULL;
607 
608  /* Process the incoming event : ClientKeyExchange */
609  tempPayload =
610  (wtls_Payload *) gwlist_search(event->u.T_Unitdata_Ind.pdu_list,
611  (void *)client_key_exchange,
612  match_handshake_type);
613 
614  if (!tempPayload) {
615  error(0, "Missing client_key_exchange. Aborting...");
616  fatalAlert(event, unexpected_message);
617  return;
618  }
619 
620  /* Keep the data so we can send it back */
621  octstr_insert(wtls_machine->handshake_data, tempPayload->data,
622  octstr_len(wtls_machine->handshake_data));
623 
624  clientKeyXchgPDU = wtls_pdu_unpack(tempPayload, wtls_machine);
625  wtls_pdu_dump(clientKeyXchgPDU, 0);
626 
627  /* Decrypt the client key exchange PDU */
628  encryptedData =
629  clientKeyXchgPDU->u.handshake.client_key_exchange->rsa_params->
630  encrypted_secret;
631  decryptedData =
632  wtls_decrypt_key(wtls_machine->key_algorithm, encryptedData);
633 
634  if (!decryptedData) {
635  error(0,
636  "Key Exchange failed. Couldn't decrypt client's secret (%d)."
637  " Aborting...", wtls_machine->key_algorithm);
638  wtls_pdu_destroy(clientKeyXchgPDU);
639  fatalAlert(event, decryption_failed);
640  return;
641  }
642  public_key = wtls_get_rsapublickey();
643  pack_int16(decryptedData, octstr_len(decryptedData),
644  octstr_len(public_key->rsa_exponent));
645  octstr_insert(decryptedData, public_key->rsa_exponent,
646  octstr_len(decryptedData));
647  pack_int16(decryptedData, octstr_len(decryptedData),
648  octstr_len(public_key->rsa_modulus));
649  octstr_insert(decryptedData, public_key->rsa_modulus,
650  octstr_len(decryptedData));
651 
652  /* Concatenate our random data */
653  concatenatedRandoms = octstr_cat(wtls_machine->client_random,
654  wtls_machine->server_random);
655 
656  /* Generate our master secret */
657  labelMaster = octstr_create("master secret");
658  wtls_machine->master_secret = wtls_calculate_prf(decryptedData,
659  labelMaster,
660  concatenatedRandoms,
661  20, wtls_machine);
662 
663  /* Process the incoming event : ChangeCipherSpec */
664  tempPayload =
665  (wtls_Payload *) gwlist_search(event->u.T_Unitdata_Ind.pdu_list,
666  (void *)ChangeCipher_PDU,
667  match_pdu_type);
668 
669  if (!tempPayload) {
670  error(0, "Missing change_cipher. Aborting...");
671  octstr_destroy(labelMaster);
672  octstr_destroy(concatenatedRandoms);
673  destroy_rsa_pubkey(public_key);
674  octstr_destroy(decryptedData);
675  octstr_destroy(encryptedData);
676  fatalAlert(event, unexpected_message);
677  return;
678  }
679 
680  changeCipherSpec_incoming_PDU = wtls_pdu_unpack(tempPayload,
681  wtls_machine);
682  octstr_dump(wtls_machine->client_write_MAC_secret, 0);
683 
684  wtls_pdu_dump(changeCipherSpec_incoming_PDU, 0);
685 
686  if (changeCipherSpec_incoming_PDU->u.cc.change == 1) {
687  debug("wtls", 0, "Need to decrypt the PDUs from now on...");
688  wtls_decrypt_pdu_list(wtls_machine,
689  event->u.T_Unitdata_Ind.pdu_list);
690  }
691 
692  /* Process the incoming event : Finished */
693  tempPayload =
694  (wtls_Payload *) gwlist_search(event->u.T_Unitdata_Ind.pdu_list,
695  (void *)finished,
696  match_handshake_type);
697  if (!tempPayload) {
698  error(0, "Failed to decrypt finished PDU. Aborting...");
699  wtls_pdu_destroy(changeCipherSpec_incoming_PDU);
700  octstr_destroy(labelMaster);
701  octstr_destroy(concatenatedRandoms);
702  destroy_rsa_pubkey(public_key);
703  octstr_destroy(decryptedData);
704  octstr_destroy(encryptedData);
705  fatalAlert(event, decrypt_error);
706  return;
707  }
708  finished_incoming_PDU = wtls_pdu_unpack(tempPayload, wtls_machine);
709  debug("wtls", 0, "Client Finished PDU:");
710  wtls_pdu_dump(finished_incoming_PDU, 0);
711 
712  /* Check the verify_data */
713  labelVerify = octstr_create("client finished");
714  checking_data = wtls_calculate_prf(wtls_machine->master_secret,
715  labelVerify,
716  (Octstr *) wtls_hash(wtls_machine->
717  handshake_data,
718  wtls_machine),
719  12, wtls_machine);
720 
721  if (octstr_compare
722  (finished_incoming_PDU->u.handshake.finished->verify_data,
723  checking_data) == 0) {
724  wtls_machine->encrypted = 1;
725  debug("wtls", 0, "DATA VERIFICATION OK");
726  }
727 
728  /* Keep the data so we can send it back in the next message
729  * octstr_insert(wtls_machine->handshake_data, tempPayload->data,
730  * octstr_len(wtls_machine->handshake_data));
731  */
732  // temporary fix
733  octstr_truncate(tempPayload->data, 15);
734  octstr_insert(wtls_machine->handshake_data, tempPayload->data,
735  octstr_len(wtls_machine->handshake_data));
736 
737  /* Create a new PDU List containing a ChangeCipherSpec and a Finished */
738  changeCipherSpecPDU = wtls_pdu_create(ChangeCipher_PDU);
739  changeCipherSpecPDU->u.cc.change = 1;
740  changeCipherSpecPDU->rlen = 1;
741  changeCipherSpecPDU->snMode =
742  wtls_machine->sequence_number_mode ? 1 : 0;
743 
744  /* Generate our verify data */
745  finishedPDU = wtls_pdu_create(Handshake_PDU);
746  finishedPDU->u.handshake.msg_type = finished;
747  finishedPDU->cipher = 1;
748  finishedPDU->rlen = 1;
749  finishedPDU->snMode = wtls_machine->sequence_number_mode ? 1 : 0;;
750  finishedPDU->u.handshake.finished = gw_malloc(sizeof(Finished));
751 
752  octstr_destroy(labelVerify);
753  labelVerify = octstr_create("server finished");
754 
756  (wtls_machine->master_secret, labelVerify, (Octstr *) wtls_hash
757  (wtls_machine->handshake_data, wtls_machine), 12, wtls_machine);
758 
759  /* Reset the accumulated Handshake data */
760  octstr_destroy(wtls_machine->handshake_data);
761  wtls_machine->handshake_data = octstr_create("");
762 
763  /* Add the pdus to our list */
764  add_pdu(wtls_machine, changeCipherSpecPDU);
765  add_pdu(wtls_machine, finishedPDU);
766 
767  /* Send it off */
768  send_queuedpdus(wtls_machine);
769 
770  octstr_destroy(labelMaster);
771  octstr_destroy(labelVerify);
772  octstr_destroy(decryptedData);
773  octstr_destroy(encryptedData);
774  octstr_destroy(concatenatedRandoms);
775 
776  wtls_pdu_destroy(finished_incoming_PDU);
777  wtls_pdu_destroy(changeCipherSpec_incoming_PDU);
778 
779  wtls_pdu_destroy(finishedPDU);
780  wtls_pdu_destroy(changeCipherSpecPDU);
781 
782  octstr_destroy(checking_data);
783  destroy_rsa_pubkey(public_key);
784 }
785 
786 static void wtls_application(WAPEvent * event, WTLSMachine * wtls_machine)
787 {
788  int listLen, i = 0;
789  WAPEvent *dgram;
790  wtls_Payload *payLoad;
791 
792  /* Apply the negotiated decryption/decoding/MAC check to the received data */
793  /* Take the userdata and pass it on up to the WTP/WSP, depending on the destination port */
794 
795  listLen = gwlist_len(event->u.T_Unitdata_Ind.pdu_list);
796  for (; i < listLen; i++) {
797  payLoad = gwlist_consume(event->u.T_Unitdata_Ind.pdu_list);
798  dgram = wap_event_create(T_DUnitdata_Ind);
799  dgram->u.T_DUnitdata_Ind.addr_tuple =
800  wap_addr_tuple_create(event->u.T_Unitdata_Ind.addr_tuple->
801  remote->address,
802  event->u.T_Unitdata_Ind.addr_tuple->
803  remote->port,
804  event->u.T_Unitdata_Ind.addr_tuple->
805  local->address,
806  event->u.T_Unitdata_Ind.addr_tuple->
807  local->port);
808  dgram->u.T_DUnitdata_Ind.user_data = payLoad->data;
809  wap_dispatch_datagram(dgram);
810  payLoad->data = NULL;
811  wtls_payload_destroy(payLoad);
812  }
813 }
814 
815 /*
816  * Feed an event to a WTP responder state machine. Handle all errors yourself,
817  * do not report them to the caller. Note: Do not put {}s of the else block
818  * inside the macro definition.
819  */
820 static void wtls_event_handle(WTLSMachine * wtls_machine, WAPEvent * event)
821 {
822  debug("wap.wtls", 0, "WTLS: wtls_machine %ld, state %s, event %s.",
823  wtls_machine->mid, stateName(wtls_machine->state),
824  wap_event_name(event->type));
825 
826  /* for T_Unitdata_Ind PDUs */
827  if (event->type == T_Unitdata_Ind) {
828  /* if encryption: decrypt all pdus in the list */
829  if (wtls_machine->encrypted)
830  wtls_decrypt_pdu_list(wtls_machine,
831  event->u.T_Unitdata_Ind.pdu_list);
832  /* add all handshake data to wtls_machine->handshake_data */
833  //add_all_handshake_data(wtls_machine, event->u.T_Unitdata_Ind.pdu_list);
834  }
835 #define STATE_NAME(state)
836 #define ROW(wtls_state, event_type, condition, action, next_state) \
837  if (wtls_machine->state == wtls_state && \
838  event->type == event_type && \
839  (condition)) { \
840  action \
841  wtls_machine->state = next_state; \
842  debug("wap.wtls", 0, "WTLS %ld: New state %s", wtls_machine->mid, #next_state); \
843  } else
844 #include "wtls_state-decl.h"
845  {
846  error(0, "WTLS: handle_event: unhandled event!");
847  debug("wap.wtls", 0,
848  "WTLS: handle_event: Unhandled event was:");
849  wap_event_destroy(event);
850  return;
851  }
852 
853  if (event)
854  wap_event_destroy(event);
855 
856  if (wtls_machine->state == NULL_STATE) {
857  wtls_machine_destroy(wtls_machine);
858  wtls_machine = NULL;
859  }
860 }
861 
862 /*
863  * Checks whether wtls machines data structure includes a specific machine.
864  * The machine in question is identified with with source and destination
865  * address and port.
866  */
867 
868 static WTLSMachine *wtls_machine_find_or_create(WAPEvent * event)
869 {
870 
871  WTLSMachine *wtls_machine = NULL;
872  long mid;
873  WAPAddrTuple *tuple;
874 
875  tuple = NULL;
876  mid = -1;
877 
878  debug("wap.wtls", 0, "event->type = %d", event->type);
879 
880  /* Get the address that this PDU came in from */
881  switch (event->type) {
882  case T_Unitdata_Ind:
883  case T_DUnitdata_Ind:
884  tuple = event->u.T_Unitdata_Ind.addr_tuple;
885  break;
887  case SEC_Terminate_Req:
888  case SEC_Exception_Req:
889  case SEC_Create_Res:
890  case SEC_Exchange_Req:
891  case SEC_Commit_Req:
892  case SEC_Unitdata_Req:
893  tuple = event->u.T_Unitdata_Ind.addr_tuple;
894  break;
895  default:
896  debug("wap.wtls", 0, "WTLS: wtls_machine_find_or_create:"
897  "unhandled event (1)");
898  wap_event_dump(event);
899  return NULL;
900  }
901 
902  /* Either the address or the machine id must be available at this point */
903  gw_assert(tuple != NULL || mid != -1);
904 
905  /* Look for the machine owning this address */
906  wtls_machine = wtls_machine_find(tuple, mid);
907 
908  /* Oh well, we didn't find one. We'll create one instead, provided
909  it meets certain criteria */
910  if (wtls_machine == NULL) {
911  switch (event->type) {
913  /* State NULL, case 1 */
914  debug("wap.wtls", 0,
915  "WTLS: received a SEC_Create_Request_Req, and don't know what to do with it...");
916  /* Create and dispatch a T_Unitdata_Req containing a HelloRequest */
917  /* And there's no need to do anything else, 'cause we return to state NULL */
918  break;
919  case T_Unitdata_Ind:
920  case T_DUnitdata_Ind:
921  /* State NULL, case 3 */
922 /* if (wtls_event_type(event) == Alert_No_Renegotiation) { */
923  /* Create and dispatch a SEC_Exception_Ind event */
924 /* debug("wap.wtls",0,"WTLS: received an Alert_no_Renegotiation; just dropped it."); */
925  /* And there's no need to do anything else, 'cause we return to state NULL */
926 /* break; */
927 /* } else */
928 /* if (event->u.T_Unitdata_Ind == ClientHello) { */
929  /* State NULL, case 2 */
930  wtls_machine = wtls_machine_create(tuple);
931  /* And stick said event into machine, which should push us into state
932  CREATING after a SEC_Create_Ind */
933 /* } */
934  break;
935  default:
936  error(0, "WTLS: wtls_machine_find_or_create:"
937  " unhandled event (2)");
938  wap_event_dump(event);
939  break;
940  }
941  }
942  return wtls_machine;
943 }
944 
945 static int is_wanted_wtls_machine(void *a, void *b)
946 {
947  machine_pattern *pat;
948  WTLSMachine *m;
949 
950  m = a;
951  pat = b;
952 
953  if (m->mid == pat->mid)
954  return 1;
955 
956  if (pat->mid != -1)
957  return 0;
958 
959  return wap_addr_tuple_same(m->addr_tuple, pat->tuple);
960 }
961 
962 static WTLSMachine *wtls_machine_find(WAPAddrTuple * tuple, long mid)
963 {
964  machine_pattern pat;
965  WTLSMachine *m;
966 
967  pat.tuple = tuple;
968  pat.mid = mid;
969 
970  m = gwlist_search(wtls_machines, &pat, is_wanted_wtls_machine);
971  return m;
972 }
973 
974 static WTLSMachine *wtls_machine_create(WAPAddrTuple * tuple)
975 {
976 
977  WTLSMachine *wtls_machine;
978  wtls_machine = gw_malloc(sizeof(WTLSMachine));
979 
980 #define MACHINE(field) field
981 #define ENUM(name) wtls_machine->name = NULL_STATE;
982 #define ADDRTUPLE(name) wtls_machine->name = NULL;
983 #define INTEGER(name) wtls_machine->name = 0;
984 #define OCTSTR(name) wtls_machine->name = NULL;
985 #define PDULIST(name) wtls_machine->name = NULL;
986 #include "wtls_machine-decl.h"
987 
988  gwlist_append(wtls_machines, wtls_machine);
989  wtls_machine->mid = counter_increase(wtls_machine_id_counter);
990  wtls_machine->addr_tuple = wap_addr_tuple_duplicate(tuple);
991  wtls_machine->server_seq_num = wtls_machine->client_seq_num = -1;
992  wtls_machine->last_refresh = -1;
993 
994  wtls_machine->handshake_data = octstr_create("");
995 
996  debug("wap.wtls", 0, "WTLS: Created WTLSMachine %ld (0x%p)",
997  wtls_machine->mid, (void *)wtls_machine);
998  return wtls_machine;
999 }
1000 
1001 /*
1002  * Destroys a WTLSMachine. Assumes it is safe to do so. Assumes it has
1003  * already been deleted from the machines list.
1004  */
1005 static void wtls_machine_destroy(void *p)
1006 {
1007  WTLSMachine *wtls_machine;
1008 
1009  wtls_machine = p;
1010  debug("wap.wtls", 0, "WTLS: Destroying WTLSMachine %ld (0x%p)",
1011  wtls_machine->mid, (void *)wtls_machine);
1012  gwlist_delete_equal(wtls_machines, wtls_machine);
1013 
1014 #define MACHINE(field) field
1015 #define ENUM(name) wtls_machine->name = NULL_STATE;
1016 #define ADDRTUPLE(name) wap_addr_tuple_destroy(wtls_machine->name);
1017 #define INTEGER(name) wtls_machine->name = 0;
1018 #define OCTSTR(name) octstr_destroy(wtls_machine->name);
1019 #define PDULIST(name) wtls_machine->name = NULL;
1020 #include "wtls_machine-decl.h"
1021 
1022  gw_free(wtls_machine);
1023 }
1024 
1025 static int wtls_machine_has_mid(void *a, void *b)
1026 {
1027  WTLSMachine *sm;
1028  long mid;
1029 
1030  sm = a;
1031  mid = *(long *)b;
1032  return sm->mid == mid;
1033 }
1034 
1035 static WTLSMachine *find_wtls_machine_using_mid(long mid)
1036 {
1037  return gwlist_search(wtls_machines, &mid, wtls_machine_has_mid);
1038 }
1039 
1040 /* Used for list searches */
1041 static int match_handshake_type(void *item, void *pattern)
1042 {
1043  wtls_Payload *matchingPayload;
1044  int type;
1045  int retrievedType;
1046 
1047  matchingPayload = (wtls_Payload *) item;
1048  type = (long)pattern;
1049 
1050  if (!matchingPayload->data)
1051  return (0);
1052  retrievedType = octstr_get_char(matchingPayload->data, 0);
1053 
1054  if (matchingPayload->type == Handshake_PDU && retrievedType == type) {
1055  return 1;
1056  } else {
1057  return 0;
1058  }
1059 }
1060 
1061 static int match_pdu_type(void *item, void *pattern)
1062 {
1063  wtls_Payload *matchingPayload;
1064  int type;
1065 
1066  matchingPayload = (wtls_Payload *) item;
1067  type = (long)pattern;
1068 
1069  if (matchingPayload->type == type) {
1070  return 1;
1071  } else {
1072  return 0;
1073  }
1074 }
1075 
1076 #endif /* HAVE_WTLS_OPENSSL */
void msg_dump(Msg *msg, int level)
Definition: msg.c:152
void error(int err, const char *fmt,...)
Definition: log.c:612
void info(int err, const char *fmt,...)
Definition: log.c:636
AlertDescription desc
Definition: wtls_pdu.h:408
ServerHello * server_hello
Definition: wtls_pdu.h:424
long gmt_unix_time
Definition: wtls_pdu.h:156
void * gwlist_search(List *list, void *pattern, int(*cmp)(void *, void *))
Definition: list.c:486
wtls_Payload * wtls_pdu_pack(wtls_PDU *pdu, WTLSMachine *wtls_machine)
CipherSuite * wtls_choose_ciphersuite(List *ciphersuites)
wtls_PDU * wtls_pdu_create(int type)
EXCHANGE SEC_Terminate_Req
ClientKeyExchange * client_key_exchange
Definition: wtls_pdu.h:436
void wtls_payload_destroy(wtls_Payload *payload)
void counter_destroy(Counter *counter)
Definition: counter.c:110
void gwlist_append(List *list, void *item)
Definition: list.c:179
static void main_thread(void *)
Definition: wap-appl.c:314
Definition: shared.h:81
Random * random
Definition: wtls_pdu.h:303
int cipher
Definition: wtls_pdu.h:448
add_pdu(wtls_machine, serverKeyXchgPDU)
void octstr_append(Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:1502
int wtls_choose_clientkeyid(List *clientKeyIDs, int *algo)
void gwlist_produce(List *list, void *item)
Definition: list.c:411
long gwlist_len(List *list)
Definition: list.c:166
Finished * finished
Definition: wtls_pdu.h:438
List * client_key_ids
Definition: wtls_pdu.h:305
T_Unitdata_Ind
void wtls_dispatch_event(WAPEvent *event)
Octstr * rsa_exponent
Definition: wtls_pdu.h:171
int krefresh
Definition: wtls_pdu.h:310
int type
Definition: smsc_cimd2.c:215
char * description
Definition: ws.c:100
Octstr * session_id
Definition: wtls_pdu.h:316
Octstr * wtls_payload_pack(wtls_Payload *payload, int seqnum)
Octstr * wtls_decrypt_key(int type, Octstr *encryptedData)
Octstr * wtls_hash(Octstr *inputData, WTLSMachine *wtls_machine)
Alert alert
Definition: wtls_pdu.h:455
#define msg_create(type)
Definition: msg.h:136
int pack_int16(Octstr *data, long charpos, int i)
void wap_event_dump(WAPEvent *event)
Definition: wap_events.c:181
void gwthread_join_every(gwthread_func_t *func)
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
int snMode
Definition: wtls_pdu.h:449
WAPAddrTuple * wap_addr_tuple_duplicate(WAPAddrTuple *tuple)
Definition: wap_addr.c:125
Octstr * data
Definition: wtls_pdu.h:469
void wtls_pdu_dump(wtls_PDU *msg, int level)
Octstr * random_bytes
Definition: wtls_pdu.h:157
WAPAddrTuple * tuple
Definition: wtp.h:189
union wtls_pdu::@93 u
Application application
Definition: wtls_pdu.h:457
ChangeCipher cc
Definition: wtls_pdu.h:454
unsigned long mid
Definition: wtls.h:93
void wtls_shutdown(void)
void wtls_init(wtls_dispatch_func_t *responder_dispatch)
Definition: msg.h:79
void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
Definition: octstr.c:1301
Counter * counter_create(void)
Definition: counter.c:94
int wtls_choose_snmode(int snmode)
void wtls_dispatch_resp(WAPEvent *event)
void wtls_pdu_destroy(wtls_PDU *msg)
void gwlist_remove_producer(List *list)
Definition: list.c:401
void wap_event_destroy_item(void *event)
Definition: wap_events.c:130
Random * wtls_get_random(void)
Random * random
Definition: wtls_pdu.h:315
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
Octstr * chksum
Definition: wtls_pdu.h:409
const char * wap_event_name(WAPEventName type)
Definition: wap_events.c:169
long gwlist_delete_equal(List *list, void *item)
Definition: list.c:266
long mid
Definition: wtp.h:191
Octstr * verify_data
Definition: wtls_pdu.h:354
int serverversion
Definition: wtls_pdu.h:314
clientHello(event, wtls_machine)
#define wap_event_create(type)
Definition: wap_events.h:107
RSAPublicKey * wtls_get_rsapublickey(void)
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
int krefresh
Definition: wtls_pdu.h:321
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
CipherSuite * ciphersuite
Definition: wtls_pdu.h:318
gw_assert(wtls_machine->packet_to_send!=NULL)
void wap_dispatch_datagram(WAPEvent *dgram)
Definition: wap.c:68
int client_key_id
Definition: wtls_pdu.h:317
int wtls_get_address_tuple(long mid, WAPAddrTuple **tuple)
int level
Definition: wtls_pdu.h:407
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
int wap_addr_tuple_same(WAPAddrTuple *a, WAPAddrTuple *b)
Definition: wap_addr.c:118
void write_to_bearerbox(Msg *pmsg)
Definition: shared.c:142
OPEN NULL_STATE NULL_STATE SEC_Create_Request_Req
Definition: octstr.c:118
void * gwlist_consume(List *list)
Definition: list.c:427
CREATING CREATING SEC_Exchange_Req
int change
Definition: wtls_pdu.h:362
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
void wtls_decrypt_pdu_list(WTLSMachine *wtls_machine, List *pdu_list)
Handshake handshake
Definition: wtls_pdu.h:456
void destroy_rsa_pubkey(RSAPublicKey *key)
int mac_algo
Definition: wtls_pdu.h:286
WAPAddrTuple * wap_addr_tuple_create(Octstr *rmt_addr, long rmt_port, Octstr *lcl_addr, long lcl_port)
Definition: wap_addr.c:96
WAPEventName type
Definition: wap_events.h:88
HandshakeType msg_type
Definition: wtls_pdu.h:417
Octstr * octstr_cat(Octstr *ostr1, Octstr *ostr2)
Definition: octstr.c:381
CompressionMethod comp_method
Definition: wtls_pdu.h:319
Octstr * wtls_calculate_prf(Octstr *secret, Octstr *label, Octstr *seed, int byteLength, WTLSMachine *wtls_machine)
int pack_int32(Octstr *data, long charpos, long i)
#define gwlist_create()
Definition: list.h:136
ClientHello * client_hello
Definition: wtls_pdu.h:422
CREATING SEC_Exception_Req
void octstr_truncate(Octstr *ostr, int new_len)
Definition: octstr.c:1325
Octstr * data
Definition: wtls_pdu.h:442
RSAEncryptedSecret * rsa_params
Definition: wtls_pdu.h:346
int rlen
Definition: wtls_pdu.h:451
WAPEvent * wtls_unpack_wdp_datagram(Msg *msg)
Octstr * rsa_modulus
Definition: wtls_pdu.h:172
List * wtls_unpack_payloadlist(Octstr *data)
void gwlist_add_producer(List *list)
Definition: list.c:383
union WAPEvent::@87 u
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
send_queuedpdus(wtls_machine)
int bulk_cipher_algo
Definition: wtls_pdu.h:285
Definition: list.c:102
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
void wap_event_destroy(WAPEvent *event)
Definition: wap_events.c:102
void wtls_dispatch_func_t(Msg *msg)
Definition: wtls.h:73
int type
Definition: wtls_pdu.h:446
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:869
wtls_PDU * wtls_pdu_unpack(wtls_Payload *payload, WTLSMachine *wtls_machine)
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.