Drop AC_CANONICAL_TARGET, unused.
[gnutls.git] / libextra / gnutls_ia.c
blobdac419858560ba36c026497695d62e46ee15e3b7
1 /*
2 * Copyright (C) 2005, 2006, 2008 Free Software Foundation
4 * Author: Simon Josefsson
6 * This file is part of GNUTLS-EXTRA.
8 * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * GNUTLS-EXTRA is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "gnutls_int.h"
23 #include "gnutls_record.h"
24 #include "gnutls_errors.h"
25 #include "gnutls_num.h"
26 #include "gnutls_state.h"
28 #define CHECKSUM_SIZE 12
30 struct gnutls_ia_client_credentials_st
32 gnutls_ia_avp_func avp_func;
33 void *avp_ptr;
36 struct gnutls_ia_server_credentials_st
38 gnutls_ia_avp_func avp_func;
39 void *avp_ptr;
42 static const char server_finished_label[] = "server phase finished";
43 static const char client_finished_label[] = "client phase finished";
44 static const char inner_permutation_label[] = "inner secret permutation";
45 static const char challenge_label[] = "inner application challenge";
48 * The TLS/IA packet is the InnerApplication token, described as
49 * follows in draft-funk-tls-inner-application-extension-01.txt:
51 * enum {
52 * application_payload(0), intermediate_phase_finished(1),
53 * final_phase_finished(2), (255)
54 * } InnerApplicationType;
56 * struct {
57 * InnerApplicationType msg_type;
58 * uint24 length;
59 * select (InnerApplicationType) {
60 * case application_payload: ApplicationPayload;
61 * case intermediate_phase_finished: IntermediatePhaseFinished;
62 * case final_phase_finished: FinalPhaseFinished;
63 * } body;
64 * } InnerApplication;
68 /* Send TLS/IA data. If data==NULL && sizeofdata==NULL, then the last
69 send was interrupted for some reason, and then we try to send it
70 again. Returns the number of bytes sent, or an error code. If
71 this return E_AGAIN and E_INTERRUPTED, call this function again
72 with data==NULL&&sizeofdata=0NULL until it returns successfully. */
73 static ssize_t
74 _gnutls_send_inner_application (gnutls_session_t session,
75 gnutls_ia_apptype_t msg_type,
76 const char *data, size_t sizeofdata)
78 opaque *p = NULL;
79 size_t plen = 0;
80 ssize_t len;
82 if (data != NULL)
84 plen = sizeofdata + 4;
85 p = gnutls_malloc (plen);
86 if (!p)
88 gnutls_assert ();
89 return GNUTLS_E_MEMORY_ERROR;
92 *(unsigned char *) p = (unsigned char) (msg_type & 0xFF);
93 _gnutls_write_uint24 (sizeofdata, p + 1);
94 memcpy (p + 4, data, sizeofdata);
97 len = _gnutls_send_int (session, GNUTLS_INNER_APPLICATION, -1, p, plen);
99 if (p)
100 gnutls_free (p);
102 return len;
105 /* Receive TLS/IA data. Store received TLS/IA message type in
106 *MSG_TYPE, and the data in DATA of max SIZEOFDATA size. Return the
107 number of bytes read, or an error code. */
108 static ssize_t
109 _gnutls_recv_inner_application (gnutls_session_t session,
110 gnutls_ia_apptype_t * msg_type,
111 opaque * data, size_t sizeofdata)
113 ssize_t len;
114 opaque pkt[4];
116 len = _gnutls_recv_int (session, GNUTLS_INNER_APPLICATION, -1, pkt, 4);
117 if (len != 4)
119 gnutls_assert ();
120 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
123 *msg_type = pkt[0];
124 len = _gnutls_read_uint24 (&pkt[1]);
126 if (*msg_type != GNUTLS_IA_APPLICATION_PAYLOAD && len != CHECKSUM_SIZE)
128 gnutls_assert ();
129 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
132 if (sizeofdata < len)
134 /* XXX push back pkt to IA buffer? */
135 gnutls_assert ();
136 return GNUTLS_E_SHORT_MEMORY_BUFFER;
139 if (len > 0)
141 int tmplen = len;
143 len = _gnutls_recv_int (session, GNUTLS_INNER_APPLICATION, -1,
144 data, tmplen);
145 if (len != tmplen)
147 gnutls_assert ();
148 /* XXX Correct? */
149 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
153 return len;
156 /* Apply the TLS PRF using the TLS/IA inner secret as keying material,
157 where the seed is the client random concatenated with the server
158 random concatenated EXTRA of EXTRA_SIZE length (which can be NULL/0
159 respectively). LABEL and LABEL_SIZE is used as the label. The
160 result is placed in pre-allocated OUT of OUTSIZE length. */
161 static int
162 _gnutls_ia_prf (gnutls_session_t session,
163 size_t label_size,
164 const char *label,
165 size_t extra_size,
166 const char *extra, size_t outsize, opaque * out)
168 int ret;
169 opaque *seed;
170 size_t seedsize = 2 * TLS_RANDOM_SIZE + extra_size;
172 seed = gnutls_malloc (seedsize);
173 if (!seed)
175 gnutls_assert ();
176 return GNUTLS_E_MEMORY_ERROR;
179 memcpy (seed, session->security_parameters.server_random, TLS_RANDOM_SIZE);
180 memcpy (seed + TLS_RANDOM_SIZE, session->security_parameters.client_random,
181 TLS_RANDOM_SIZE);
182 memcpy (seed + 2 * TLS_RANDOM_SIZE, extra, extra_size);
184 ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
185 TLS_MASTER_SIZE,
186 label, label_size, seed, seedsize, outsize, out);
188 gnutls_free (seed);
190 return ret;
194 * gnutls_ia_permute_inner_secret:
195 * @session: is a #gnutls_session_t structure.
196 * @session_keys_size: Size of generated session keys (0 if none).
197 * @session_keys: Generated session keys, used to permute inner secret
198 * (NULL if none).
200 * Permute the inner secret using the generated session keys.
202 * This can be called in the TLS/IA AVP callback to mix any generated
203 * session keys with the TLS/IA inner secret.
205 * Return value: Return zero on success, or a negative error code.
208 gnutls_ia_permute_inner_secret (gnutls_session_t session,
209 size_t session_keys_size,
210 const char *session_keys)
212 return _gnutls_ia_prf (session,
213 sizeof (inner_permutation_label) - 1,
214 inner_permutation_label,
215 session_keys_size,
216 session_keys,
217 TLS_RANDOM_SIZE,
218 session->security_parameters.inner_secret);
222 * gnutls_ia_generate_challenge:
223 * @session: is a #gnutls_session_t structure.
224 * @buffer_size: size of output buffer.
225 * @buffer: pre-allocated buffer to contain @buffer_size bytes of output.
227 * Generate an application challenge that the client cannot control or
228 * predict, based on the TLS/IA inner secret.
230 * Return value: Returns 0 on success, or an negative error code.
233 gnutls_ia_generate_challenge (gnutls_session_t session,
234 size_t buffer_size, char *buffer)
236 return _gnutls_ia_prf (session,
237 sizeof (challenge_label) - 1,
238 challenge_label, 0, NULL, buffer_size, buffer);
242 * gnutls_ia_extract_inner_secret:
243 * @session: is a #gnutls_session_t structure.
244 * @buffer: pre-allocated buffer to hold 48 bytes of inner secret.
246 * Copy the 48 bytes large inner secret into the specified buffer
248 * This function is typically used after the TLS/IA handshake has
249 * concluded. The TLS/IA inner secret can be used as input to a PRF
250 * to derive session keys. Do not use the inner secret directly as a
251 * session key, because for a resumed session that does not include an
252 * application phase, the inner secret will be identical to the inner
253 * secret in the original session. It is important to include, for
254 * example, the client and server randomness when deriving a sesssion
255 * key from the inner secret.
257 void
258 gnutls_ia_extract_inner_secret (gnutls_session_t session, char *buffer)
260 memcpy (buffer, session->security_parameters.inner_secret, TLS_MASTER_SIZE);
264 * gnutls_ia_endphase_send:
265 * @session: is a #gnutls_session_t structure.
266 * @final_p: Set iff this should signal the final phase.
268 * Send a TLS/IA end phase message.
270 * In the client, this should only be used to acknowledge an end phase
271 * message sent by the server.
273 * In the server, this can be called instead of gnutls_ia_send() if
274 * the server wishes to end an application phase.
276 * Return value: Return 0 on success, or an error code.
279 gnutls_ia_endphase_send (gnutls_session_t session, int final_p)
281 opaque local_checksum[CHECKSUM_SIZE];
282 int client = session->security_parameters.entity == GNUTLS_CLIENT;
283 const char *label = client ? client_finished_label : server_finished_label;
284 int size_of_label = client ? sizeof (client_finished_label) :
285 sizeof (server_finished_label);
286 ssize_t len;
287 int ret;
289 ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
290 TLS_MASTER_SIZE, label, size_of_label - 1,
291 /* XXX specification unclear on seed. */
292 "", 0, CHECKSUM_SIZE, local_checksum);
293 if (ret < 0)
294 return ret;
296 len = _gnutls_send_inner_application
297 (session,
298 final_p ? GNUTLS_IA_FINAL_PHASE_FINISHED :
299 GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED, local_checksum, CHECKSUM_SIZE);
301 /* XXX Instead of calling this function over and over...?
302 * while (len == GNUTLS_E_AGAIN || len == GNUTLS_E_INTERRUPTED)
303 * len = _gnutls_io_write_flush(session);
306 if (len < 0)
308 gnutls_assert ();
309 return len;
312 return 0;
316 * gnutls_ia_verify_endphase:
317 * @session: is a #gnutls_session_t structure.
318 * @checksum: 12-byte checksum data, received from gnutls_ia_recv().
320 * Verify TLS/IA end phase checksum data. If verification fails, the
321 * %GNUTLS_A_INNER_APPLICATION_VERIFICATION alert is sent to the other
322 * sie.
324 * This function is called when gnutls_ia_recv() return
325 * %GNUTLS_E_WARNING_IA_IPHF_RECEIVED or
326 * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED.
328 * Return value: Return 0 on successful verification, or an error
329 * code. If the checksum verification of the end phase message fails,
330 * %GNUTLS_E_IA_VERIFY_FAILED is returned.
333 gnutls_ia_verify_endphase (gnutls_session_t session, const char *checksum)
335 char local_checksum[CHECKSUM_SIZE];
336 int client = session->security_parameters.entity == GNUTLS_CLIENT;
337 const char *label = client ? server_finished_label : client_finished_label;
338 int size_of_label = client ? sizeof (server_finished_label) :
339 sizeof (client_finished_label);
340 int ret;
342 ret = _gnutls_PRF (session, session->security_parameters.inner_secret,
343 TLS_MASTER_SIZE,
344 label, size_of_label - 1,
345 "", 0, CHECKSUM_SIZE, local_checksum);
346 if (ret < 0)
348 gnutls_assert ();
349 return ret;
352 if (memcmp (local_checksum, checksum, CHECKSUM_SIZE) != 0)
354 ret = gnutls_alert_send (session, GNUTLS_AL_FATAL,
355 GNUTLS_A_INNER_APPLICATION_VERIFICATION);
356 if (ret < 0)
358 gnutls_assert ();
359 return ret;
362 return GNUTLS_E_IA_VERIFY_FAILED;
365 return 0;
369 * gnutls_ia_send: Send peer the specified TLS/IA data.
370 * @session: is a #gnutls_session_t structure.
371 * @data: contains the data to send
372 * @sizeofdata: is the length of the data
374 * Send TLS/IA application payload data. This function has the
375 * similar semantics with send(). The only difference is that is
376 * accepts a GNUTLS session, and uses different error codes.
378 * The TLS/IA protocol is synchronous, so you cannot send more than
379 * one packet at a time. The client always send the first packet.
381 * To finish an application phase in the server, use
382 * gnutls_ia_endphase_send(). The client cannot end an application
383 * phase unilaterally; rather, a client is required to respond with an
384 * endphase of its own if gnutls_ia_recv indicates that the server has
385 * sent one.
387 * If the EINTR is returned by the internal push function (the default
388 * is send()} then %GNUTLS_E_INTERRUPTED will be returned. If
389 * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must call
390 * this function again, with the same parameters; alternatively you
391 * could provide a %NULL pointer for data, and 0 for size.
393 * Returns: The number of bytes sent, or a negative error code.
395 ssize_t
396 gnutls_ia_send (gnutls_session_t session, const char *data, size_t sizeofdata)
398 ssize_t len;
400 len = _gnutls_send_inner_application (session,
401 GNUTLS_IA_APPLICATION_PAYLOAD,
402 data, sizeofdata);
404 return len;
408 * gnutls_ia_recv - read data from the TLS/IA protocol
409 * @session: is a #gnutls_session_t structure.
410 * @data: the buffer that the data will be read into, must hold >= 12 bytes.
411 * @sizeofdata: the number of requested bytes, must be >= 12.
413 * Receive TLS/IA data. This function has the similar semantics with
414 * recv(). The only difference is that is accepts a GNUTLS session,
415 * and uses different error codes.
417 * If the server attempt to finish an application phase, this function
418 * will return %GNUTLS_E_WARNING_IA_IPHF_RECEIVED or
419 * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED. The caller should then invoke
420 * gnutls_ia_verify_endphase(), and if it runs the client side, also
421 * send an endphase message of its own using gnutls_ia_endphase_send.
423 * If EINTR is returned by the internal push function (the default is
424 * @code{recv()}) then GNUTLS_E_INTERRUPTED will be returned. If
425 * GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN is returned, you must call
426 * this function again, with the same parameters; alternatively you
427 * could provide a NULL pointer for data, and 0 for size.
429 * Returns: The number of bytes received. A negative error code is
430 * returned in case of an error. The
431 * %GNUTLS_E_WARNING_IA_IPHF_RECEIVED and
432 * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED errors are returned when an
433 * application phase finished message has been sent by the server.
435 ssize_t
436 gnutls_ia_recv (gnutls_session_t session, char *data, size_t sizeofdata)
438 gnutls_ia_apptype_t msg_type = 0;
439 ssize_t len;
441 len = _gnutls_recv_inner_application (session, &msg_type, data, sizeofdata);
443 if (msg_type == GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED)
444 return GNUTLS_E_WARNING_IA_IPHF_RECEIVED;
445 else if (msg_type == GNUTLS_IA_FINAL_PHASE_FINISHED)
446 return GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
448 return len;
451 /* XXX rewrite the following two functions as state machines, to
452 handle EAGAIN/EINTERRUPTED? just add more problems to callers,
453 though. */
456 _gnutls_ia_client_handshake (gnutls_session_t session)
458 char *buf = NULL;
459 size_t buflen = 0;
460 char tmp[1024]; /* XXX */
461 ssize_t len;
462 int ret;
463 const struct gnutls_ia_client_credentials_st *cred =
464 _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
466 if (cred == NULL)
467 return GNUTLS_E_INTERNAL_ERROR;
469 while (1)
471 char *avp;
472 size_t avplen;
474 ret = cred->avp_func (session, cred->avp_ptr,
475 buf, buflen, &avp, &avplen);
476 if (ret)
478 int tmpret;
479 tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL,
480 GNUTLS_A_INNER_APPLICATION_FAILURE);
481 if (tmpret < 0)
482 gnutls_assert ();
483 return ret;
486 len = gnutls_ia_send (session, avp, avplen);
487 gnutls_free (avp);
488 if (len < 0)
489 return len;
491 len = gnutls_ia_recv (session, tmp, sizeof (tmp));
492 if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
493 len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
495 ret = gnutls_ia_verify_endphase (session, tmp);
496 if (ret < 0)
497 return ret;
499 ret = gnutls_ia_endphase_send
500 (session, len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED);
501 if (ret < 0)
502 return ret;
505 if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED)
507 buf = NULL;
508 buflen = 0;
509 continue;
511 else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
512 break;
514 if (len < 0)
515 return len;
517 buflen = len;
518 buf = tmp;
521 return 0;
525 _gnutls_ia_server_handshake (gnutls_session_t session)
527 gnutls_ia_apptype_t msg_type;
528 ssize_t len;
529 char buf[1024];
530 int ret;
531 const struct gnutls_ia_server_credentials_st *cred =
532 _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL);
534 if (cred == NULL)
535 return GNUTLS_E_INTERNAL_ERROR;
539 char *avp;
540 size_t avplen;
542 len = gnutls_ia_recv (session, buf, sizeof (buf));
543 if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
544 len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
546 ret = gnutls_ia_verify_endphase (session, buf);
547 if (ret < 0)
548 return ret;
551 if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED)
552 continue;
553 else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)
554 break;
556 if (len < 0)
557 return len;
559 avp = NULL;
560 avplen = 0;
562 ret = cred->avp_func (session, cred->avp_ptr, buf, len, &avp, &avplen);
563 if (ret < 0)
565 int tmpret;
566 tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL,
567 GNUTLS_A_INNER_APPLICATION_FAILURE);
568 if (tmpret < 0)
569 gnutls_assert ();
570 return ret;
573 msg_type = ret;
575 if (msg_type != GNUTLS_IA_APPLICATION_PAYLOAD)
577 ret = gnutls_ia_endphase_send (session, msg_type ==
578 GNUTLS_IA_FINAL_PHASE_FINISHED);
579 if (ret < 0)
580 return ret;
582 else
584 len = gnutls_ia_send (session, avp, avplen);
585 gnutls_free (avp);
586 if (len < 0)
587 return len;
590 while (1);
592 return 0;
596 * gnutls_ia_handshake_p:
597 * @session: is a #gnutls_session_t structure.
599 * Predicate to be used after gnutls_handshake() to decide whether to
600 * invoke gnutls_ia_handshake(). Usable by both clients and servers.
602 * Return value: non-zero if TLS/IA handshake is expected, zero
603 * otherwise.
606 gnutls_ia_handshake_p (gnutls_session_t session)
608 tls_ext_st *ext = &session->security_parameters.extensions;
610 /* Either local side or peer doesn't do TLS/IA: don't do IA */
612 if (!ext->gnutls_ia_enable || !ext->gnutls_ia_peer_enable)
613 return 0;
615 /* Not resuming or we don't allow skipping on resumption locally: do IA */
617 if (!ext->gnutls_ia_allowskip || !gnutls_session_is_resumed (session))
618 return 1;
620 /* If we're resuming and we and the peer both allow skipping on resumption:
621 * don't do IA */
623 return !ext->gnutls_ia_peer_allowskip;
628 * gnutls_ia_handshake:
629 * @session: is a #gnutls_session_t structure.
631 * Perform a TLS/IA handshake. This should be called after
632 * gnutls_handshake() iff gnutls_ia_handshake_p().
634 * Return 0 on success, or an error code.
637 gnutls_ia_handshake (gnutls_session_t session)
639 int ret;
641 if (session->security_parameters.entity == GNUTLS_CLIENT)
642 ret = _gnutls_ia_client_handshake (session);
643 else
644 ret = _gnutls_ia_server_handshake (session);
646 return ret;
650 * gnutls_ia_allocate_client_credentials - Used to allocate an gnutls_ia_server_credentials_t structure
651 * @sc: is a pointer to an #gnutls_ia_server_credentials_t structure.
653 * This structure is complex enough to manipulate directly thus this
654 * helper function is provided in order to allocate it.
656 * Adding this credential to a session will enable TLS/IA, and will
657 * require an Application Phase after the TLS handshake (if the server
658 * support TLS/IA). Use gnutls_ia_require_inner_phase() to toggle the
659 * TLS/IA mode.
661 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
662 * an error code is returned.
665 gnutls_ia_allocate_client_credentials (gnutls_ia_client_credentials_t * sc)
667 *sc = gnutls_calloc (1, sizeof (**sc));
669 if (*sc == NULL)
670 return GNUTLS_E_MEMORY_ERROR;
672 return 0;
676 * gnutls_ia_free_client_credentials - Used to free an allocated #gnutls_ia_client_credentials_t structure
677 * @sc: is an #gnutls_ia_client_credentials_t structure.
679 * This structure is complex enough to manipulate directly thus this
680 * helper function is provided in order to free (deallocate) it.
683 void
684 gnutls_ia_free_client_credentials (gnutls_ia_client_credentials_t sc)
686 gnutls_free (sc);
690 * gnutls_ia_set_client_avp_function - Used to set a AVP callback
691 * @cred: is a #gnutls_ia_client_credentials_t structure.
692 * @avp_func: is the callback function
694 * Set the TLS/IA AVP callback handler used for the session.
696 * The AVP callback is called to process AVPs received from the
697 * server, and to get a new AVP to send to the server.
699 * The callback's function form is:
700 * int (*avp_func) (gnutls_session_t session, void *ptr,
701 * const char *last, size_t lastlen,
702 * char **next, size_t *nextlen);
704 * The @session parameter is the #gnutls_session_t structure
705 * corresponding to the current session. The @ptr parameter is the
706 * application hook pointer, set through
707 * gnutls_ia_set_client_avp_ptr(). The AVP received from the server
708 * is present in @last of @lastlen size, which will be %NULL on the
709 * first invocation. The newly allocated output AVP to send to the
710 * server should be placed in *@next of *@nextlen size.
712 * The callback may invoke gnutls_ia_permute_inner_secret() to mix any
713 * generated session keys with the TLS/IA inner secret.
715 * Return 0 (%GNUTLS_IA_APPLICATION_PAYLOAD) on success, or a negative
716 * error code to abort the TLS/IA handshake.
718 * Note that the callback must use allocate the @next parameter using
719 * gnutls_malloc(), because it is released via gnutls_free() by the
720 * TLS/IA handshake function.
723 void
724 gnutls_ia_set_client_avp_function (gnutls_ia_client_credentials_t cred,
725 gnutls_ia_avp_func avp_func)
727 cred->avp_func = avp_func;
731 * gnutls_ia_set_client_avp_ptr - Sets a pointer to be sent to TLS/IA callback
732 * @cred: is a #gnutls_ia_client_credentials_t structure.
733 * @ptr: is the pointer
735 * Sets the pointer that will be provided to the TLS/IA callback
736 * function as the first argument.
738 void
739 gnutls_ia_set_client_avp_ptr (gnutls_ia_client_credentials_t cred, void *ptr)
741 cred->avp_ptr = ptr;
745 * gnutls_ia_get_client_avp_ptr - Returns the pointer which is sent to TLS/IA callback
746 * @cred: is a #gnutls_ia_client_credentials_t structure.
748 * Returns the pointer that will be provided to the TLS/IA callback
749 * function as the first argument.
751 * Returns: The client callback data pointer.
753 void *
754 gnutls_ia_get_client_avp_ptr (gnutls_ia_client_credentials_t cred)
756 return cred->avp_ptr;
760 * gnutls_ia_allocate_server_credentials - Used to allocate an gnutls_ia_server_credentials_t structure
761 * @sc: is a pointer to an #gnutls_ia_server_credentials_t structure.
763 * This structure is complex enough to manipulate directly thus this
764 * helper function is provided in order to allocate it.
766 * Adding this credential to a session will enable TLS/IA, and will
767 * require an Application Phase after the TLS handshake (if the client
768 * support TLS/IA). Use gnutls_ia_require_inner_phase() to toggle the
769 * TLS/IA mode.
771 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
772 * an error code is returned.
775 gnutls_ia_allocate_server_credentials (gnutls_ia_server_credentials_t * sc)
777 *sc = gnutls_calloc (1, sizeof (**sc));
779 if (*sc == NULL)
780 return GNUTLS_E_MEMORY_ERROR;
782 return 0;
786 * gnutls_ia_free_server_credentials - Used to free an allocated #gnutls_ia_server_credentials_t structure
787 * @sc: is an #gnutls_ia_server_credentials_t structure.
789 * This structure is complex enough to manipulate directly thus this
790 * helper function is provided in order to free (deallocate) it.
793 void
794 gnutls_ia_free_server_credentials (gnutls_ia_server_credentials_t sc)
796 gnutls_free (sc);
800 * gnutls_ia_set_server_credentials_function - Used to set a AVP callback
801 * @cred: is a #gnutls_ia_server_credentials_t structure.
802 * @func: is the callback function
804 * Set the TLS/IA AVP callback handler used for the session.
806 * The callback's function form is:
807 * int (*avp_func) (gnutls_session_t session, void *ptr,
808 * const char *last, size_t lastlen,
809 * char **next, size_t *nextlen);
811 * The @session parameter is the #gnutls_session_t structure
812 * corresponding to the current session. The @ptr parameter is the
813 * application hook pointer, set through
814 * gnutls_ia_set_server_avp_ptr(). The AVP received from the client
815 * is present in @last of @lastlen size. The newly allocated output
816 * AVP to send to the client should be placed in *@next of *@nextlen
817 * size.
819 * The AVP callback is called to process incoming AVPs from the
820 * client, and to get a new AVP to send to the client. It can also be
821 * used to instruct the TLS/IA handshake to do go into the
822 * Intermediate or Final phases. It return a negative error code, or
823 * an #gnutls_ia_apptype_t message type.
825 * The callback may invoke gnutls_ia_permute_inner_secret() to mix any
826 * generated session keys with the TLS/IA inner secret.
828 * Specifically, return %GNUTLS_IA_APPLICATION_PAYLOAD (0) to send
829 * another AVP to the client, return
830 * %GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED (1) to indicate that an
831 * IntermediatePhaseFinished message should be sent, and return
832 * %GNUTLS_IA_FINAL_PHASE_FINISHED (2) to indicate that an
833 * FinalPhaseFinished message should be sent. In the last two cases,
834 * the contents of the @next and @nextlen parameter is not used.
836 * Note that the callback must use allocate the @next parameter using
837 * gnutls_malloc(), because it is released via gnutls_free() by the
838 * TLS/IA handshake function.
840 void
841 gnutls_ia_set_server_avp_function (gnutls_ia_server_credentials_t cred,
842 gnutls_ia_avp_func avp_func)
844 cred->avp_func = avp_func;
848 * gnutls_ia_set_server_avp_ptr - Sets a pointer to be sent to TLS/IA callback
849 * @cred: is a #gnutls_ia_client_credentials_t structure.
850 * @ptr: is the pointer
852 * Sets the pointer that will be provided to the TLS/IA callback
853 * function as the first argument.
855 void
856 gnutls_ia_set_server_avp_ptr (gnutls_ia_server_credentials_t cred, void *ptr)
858 cred->avp_ptr = ptr;
862 * gnutls_ia_get_server_avp_ptr - Returns the pointer which is sent to TLS/IA callback
863 * @cred: is a #gnutls_ia_client_credentials_t structure.
865 * Returns the pointer that will be provided to the TLS/IA callback
866 * function as the first argument.
868 * Returns: The server callback data pointer.
870 void *
871 gnutls_ia_get_server_avp_ptr (gnutls_ia_server_credentials_t cred)
873 return cred->avp_ptr;
877 * gnutls_ia_enable - Indicate willingness for TLS/IA application phases
878 * @session: is a #gnutls_session_t structure.
879 * @allow_skip_on_resume: non-zero if local party allows to skip the
880 * TLS/IA application phases for a resumed session.
882 * Specify whether we must advertise support for the TLS/IA extension
883 * during the handshake.
885 * At the client side, we always advertise TLS/IA if gnutls_ia_enable
886 * was called before the handshake; at the server side, we also
887 * require that the client has advertised that it wants to run TLS/IA
888 * before including the advertisement, as required by the protocol.
890 * Similarly, at the client side we always advertise that we allow
891 * TLS/IA to be skipped for resumed sessions if @allow_skip_on_resume
892 * is non-zero; at the server side, we also require that the session
893 * is indeed resumable and that the client has also advertised that it
894 * allows TLS/IA to be skipped for resumed sessions.
896 * After the TLS handshake, call gnutls_ia_handshake_p() to find out
897 * whether both parties agreed to do a TLS/IA handshake, before
898 * calling gnutls_ia_handshake() or one of the lower level gnutls_ia_*
899 * functions.
901 void
902 gnutls_ia_enable (gnutls_session_t session, int allow_skip_on_resume)
904 session->security_parameters.extensions.gnutls_ia_enable = 1;
905 session->security_parameters.extensions.gnutls_ia_allowskip =
906 allow_skip_on_resume;