tlssession.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  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. #ifndef QCRYPTO_TLSSESSION_H
  21. #define QCRYPTO_TLSSESSION_H
  22. #include "crypto/tlscreds.h"
  23. /**
  24. * QCryptoTLSSession:
  25. *
  26. * The QCryptoTLSSession object encapsulates the
  27. * logic to integrate with a TLS providing library such
  28. * as GNUTLS, to setup and run TLS sessions.
  29. *
  30. * The API is designed such that it has no assumption about
  31. * the type of transport it is running over. It may be a
  32. * traditional TCP socket, or something else entirely. The
  33. * only requirement is a full-duplex stream of some kind.
  34. *
  35. * <example>
  36. * <title>Using TLS session objects</title>
  37. * <programlisting>
  38. * static ssize_t mysock_send(const char *buf, size_t len,
  39. * void *opaque)
  40. * {
  41. * int fd = GPOINTER_TO_INT(opaque);
  42. *
  43. * return write(*fd, buf, len);
  44. * }
  45. *
  46. * static ssize_t mysock_recv(const char *buf, size_t len,
  47. * void *opaque)
  48. * {
  49. * int fd = GPOINTER_TO_INT(opaque);
  50. *
  51. * return read(*fd, buf, len);
  52. * }
  53. *
  54. * static int mysock_run_tls(int sockfd,
  55. * QCryptoTLSCreds *creds,
  56. * Error **errp)
  57. * {
  58. * QCryptoTLSSession *sess;
  59. *
  60. * sess = qcrypto_tls_session_new(creds,
  61. * "vnc.example.com",
  62. * NULL,
  63. * QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
  64. * errp);
  65. * if (sess == NULL) {
  66. * return -1;
  67. * }
  68. *
  69. * qcrypto_tls_session_set_callbacks(sess,
  70. * mysock_send,
  71. * mysock_recv
  72. * GINT_TO_POINTER(fd));
  73. *
  74. * while (1) {
  75. * int ret = qcrypto_tls_session_handshake(sess, errp);
  76. *
  77. * if (ret < 0) {
  78. * qcrypto_tls_session_free(sess);
  79. * return -1;
  80. * }
  81. *
  82. * switch(ret) {
  83. * case QCRYPTO_TLS_HANDSHAKE_COMPLETE:
  84. * if (qcrypto_tls_session_check_credentials(sess, errp) < )) {
  85. * qcrypto_tls_session_free(sess);
  86. * return -1;
  87. * }
  88. * goto done;
  89. * case QCRYPTO_TLS_HANDSHAKE_RECVING:
  90. * ...wait for GIO_IN event on fd...
  91. * break;
  92. * case QCRYPTO_TLS_HANDSHAKE_SENDING:
  93. * ...wait for GIO_OUT event on fd...
  94. * break;
  95. * }
  96. * }
  97. * done:
  98. *
  99. * ....send/recv payload data on sess...
  100. *
  101. * qcrypto_tls_session_free(sess):
  102. * }
  103. * </programlisting>
  104. * </example>
  105. */
  106. typedef struct QCryptoTLSSession QCryptoTLSSession;
  107. #define QCRYPTO_TLS_SESSION_ERR_BLOCK -2
  108. /**
  109. * qcrypto_tls_session_new:
  110. * @creds: pointer to a TLS credentials object
  111. * @hostname: optional hostname to validate
  112. * @aclname: optional ACL to validate peer credentials against
  113. * @endpoint: role of the TLS session, client or server
  114. * @errp: pointer to a NULL-initialized error object
  115. *
  116. * Create a new TLS session object that will be used to
  117. * negotiate a TLS session over an arbitrary data channel.
  118. * The session object can operate as either the server or
  119. * client, according to the value of the @endpoint argument.
  120. *
  121. * For clients, the @hostname parameter should hold the full
  122. * unmodified hostname as requested by the user. This will
  123. * be used to verify the against the hostname reported in
  124. * the server's credentials (aka x509 certificate).
  125. *
  126. * The @aclname parameter (optionally) specifies the name
  127. * of an access control list that will be used to validate
  128. * the peer's credentials. For x509 credentials, the ACL
  129. * will be matched against the CommonName shown in the peer's
  130. * certificate. If the session is acting as a server, setting
  131. * an ACL will require that the client provide a validate
  132. * x509 client certificate.
  133. *
  134. * After creating the session object, the I/O callbacks
  135. * must be set using the qcrypto_tls_session_set_callbacks()
  136. * method. A TLS handshake sequence must then be completed
  137. * using qcrypto_tls_session_handshake(), before payload
  138. * data is permitted to be sent/received.
  139. *
  140. * The session object must be released by calling
  141. * qcrypto_tls_session_free() when no longer required
  142. *
  143. * Returns: a TLS session object, or NULL on error.
  144. */
  145. QCryptoTLSSession *qcrypto_tls_session_new(QCryptoTLSCreds *creds,
  146. const char *hostname,
  147. const char *aclname,
  148. QCryptoTLSCredsEndpoint endpoint,
  149. Error **errp);
  150. /**
  151. * qcrypto_tls_session_free:
  152. * @sess: the TLS session object
  153. *
  154. * Release all memory associated with the TLS session
  155. * object previously allocated by qcrypto_tls_session_new()
  156. */
  157. void qcrypto_tls_session_free(QCryptoTLSSession *sess);
  158. G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoTLSSession, qcrypto_tls_session_free)
  159. /**
  160. * qcrypto_tls_session_check_credentials:
  161. * @sess: the TLS session object
  162. * @errp: pointer to a NULL-initialized error object
  163. *
  164. * Validate the peer's credentials after a successful
  165. * TLS handshake. It is an error to call this before
  166. * qcrypto_tls_session_handshake() returns
  167. * QCRYPTO_TLS_HANDSHAKE_COMPLETE
  168. *
  169. * Returns 0 if the credentials validated, -1 on error
  170. */
  171. int qcrypto_tls_session_check_credentials(QCryptoTLSSession *sess,
  172. Error **errp);
  173. /*
  174. * These must return QCRYPTO_TLS_SESSION_ERR_BLOCK if the I/O
  175. * would block, but on other errors, must fill 'errp'
  176. */
  177. typedef ssize_t (*QCryptoTLSSessionWriteFunc)(const char *buf,
  178. size_t len,
  179. void *opaque,
  180. Error **errp);
  181. typedef ssize_t (*QCryptoTLSSessionReadFunc)(char *buf,
  182. size_t len,
  183. void *opaque,
  184. Error **errp);
  185. /**
  186. * qcrypto_tls_session_set_callbacks:
  187. * @sess: the TLS session object
  188. * @writeFunc: callback for sending data
  189. * @readFunc: callback to receiving data
  190. * @opaque: data to pass to callbacks
  191. *
  192. * Sets the callback functions that are to be used for sending
  193. * and receiving data on the underlying data channel. Typically
  194. * the callbacks to write/read to/from a TCP socket, but there
  195. * is no assumption made about the type of channel used.
  196. *
  197. * The @writeFunc callback will be passed the encrypted
  198. * data to send to the remote peer.
  199. *
  200. * The @readFunc callback will be passed a pointer to fill
  201. * with encrypted data received from the remote peer
  202. */
  203. void qcrypto_tls_session_set_callbacks(QCryptoTLSSession *sess,
  204. QCryptoTLSSessionWriteFunc writeFunc,
  205. QCryptoTLSSessionReadFunc readFunc,
  206. void *opaque);
  207. /**
  208. * qcrypto_tls_session_write:
  209. * @sess: the TLS session object
  210. * @buf: the plain text to send
  211. * @len: the length of @buf
  212. * @errp: pointer to hold returned error object
  213. *
  214. * Encrypt @len bytes of the data in @buf and send
  215. * it to the remote peer using the callback previously
  216. * registered with qcrypto_tls_session_set_callbacks()
  217. *
  218. * It is an error to call this before
  219. * qcrypto_tls_session_handshake() returns
  220. * QCRYPTO_TLS_HANDSHAKE_COMPLETE
  221. *
  222. * Returns: the number of bytes sent,
  223. * or QCRYPTO_TLS_SESSION_ERR_BLOCK if the write would block,
  224. * or -1 on error.
  225. */
  226. ssize_t qcrypto_tls_session_write(QCryptoTLSSession *sess,
  227. const char *buf,
  228. size_t len,
  229. Error **errp);
  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. * @gracefulTermination: treat premature termination as graceful EOF
  236. * @errp: pointer to hold returned error object
  237. *
  238. * Receive up to @len bytes of data from the remote peer
  239. * using the callback previously registered with
  240. * qcrypto_tls_session_set_callbacks(), decrypt it and
  241. * store it in @buf.
  242. *
  243. * If @gracefulTermination is true, then a premature termination
  244. * of the TLS session will be treated as indicating EOF, as
  245. * opposed to an error.
  246. *
  247. * It is an error to call this before
  248. * qcrypto_tls_session_handshake() returns
  249. * QCRYPTO_TLS_HANDSHAKE_COMPLETE
  250. *
  251. * Returns: the number of bytes received,
  252. * or QCRYPTO_TLS_SESSION_ERR_BLOCK if the receive would block,
  253. * or -1 on error.
  254. */
  255. ssize_t qcrypto_tls_session_read(QCryptoTLSSession *sess,
  256. char *buf,
  257. size_t len,
  258. bool gracefulTermination,
  259. Error **errp);
  260. /**
  261. * qcrypto_tls_session_check_pending:
  262. * @sess: the TLS session object
  263. *
  264. * Check if there are unread data in the TLS buffers that have
  265. * already been read from the underlying data source.
  266. *
  267. * Returns: the number of bytes available or zero
  268. */
  269. size_t qcrypto_tls_session_check_pending(QCryptoTLSSession *sess);
  270. /**
  271. * qcrypto_tls_session_handshake:
  272. * @sess: the TLS session object
  273. * @errp: pointer to a NULL-initialized error object
  274. *
  275. * Start, or continue, a TLS handshake sequence. If
  276. * the underlying data channel is non-blocking, then
  277. * this method may return control before the handshake
  278. * is complete. On non-blocking channels the
  279. * return value determines whether the handshake
  280. * has completed, or is waiting to send or receive
  281. * data. In the latter cases, the caller should setup
  282. * an event loop watch and call this method again
  283. * once the underlying data channel is ready to read
  284. * or write again
  285. */
  286. int qcrypto_tls_session_handshake(QCryptoTLSSession *sess,
  287. Error **errp);
  288. typedef enum {
  289. QCRYPTO_TLS_HANDSHAKE_COMPLETE,
  290. QCRYPTO_TLS_HANDSHAKE_SENDING,
  291. QCRYPTO_TLS_HANDSHAKE_RECVING,
  292. } QCryptoTLSSessionHandshakeStatus;
  293. typedef enum {
  294. QCRYPTO_TLS_BYE_COMPLETE,
  295. QCRYPTO_TLS_BYE_SENDING,
  296. QCRYPTO_TLS_BYE_RECVING,
  297. } QCryptoTLSSessionByeStatus;
  298. /**
  299. * qcrypto_tls_session_bye:
  300. * @session: the TLS session object
  301. * @errp: pointer to a NULL-initialized error object
  302. *
  303. * Start, or continue, a TLS termination sequence. If the underlying
  304. * data channel is non-blocking, then this method may return control
  305. * before the termination is complete. The return value will indicate
  306. * whether the termination has completed, or is waiting to send or
  307. * receive data. In the latter cases, the caller should setup an event
  308. * loop watch and call this method again once the underlying data
  309. * channel is ready to read or write again.
  310. */
  311. int
  312. qcrypto_tls_session_bye(QCryptoTLSSession *session, Error **errp);
  313. /**
  314. * qcrypto_tls_session_get_key_size:
  315. * @sess: the TLS session object
  316. * @errp: pointer to a NULL-initialized error object
  317. *
  318. * Check the size of the data channel encryption key
  319. *
  320. * Returns: the length in bytes of the encryption key
  321. * or -1 on error
  322. */
  323. int qcrypto_tls_session_get_key_size(QCryptoTLSSession *sess,
  324. Error **errp);
  325. /**
  326. * qcrypto_tls_session_get_peer_name:
  327. * @sess: the TLS session object
  328. *
  329. * Get the identified name of the remote peer. If the
  330. * TLS session was negotiated using x509 certificate
  331. * credentials, this will return the CommonName from
  332. * the peer's certificate. If no identified name is
  333. * available it will return NULL.
  334. *
  335. * The returned data must be released with g_free()
  336. * when no longer required.
  337. *
  338. * Returns: the peer's name or NULL.
  339. */
  340. char *qcrypto_tls_session_get_peer_name(QCryptoTLSSession *sess);
  341. #endif /* QCRYPTO_TLSSESSION_H */