/* $Id$ */ /* * Copyright (C) 2009-2011 Teluu Inc. (http://www.teluu.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __PJ_SSL_SOCK_H__ #define __PJ_SSL_SOCK_H__ /** * @file ssl_sock.h * @brief Secure socket */ #include #include #include PJ_BEGIN_DECL /** * @defgroup PJ_SSL_SOCK Secure socket I/O * @brief Secure socket provides security on socket operation using standard * security protocols such as SSL and TLS. * @ingroup PJ_IO * @{ * * Secure socket wraps normal socket and applies security features, i.e: * privacy and data integrity, on the socket traffic, using standard security * protocols such as SSL and TLS. * * Secure socket employs active socket operations, which is similar to (and * described more detail) in \ref PJ_ACTIVESOCK. */ /** * This opaque structure describes the secure socket. */ typedef struct pj_ssl_sock_t pj_ssl_sock_t; /** * Opaque declaration of endpoint certificate or credentials. This may contains * certificate, private key, and trusted Certificate Authorities list. */ typedef struct pj_ssl_cert_t pj_ssl_cert_t; typedef enum pj_ssl_cert_verify_flag_t { /** * No error in verification. */ PJ_SSL_CERT_ESUCCESS = 0, /** * The issuer certificate cannot be found. */ PJ_SSL_CERT_EISSUER_NOT_FOUND = (1 << 0), /** * The certificate is untrusted. */ PJ_SSL_CERT_EUNTRUSTED = (1 << 1), /** * The certificate has expired or not yet valid. */ PJ_SSL_CERT_EVALIDITY_PERIOD = (1 << 2), /** * One or more fields of the certificate cannot be decoded due to * invalid format. */ PJ_SSL_CERT_EINVALID_FORMAT = (1 << 3), /** * The certificate cannot be used for the specified purpose. */ PJ_SSL_CERT_EINVALID_PURPOSE = (1 << 4), /** * The issuer info in the certificate does not match to the (candidate) * issuer certificate, e.g: issuer name not match to subject name * of (candidate) issuer certificate. */ PJ_SSL_CERT_EISSUER_MISMATCH = (1 << 5), /** * The CRL certificate cannot be found or cannot be read properly. */ PJ_SSL_CERT_ECRL_FAILURE = (1 << 6), /** * The certificate has been revoked. */ PJ_SSL_CERT_EREVOKED = (1 << 7), /** * The certificate chain length is too long. */ PJ_SSL_CERT_ECHAIN_TOO_LONG = (1 << 8), /** * The server identity does not match to any identities specified in * the certificate, e.g: subjectAltName extension, subject common name. * This flag will only be set by application as SSL socket does not * perform server identity verification. */ PJ_SSL_CERT_EIDENTITY_NOT_MATCH = (1 << 30), /** * Unknown verification error. */ PJ_SSL_CERT_EUNKNOWN = (1 << 31) } pj_ssl_cert_verify_flag_t; typedef enum pj_ssl_cert_name_type { PJ_SSL_CERT_NAME_UNKNOWN = 0, PJ_SSL_CERT_NAME_RFC822, PJ_SSL_CERT_NAME_DNS, PJ_SSL_CERT_NAME_URI, PJ_SSL_CERT_NAME_IP } pj_ssl_cert_name_type; /** * Describe structure of certificate info. */ typedef struct pj_ssl_cert_info { unsigned version; /**< Certificate version */ pj_uint8_t serial_no[20]; /**< Serial number, array of octets, first index is MSB */ struct { pj_str_t cn; /**< Common name */ pj_str_t info; /**< One line subject, fields are separated by slash, e.g: "CN=sample.org/OU=HRD" */ } subject; /**< Subject */ struct { pj_str_t cn; /**< Common name */ pj_str_t info; /**< One line subject, fields are separated by slash.*/ } issuer; /**< Issuer */ struct { pj_time_val start; /**< Validity start */ pj_time_val end; /**< Validity end */ pj_bool_t gmt; /**< Flag if validity date/time use GMT */ } validity; /**< Validity */ struct { unsigned cnt; /**< # of entry */ struct { pj_ssl_cert_name_type type; /**< Name type */ pj_str_t name; /**< The name */ } *entry; /**< Subject alt name entry */ } subj_alt_name; /**< Subject alternative name extension */ pj_str_t raw; /**< Raw certificate in PEM format, only available for remote certificate. */ struct { unsigned cnt; /**< # of entry */ pj_str_t *cert_raw; } raw_chain; } pj_ssl_cert_info; /** * The SSL certificate buffer. */ typedef pj_str_t pj_ssl_cert_buffer; /** * Create credential from files. TLS server application can provide multiple * certificates (RSA, ECC, and DSA) by supplying certificate name with "_rsa" * suffix, e.g: "pjsip_rsa.pem", the library will automatically check for * other certificates with "_ecc" and "_dsa" suffix. * * @param CA_file The file of trusted CA list. * @param cert_file The file of certificate. * @param privkey_file The file of private key. * @param privkey_pass The password of private key, if any. * @param p_cert Pointer to credential instance to be created. * * @return PJ_SUCCESS when successful. */ PJ_DECL(pj_status_t) pj_ssl_cert_load_from_files(pj_pool_t *pool, const pj_str_t *CA_file, const pj_str_t *cert_file, const pj_str_t *privkey_file, const pj_str_t *privkey_pass, pj_ssl_cert_t **p_cert); /** * Create credential from files. TLS server application can provide multiple * certificates (RSA, ECC, and DSA) by supplying certificate name with "_rsa" * suffix, e.g: "pjsip_rsa.pem", the library will automatically check for * other certificates with "_ecc" and "_dsa" suffix. * * This is the same as pj_ssl_cert_load_from_files() but also * accepts an additional param CA_path to load CA certificates from * a directory. * * @param CA_file The file of trusted CA list. * @param CA_path The path to a directory of trusted CA list. * @param cert_file The file of certificate. * @param privkey_file The file of private key. * @param privkey_pass The password of private key, if any. * @param p_cert Pointer to credential instance to be created. * * @return PJ_SUCCESS when successful. */ PJ_DECL(pj_status_t) pj_ssl_cert_load_from_files2( pj_pool_t *pool, const pj_str_t *CA_file, const pj_str_t *CA_path, const pj_str_t *cert_file, const pj_str_t *privkey_file, const pj_str_t *privkey_pass, pj_ssl_cert_t **p_cert); /** * Create credential from data buffer. The certificate expected is in * PEM format. * * @param CA_file The buffer of trusted CA list. * @param cert_file The buffer of certificate. * @param privkey_file The buffer of private key. * @param privkey_pass The password of private key, if any. * @param p_cert Pointer to credential instance to be created. * * @return PJ_SUCCESS when successful. */ PJ_DECL(pj_status_t) pj_ssl_cert_load_from_buffer(pj_pool_t *pool, const pj_ssl_cert_buffer *CA_buf, const pj_ssl_cert_buffer *cert_buf, const pj_ssl_cert_buffer *privkey_buf, const pj_str_t *privkey_pass, pj_ssl_cert_t **p_cert); /** * Dump SSL certificate info. * * @param ci The certificate info. * @param indent String for left indentation. * @param buf The buffer where certificate info will be printed on. * @param buf_size The buffer size. * * @return The length of the dump result, or -1 when buffer size * is not sufficient. */ PJ_DECL(pj_ssize_t) pj_ssl_cert_info_dump(const pj_ssl_cert_info *ci, const char *indent, char *buf, pj_size_t buf_size); /** * Get SSL certificate verification error messages from verification status. * * @param verify_status The SSL certificate verification status. * @param error_strings Array of strings to receive the verification error * messages. * @param count On input it specifies maximum error messages should be * retrieved. On output it specifies the number of error * messages retrieved. * * @return PJ_SUCCESS when successful. */ PJ_DECL(pj_status_t) pj_ssl_cert_get_verify_status_strings( pj_uint32_t verify_status, const char *error_strings[], unsigned *count); /** * Wipe out the keys in the SSL certificate. * * @param cert The SSL certificate. * */ PJ_DECL(void) pj_ssl_cert_wipe_keys(pj_ssl_cert_t *cert); /** * Cipher suites enumeration. */ typedef enum pj_ssl_cipher { /* Unsupported cipher */ PJ_TLS_UNKNOWN_CIPHER = -1, /* NULL */ PJ_TLS_NULL_WITH_NULL_NULL = 0x00000000, /* TLS/SSLv3 */ PJ_TLS_RSA_WITH_NULL_MD5 = 0x00000001, PJ_TLS_RSA_WITH_NULL_SHA = 0x00000002, PJ_TLS_RSA_WITH_NULL_SHA256 = 0x0000003B, PJ_TLS_RSA_WITH_RC4_128_MD5 = 0x00000004, PJ_TLS_RSA_WITH_RC4_128_SHA = 0x00000005, PJ_TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x0000000A, PJ_TLS_RSA_WITH_AES_128_CBC_SHA = 0x0000002F, PJ_TLS_RSA_WITH_AES_256_CBC_SHA = 0x00000035, PJ_TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x0000003C, PJ_TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x0000003D, PJ_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x0000000D, PJ_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x00000010, PJ_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x00000013, PJ_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x00000016, PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x00000030, PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x00000031, PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x00000032, PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x00000033, PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x00000036, PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x00000037, PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x00000038, PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x00000039, PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x0000003E, PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x0000003F, PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x00000040, PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x00000067, PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x00000068, PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x00000069, PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x0000006A, PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x0000006B, PJ_TLS_DH_anon_WITH_RC4_128_MD5 = 0x00000018, PJ_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x0000001B, PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x00000034, PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x0000003A, PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x0000006C, PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x0000006D, /* TLS (deprecated) */ PJ_TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x00000003, PJ_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x00000006, PJ_TLS_RSA_WITH_IDEA_CBC_SHA = 0x00000007, PJ_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x00000008, PJ_TLS_RSA_WITH_DES_CBC_SHA = 0x00000009, PJ_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0000000B, PJ_TLS_DH_DSS_WITH_DES_CBC_SHA = 0x0000000C, PJ_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0000000E, PJ_TLS_DH_RSA_WITH_DES_CBC_SHA = 0x0000000F, PJ_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x00000011, PJ_TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x00000012, PJ_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x00000014, PJ_TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x00000015, PJ_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x00000017, PJ_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x00000019, PJ_TLS_DH_anon_WITH_DES_CBC_SHA = 0x0000001A, /* SSLv3 */ PJ_SSL_FORTEZZA_KEA_WITH_NULL_SHA = 0x0000001C, PJ_SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA = 0x0000001D, PJ_SSL_FORTEZZA_KEA_WITH_RC4_128_SHA = 0x0000001E, /* SSLv2 */ PJ_SSL_CK_RC4_128_WITH_MD5 = 0x00010080, PJ_SSL_CK_RC4_128_EXPORT40_WITH_MD5 = 0x00020080, PJ_SSL_CK_RC2_128_CBC_WITH_MD5 = 0x00030080, PJ_SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 = 0x00040080, PJ_SSL_CK_IDEA_128_CBC_WITH_MD5 = 0x00050080, PJ_SSL_CK_DES_64_CBC_WITH_MD5 = 0x00060040, PJ_SSL_CK_DES_192_EDE3_CBC_WITH_MD5 = 0x000700C0 } pj_ssl_cipher; /** * Get cipher list supported by SSL/TLS backend. * * @param ciphers The ciphers buffer to receive cipher list. * @param cipher_num Maximum number of ciphers to be received. * * @return PJ_SUCCESS when successful. */ PJ_DECL(pj_status_t) pj_ssl_cipher_get_availables(pj_ssl_cipher ciphers[], unsigned *cipher_num); /** * Check if the specified cipher is supported by SSL/TLS backend. * * @param cipher The cipher. * * @return PJ_TRUE when supported. */ PJ_DECL(pj_bool_t) pj_ssl_cipher_is_supported(pj_ssl_cipher cipher); /** * Get cipher name string. * * @param cipher The cipher. * * @return The cipher name or NULL if cipher is not recognized/ * supported. */ PJ_DECL(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher); /** * Get cipher ID from cipher name string. Note that on different backends * (e.g. OpenSSL or Symbian implementation), cipher names may not be * equivalent for the same cipher ID. * * @param cipher_name The cipher name string. * * @return The cipher ID or PJ_TLS_UNKNOWN_CIPHER if the cipher * name string is not recognized/supported. */ PJ_DECL(pj_ssl_cipher) pj_ssl_cipher_id(const char *cipher_name); /** * Elliptic curves enumeration. */ typedef enum pj_ssl_curve { PJ_TLS_UNKNOWN_CURVE = 0, PJ_TLS_CURVE_SECT163K1 = 1, PJ_TLS_CURVE_SECT163R1 = 2, PJ_TLS_CURVE_SECT163R2 = 3, PJ_TLS_CURVE_SECT193R1 = 4, PJ_TLS_CURVE_SECT193R2 = 5, PJ_TLS_CURVE_SECT233K1 = 6, PJ_TLS_CURVE_SECT233R1 = 7, PJ_TLS_CURVE_SECT239K1 = 8, PJ_TLS_CURVE_SECT283K1 = 9, PJ_TLS_CURVE_SECT283R1 = 10, PJ_TLS_CURVE_SECT409K1 = 11, PJ_TLS_CURVE_SECT409R1 = 12, PJ_TLS_CURVE_SECT571K1 = 13, PJ_TLS_CURVE_SECT571R1 = 14, PJ_TLS_CURVE_SECP160K1 = 15, PJ_TLS_CURVE_SECP160R1 = 16, PJ_TLS_CURVE_SECP160R2 = 17, PJ_TLS_CURVE_SECP192K1 = 18, PJ_TLS_CURVE_SECP192R1 = 19, PJ_TLS_CURVE_SECP224K1 = 20, PJ_TLS_CURVE_SECP224R1 = 21, PJ_TLS_CURVE_SECP256K1 = 22, PJ_TLS_CURVE_SECP256R1 = 23, PJ_TLS_CURVE_SECP384R1 = 24, PJ_TLS_CURVE_SECP521R1 = 25, PJ_TLS_CURVE_BRAINPOOLP256R1 = 26, PJ_TLS_CURVE_BRAINPOOLP384R1 = 27, PJ_TLS_CURVE_BRAINPOOLP512R1 = 28, PJ_TLS_CURVE_ARBITRARY_EXPLICIT_PRIME_CURVES = 0XFF01, PJ_TLS_CURVE_ARBITRARY_EXPLICIT_CHAR2_CURVES = 0XFF02 } pj_ssl_curve; /** * Get curve list supported by SSL/TLS backend. * * @param curves The curves buffer to receive curve list. * @param curves_num Maximum number of curves to be received. * * @return PJ_SUCCESS when successful. */ PJ_DECL(pj_status_t) pj_ssl_curve_get_availables(pj_ssl_curve curves[], unsigned *curve_num); /** * Check if the specified curve is supported by SSL/TLS backend. * * @param curve The curve. * * @return PJ_TRUE when supported. */ PJ_DECL(pj_bool_t) pj_ssl_curve_is_supported(pj_ssl_curve curve); /** * Get curve name string. * * @param curve The curve. * * @return The curve name or NULL if curve is not recognized/ * supported. */ PJ_DECL(const char*) pj_ssl_curve_name(pj_ssl_curve curve); /** * Get curve ID from curve name string. Note that on different backends * (e.g. OpenSSL or Symbian implementation), curve names may not be * equivalent for the same curve ID. * * @param curve_name The curve name string. * * @return The curve ID or PJ_TLS_UNKNOWN_CURVE if the curve * name string is not recognized/supported. */ PJ_DECL(pj_ssl_curve) pj_ssl_curve_id(const char *curve_name); /* * Entropy enumeration */ typedef enum pj_ssl_entropy { PJ_SSL_ENTROPY_NONE = 0, PJ_SSL_ENTROPY_EGD = 1, PJ_SSL_ENTROPY_RANDOM = 2, PJ_SSL_ENTROPY_URANDOM = 3, PJ_SSL_ENTROPY_FILE = 4, PJ_SSL_ENTROPY_UNKNOWN = 0x0F } pj_ssl_entropy_t; /** * This structure contains the callbacks to be called by the secure socket. */ typedef struct pj_ssl_sock_cb { /** * This callback is called when a data arrives as the result of * pj_ssl_sock_start_read(). * * @param ssock The secure socket. * @param data The buffer containing the new data, if any. If * the status argument is non-PJ_SUCCESS, this * argument may be NULL. * @param size The length of data in the buffer. * @param status The status of the read operation. This may contain * non-PJ_SUCCESS for example when the TCP connection * has been closed. In this case, the buffer may * contain left over data from previous callback which * the application may want to process. * @param remainder If application wishes to leave some data in the * buffer (common for TCP applications), it should * move the remainder data to the front part of the * buffer and set the remainder length here. The value * of this parameter will be ignored for datagram * sockets. * * @return PJ_TRUE if further read is desired, and PJ_FALSE * when application no longer wants to receive data. * Application may destroy the secure socket in the * callback and return PJ_FALSE here. */ pj_bool_t (*on_data_read)(pj_ssl_sock_t *ssock, void *data, pj_size_t size, pj_status_t status, pj_size_t *remainder); /** * This callback is called when a packet arrives as the result of * pj_ssl_sock_start_recvfrom(). * * @param ssock The secure socket. * @param data The buffer containing the packet, if any. If * the status argument is non-PJ_SUCCESS, this * argument will be set to NULL. * @param size The length of packet in the buffer. If * the status argument is non-PJ_SUCCESS, this * argument will be set to zero. * @param src_addr Source address of the packet. * @param addr_len Length of the source address. * @param status This contains * * @return PJ_TRUE if further read is desired, and PJ_FALSE * when application no longer wants to receive data. * Application may destroy the secure socket in the * callback and return PJ_FALSE here. */ pj_bool_t (*on_data_recvfrom)(pj_ssl_sock_t *ssock, void *data, pj_size_t size, const pj_sockaddr_t *src_addr, int addr_len, pj_status_t status); /** * This callback is called when data has been sent. * * @param ssock The secure socket. * @param send_key Key associated with the send operation. * @param sent If value is positive non-zero it indicates the * number of data sent. When the value is negative, * it contains the error code which can be retrieved * by negating the value (i.e. status=-sent). * * @return Application may destroy the secure socket in the * callback and return PJ_FALSE here. */ pj_bool_t (*on_data_sent)(pj_ssl_sock_t *ssock, pj_ioqueue_op_key_t *send_key, pj_ssize_t sent); /** * This callback is called when new connection arrives as the result * of pj_ssl_sock_start_accept(). If the status of accept operation is * needed use on_accept_complete2 instead of this callback. * * @param ssock The secure socket. * @param newsock The new incoming secure socket. * @param src_addr The source address of the connection. * @param addr_len Length of the source address. * * @return PJ_TRUE if further accept() is desired, and PJ_FALSE * when application no longer wants to accept incoming * connection. Application may destroy the secure socket * in the callback and return PJ_FALSE here. */ pj_bool_t (*on_accept_complete)(pj_ssl_sock_t *ssock, pj_ssl_sock_t *newsock, const pj_sockaddr_t *src_addr, int src_addr_len); /** * This callback is called when new connection arrives as the result * of pj_ssl_sock_start_accept(). * * @param asock The active socket. * @param newsock The new incoming socket. * @param src_addr The source address of the connection. * @param addr_len Length of the source address. * @param status The status of the accept operation. This may contain * non-PJ_SUCCESS for example when the TCP listener is in * bad state for example on iOS platform after the * application waking up from background. * * @return PJ_TRUE if further accept() is desired, and PJ_FALSE * when application no longer wants to accept incoming * connection. Application may destroy the active socket * in the callback and return PJ_FALSE here. */ pj_bool_t (*on_accept_complete2)(pj_ssl_sock_t *ssock, pj_ssl_sock_t *newsock, const pj_sockaddr_t *src_addr, int src_addr_len, pj_status_t status); /** * This callback is called when pending connect operation has been * completed. * * @param ssock The secure socket. * @param status The connection result. If connection has been * successfully established, the status will contain * PJ_SUCCESS. * * @return Application may destroy the secure socket in the * callback and return PJ_FALSE here. */ pj_bool_t (*on_connect_complete)(pj_ssl_sock_t *ssock, pj_status_t status); } pj_ssl_sock_cb; /** * Enumeration of secure socket protocol types. * This can be combined using bitwise OR operation. */ typedef enum pj_ssl_sock_proto { /** * Default protocol of backend. */ PJ_SSL_SOCK_PROTO_DEFAULT = 0, /** * SSLv2.0 protocol. */ PJ_SSL_SOCK_PROTO_SSL2 = (1 << 0), /** * SSLv3.0 protocol. */ PJ_SSL_SOCK_PROTO_SSL3 = (1 << 1), /** * TLSv1.0 protocol. */ PJ_SSL_SOCK_PROTO_TLS1 = (1 << 2), /** * TLSv1.1 protocol. */ PJ_SSL_SOCK_PROTO_TLS1_1 = (1 << 3), /** * TLSv1.2 protocol. */ PJ_SSL_SOCK_PROTO_TLS1_2 = (1 << 4), /** * Certain backend implementation e.g:OpenSSL, has feature to enable all * protocol. */ PJ_SSL_SOCK_PROTO_SSL23 = (1 << 16) - 1, PJ_SSL_SOCK_PROTO_ALL = PJ_SSL_SOCK_PROTO_SSL23, /** * DTLSv1.0 protocol. */ PJ_SSL_SOCK_PROTO_DTLS1 = (1 << 16), } pj_ssl_sock_proto; /** * Definition of secure socket info structure. */ typedef struct pj_ssl_sock_info { /** * Describes whether secure socket connection is established, i.e: TLS/SSL * handshaking has been done successfully. */ pj_bool_t established; /** * Describes secure socket protocol being used, see #pj_ssl_sock_proto. * Use bitwise OR operation to combine the protocol type. */ pj_uint32_t proto; /** * Describes cipher suite being used, this will only be set when connection * is established. */ pj_ssl_cipher cipher; /** * Describes local address. */ pj_sockaddr local_addr; /** * Describes remote address. */ pj_sockaddr remote_addr; /** * Describes active local certificate info. */ pj_ssl_cert_info *local_cert_info; /** * Describes active remote certificate info. */ pj_ssl_cert_info *remote_cert_info; /** * Status of peer certificate verification. */ pj_uint32_t verify_status; /** * Last native error returned by the backend. */ unsigned long last_native_err; /** * Group lock assigned to the ioqueue key. */ pj_grp_lock_t *grp_lock; } pj_ssl_sock_info; /** * Definition of secure socket creation parameters. */ typedef struct pj_ssl_sock_param { /** * Optional group lock to be assigned to the ioqueue key. * * Note that when a secure socket listener is configured with a group * lock, any new secure socket of an accepted incoming connection * will have its own group lock created automatically by the library, * this group lock can be queried via pj_ssl_sock_get_info() in the info * field pj_ssl_sock_info::grp_lock. */ pj_grp_lock_t *grp_lock; /** * Specifies socket address family, either pj_AF_INET() and pj_AF_INET6(). * * Default is pj_AF_INET(). */ int sock_af; /** * Specify socket type, either pj_SOCK_DGRAM() or pj_SOCK_STREAM(). * * Default is pj_SOCK_STREAM(). */ int sock_type; /** * Specify the ioqueue to use. Secure socket uses the ioqueue to perform * active socket operations, see \ref PJ_ACTIVESOCK for more detail. */ pj_ioqueue_t *ioqueue; /** * Specify the timer heap to use. Secure socket uses the timer to provide * auto cancelation on asynchronous operation when it takes longer time * than specified timeout period, e.g: security negotiation timeout. */ pj_timer_heap_t *timer_heap; /** * Specify secure socket callbacks, see #pj_ssl_sock_cb. */ pj_ssl_sock_cb cb; /** * Specify secure socket user data. */ void *user_data; /** * Specify security protocol to use, see #pj_ssl_sock_proto. Use bitwise OR * operation to combine the protocol type. * * Default is PJ_SSL_SOCK_PROTO_DEFAULT. */ pj_uint32_t proto; /** * Number of concurrent asynchronous operations that is to be supported * by the secure socket. This value only affects socket receive and * accept operations -- the secure socket will issue one or more * asynchronous read and accept operations based on the value of this * field. Setting this field to more than one will allow more than one * incoming data or incoming connections to be processed simultaneously * on multiprocessor systems, when the ioqueue is polled by more than * one threads. * * The default value is 1. */ unsigned async_cnt; /** * The ioqueue concurrency to be forced on the socket when it is * registered to the ioqueue. See #pj_ioqueue_set_concurrency() for more * info about ioqueue concurrency. * * When this value is -1, the concurrency setting will not be forced for * this socket, and the socket will inherit the concurrency setting of * the ioqueue. When this value is zero, the secure socket will disable * concurrency for the socket. When this value is +1, the secure socket * will enable concurrency for the socket. * * The default value is -1. */ int concurrency; /** * If this option is specified, the secure socket will make sure that * asynchronous send operation with stream oriented socket will only * call the callback after all data has been sent. This means that the * secure socket will automatically resend the remaining data until * all data has been sent. * * Please note that when this option is specified, it is possible that * error is reported after partial data has been sent. Also setting * this will disable the ioqueue concurrency for the socket. * * Default value is 1. */ pj_bool_t whole_data; /** * Specify buffer size for sending operation. Buffering sending data * is used for allowing application to perform multiple outstanding * send operations. Whenever application specifies this setting too * small, sending operation may return PJ_ENOMEM. * * Default value is 8192 bytes. */ pj_size_t send_buffer_size; /** * Specify buffer size for receiving encrypted (and perhaps compressed) * data on underlying socket. This setting is unused on Symbian, since * SSL/TLS Symbian backend, CSecureSocket, can use application buffer * directly. * * Default value is 1500. */ pj_size_t read_buffer_size; /** * Number of ciphers contained in the specified cipher preference. * If this is set to zero, then the cipher list used will be determined * by the backend default (for OpenSSL backend, setting * PJ_SSL_SOCK_OSSL_CIPHERS will be used). */ unsigned ciphers_num; /** * Ciphers and order preference. If empty, then default cipher list and * its default order of the backend will be used. */ pj_ssl_cipher *ciphers; /** * Number of curves contained in the specified curve preference. * If this is set to zero, then default curve list of the backend * will be used. * * Default: 0 (zero). */ unsigned curves_num; /** * Curves and order preference. The #pj_ssl_curve_get_availables() * can be used to check the available curves supported by backend. */ pj_ssl_curve *curves; /** * The supported signature algorithms. Set the sigalgs string * using this form: * "+:+" * Digests are: "RSA", "DSA" or "ECDSA" * Algorithms are: "MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512" * Example: "ECDSA+SHA256:RSA+SHA256" */ pj_str_t sigalgs; /** * Reseed random number generator. * For type #PJ_SSL_ENTROPY_FILE, parameter \a entropy_path * must be set to a file. * For type #PJ_SSL_ENTROPY_EGD, parameter \a entropy_path * must be set to a socket. * * Default value is PJ_SSL_ENTROPY_NONE. */ pj_ssl_entropy_t entropy_type; /** * When using a file/socket for entropy #PJ_SSL_ENTROPY_EGD or * #PJ_SSL_ENTROPY_FILE, \a entropy_path must contain the path * to entropy socket/file. * * Default value is an empty string. */ pj_str_t entropy_path; /** * Security negotiation timeout. If this is set to zero (both sec and * msec), the negotiation doesn't have a timeout. * * Default value is zero. */ pj_time_val timeout; /** * Specify whether endpoint should verify peer certificate. * * Default value is PJ_FALSE. */ pj_bool_t verify_peer; /** * When secure socket is acting as server (handles incoming connection), * it will require the client to provide certificate. * * Default value is PJ_FALSE. */ pj_bool_t require_client_cert; /** * Server name indication. When secure socket is acting as client * (perform outgoing connection) and the server may host multiple * 'virtual' servers at a single underlying network address, setting * this will allow client to tell the server a name of the server * it is contacting. * * Default value is zero/not-set. */ pj_str_t server_name; /** * Specify if SO_REUSEADDR should be used for listening socket. This * option will only be used with accept() operation. * * Default is PJ_FALSE. */ pj_bool_t reuse_addr; /** * QoS traffic type to be set on this transport. When application wants * to apply QoS tagging to the transport, it's preferable to set this * field rather than \a qos_param fields since this is more portable. * * Default value is PJ_QOS_TYPE_BEST_EFFORT. */ pj_qos_type qos_type; /** * Set the low level QoS parameters to the transport. This is a lower * level operation than setting the \a qos_type field and may not be * supported on all platforms. * * By default all settings in this structure are disabled. */ pj_qos_params qos_params; /** * Specify if the transport should ignore any errors when setting the QoS * traffic type/parameters. * * Default: PJ_TRUE */ pj_bool_t qos_ignore_error; /** * Specify options to be set on the transport. * * By default there is no options. * */ pj_sockopt_params sockopt_params; /** * Specify if the transport should ignore any errors when setting the * sockopt parameters. * * Default: PJ_TRUE * */ pj_bool_t sockopt_ignore_error; } pj_ssl_sock_param; /** * The parameter for pj_ssl_sock_start_connect2(). */ typedef struct pj_ssl_start_connect_param { /** * The pool to allocate some internal data for the operation. */ pj_pool_t *pool; /** * Local address. */ const pj_sockaddr_t *localaddr; /** * Port range for socket binding, relative to the start port number * specified in \a localaddr. This is only applicable when the start port * number is non zero. */ pj_uint16_t local_port_range; /** * Remote address. */ const pj_sockaddr_t *remaddr; /** * Length of buffer containing above addresses. */ int addr_len; } pj_ssl_start_connect_param; /** * Initialize the secure socket parameters for its creation with * the default values. * * @param param The parameter to be initialized. */ PJ_DECL(void) pj_ssl_sock_param_default(pj_ssl_sock_param *param); /** * Duplicate pj_ssl_sock_param. * * @param pool Pool to allocate memory. * @param dst Destination parameter. * @param src Source parameter. */ PJ_DECL(void) pj_ssl_sock_param_copy(pj_pool_t *pool, pj_ssl_sock_param *dst, const pj_ssl_sock_param *src); /** * Create secure socket instance. * * @param pool The pool for allocating secure socket instance. * @param param The secure socket parameter, see #pj_ssl_sock_param. * @param p_ssock Pointer to secure socket instance to be created. * * @return PJ_SUCCESS when successful. */ PJ_DECL(pj_status_t) pj_ssl_sock_create(pj_pool_t *pool, const pj_ssl_sock_param *param, pj_ssl_sock_t **p_ssock); /** * Set secure socket certificate or credentials. Credentials may include * certificate, private key and trusted Certification Authorities list. * Normally, server socket must provide certificate (and private key). * Socket client may also need to provide certificate in case requested * by the server. * * @param ssock The secure socket instance. * @param pool The pool. * @param cert The endpoint certificate/credentials, see * #pj_ssl_cert_t. * * @return PJ_SUCCESS if the operation has been successful, * or the appropriate error code on failure. */ PJ_DECL(pj_status_t) pj_ssl_sock_set_certificate( pj_ssl_sock_t *ssock, pj_pool_t *pool, const pj_ssl_cert_t *cert); /** * Close and destroy the secure socket. * * @param ssock The secure socket. * * @return PJ_SUCCESS if the operation has been successful, * or the appropriate error code on failure. */ PJ_DECL(pj_status_t) pj_ssl_sock_close(pj_ssl_sock_t *ssock); /** * Associate arbitrary data with the secure socket. Application may * inspect this data in the callbacks and associate it with higher * level processing. * * @param ssock The secure socket. * @param user_data The user data to be associated with the secure * socket. * * @return PJ_SUCCESS if the operation has been successful, * or the appropriate error code on failure. */ PJ_DECL(pj_status_t) pj_ssl_sock_set_user_data(pj_ssl_sock_t *ssock, void *user_data); /** * Retrieve the user data previously associated with this secure * socket. * * @param ssock The secure socket. * * @return The user data. */ PJ_DECL(void*) pj_ssl_sock_get_user_data(pj_ssl_sock_t *ssock); /** * Retrieve the local address and port used by specified secure socket. * * @param ssock The secure socket. * @param info The info buffer to be set, see #pj_ssl_sock_info. * * @return PJ_SUCCESS on successful. */ PJ_DECL(pj_status_t) pj_ssl_sock_get_info(pj_ssl_sock_t *ssock, pj_ssl_sock_info *info); /** * Starts read operation on this secure socket. This function will create * \a async_cnt number of buffers (the \a async_cnt parameter was given * in \a pj_ssl_sock_create() function) where each buffer is \a buff_size * long. The buffers are allocated from the specified \a pool. Once the * buffers are created, it then issues \a async_cnt number of asynchronous * \a recv() operations to the socket and returns back to caller. Incoming * data on the socket will be reported back to application via the * \a on_data_read() callback. * * Application only needs to call this function once to initiate read * operations. Further read operations will be done automatically by the * secure socket when \a on_data_read() callback returns non-zero. * * @param ssock The secure socket. * @param pool Pool used to allocate buffers for incoming data. * @param buff_size The size of each buffer, in bytes. * @param flags Flags to be given to pj_ioqueue_recv(). * * @return PJ_SUCCESS if the operation has been successful, * or the appropriate error code on failure. */ PJ_DECL(pj_status_t) pj_ssl_sock_start_read(pj_ssl_sock_t *ssock, pj_pool_t *pool, unsigned buff_size, pj_uint32_t flags); /** * Same as #pj_ssl_sock_start_read(), except that the application * supplies the buffers for the read operation so that the acive socket * does not have to allocate the buffers. * * @param ssock The secure socket. * @param pool Pool used to allocate buffers for incoming data. * @param buff_size The size of each buffer, in bytes. * @param readbuf Array of packet buffers, each has buff_size size. * @param flags Flags to be given to pj_ioqueue_recv(). * * @return PJ_SUCCESS if the operation has been successful, * or the appropriate error code on failure. */ PJ_DECL(pj_status_t) pj_ssl_sock_start_read2(pj_ssl_sock_t *ssock, pj_pool_t *pool, unsigned buff_size, void *readbuf[], pj_uint32_t flags); /** * Same as pj_ssl_sock_start_read(), except that this function is used * only for datagram sockets, and it will trigger \a on_data_recvfrom() * callback instead. * * @param ssock The secure socket. * @param pool Pool used to allocate buffers for incoming data. * @param buff_size The size of each buffer, in bytes. * @param flags Flags to be given to pj_ioqueue_recvfrom(). * * @return PJ_SUCCESS if the operation has been successful, * or the appropriate error code on failure. */ PJ_DECL(pj_status_t) pj_ssl_sock_start_recvfrom(pj_ssl_sock_t *ssock, pj_pool_t *pool, unsigned buff_size, pj_uint32_t flags); /** * Same as #pj_ssl_sock_start_recvfrom() except that the recvfrom() * operation takes the buffer from the argument rather than creating * new ones. * * @param ssock The secure socket. * @param pool Pool used to allocate buffers for incoming data. * @param buff_size The size of each buffer, in bytes. * @param readbuf Array of packet buffers, each has buff_size size. * @param flags Flags to be given to pj_ioqueue_recvfrom(). * * @return PJ_SUCCESS if the operation has been successful, * or the appropriate error code on failure. */ PJ_DECL(pj_status_t) pj_ssl_sock_start_recvfrom2(pj_ssl_sock_t *ssock, pj_pool_t *pool, unsigned buff_size, void *readbuf[], pj_uint32_t flags); /** * Send data using the socket. * * @param ssock The secure socket. * @param send_key The operation key to send the data, which is useful * if application wants to submit multiple pending * send operations and want to track which exact data * has been sent in the \a on_data_sent() callback. * @param data The data to be sent. This data must remain valid * until the data has been sent. * @param size The size of the data. * @param flags Flags to be given to pj_ioqueue_send(). * * @return PJ_SUCCESS if data has been sent immediately, or * PJ_EPENDING if data cannot be sent immediately or * PJ_ENOMEM when sending buffer could not handle all * queued data, see \a send_buffer_size. The callback * \a on_data_sent() will be called when data is actually * sent. Any other return value indicates error condition. */ PJ_DECL(pj_status_t) pj_ssl_sock_send(pj_ssl_sock_t *ssock, pj_ioqueue_op_key_t *send_key, const void *data, pj_ssize_t *size, unsigned flags); /** * Send datagram using the socket. * * @param ssock The secure socket. * @param send_key The operation key to send the data, which is useful * if application wants to submit multiple pending * send operations and want to track which exact data * has been sent in the \a on_data_sent() callback. * @param data The data to be sent. This data must remain valid * until the data has been sent. * @param size The size of the data. * @param flags Flags to be given to pj_ioqueue_send(). * @param addr The destination address. * @param addr_len Length of buffer containing destination address. * * @return PJ_SUCCESS if data has been sent immediately, or * PJ_EPENDING if data cannot be sent immediately. In * this case the \a on_data_sent() callback will be * called when data is actually sent. Any other return * value indicates error condition. */ PJ_DECL(pj_status_t) pj_ssl_sock_sendto(pj_ssl_sock_t *ssock, pj_ioqueue_op_key_t *send_key, const void *data, pj_ssize_t *size, unsigned flags, const pj_sockaddr_t *addr, int addr_len); /** * Starts asynchronous socket accept() operations on this secure socket. * This function will issue \a async_cnt number of asynchronous \a accept() * operations to the socket and returns back to caller. Incoming * connection on the socket will be reported back to application via the * \a on_accept_complete() callback. * * Application only needs to call this function once to initiate accept() * operations. Further accept() operations will be done automatically by * the secure socket when \a on_accept_complete() callback returns non-zero. * * @param ssock The secure socket. * @param pool Pool used to allocate some internal data for the * operation. * @param localaddr Local address to bind on. * @param addr_len Length of buffer containing local address. * * @return PJ_SUCCESS if the operation has been successful, * or the appropriate error code on failure. */ PJ_DECL(pj_status_t) pj_ssl_sock_start_accept(pj_ssl_sock_t *ssock, pj_pool_t *pool, const pj_sockaddr_t *local_addr, int addr_len); /** * Same as #pj_ssl_sock_start_accept(), but application can provide * a secure socket parameter, which will be used to create a new secure * socket reported in \a on_accept_complete() callback when there is * an incoming connection. * * @param ssock The secure socket. * @param pool Pool used to allocate some internal data for the * operation. * @param localaddr Local address to bind on. * @param addr_len Length of buffer containing local address. * @param newsock_param Secure socket parameter for new accepted sockets. * * @return PJ_SUCCESS if the operation has been successful, * or the appropriate error code on failure. */ PJ_DECL(pj_status_t) pj_ssl_sock_start_accept2(pj_ssl_sock_t *ssock, pj_pool_t *pool, const pj_sockaddr_t *local_addr, int addr_len, const pj_ssl_sock_param *newsock_param); /** * Starts asynchronous socket connect() operation and SSL/TLS handshaking * for this socket. Once the connection is done (either successfully or not), * the \a on_connect_complete() callback will be called. * * @param ssock The secure socket. * @param pool The pool to allocate some internal data for the * operation. * @param localaddr Local address. * @param remaddr Remote address. * @param addr_len Length of buffer containing above addresses. * * @return PJ_SUCCESS if connection can be established immediately * or PJ_EPENDING if connection cannot be established * immediately. In this case the \a on_connect_complete() * callback will be called when connection is complete. * Any other return value indicates error condition. */ PJ_DECL(pj_status_t) pj_ssl_sock_start_connect(pj_ssl_sock_t *ssock, pj_pool_t *pool, const pj_sockaddr_t *localaddr, const pj_sockaddr_t *remaddr, int addr_len); /** * Same as #pj_ssl_sock_start_connect(), but application can provide a * \a port_range parameter, which will be used to bind the socket to * random port. * * @param ssock The secure socket. * * @param connect_param The parameter, refer to \a pj_ssl_start_connect_param. * * @return PJ_SUCCESS if connection can be established immediately * or PJ_EPENDING if connection cannot be established * immediately. In this case the \a on_connect_complete() * callback will be called when connection is complete. * Any other return value indicates error condition. */ PJ_DECL(pj_status_t) pj_ssl_sock_start_connect2( pj_ssl_sock_t *ssock, pj_ssl_start_connect_param *connect_param); /** * Starts SSL/TLS renegotiation over an already established SSL connection * for this socket. This operation is performed transparently, no callback * will be called once the renegotiation completed successfully. However, * when the renegotiation fails, the connection will be closed and callback * \a on_data_read() will be invoked with non-PJ_SUCCESS status code. * * @param ssock The secure socket. * * @return PJ_SUCCESS if renegotiation is completed immediately, * or PJ_EPENDING if renegotiation has been started and * waiting for completion, or the appropriate error code * on failure. */ PJ_DECL(pj_status_t) pj_ssl_sock_renegotiate(pj_ssl_sock_t *ssock); /** * @} */ PJ_END_DECL #endif /* __PJ_SSL_SOCK_H__ */