qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

tlssession.h (11078B)


      1 /*
      2  * QEMU crypto TLS session support
      3  *
      4  * Copyright (c) 2015 Red Hat, Inc.
      5  *
      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.
     10  *
     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.
     15  *
     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/>.
     18  *
     19  */
     20 
     21 #ifndef QCRYPTO_TLSSESSION_H
     22 #define QCRYPTO_TLSSESSION_H
     23 
     24 #include "crypto/tlscreds.h"
     25 
     26 /**
     27  * QCryptoTLSSession:
     28  *
     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.
     32  *
     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.
     37  *
     38  * <example>
     39  *   <title>Using TLS session objects</title>
     40  *   <programlisting>
     41  * static ssize_t mysock_send(const char *buf, size_t len,
     42  *                            void *opaque)
     43  * {
     44  *    int fd = GPOINTER_TO_INT(opaque);
     45  *
     46  *    return write(*fd, buf, len);
     47  * }
     48  *
     49  * static ssize_t mysock_recv(const char *buf, size_t len,
     50  *                            void *opaque)
     51  * {
     52  *    int fd = GPOINTER_TO_INT(opaque);
     53  *
     54  *    return read(*fd, buf, len);
     55  * }
     56  *
     57  * static int mysock_run_tls(int sockfd,
     58  *                           QCryptoTLSCreds *creds,
     59  *                           Error **errp)
     60  * {
     61  *    QCryptoTLSSession *sess;
     62  *
     63  *    sess = qcrypto_tls_session_new(creds,
     64  *                                   "vnc.example.com",
     65  *                                   NULL,
     66  *                                   QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
     67  *                                   errp);
     68  *    if (sess == NULL) {
     69  *       return -1;
     70  *    }
     71  *
     72  *    qcrypto_tls_session_set_callbacks(sess,
     73  *                                      mysock_send,
     74  *                                      mysock_recv
     75  *                                      GINT_TO_POINTER(fd));
     76  *
     77  *    while (1) {
     78  *       if (qcrypto_tls_session_handshake(sess, errp) < 0) {
     79  *           qcrypto_tls_session_free(sess);
     80  *           return -1;
     81  *       }
     82  *
     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);
     87  *               return -1;
     88  *           }
     89  *           goto done;
     90  *       case QCRYPTO_TLS_HANDSHAKE_RECVING:
     91  *           ...wait for GIO_IN event on fd...
     92  *           break;
     93  *       case QCRYPTO_TLS_HANDSHAKE_SENDING:
     94  *           ...wait for GIO_OUT event on fd...
     95  *           break;
     96  *       }
     97  *    }
     98  *   done:
     99  *
    100  *    ....send/recv payload data on sess...
    101  *
    102  *    qcrypto_tls_session_free(sess):
    103  * }
    104  *   </programlisting>
    105  * </example>
    106  */
    107 
    108 typedef struct QCryptoTLSSession QCryptoTLSSession;
    109 
    110 
    111 /**
    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
    118  *
    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.
    123  *
    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).
    128  *
    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.
    136  *
    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.
    142  *
    143  * The session object must be released by calling
    144  * qcrypto_tls_session_free() when no longer required
    145  *
    146  * Returns: a TLS session object, or NULL on error.
    147  */
    148 QCryptoTLSSession *qcrypto_tls_session_new(QCryptoTLSCreds *creds,
    149                                            const char *hostname,
    150                                            const char *aclname,
    151                                            QCryptoTLSCredsEndpoint endpoint,
    152                                            Error **errp);
    153 
    154 /**
    155  * qcrypto_tls_session_free:
    156  * @sess: the TLS session object
    157  *
    158  * Release all memory associated with the TLS session
    159  * object previously allocated by qcrypto_tls_session_new()
    160  */
    161 void qcrypto_tls_session_free(QCryptoTLSSession *sess);
    162 
    163 G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoTLSSession, qcrypto_tls_session_free)
    164 
    165 /**
    166  * qcrypto_tls_session_check_credentials:
    167  * @sess: the TLS session object
    168  * @errp: pointer to a NULL-initialized error object
    169  *
    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
    174  *
    175  * Returns 0 if the credentials validated, -1 on error
    176  */
    177 int qcrypto_tls_session_check_credentials(QCryptoTLSSession *sess,
    178                                           Error **errp);
    179 
    180 typedef ssize_t (*QCryptoTLSSessionWriteFunc)(const char *buf,
    181                                               size_t len,
    182                                               void *opaque);
    183 typedef ssize_t (*QCryptoTLSSessionReadFunc)(char *buf,
    184                                              size_t len,
    185                                              void *opaque);
    186 
    187 /**
    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
    193  *
    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.
    198  *
    199  * The @writeFunc callback will be passed the encrypted
    200  * data to send to the remote peer.
    201  *
    202  * The @readFunc callback will be passed a pointer to fill
    203  * with encrypted data received from the remote peer
    204  */
    205 void qcrypto_tls_session_set_callbacks(QCryptoTLSSession *sess,
    206                                        QCryptoTLSSessionWriteFunc writeFunc,
    207                                        QCryptoTLSSessionReadFunc readFunc,
    208                                        void *opaque);
    209 
    210 /**
    211  * qcrypto_tls_session_write:
    212  * @sess: the TLS session object
    213  * @buf: the plain text to send
    214  * @len: the length of @buf
    215  *
    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()
    219  *
    220  * It is an error to call this before
    221  * qcrypto_tls_session_get_handshake_status() returns
    222  * QCRYPTO_TLS_HANDSHAKE_COMPLETE
    223  *
    224  * Returns: the number of bytes sent, or -1 on error
    225  */
    226 ssize_t qcrypto_tls_session_write(QCryptoTLSSession *sess,
    227                                   const char *buf,
    228                                   size_t len);
    229 
    230 /**
    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
    235  *
    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
    239  * store it in @buf.
    240  *
    241  * It is an error to call this before
    242  * qcrypto_tls_session_get_handshake_status() returns
    243  * QCRYPTO_TLS_HANDSHAKE_COMPLETE
    244  *
    245  * Returns: the number of bytes received, or -1 on error
    246  */
    247 ssize_t qcrypto_tls_session_read(QCryptoTLSSession *sess,
    248                                  char *buf,
    249                                  size_t len);
    250 
    251 /**
    252  * qcrypto_tls_session_handshake:
    253  * @sess: the TLS session object
    254  * @errp: pointer to a NULL-initialized error object
    255  *
    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
    266  * or write again
    267  */
    268 int qcrypto_tls_session_handshake(QCryptoTLSSession *sess,
    269                                   Error **errp);
    270 
    271 typedef enum {
    272     QCRYPTO_TLS_HANDSHAKE_COMPLETE,
    273     QCRYPTO_TLS_HANDSHAKE_SENDING,
    274     QCRYPTO_TLS_HANDSHAKE_RECVING,
    275 } QCryptoTLSSessionHandshakeStatus;
    276 
    277 /**
    278  * qcrypto_tls_session_get_handshake_status:
    279  * @sess: the TLS session object
    280  *
    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
    285  * remote peer.
    286  *
    287  * Once this returns QCRYPTO_TLS_HANDSHAKE_COMPLETE
    288  * it is permitted to send/receive payload data on
    289  * the channel
    290  */
    291 QCryptoTLSSessionHandshakeStatus
    292 qcrypto_tls_session_get_handshake_status(QCryptoTLSSession *sess);
    293 
    294 /**
    295  * qcrypto_tls_session_get_key_size:
    296  * @sess: the TLS session object
    297  * @errp: pointer to a NULL-initialized error object
    298  *
    299  * Check the size of the data channel encryption key
    300  *
    301  * Returns: the length in bytes of the encryption key
    302  * or -1 on error
    303  */
    304 int qcrypto_tls_session_get_key_size(QCryptoTLSSession *sess,
    305                                      Error **errp);
    306 
    307 /**
    308  * qcrypto_tls_session_get_peer_name:
    309  * @sess: the TLS session object
    310  *
    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.
    316  *
    317  * The returned data must be released with g_free()
    318  * when no longer required.
    319  *
    320  * Returns: the peer's name or NULL.
    321  */
    322 char *qcrypto_tls_session_get_peer_name(QCryptoTLSSession *sess);
    323 
    324 #endif /* QCRYPTO_TLSSESSION_H */