2 * QEMU crypto TLS session support
4 * Copyright (c) 2015 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #ifndef QCRYPTO_TLSSESSION_H
22 #define QCRYPTO_TLSSESSION_H
24 #include "crypto/tlscreds.h"
29 * The QCryptoTLSSession object encapsulates the
30 * logic to integrate with a TLS providing library such
31 * as GNUTLS, to setup and run TLS sessions.
33 * The API is designed such that it has no assumption about
34 * the type of transport it is running over. It may be a
35 * traditional TCP socket, or something else entirely. The
36 * only requirement is a full-duplex stream of some kind.
39 * <title>Using TLS session objects</title>
41 * static ssize_t mysock_send(const char *buf, size_t len,
44 * int fd = GPOINTER_TO_INT(opaque);
46 * return write(*fd, buf, len);
49 * static ssize_t mysock_recv(const char *buf, size_t len,
52 * int fd = GPOINTER_TO_INT(opaque);
54 * return read(*fd, buf, len);
57 * static int mysock_run_tls(int sockfd,
58 * QCryptoTLSCreds *creds,
61 * QCryptoTLSSession *sess;
63 * sess = qcrypto_tls_session_new(creds,
66 * QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
72 * qcrypto_tls_session_set_callbacks(sess,
75 * GINT_TO_POINTER(fd));
78 * if (qcrypto_tls_session_handshake(sess, errp) < 0) {
79 * qcrypto_tls_session_free(sess);
83 * switch(qcrypto_tls_session_get_handshake_status(sess)) {
84 * case QCRYPTO_TLS_HANDSHAKE_COMPLETE:
85 * if (qcrypto_tls_session_check_credentials(sess, errp) < )) {
86 * qcrypto_tls_session_free(sess);
90 * case QCRYPTO_TLS_HANDSHAKE_RECVING:
91 * ...wait for GIO_IN event on fd...
93 * case QCRYPTO_TLS_HANDSHAKE_SENDING:
94 * ...wait for GIO_OUT event on fd...
100 * ....send/recv payload data on sess...
102 * qcrypto_tls_session_free(sess):
108 typedef struct QCryptoTLSSession QCryptoTLSSession
;
112 * qcrypto_tls_session_new:
113 * @creds: pointer to a TLS credentials object
114 * @hostname: optional hostname to validate
115 * @aclname: optional ACL to validate peer credentials against
116 * @endpoint: role of the TLS session, client or server
117 * @errp: pointer to a NULL-initialized error object
119 * Create a new TLS session object that will be used to
120 * negotiate a TLS session over an arbitrary data channel.
121 * The session object can operate as either the server or
122 * client, according to the value of the @endpoint argument.
124 * For clients, the @hostname parameter should hold the full
125 * unmodified hostname as requested by the user. This will
126 * be used to verify the against the hostname reported in
127 * the server's credentials (aka x509 certificate).
129 * The @aclname parameter (optionally) specifies the name
130 * of an access control list that will be used to validate
131 * the peer's credentials. For x509 credentials, the ACL
132 * will be matched against the CommonName shown in the peer's
133 * certificate. If the session is acting as a server, setting
134 * an ACL will require that the client provide a validate
135 * x509 client certificate.
137 * After creating the session object, the I/O callbacks
138 * must be set using the qcrypto_tls_session_set_callbacks()
139 * method. A TLS handshake sequence must then be completed
140 * using qcrypto_tls_session_handshake(), before payload
141 * data is permitted to be sent/received.
143 * The session object must be released by calling
144 * qcrypto_tls_session_free() when no longer required
146 * Returns: a TLS session object, or NULL on error.
148 QCryptoTLSSession
*qcrypto_tls_session_new(QCryptoTLSCreds
*creds
,
149 const char *hostname
,
151 QCryptoTLSCredsEndpoint endpoint
,
155 * qcrypto_tls_session_free:
156 * @sess: the TLS session object
158 * Release all memory associated with the TLS session
159 * object previously allocated by qcrypto_tls_session_new()
161 void qcrypto_tls_session_free(QCryptoTLSSession
*sess
);
163 G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoTLSSession
, qcrypto_tls_session_free
)
166 * qcrypto_tls_session_check_credentials:
167 * @sess: the TLS session object
168 * @errp: pointer to a NULL-initialized error object
170 * Validate the peer's credentials after a successful
171 * TLS handshake. It is an error to call this before
172 * qcrypto_tls_session_get_handshake_status() returns
173 * QCRYPTO_TLS_HANDSHAKE_COMPLETE
175 * Returns 0 if the credentials validated, -1 on error
177 int qcrypto_tls_session_check_credentials(QCryptoTLSSession
*sess
,
180 typedef ssize_t (*QCryptoTLSSessionWriteFunc
)(const char *buf
,
183 typedef ssize_t (*QCryptoTLSSessionReadFunc
)(char *buf
,
188 * qcrypto_tls_session_set_callbacks:
189 * @sess: the TLS session object
190 * @writeFunc: callback for sending data
191 * @readFunc: callback to receiving data
192 * @opaque: data to pass to callbacks
194 * Sets the callback functions that are to be used for sending
195 * and receiving data on the underlying data channel. Typically
196 * the callbacks to write/read to/from a TCP socket, but there
197 * is no assumption made about the type of channel used.
199 * The @writeFunc callback will be passed the encrypted
200 * data to send to the remote peer.
202 * The @readFunc callback will be passed a pointer to fill
203 * with encrypted data received from the remote peer
205 void qcrypto_tls_session_set_callbacks(QCryptoTLSSession
*sess
,
206 QCryptoTLSSessionWriteFunc writeFunc
,
207 QCryptoTLSSessionReadFunc readFunc
,
211 * qcrypto_tls_session_write:
212 * @sess: the TLS session object
213 * @buf: the plain text to send
214 * @len: the length of @buf
216 * Encrypt @len bytes of the data in @buf and send
217 * it to the remote peer using the callback previously
218 * registered with qcrypto_tls_session_set_callbacks()
220 * It is an error to call this before
221 * qcrypto_tls_session_get_handshake_status() returns
222 * QCRYPTO_TLS_HANDSHAKE_COMPLETE
224 * Returns: the number of bytes sent, or -1 on error
226 ssize_t
qcrypto_tls_session_write(QCryptoTLSSession
*sess
,
231 * qcrypto_tls_session_read:
232 * @sess: the TLS session object
233 * @buf: to fill with plain text received
234 * @len: the length of @buf
236 * Receive up to @len bytes of data from the remote peer
237 * using the callback previously registered with
238 * qcrypto_tls_session_set_callbacks(), decrypt it and
241 * It is an error to call this before
242 * qcrypto_tls_session_get_handshake_status() returns
243 * QCRYPTO_TLS_HANDSHAKE_COMPLETE
245 * Returns: the number of bytes received, or -1 on error
247 ssize_t
qcrypto_tls_session_read(QCryptoTLSSession
*sess
,
252 * qcrypto_tls_session_handshake:
253 * @sess: the TLS session object
254 * @errp: pointer to a NULL-initialized error object
256 * Start, or continue, a TLS handshake sequence. If
257 * the underlying data channel is non-blocking, then
258 * this method may return control before the handshake
259 * is complete. On non-blocking channels the
260 * qcrypto_tls_session_get_handshake_status() method
261 * should be used to determine whether the handshake
262 * has completed, or is waiting to send or receive
263 * data. In the latter cases, the caller should setup
264 * an event loop watch and call this method again
265 * once the underlying data channel is ready to read
268 int qcrypto_tls_session_handshake(QCryptoTLSSession
*sess
,
272 QCRYPTO_TLS_HANDSHAKE_COMPLETE
,
273 QCRYPTO_TLS_HANDSHAKE_SENDING
,
274 QCRYPTO_TLS_HANDSHAKE_RECVING
,
275 } QCryptoTLSSessionHandshakeStatus
;
278 * qcrypto_tls_session_get_handshake_status:
279 * @sess: the TLS session object
281 * Check the status of the TLS handshake. This
282 * is used with non-blocking data channels to
283 * determine whether the handshake is waiting
284 * to send or receive further data to/from the
287 * Once this returns QCRYPTO_TLS_HANDSHAKE_COMPLETE
288 * it is permitted to send/receive payload data on
291 QCryptoTLSSessionHandshakeStatus
292 qcrypto_tls_session_get_handshake_status(QCryptoTLSSession
*sess
);
295 * qcrypto_tls_session_get_key_size:
296 * @sess: the TLS session object
297 * @errp: pointer to a NULL-initialized error object
299 * Check the size of the data channel encryption key
301 * Returns: the length in bytes of the encryption key
304 int qcrypto_tls_session_get_key_size(QCryptoTLSSession
*sess
,
308 * qcrypto_tls_session_get_peer_name:
309 * @sess: the TLS session object
311 * Get the identified name of the remote peer. If the
312 * TLS session was negotiated using x509 certificate
313 * credentials, this will return the CommonName from
314 * the peer's certificate. If no identified name is
315 * available it will return NULL.
317 * The returned data must be released with g_free()
318 * when no longer required.
320 * Returns: the peer's name or NULL.
322 char *qcrypto_tls_session_get_peer_name(QCryptoTLSSession
*sess
);
324 #endif /* QCRYPTO_TLSSESSION_H */