2 * Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation,
5 * Author: Simon Josefsson
7 * This file is part of GnuTLS-EXTRA.
9 * GnuTLS-extra is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * GnuTLS-extra is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "gnutls_int.h"
24 #include "gnutls_record.h"
25 #include "gnutls_errors.h"
26 #include "gnutls_num.h"
27 #include "gnutls_state.h"
28 #include <gnutls/extra.h>
29 #include <ext_inner_application.h>
31 #define CHECKSUM_SIZE 12
33 struct gnutls_ia_client_credentials_st
35 gnutls_ia_avp_func avp_func
;
39 struct gnutls_ia_server_credentials_st
41 gnutls_ia_avp_func avp_func
;
45 static const char server_finished_label
[] = "server phase finished";
46 static const char client_finished_label
[] = "client phase finished";
47 static const char inner_permutation_label
[] = "inner secret permutation";
48 static const char challenge_label
[] = "inner application challenge";
51 * The TLS/IA packet is the InnerApplication token, described as
52 * follows in draft-funk-tls-inner-application-extension-01.txt:
55 * application_payload(0), intermediate_phase_finished(1),
56 * final_phase_finished(2), (255)
57 * } InnerApplicationType;
60 * InnerApplicationType msg_type;
62 * select (InnerApplicationType) {
63 * case application_payload: ApplicationPayload;
64 * case intermediate_phase_finished: IntermediatePhaseFinished;
65 * case final_phase_finished: FinalPhaseFinished;
71 /* Send TLS/IA data. If data==NULL && sizeofdata==NULL, then the last
72 send was interrupted for some reason, and then we try to send it
73 again. Returns the number of bytes sent, or an error code. If
74 this return E_AGAIN and E_INTERRUPTED, call this function again
75 with data==NULL&&sizeofdata=0NULL until it returns successfully. */
77 _gnutls_send_inner_application (gnutls_session_t session
,
78 gnutls_ia_apptype_t msg_type
,
79 const char *data
, size_t sizeofdata
)
87 plen
= sizeofdata
+ 4;
88 p
= gnutls_malloc (plen
);
92 return GNUTLS_E_MEMORY_ERROR
;
95 *(unsigned char *) p
= (unsigned char) (msg_type
& 0xFF);
96 _gnutls_write_uint24 (sizeofdata
, p
+ 1);
97 memcpy (p
+ 4, data
, sizeofdata
);
101 _gnutls_send_int (session
, GNUTLS_INNER_APPLICATION
, -1,
102 EPOCH_WRITE_CURRENT
, p
, plen
, MBUFFER_FLUSH
);
110 /* Receive TLS/IA data. Store received TLS/IA message type in
111 *MSG_TYPE, and the data in DATA of max SIZEOFDATA size. Return the
112 number of bytes read, or an error code. */
114 _gnutls_recv_inner_application (gnutls_session_t session
,
115 gnutls_ia_apptype_t
* msg_type
,
116 opaque
* data
, size_t sizeofdata
)
122 len
= _gnutls_recv_int (session
, GNUTLS_INNER_APPLICATION
, -1, pkt
, 4);
126 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
130 len24
= _gnutls_read_uint24 (&pkt
[1]);
132 if (*msg_type
!= GNUTLS_IA_APPLICATION_PAYLOAD
&& len24
!= CHECKSUM_SIZE
)
135 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
138 if (sizeofdata
< len24
)
140 /* XXX push back pkt to IA buffer? */
142 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
147 uint32_t tmplen
= len24
;
149 len24
= _gnutls_recv_int (session
, GNUTLS_INNER_APPLICATION
, -1,
155 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
162 /* Apply the TLS PRF using the TLS/IA inner secret as keying material,
163 where the seed is the client random concatenated with the server
164 random concatenated EXTRA of EXTRA_SIZE length (which can be NULL/0
165 respectively). LABEL and LABEL_SIZE is used as the label. The
166 result is placed in pre-allocated OUT of OUTSIZE length. */
168 _gnutls_ia_prf (gnutls_session_t session
,
172 const char *extra
, size_t outsize
, opaque
* out
)
176 size_t seedsize
= 2 * GNUTLS_RANDOM_SIZE
+ extra_size
;
177 extension_priv_data_t epriv
;
181 _gnutls_ext_get_session_data (session
, GNUTLS_EXTENSION_INNER_APPLICATION
,
190 seed
= gnutls_malloc (seedsize
);
194 return GNUTLS_E_MEMORY_ERROR
;
197 memcpy (seed
, session
->security_parameters
.server_random
,
199 memcpy (seed
+ GNUTLS_RANDOM_SIZE
,
200 session
->security_parameters
.client_random
, GNUTLS_RANDOM_SIZE
);
201 memcpy (seed
+ 2 * GNUTLS_RANDOM_SIZE
, extra
, extra_size
);
203 ret
= _gnutls_PRF (session
, priv
->inner_secret
,
205 label
, label_size
, seed
, seedsize
, outsize
, out
);
213 * gnutls_ia_permute_inner_secret:
214 * @session: is a #gnutls_session_t structure.
215 * @session_keys_size: Size of generated session keys (0 if none).
216 * @session_keys: Generated session keys, used to permute inner secret
219 * Permute the inner secret using the generated session keys.
221 * This can be called in the TLS/IA AVP callback to mix any generated
222 * session keys with the TLS/IA inner secret.
224 * Return value: Return zero on success, or a negative error code.
227 gnutls_ia_permute_inner_secret (gnutls_session_t session
,
228 size_t session_keys_size
,
229 const char *session_keys
)
231 extension_priv_data_t epriv
;
236 _gnutls_ext_get_session_data (session
, GNUTLS_EXTENSION_INNER_APPLICATION
,
245 return _gnutls_ia_prf (session
,
246 sizeof (inner_permutation_label
) - 1,
247 inner_permutation_label
,
250 GNUTLS_RANDOM_SIZE
, priv
->inner_secret
);
254 * gnutls_ia_generate_challenge:
255 * @session: is a #gnutls_session_t structure.
256 * @buffer_size: size of output buffer.
257 * @buffer: pre-allocated buffer to contain @buffer_size bytes of output.
259 * Generate an application challenge that the client cannot control or
260 * predict, based on the TLS/IA inner secret.
262 * Return value: Returns 0 on success, or an negative error code.
265 gnutls_ia_generate_challenge (gnutls_session_t session
,
266 size_t buffer_size
, char *buffer
)
268 return _gnutls_ia_prf (session
,
269 sizeof (challenge_label
) - 1,
270 challenge_label
, 0, NULL
, buffer_size
, buffer
);
274 * gnutls_ia_extract_inner_secret:
275 * @session: is a #gnutls_session_t structure.
276 * @buffer: pre-allocated buffer to hold 48 bytes of inner secret.
278 * Copy the 48 bytes large inner secret into the specified buffer
280 * This function is typically used after the TLS/IA handshake has
281 * concluded. The TLS/IA inner secret can be used as input to a PRF
282 * to derive session keys. Do not use the inner secret directly as a
283 * session key, because for a resumed session that does not include an
284 * application phase, the inner secret will be identical to the inner
285 * secret in the original session. It is important to include, for
286 * example, the client and server randomness when deriving a sesssion
287 * key from the inner secret.
290 gnutls_ia_extract_inner_secret (gnutls_session_t session
, char *buffer
)
292 extension_priv_data_t epriv
;
297 _gnutls_ext_get_session_data (session
, GNUTLS_EXTENSION_INNER_APPLICATION
,
306 memcpy (buffer
, priv
->inner_secret
, GNUTLS_MASTER_SIZE
);
310 * gnutls_ia_endphase_send:
311 * @session: is a #gnutls_session_t structure.
312 * @final_p: Set iff this should signal the final phase.
314 * Send a TLS/IA end phase message.
316 * In the client, this should only be used to acknowledge an end phase
317 * message sent by the server.
319 * In the server, this can be called instead of gnutls_ia_send() if
320 * the server wishes to end an application phase.
322 * Return value: Return 0 on success, or an error code.
325 gnutls_ia_endphase_send (gnutls_session_t session
, int final_p
)
327 opaque local_checksum
[CHECKSUM_SIZE
];
328 int client
= session
->security_parameters
.entity
== GNUTLS_CLIENT
;
329 const char *label
= client
? client_finished_label
: server_finished_label
;
330 int size_of_label
= client
? sizeof (client_finished_label
) :
331 sizeof (server_finished_label
);
334 extension_priv_data_t epriv
;
338 _gnutls_ext_get_session_data (session
, GNUTLS_EXTENSION_INNER_APPLICATION
,
347 ret
= _gnutls_PRF (session
, priv
->inner_secret
,
348 GNUTLS_MASTER_SIZE
, label
, size_of_label
- 1,
349 /* XXX specification unclear on seed. */
350 "", 0, CHECKSUM_SIZE
, local_checksum
);
354 len
= _gnutls_send_inner_application
356 final_p
? GNUTLS_IA_FINAL_PHASE_FINISHED
:
357 GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED
, local_checksum
, CHECKSUM_SIZE
);
359 /* XXX Instead of calling this function over and over...?
360 * while (len == GNUTLS_E_AGAIN || len == GNUTLS_E_INTERRUPTED)
361 * len = _gnutls_io_write_flush(session);
374 * gnutls_ia_verify_endphase:
375 * @session: is a #gnutls_session_t structure.
376 * @checksum: 12-byte checksum data, received from gnutls_ia_recv().
378 * Verify TLS/IA end phase checksum data. If verification fails, the
379 * %GNUTLS_A_INNER_APPLICATION_VERIFICATION alert is sent to the other
382 * This function is called when gnutls_ia_recv() return
383 * %GNUTLS_E_WARNING_IA_IPHF_RECEIVED or
384 * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED.
386 * Return value: Return 0 on successful verification, or an error
387 * code. If the checksum verification of the end phase message fails,
388 * %GNUTLS_E_IA_VERIFY_FAILED is returned.
391 gnutls_ia_verify_endphase (gnutls_session_t session
, const char *checksum
)
393 char local_checksum
[CHECKSUM_SIZE
];
394 int client
= session
->security_parameters
.entity
== GNUTLS_CLIENT
;
395 const char *label
= client
? server_finished_label
: client_finished_label
;
396 int size_of_label
= client
? sizeof (server_finished_label
) :
397 sizeof (client_finished_label
);
399 extension_priv_data_t epriv
;
403 _gnutls_ext_get_session_data (session
, GNUTLS_EXTENSION_INNER_APPLICATION
,
412 ret
= _gnutls_PRF (session
, priv
->inner_secret
,
414 label
, size_of_label
- 1,
415 "", 0, CHECKSUM_SIZE
, local_checksum
);
422 if (memcmp (local_checksum
, checksum
, CHECKSUM_SIZE
) != 0)
424 ret
= gnutls_alert_send (session
, GNUTLS_AL_FATAL
,
425 GNUTLS_A_INNER_APPLICATION_VERIFICATION
);
432 return GNUTLS_E_IA_VERIFY_FAILED
;
440 * @session: is a #gnutls_session_t structure.
441 * @data: contains the data to send
442 * @sizeofdata: is the length of the data
444 * Send TLS/IA application payload data. This function has the
445 * similar semantics with send(). The only difference is that it
446 * accepts a GnuTLS session, and uses different error codes.
448 * The TLS/IA protocol is synchronous, so you cannot send more than
449 * one packet at a time. The client always send the first packet.
451 * To finish an application phase in the server, use
452 * gnutls_ia_endphase_send(). The client cannot end an application
453 * phase unilaterally; rather, a client is required to respond with an
454 * endphase of its own if gnutls_ia_recv indicates that the server has
457 * If the EINTR is returned by the internal push function (the default
458 * is send()} then %GNUTLS_E_INTERRUPTED will be returned. If
459 * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must call
460 * this function again, with the same parameters; alternatively you
461 * could provide a %NULL pointer for data, and 0 for size.
463 * Returns: The number of bytes sent, or a negative error code.
466 gnutls_ia_send (gnutls_session_t session
, const char *data
, size_t sizeofdata
)
470 len
= _gnutls_send_inner_application (session
,
471 GNUTLS_IA_APPLICATION_PAYLOAD
,
479 * @session: is a #gnutls_session_t structure.
480 * @data: the buffer that the data will be read into, must hold >= 12 bytes.
481 * @sizeofdata: the number of requested bytes, must be >= 12.
483 * Receive TLS/IA data. This function has the similar semantics with
484 * recv(). The only difference is that it accepts a GnuTLS session,
485 * and uses different error codes.
487 * If the server attempt to finish an application phase, this function
488 * will return %GNUTLS_E_WARNING_IA_IPHF_RECEIVED or
489 * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED. The caller should then invoke
490 * gnutls_ia_verify_endphase(), and if it runs the client side, also
491 * send an endphase message of its own using gnutls_ia_endphase_send.
493 * If EINTR is returned by the internal push function (the default is
494 * @code{recv()}) then GNUTLS_E_INTERRUPTED will be returned. If
495 * GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN is returned, you must call
496 * this function again, with the same parameters; alternatively you
497 * could provide a NULL pointer for data, and 0 for size.
499 * Returns: The number of bytes received. A negative error code is
500 * returned in case of an error. The
501 * %GNUTLS_E_WARNING_IA_IPHF_RECEIVED and
502 * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED errors are returned when an
503 * application phase finished message has been sent by the server.
506 gnutls_ia_recv (gnutls_session_t session
, char *data
, size_t sizeofdata
)
508 gnutls_ia_apptype_t msg_type
= 0;
511 len
= _gnutls_recv_inner_application (session
, &msg_type
, data
, sizeofdata
);
513 if (msg_type
== GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED
)
514 return GNUTLS_E_WARNING_IA_IPHF_RECEIVED
;
515 else if (msg_type
== GNUTLS_IA_FINAL_PHASE_FINISHED
)
516 return GNUTLS_E_WARNING_IA_FPHF_RECEIVED
;
521 /* XXX rewrite the following two functions as state machines, to
522 handle EAGAIN/EINTERRUPTED? just add more problems to callers,
526 _gnutls_ia_client_handshake (gnutls_session_t session
)
530 char tmp
[1024]; /* XXX */
533 const struct gnutls_ia_client_credentials_st
*cred
=
534 _gnutls_get_cred (session
->key
, GNUTLS_CRD_IA
, NULL
);
537 return GNUTLS_E_INTERNAL_ERROR
;
544 ret
= cred
->avp_func (session
, cred
->avp_ptr
,
545 buf
, buflen
, &avp
, &avplen
);
549 tmpret
= gnutls_alert_send (session
, GNUTLS_AL_FATAL
,
550 GNUTLS_A_INNER_APPLICATION_FAILURE
);
556 len
= gnutls_ia_send (session
, avp
, avplen
);
561 len
= gnutls_ia_recv (session
, tmp
, sizeof (tmp
));
562 if (len
== GNUTLS_E_WARNING_IA_IPHF_RECEIVED
||
563 len
== GNUTLS_E_WARNING_IA_FPHF_RECEIVED
)
565 ret
= gnutls_ia_verify_endphase (session
, tmp
);
569 ret
= gnutls_ia_endphase_send
570 (session
, len
== GNUTLS_E_WARNING_IA_FPHF_RECEIVED
);
575 if (len
== GNUTLS_E_WARNING_IA_IPHF_RECEIVED
)
581 else if (len
== GNUTLS_E_WARNING_IA_FPHF_RECEIVED
)
595 _gnutls_ia_server_handshake (gnutls_session_t session
)
597 gnutls_ia_apptype_t msg_type
;
601 const struct gnutls_ia_server_credentials_st
*cred
=
602 _gnutls_get_cred (session
->key
, GNUTLS_CRD_IA
, NULL
);
605 return GNUTLS_E_INTERNAL_ERROR
;
612 len
= gnutls_ia_recv (session
, buf
, sizeof (buf
));
613 if (len
== GNUTLS_E_WARNING_IA_IPHF_RECEIVED
||
614 len
== GNUTLS_E_WARNING_IA_FPHF_RECEIVED
)
616 ret
= gnutls_ia_verify_endphase (session
, buf
);
621 if (len
== GNUTLS_E_WARNING_IA_IPHF_RECEIVED
)
623 else if (len
== GNUTLS_E_WARNING_IA_FPHF_RECEIVED
)
632 ret
= cred
->avp_func (session
, cred
->avp_ptr
, buf
, len
, &avp
, &avplen
);
636 tmpret
= gnutls_alert_send (session
, GNUTLS_AL_FATAL
,
637 GNUTLS_A_INNER_APPLICATION_FAILURE
);
645 if (msg_type
!= GNUTLS_IA_APPLICATION_PAYLOAD
)
647 ret
= gnutls_ia_endphase_send (session
, msg_type
==
648 GNUTLS_IA_FINAL_PHASE_FINISHED
);
654 len
= gnutls_ia_send (session
, avp
, avplen
);
666 * gnutls_ia_handshake_p:
667 * @session: is a #gnutls_session_t structure.
669 * Predicate to be used after gnutls_handshake() to decide whether to
670 * invoke gnutls_ia_handshake(). Usable by both clients and servers.
672 * Return value: non-zero if TLS/IA handshake is expected, zero
676 gnutls_ia_handshake_p (gnutls_session_t session
)
678 extension_priv_data_t epriv
;
683 _gnutls_ext_get_session_data (session
, GNUTLS_EXTENSION_SERVER_NAME
,
692 /* Either local side or peer doesn't do TLS/IA: don't do IA */
694 if (!(priv
->flags
& IA_ENABLE
) || !(priv
->flags
& IA_PEER_ENABLE
))
697 /* Not resuming or we don't allow skipping on resumption locally: do IA */
699 if (!(priv
->flags
& IA_ALLOW_SKIP
) || !gnutls_session_is_resumed (session
))
702 /* If we're resuming and we and the peer both allow skipping on resumption:
705 return !(priv
->flags
& IA_PEER_ALLOW_SKIP
);
710 * gnutls_ia_handshake:
711 * @session: is a #gnutls_session_t structure.
713 * Perform a TLS/IA handshake. This should be called after
714 * gnutls_handshake() iff gnutls_ia_handshake_p().
716 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
717 * otherwise an error code is returned.
720 gnutls_ia_handshake (gnutls_session_t session
)
724 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
725 ret
= _gnutls_ia_client_handshake (session
);
727 ret
= _gnutls_ia_server_handshake (session
);
733 * gnutls_ia_allocate_client_credentials:
734 * @sc: is a pointer to a #gnutls_ia_server_credentials_t structure.
736 * This structure is complex enough to manipulate directly thus this
737 * helper function is provided in order to allocate it.
739 * Adding this credential to a session will enable TLS/IA, and will
740 * require an Application Phase after the TLS handshake (if the server
741 * support TLS/IA). Use gnutls_ia_enable() to toggle the TLS/IA mode.
743 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
744 * an error code is returned.
747 gnutls_ia_allocate_client_credentials (gnutls_ia_client_credentials_t
* sc
)
749 *sc
= gnutls_calloc (1, sizeof (**sc
));
752 return GNUTLS_E_MEMORY_ERROR
;
758 * gnutls_ia_free_client_credentials:
759 * @sc: is a #gnutls_ia_client_credentials_t structure.
761 * This structure is complex enough to manipulate directly thus this
762 * helper function is provided in order to free (deallocate) it.
766 gnutls_ia_free_client_credentials (gnutls_ia_client_credentials_t sc
)
772 * gnutls_ia_set_client_avp_function:
773 * @cred: is a #gnutls_ia_client_credentials_t structure.
774 * @avp_func: is the callback function
776 * Set the TLS/IA AVP callback handler used for the session.
778 * The AVP callback is called to process AVPs received from the
779 * server, and to get a new AVP to send to the server.
781 * The callback's function form is:
782 * int (*avp_func) (gnutls_session_t session, void *ptr,
783 * const char *last, size_t lastlen,
784 * char **next, size_t *nextlen);
786 * The @session parameter is the #gnutls_session_t structure
787 * corresponding to the current session. The @ptr parameter is the
788 * application hook pointer, set through
789 * gnutls_ia_set_client_avp_ptr(). The AVP received from the server
790 * is present in @last of @lastlen size, which will be %NULL on the
791 * first invocation. The newly allocated output AVP to send to the
792 * server should be placed in *@next of *@nextlen size.
794 * The callback may invoke gnutls_ia_permute_inner_secret() to mix any
795 * generated session keys with the TLS/IA inner secret.
797 * Return 0 (%GNUTLS_IA_APPLICATION_PAYLOAD) on success, or a negative
798 * error code to abort the TLS/IA handshake.
800 * Note that the callback must use allocate the @next parameter using
801 * gnutls_malloc(), because it is released via gnutls_free() by the
802 * TLS/IA handshake function.
806 gnutls_ia_set_client_avp_function (gnutls_ia_client_credentials_t cred
,
807 gnutls_ia_avp_func avp_func
)
809 cred
->avp_func
= avp_func
;
813 * gnutls_ia_set_client_avp_ptr:
814 * @cred: is a #gnutls_ia_client_credentials_t structure.
815 * @ptr: is the pointer
817 * Sets the pointer that will be provided to the TLS/IA callback
818 * function as the first argument.
821 gnutls_ia_set_client_avp_ptr (gnutls_ia_client_credentials_t cred
, void *ptr
)
827 * gnutls_ia_get_client_avp_ptr:
828 * @cred: is a #gnutls_ia_client_credentials_t structure.
830 * Returns the pointer that will be provided to the TLS/IA callback
831 * function as the first argument.
833 * Returns: The client callback data pointer.
836 gnutls_ia_get_client_avp_ptr (gnutls_ia_client_credentials_t cred
)
838 return cred
->avp_ptr
;
842 * gnutls_ia_allocate_server_credentials:
843 * @sc: is a pointer to a #gnutls_ia_server_credentials_t structure.
845 * This structure is complex enough to manipulate directly thus this
846 * helper function is provided in order to allocate it.
848 * Adding this credential to a session will enable TLS/IA, and will
849 * require an Application Phase after the TLS handshake (if the client
850 * support TLS/IA). Use gnutls_ia_enable() to toggle the TLS/IA mode.
852 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
853 * an error code is returned.
856 gnutls_ia_allocate_server_credentials (gnutls_ia_server_credentials_t
* sc
)
858 *sc
= gnutls_calloc (1, sizeof (**sc
));
861 return GNUTLS_E_MEMORY_ERROR
;
867 * gnutls_ia_free_server_credentials:
868 * @sc: is a #gnutls_ia_server_credentials_t structure.
870 * This structure is complex enough to manipulate directly thus this
871 * helper function is provided in order to free (deallocate) it.
875 gnutls_ia_free_server_credentials (gnutls_ia_server_credentials_t sc
)
881 * gnutls_ia_set_server_credentials_function:
882 * @cred: is a #gnutls_ia_server_credentials_t structure.
883 * @func: is the callback function
885 * Set the TLS/IA AVP callback handler used for the session.
887 * The callback's function form is:
888 * int (*avp_func) (gnutls_session_t session, void *ptr,
889 * const char *last, size_t lastlen,
890 * char **next, size_t *nextlen);
892 * The @session parameter is the #gnutls_session_t structure
893 * corresponding to the current session. The @ptr parameter is the
894 * application hook pointer, set through
895 * gnutls_ia_set_server_avp_ptr(). The AVP received from the client
896 * is present in @last of @lastlen size. The newly allocated output
897 * AVP to send to the client should be placed in *@next of *@nextlen
900 * The AVP callback is called to process incoming AVPs from the
901 * client, and to get a new AVP to send to the client. It can also be
902 * used to instruct the TLS/IA handshake to do go into the
903 * Intermediate or Final phases. It return a negative error code, or
904 * a #gnutls_ia_apptype_t message type.
906 * The callback may invoke gnutls_ia_permute_inner_secret() to mix any
907 * generated session keys with the TLS/IA inner secret.
909 * Specifically, return %GNUTLS_IA_APPLICATION_PAYLOAD (0) to send
910 * another AVP to the client, return
911 * %GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED (1) to indicate that an
912 * IntermediatePhaseFinished message should be sent, and return
913 * %GNUTLS_IA_FINAL_PHASE_FINISHED (2) to indicate that an
914 * FinalPhaseFinished message should be sent. In the last two cases,
915 * the contents of the @next and @nextlen parameter is not used.
917 * Note that the callback must use allocate the @next parameter using
918 * gnutls_malloc(), because it is released via gnutls_free() by the
919 * TLS/IA handshake function.
922 gnutls_ia_set_server_avp_function (gnutls_ia_server_credentials_t cred
,
923 gnutls_ia_avp_func avp_func
)
925 cred
->avp_func
= avp_func
;
929 * gnutls_ia_set_server_avp_ptr:
930 * @cred: is a #gnutls_ia_client_credentials_t structure.
931 * @ptr: is the pointer
933 * Sets the pointer that will be provided to the TLS/IA callback
934 * function as the first argument.
937 gnutls_ia_set_server_avp_ptr (gnutls_ia_server_credentials_t cred
, void *ptr
)
943 * gnutls_ia_get_server_avp_ptr:
944 * @cred: is a #gnutls_ia_client_credentials_t structure.
946 * Returns the pointer that will be provided to the TLS/IA callback
947 * function as the first argument.
949 * Returns: The server callback data pointer.
952 gnutls_ia_get_server_avp_ptr (gnutls_ia_server_credentials_t cred
)
954 return cred
->avp_ptr
;
959 * @session: is a #gnutls_session_t structure.
960 * @allow_skip_on_resume: non-zero if local party allows one to skip the
961 * TLS/IA application phases for a resumed session.
963 * Specify whether we must advertise support for the TLS/IA extension
964 * during the handshake.
966 * At the client side, we always advertise TLS/IA if gnutls_ia_enable
967 * was called before the handshake; at the server side, we also
968 * require that the client has advertised that it wants to run TLS/IA
969 * before including the advertisement, as required by the protocol.
971 * Similarly, at the client side we always advertise that we allow
972 * TLS/IA to be skipped for resumed sessions if @allow_skip_on_resume
973 * is non-zero; at the server side, we also require that the session
974 * is indeed resumable and that the client has also advertised that it
975 * allows TLS/IA to be skipped for resumed sessions.
977 * After the TLS handshake, call gnutls_ia_handshake_p() to find out
978 * whether both parties agreed to do a TLS/IA handshake, before
979 * calling gnutls_ia_handshake() or one of the lower level gnutls_ia_*
983 gnutls_ia_enable (gnutls_session_t session
, int allow_skip_on_resume
)
985 extension_priv_data_t epriv
;
988 priv
= gnutls_calloc (1, sizeof (*priv
));
997 priv
->flags
|= IA_ENABLE
;
998 if (allow_skip_on_resume
)
999 priv
->flags
|= IA_ALLOW_SKIP
;
1001 _gnutls_ext_set_session_data (session
, GNUTLS_EXTENSION_INNER_APPLICATION
,