Import wpa_supplicant 0.5.8
[dragonfly.git] / contrib / wpa_supplicant-0.5.8 / eap_tls_common.c
1 /*
2  * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions
3  * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eap_i.h"
19 #include "eap_tls_common.h"
20 #include "config_ssid.h"
21 #include "md5.h"
22 #include "sha1.h"
23 #include "tls.h"
24 #include "config.h"
25
26
27 static int eap_tls_check_blob(struct eap_sm *sm, const char **name,
28                               const u8 **data, size_t *data_len)
29 {
30         const struct wpa_config_blob *blob;
31
32         if (*name == NULL || os_strncmp(*name, "blob://", 7) != 0)
33                 return 0;
34
35         blob = eap_get_config_blob(sm, *name + 7);
36         if (blob == NULL) {
37                 wpa_printf(MSG_ERROR, "%s: Named configuration blob '%s' not "
38                            "found", __func__, *name + 7);
39                 return -1;
40         }
41
42         *name = NULL;
43         *data = blob->data;
44         *data_len = blob->len;
45
46         return 0;
47 }
48
49
50 static void eap_tls_params_from_conf1(struct tls_connection_params *params,
51                                       struct wpa_ssid *config)
52 {
53         params->ca_cert = (char *) config->ca_cert;
54         params->ca_path = (char *) config->ca_path;
55         params->client_cert = (char *) config->client_cert;
56         params->private_key = (char *) config->private_key;
57         params->private_key_passwd = (char *) config->private_key_passwd;
58         params->dh_file = (char *) config->dh_file;
59         params->subject_match = (char *) config->subject_match;
60         params->altsubject_match = (char *) config->altsubject_match;
61         params->engine_id = config->engine_id;
62         params->pin = config->pin;
63         params->key_id = config->key_id;
64 }
65
66
67 static void eap_tls_params_from_conf2(struct tls_connection_params *params,
68                                       struct wpa_ssid *config)
69 {
70         params->ca_cert = (char *) config->ca_cert2;
71         params->ca_path = (char *) config->ca_path2;
72         params->client_cert = (char *) config->client_cert2;
73         params->private_key = (char *) config->private_key2;
74         params->private_key_passwd = (char *) config->private_key2_passwd;
75         params->dh_file = (char *) config->dh_file2;
76         params->subject_match = (char *) config->subject_match2;
77         params->altsubject_match = (char *) config->altsubject_match2;
78 }
79
80
81 static int eap_tls_params_from_conf(struct eap_sm *sm,
82                                     struct eap_ssl_data *data,
83                                     struct tls_connection_params *params,
84                                     struct wpa_ssid *config, int phase2)
85 {
86         os_memset(params, 0, sizeof(*params));
87         params->engine = config->engine;
88         if (phase2)
89                 eap_tls_params_from_conf2(params, config);
90         else
91                 eap_tls_params_from_conf1(params, config);
92         params->tls_ia = data->tls_ia;
93
94
95         if (eap_tls_check_blob(sm, &params->ca_cert, &params->ca_cert_blob,
96                                &params->ca_cert_blob_len) ||
97             eap_tls_check_blob(sm, &params->client_cert,
98                                &params->client_cert_blob,
99                                &params->client_cert_blob_len) ||
100             eap_tls_check_blob(sm, &params->private_key,
101                                &params->private_key_blob,
102                                &params->private_key_blob_len) ||
103             eap_tls_check_blob(sm, &params->dh_file, &params->dh_blob,
104                                &params->dh_blob_len)) {
105                 wpa_printf(MSG_INFO, "SSL: Failed to get configuration blobs");
106                 return -1;
107         }
108
109         return 0;
110 }
111
112
113 static int eap_tls_init_connection(struct eap_sm *sm,
114                                    struct eap_ssl_data *data,
115                                    struct wpa_ssid *config,
116                                    struct tls_connection_params *params)
117 {
118         int res;
119
120         data->conn = tls_connection_init(sm->ssl_ctx);
121         if (data->conn == NULL) {
122                 wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
123                            "connection");
124                 return -1;
125         }
126
127         res = tls_connection_set_params(sm->ssl_ctx, data->conn, params);
128         if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) {
129                 /* At this point with the pkcs11 engine the PIN might be wrong.
130                  * We reset the PIN in the configuration to be sure to not use
131                  * it again and the calling function must request a new one */
132                 os_free(config->pin);
133                 config->pin = NULL;
134         } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) {
135                 wpa_printf(MSG_INFO, "TLS: Failed to load private key");
136                 /* We don't know exactly but maybe the PIN was wrong,
137                  * so ask for a new one. */
138                 os_free(config->pin);
139                 config->pin = NULL;
140                 eap_sm_request_pin(sm);
141                 sm->ignore = TRUE;
142                 return -1;
143         } else if (res) {
144                 wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection "
145                            "parameters");
146                 return -1;
147         }
148
149         return 0;
150 }
151
152
153 /**
154  * eap_tls_ssl_init - Initialize shared TLS functionality
155  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
156  * @data: Data for TLS processing
157  * @config: Pointer to the network configuration
158  * Returns: 0 on success, -1 on failure
159  *
160  * This function is used to initialize shared TLS functionality for EAP-TLS,
161  * EAP-PEAP, EAP-TTLS, and EAP-FAST.
162  */
163 int eap_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
164                      struct wpa_ssid *config)
165 {
166         int ret = -1;
167         struct tls_connection_params params;
168
169         if (config == NULL)
170                 return -1;
171
172         data->eap = sm;
173         data->phase2 = sm->init_phase2;
174         if (eap_tls_params_from_conf(sm, data, &params, config, data->phase2) <
175             0)
176                 goto done;
177
178         if (eap_tls_init_connection(sm, data, config, &params) < 0)
179                 goto done;
180
181         data->tls_out_limit = config->fragment_size;
182         if (data->phase2) {
183                 /* Limit the fragment size in the inner TLS authentication
184                  * since the outer authentication with EAP-PEAP does not yet
185                  * support fragmentation */
186                 if (data->tls_out_limit > 100)
187                         data->tls_out_limit -= 100;
188         }
189
190         if (config->phase1 &&
191             os_strstr(config->phase1, "include_tls_length=1")) {
192                 wpa_printf(MSG_DEBUG, "TLS: Include TLS Message Length in "
193                            "unfragmented packets");
194                 data->include_tls_length = 1;
195         }
196
197         ret = 0;
198
199 done:
200         return ret;
201 }
202
203
204 /**
205  * eap_tls_ssl_deinit - Deinitialize shared TLS functionality
206  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
207  * @data: Data for TLS processing
208  *
209  * This function deinitializes shared TLS functionality that was initialized
210  * with eap_tls_ssl_init().
211  */
212 void eap_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
213 {
214         tls_connection_deinit(sm->ssl_ctx, data->conn);
215         os_free(data->tls_in);
216         os_free(data->tls_out);
217 }
218
219
220 /**
221  * eap_tls_derive_key - Derive a key based on TLS session data
222  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
223  * @data: Data for TLS processing
224  * @label: Label string for deriving the keys, e.g., "client EAP encryption"
225  * @len: Length of the key material to generate (usually 64 for MSK)
226  * Returns: Pointer to allocated key on success or %NULL on failure
227  *
228  * This function uses TLS-PRF to generate pseudo-random data based on the TLS
229  * session data (client/server random and master key). Each key type may use a
230  * different label to bind the key usage into the generated material.
231  *
232  * The caller is responsible for freeing the returned buffer.
233  */
234 u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
235                         const char *label, size_t len)
236 {
237         struct tls_keys keys;
238         u8 *rnd = NULL, *out;
239
240         out = os_malloc(len);
241         if (out == NULL)
242                 return NULL;
243
244         /* First, try to use TLS library function for PRF, if available. */
245         if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
246             0)
247                 return out;
248
249         /*
250          * TLS library did not support key generation, so get the needed TLS
251          * session parameters and use an internal implementation of TLS PRF to
252          * derive the key.
253          */
254         if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
255                 goto fail;
256
257         if (keys.client_random == NULL || keys.server_random == NULL ||
258             keys.master_key == NULL)
259                 goto fail;
260
261         rnd = os_malloc(keys.client_random_len + keys.server_random_len);
262         if (rnd == NULL)
263                 goto fail;
264         os_memcpy(rnd, keys.client_random, keys.client_random_len);
265         os_memcpy(rnd + keys.client_random_len, keys.server_random,
266                   keys.server_random_len);
267
268         if (tls_prf(keys.master_key, keys.master_key_len,
269                     label, rnd, keys.client_random_len +
270                     keys.server_random_len, out, len))
271                 goto fail;
272
273         os_free(rnd);
274         return out;
275
276 fail:
277         os_free(out);
278         os_free(rnd);
279         return NULL;
280 }
281
282
283 /**
284  * eap_tls_data_reassemble - Reassemble TLS data
285  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
286  * @data: Data for TLS processing
287  * @in_data: Next incoming TLS segment
288  * @in_len: Length of in_data
289  * @out_len: Variable for returning output data length
290  * @need_more_input: Variable for returning whether more input data is needed
291  * to reassemble this TLS packet
292  * Returns: Pointer to output data, %NULL on error or when more data is needed
293  * for the full message (in which case, *need_more_input is also set to 1).
294  *
295  * This function reassembles TLS fragments. Caller must not free the returned
296  * data buffer since an internal pointer to it is maintained.
297  */
298 const u8 * eap_tls_data_reassemble(
299         struct eap_sm *sm, struct eap_ssl_data *data, const u8 *in_data,
300         size_t in_len, size_t *out_len, int *need_more_input)
301 {
302         u8 *buf;
303
304         *need_more_input = 0;
305
306         if (data->tls_in_left > in_len || data->tls_in) {
307                 if (data->tls_in_len + in_len == 0) {
308                         os_free(data->tls_in);
309                         data->tls_in = NULL;
310                         data->tls_in_len = 0;
311                         wpa_printf(MSG_WARNING, "SSL: Invalid reassembly "
312                                    "state: tls_in_left=%lu tls_in_len=%lu "
313                                    "in_len=%lu",
314                                    (unsigned long) data->tls_in_left,
315                                    (unsigned long) data->tls_in_len,
316                                    (unsigned long) in_len);
317                         return NULL;
318                 }
319                 if (data->tls_in_len + in_len > 65536) {
320                         /* Limit length to avoid rogue servers from causing
321                          * large memory allocations. */
322                         os_free(data->tls_in);
323                         data->tls_in = NULL;
324                         data->tls_in_len = 0;
325                         wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
326                                    " over 64 kB)");
327                         return NULL;
328                 }
329                 buf = os_realloc(data->tls_in, data->tls_in_len + in_len);
330                 if (buf == NULL) {
331                         os_free(data->tls_in);
332                         data->tls_in = NULL;
333                         data->tls_in_len = 0;
334                         wpa_printf(MSG_INFO, "SSL: Could not allocate memory "
335                                    "for TLS data");
336                         return NULL;
337                 }
338                 os_memcpy(buf + data->tls_in_len, in_data, in_len);
339                 data->tls_in = buf;
340                 data->tls_in_len += in_len;
341                 if (in_len > data->tls_in_left) {
342                         wpa_printf(MSG_INFO, "SSL: more data than TLS message "
343                                    "length indicated");
344                         data->tls_in_left = 0;
345                         return NULL;
346                 }
347                 data->tls_in_left -= in_len;
348                 if (data->tls_in_left > 0) {
349                         wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input "
350                                    "data", (unsigned long) data->tls_in_left);
351                         *need_more_input = 1;
352                         return NULL;
353                 }
354         } else {
355                 data->tls_in_left = 0;
356                 data->tls_in = os_malloc(in_len ? in_len : 1);
357                 if (data->tls_in == NULL)
358                         return NULL;
359                 os_memcpy(data->tls_in, in_data, in_len);
360                 data->tls_in_len = in_len;
361         }
362
363         *out_len = data->tls_in_len;
364         return data->tls_in;
365 }
366
367
368 static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data,
369                                  const u8 *in_data, size_t in_len,
370                                  u8 **out_data, size_t *out_len)
371 {
372         const u8 *msg;
373         size_t msg_len;
374         int need_more_input;
375         u8 *appl_data;
376         size_t appl_data_len;
377
378         msg = eap_tls_data_reassemble(sm, data, in_data, in_len,
379                                       &msg_len, &need_more_input);
380         if (msg == NULL)
381                 return need_more_input ? 1 : -1;
382
383         /* Full TLS message reassembled - continue handshake processing */
384         if (data->tls_out) {
385                 /* This should not happen.. */
386                 wpa_printf(MSG_INFO, "SSL: eap_tls_process_helper - pending "
387                            "tls_out data even though tls_out_len = 0");
388                 os_free(data->tls_out);
389                 WPA_ASSERT(data->tls_out == NULL);
390         }
391         appl_data = NULL;
392         data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn,
393                                                  msg, msg_len,
394                                                  &data->tls_out_len,
395                                                  &appl_data, &appl_data_len);
396
397         /* Clear reassembled input data (if the buffer was needed). */
398         data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
399         os_free(data->tls_in);
400         data->tls_in = NULL;
401
402         if (appl_data &&
403             tls_connection_established(sm->ssl_ctx, data->conn) &&
404             !tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
405                 wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data",
406                                 appl_data, appl_data_len);
407                 *out_data = appl_data;
408                 *out_len = appl_data_len;
409                 return 2;
410         }
411
412         os_free(appl_data);
413
414         return 0;
415 }
416
417
418 static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type,
419                                   int peap_version, u8 id, int ret,
420                                   u8 **out_data, size_t *out_len)
421 {
422         size_t len;
423         u8 *pos, *flags;
424         int more_fragments, length_included;
425         
426         wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
427                    "%lu bytes)",
428                    (unsigned long) data->tls_out_len - data->tls_out_pos,
429                    (unsigned long) data->tls_out_len);
430
431         len = data->tls_out_len - data->tls_out_pos;
432         if (len > data->tls_out_limit) {
433                 more_fragments = 1;
434                 len = data->tls_out_limit;
435                 wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments "
436                            "will follow", (unsigned long) len);
437         } else
438                 more_fragments = 0;
439
440         length_included = data->tls_out_pos == 0 &&
441                 (data->tls_out_len > data->tls_out_limit ||
442                  data->include_tls_length);
443
444         *out_data = (u8 *)
445                 eap_msg_alloc(EAP_VENDOR_IETF, eap_type, out_len,
446                               1 + length_included * 4 + len, EAP_CODE_RESPONSE,
447                               id, &pos);
448         if (*out_data == NULL)
449                 return -1;
450
451         flags = pos++;
452         *flags = peap_version;
453         if (more_fragments)
454                 *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
455         if (length_included) {
456                 *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
457                 WPA_PUT_BE32(pos, data->tls_out_len);
458                 pos += 4;
459         }
460
461         os_memcpy(pos, &data->tls_out[data->tls_out_pos], len);
462         data->tls_out_pos += len;
463
464         if (!more_fragments) {
465                 data->tls_out_len = 0;
466                 data->tls_out_pos = 0;
467                 os_free(data->tls_out);
468                 data->tls_out = NULL;
469         }
470
471         return ret;
472 }
473
474
475 /**
476  * eap_tls_process_helper - Process TLS handshake message
477  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
478  * @data: Data for TLS processing
479  * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
480  * @peap_version: Version number for EAP-PEAP/TTLS
481  * @id: EAP identifier for the response
482  * @in_data: Message received from the server
483  * @in_len: Length of in_data
484  * @out_data: Buffer for returning a pointer to the response message
485  * @out_len: Buffer for returning the length of the response message
486  * Returns: 0 on success, 1 if more input data is needed, or -1 on failure
487  *
488  * This function can be used to process TLS handshake messages. It reassembles
489  * the received fragments and uses a TLS library to process the messages. The
490  * response data from the TLS library is fragmented to suitable output messages
491  * that the caller can send out.
492  *
493  * out_data is used to return the response message if the return value of this
494  * function is 0 or -1. In case of failure, the message is likely a TLS alarm
495  * message. The caller is responsible for freeing the allocated buffer if
496  * *out_data is not %NULL.
497  */
498 int eap_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
499                            EapType eap_type, int peap_version,
500                            u8 id, const u8 *in_data, size_t in_len,
501                            u8 **out_data, size_t *out_len)
502 {
503         int ret = 0;
504
505         WPA_ASSERT(data->tls_out_len == 0 || in_len == 0);
506         *out_len = 0;
507         *out_data = NULL;
508
509         if (data->tls_out_len == 0) {
510                 /* No more data to send out - expect to receive more data from
511                  * the AS. */
512                 int res = eap_tls_process_input(sm, data, in_data, in_len,
513                                                 out_data, out_len);
514                 if (res)
515                         return res;
516         }
517
518         if (data->tls_out == NULL) {
519                 data->tls_out_len = 0;
520                 return -1;
521         }
522
523         if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) {
524                 wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to "
525                            "report error");
526                 ret = -1;
527                 /* TODO: clean pin if engine used? */
528         }
529
530         if (data->tls_out_len == 0) {
531                 /* TLS negotiation should now be complete since all other cases
532                  * needing more data should have been caught above based on
533                  * the TLS Message Length field. */
534                 wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
535                 os_free(data->tls_out);
536                 data->tls_out = NULL;
537                 return 1;
538         }
539
540         return eap_tls_process_output(data, eap_type, peap_version, id, ret,
541                                       out_data, out_len);
542 }
543
544
545 /**
546  * eap_tls_build_ack - Build a TLS ACK frames
547  * @data: Data for TLS processing
548  * @respDataLen: Buffer for returning the length of the response message
549  * @id: EAP identifier for the response
550  * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
551  * @peap_version: Version number for EAP-PEAP/TTLS
552  * Returns: Pointer to allocated ACK frames or %NULL on failure
553  */
554 u8 * eap_tls_build_ack(struct eap_ssl_data *data, size_t *respDataLen, u8 id,
555                        EapType eap_type, int peap_version)
556 {
557         struct eap_hdr *resp;
558         u8 *pos;
559
560         resp = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, respDataLen,
561                              1, EAP_CODE_RESPONSE, id, &pos);
562         if (resp == NULL)
563                 return NULL;
564         wpa_printf(MSG_DEBUG, "SSL: Building ACK");
565         *pos = peap_version; /* Flags */
566         return (u8 *) resp;
567 }
568
569
570 /**
571  * eap_tls_reauth_init - Re-initialize shared TLS for session resumption
572  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
573  * @data: Data for TLS processing
574  * Returns: 0 on success, -1 on failure
575  */
576 int eap_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data)
577 {
578         os_free(data->tls_in);
579         data->tls_in = NULL;
580         data->tls_in_len = data->tls_in_left = data->tls_in_total = 0;
581         os_free(data->tls_out);
582         data->tls_out = NULL;
583         data->tls_out_len = data->tls_out_pos = 0;
584
585         return tls_connection_shutdown(sm->ssl_ctx, data->conn);
586 }
587
588
589 /**
590  * eap_tls_status - Get TLS status
591  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
592  * @data: Data for TLS processing
593  * @buf: Buffer for status information
594  * @buflen: Maximum buffer length
595  * @verbose: Whether to include verbose status information
596  * Returns: Number of bytes written to buf.
597  */
598 int eap_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, char *buf,
599                    size_t buflen, int verbose)
600 {
601         char name[128];
602         int len = 0, ret;
603
604         if (tls_get_cipher(sm->ssl_ctx, data->conn, name, sizeof(name)) == 0) {
605                 ret = os_snprintf(buf + len, buflen - len,
606                                   "EAP TLS cipher=%s\n", name);
607                 if (ret < 0 || (size_t) ret >= buflen - len)
608                         return len;
609                 len += ret;
610         }
611
612         return len;
613 }
614
615
616 /**
617  * eap_tls_process_init - Initial validation and processing of EAP requests
618  * @sm: Pointer to EAP state machine allocated with eap_sm_init()
619  * @data: Data for TLS processing
620  * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...)
621  * @ret: Return values from EAP request validation and processing
622  * @reqData: EAP request to be processed (eapReqData)
623  * @reqDataLen: Length of the EAP request
624  * @len: Buffer for returning length of the remaining payload
625  * @flags: Buffer for returning TLS flags
626  * Returns: Buffer to payload after TLS flags and length or %NULL on failure
627  */
628 const u8 * eap_tls_process_init(struct eap_sm *sm, struct eap_ssl_data *data,
629                                 EapType eap_type, struct eap_method_ret *ret,
630                                 const u8 *reqData, size_t reqDataLen,
631                                 size_t *len, u8 *flags)
632 {
633         const u8 *pos;
634         size_t left;
635         unsigned int tls_msg_len;
636
637         if (tls_get_errors(sm->ssl_ctx)) {
638                 wpa_printf(MSG_INFO, "SSL: TLS errors detected");
639                 ret->ignore = TRUE;
640                 return NULL;
641         }
642
643         pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, reqDataLen,
644                                &left);
645         if (pos == NULL) {
646                 ret->ignore = TRUE;
647                 return NULL;
648         }
649         *flags = *pos++;
650         left--;
651         wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - "
652                    "Flags 0x%02x", (unsigned long) reqDataLen, *flags);
653         if (*flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
654                 if (left < 4) {
655                         wpa_printf(MSG_INFO, "SSL: Short frame with TLS "
656                                    "length");
657                         ret->ignore = TRUE;
658                         return NULL;
659                 }
660                 tls_msg_len = WPA_GET_BE32(pos);
661                 wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d",
662                            tls_msg_len);
663                 if (data->tls_in_left == 0) {
664                         data->tls_in_total = tls_msg_len;
665                         data->tls_in_left = tls_msg_len;
666                         os_free(data->tls_in);
667                         data->tls_in = NULL;
668                         data->tls_in_len = 0;
669                 }
670                 pos += 4;
671                 left -= 4;
672         }
673
674         ret->ignore = FALSE;
675         ret->methodState = METHOD_MAY_CONT;
676         ret->decision = DECISION_FAIL;
677         ret->allowNotifications = TRUE;
678
679         *len = (size_t) left;
680         return pos;
681 }