+#ifndef OPENSSL_NO_PSK
+int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
+ {
+ if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN)
+ {
+ SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+ if (ctx->psk_identity_hint != NULL)
+ OPENSSL_free(ctx->psk_identity_hint);
+ if (identity_hint != NULL)
+ {
+ ctx->psk_identity_hint = BUF_strdup(identity_hint);
+ if (ctx->psk_identity_hint == NULL)
+ return 0;
+ }
+ else
+ ctx->psk_identity_hint = NULL;
+ return 1;
+ }
+
+int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint)
+ {
+ if (s == NULL)
+ return 0;
+
+ if (s->session == NULL)
+ return 1; /* session not created yet, ignored */
+
+ if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN)
+ {
+ SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
+ return 0;
+ }
+ if (s->session->psk_identity_hint != NULL)
+ OPENSSL_free(s->session->psk_identity_hint);
+ if (identity_hint != NULL)
+ {
+ s->session->psk_identity_hint = BUF_strdup(identity_hint);
+ if (s->session->psk_identity_hint == NULL)
+ return 0;
+ }
+ else
+ s->session->psk_identity_hint = NULL;
+ return 1;
+ }
+
+const char *SSL_get_psk_identity_hint(const SSL *s)
+ {
+ if (s == NULL || s->session == NULL)
+ return NULL;
+ return(s->session->psk_identity_hint);
+ }
+
+const char *SSL_get_psk_identity(const SSL *s)
+ {
+ if (s == NULL || s->session == NULL)
+ return NULL;
+ return(s->session->psk_identity);
+ }
+
+void SSL_set_psk_client_callback(SSL *s,
+ unsigned int (*cb)(SSL *ssl, const char *hint,
+ char *identity, unsigned int max_identity_len, unsigned char *psk,
+ unsigned int max_psk_len))
+ {
+ s->psk_client_callback = cb;
+ }
+
+void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx,
+ unsigned int (*cb)(SSL *ssl, const char *hint,
+ char *identity, unsigned int max_identity_len, unsigned char *psk,
+ unsigned int max_psk_len))
+ {
+ ctx->psk_client_callback = cb;
+ }
+
+void SSL_set_psk_server_callback(SSL *s,
+ unsigned int (*cb)(SSL *ssl, const char *identity,
+ unsigned char *psk, unsigned int max_psk_len))
+ {
+ s->psk_server_callback = cb;
+ }
+
+void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx,
+ unsigned int (*cb)(SSL *ssl, const char *identity,
+ unsigned char *psk, unsigned int max_psk_len))
+ {
+ ctx->psk_server_callback = cb;
+ }
+#endif
+
+void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))
+ {
+ SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
+ }
+void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))
+ {
+ SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
+ }
+
+/* Allocates new EVP_MD_CTX and sets pointer to it into given pointer
+ * vairable, freeing EVP_MD_CTX previously stored in that variable, if
+ * any. If EVP_MD pointer is passed, initializes ctx with this md
+ * Returns newly allocated ctx;
+ */
+
+EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md)
+{
+ ssl_clear_hash_ctx(hash);
+ *hash = EVP_MD_CTX_create();
+ if (md) EVP_DigestInit_ex(*hash,md,NULL);
+ return *hash;
+}
+void ssl_clear_hash_ctx(EVP_MD_CTX **hash)
+{
+
+ if (*hash) EVP_MD_CTX_destroy(*hash);
+ *hash=NULL;
+}
+