#ifndef OPENSSL_NO_ENGINE
# include <openssl/engine.h>
#endif
+#include <openssl/async.h>
const char SSL_version_str[] = OPENSSL_VERSION_TEXT;
(int (*)(SSL *, const char *, int, unsigned char *))
ssl_undefined_function,
0, /* finish_mac_length */
- (int (*)(SSL *, int, unsigned char *))ssl_undefined_function,
NULL, /* client_finished_label */
0, /* client_finished_label_len */
NULL, /* server_finished_label */
int use_context))ssl_undefined_function,
};
+struct ssl_async_args {
+ SSL *s;
+ void *buf;
+ int num;
+ int type;
+ union {
+ int (*func1)(SSL *, void *, int);
+ int (*func2)(SSL *, const void *, int);
+ } f;
+};
+
static void clear_ciphers(SSL *s)
{
/* clear the current cipher */
return 0;
}
- s->type = 0;
-
- s->state = SSL_ST_BEFORE | ((s->server) ? SSL_ST_ACCEPT : SSL_ST_CONNECT);
+ ossl_statem_clear(s);
s->version = s->method->version;
s->client_version = s->version;
* Check to see if we were changed into a different method, if so, revert
* back if we are not doing session-id reuse.
*/
- if (!s->in_handshake && (s->session == NULL)
+ if (!ossl_statem_get_in_handshake(s) && (s->session == NULL)
&& (s->method != s->ctx->method)) {
s->method->ssl_free(s);
s->method = s->ctx->method;
s->generate_session_id = ctx->generate_session_id;
s->param = X509_VERIFY_PARAM_new();
- if (!s->param)
+ if (s->param == NULL)
goto err;
X509_VERIFY_PARAM_inherit(s->param, ctx->param);
s->quiet_shutdown = ctx->quiet_shutdown;
s->verify_result = X509_V_OK;
+ s->default_passwd_callback = ctx->default_passwd_callback;
+ s->default_passwd_callback_userdata = ctx->default_passwd_callback_userdata;
+
s->method = ctx->method;
if (!s->method->ssl_new(s))
s->psk_server_callback = ctx->psk_server_callback;
#endif
+ s->job = NULL;
+
return (s);
err:
SSL_free(s);
}
/*
- * what if we are setup as SSLv2 but want to talk SSLv3 or vice-versa
+ * what if we are setup for one protocol version but want to talk another
*/
if (t->method != f->method) {
t->method->ssl_free(t); /* cleanup current */
ssl->cert->key->privatekey));
}
+int SSL_waiting_for_async(SSL *s)
+{
+ if(s->job)
+ return 1;
+
+ return 0;
+}
+
+int SSL_get_async_wait_fd(SSL *s)
+{
+ if (!s->job)
+ return -1;
+
+ return ASYNC_get_wait_fd(s->job);
+}
+
int SSL_accept(SSL *s)
{
- if (s->handshake_func == 0)
+ if (s->handshake_func == 0) {
/* Not properly initialized yet */
SSL_set_accept_state(s);
+ }
- return (s->method->ssl_accept(s));
+ return SSL_do_handshake(s);
}
int SSL_connect(SSL *s)
{
- if (s->handshake_func == 0)
+ if (s->handshake_func == 0) {
/* Not properly initialized yet */
SSL_set_connect_state(s);
+ }
- return (s->method->ssl_connect(s));
+ return SSL_do_handshake(s);
}
long SSL_get_default_timeout(const SSL *s)
return (s->method->get_timeout());
}
+static int ssl_start_async_job(SSL *s, struct ssl_async_args *args,
+ int (*func)(void *)) {
+ int ret;
+ switch(ASYNC_start_job(&s->job, &ret, func, args,
+ sizeof(struct ssl_async_args))) {
+ case ASYNC_ERR:
+ s->rwstate = SSL_NOTHING;
+ SSLerr(SSL_F_SSL_START_ASYNC_JOB, SSL_R_FAILED_TO_INIT_ASYNC);
+ return -1;
+ case ASYNC_PAUSE:
+ s->rwstate = SSL_ASYNC_PAUSED;
+ return -1;
+ case ASYNC_FINISH:
+ s->job = NULL;
+ return ret;
+ default:
+ s->rwstate = SSL_NOTHING;
+ SSLerr(SSL_F_SSL_START_ASYNC_JOB, ERR_R_INTERNAL_ERROR);
+ /* Shouldn't happen */
+ return -1;
+ }
+}
+
+static int ssl_io_intern(void *vargs)
+{
+ struct ssl_async_args *args;
+ SSL *s;
+ void *buf;
+ int num;
+
+ args = (struct ssl_async_args *)vargs;
+ s = args->s;
+ buf = args->buf;
+ num = args->num;
+ if (args->type == 1)
+ return args->f.func1(s, buf, num);
+ else
+ return args->f.func2(s, buf, num);
+}
+
int SSL_read(SSL *s, void *buf, int num)
{
if (s->handshake_func == 0) {
s->rwstate = SSL_NOTHING;
return (0);
}
- return (s->method->ssl_read(s, buf, num));
+
+ if((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ struct ssl_async_args args;
+
+ args.s = s;
+ args.buf = buf;
+ args.num = num;
+ args.type = 1;
+ args.f.func1 = s->method->ssl_read;
+
+ return ssl_start_async_job(s, &args, ssl_io_intern);
+ } else {
+ return s->method->ssl_read(s, buf, num);
+ }
}
int SSL_peek(SSL *s, void *buf, int num)
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
return (0);
}
- return (s->method->ssl_peek(s, buf, num));
+ if((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ struct ssl_async_args args;
+
+ args.s = s;
+ args.buf = buf;
+ args.num = num;
+ args.type = 1;
+ args.f.func1 = s->method->ssl_peek;
+
+ return ssl_start_async_job(s, &args, ssl_io_intern);
+ } else {
+ return s->method->ssl_peek(s, buf, num);
+ }
}
int SSL_write(SSL *s, const void *buf, int num)
SSLerr(SSL_F_SSL_WRITE, SSL_R_PROTOCOL_IS_SHUTDOWN);
return (-1);
}
- return (s->method->ssl_write(s, buf, num));
+
+ if((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ struct ssl_async_args args;
+
+ args.s = s;
+ args.buf = (void *)buf;
+ args.num = num;
+ args.type = 2;
+ args.f.func2 = s->method->ssl_write;
+
+ return ssl_start_async_job(s, &args, ssl_io_intern);
+ } else {
+ return s->method->ssl_write(s, buf, num);
+ }
}
int SSL_shutdown(SSL *s)
return -1;
}
- if ((s != NULL) && !SSL_in_init(s))
+ if (!SSL_in_init(s))
return (s->method->ssl_shutdown(s));
else
return (1);
return TLS_CIPHER_LEN;
}
case SSL_CTRL_GET_EXTMS_SUPPORT:
- if (!s->session || SSL_in_init(s) || s->in_handshake)
+ if (!s->session || SSL_in_init(s) || ossl_statem_get_in_handshake(s))
return -1;
if (s->session->flags & SSL_SESS_FLAG_EXTMS)
return 1;
int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b)
{
- long l;
-
- l = a->id - b->id;
- if (l == 0L)
- return (0);
- else
- return ((l > 0) ? 1 : -1);
+ if (a->id > b->id)
+ return 1;
+ if (a->id < b->id)
+ return -1;
+ return 0;
}
int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap,
const SSL_CIPHER *const *bp)
{
- long l;
-
- l = (*ap)->id - (*bp)->id;
- if (l == 0L)
- return (0);
- else
- return ((l > 0) ? 1 : -1);
+ if ((*ap)->id > (*bp)->id)
+ return 1;
+ if ((*ap)->id < (*bp)->id)
+ return -1;
+ return 0;
}
/** return a STACK of the ciphers available for the SSL and in order of
return 1;
}
-/* works well for SSLv2, not so good for SSLv3 */
char *SSL_get_shared_ciphers(const SSL *s, char *buf, int len)
{
char *p;
{
OPENSSL_free(ctx->alpn_client_proto_list);
ctx->alpn_client_proto_list = OPENSSL_malloc(protos_len);
- if (!ctx->alpn_client_proto_list)
+ if (ctx->alpn_client_proto_list == NULL)
return 1;
memcpy(ctx->alpn_client_proto_list, protos, protos_len);
ctx->alpn_client_proto_list_len = protos_len;
{
OPENSSL_free(ssl->alpn_client_proto_list);
ssl->alpn_client_proto_list = OPENSSL_malloc(protos_len);
- if (!ssl->alpn_client_proto_list)
+ if (ssl->alpn_client_proto_list == NULL)
return 1;
memcpy(ssl->alpn_client_proto_list, protos, protos_len);
ssl->alpn_client_proto_list_len = protos_len;
}
ret->param = X509_VERIFY_PARAM_new();
- if (!ret->param)
+ if (ret->param == NULL)
goto err;
if ((ret->md5 = EVP_get_digestbyname("ssl3-md5")) == NULL) {
ctx->default_passwd_callback_userdata = u;
}
+void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb)
+{
+ s->default_passwd_callback = cb;
+}
+
+void SSL_set_default_passwd_cb_userdata(SSL *s, void *u)
+{
+ s->default_passwd_callback_userdata = u;
+}
+
void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
int (*cb) (X509_STORE_CTX *, void *),
void *arg)
rsa_enc_export, rsa_sign, dsa_sign, dh_rsa, dh_dsa);
#endif
+#ifndef OPENSSL_NO_GOST
+ cpk = &(c->pkeys[SSL_PKEY_GOST12_512]);
+ if (cpk->x509 != NULL && cpk->privatekey != NULL) {
+ mask_k |= SSL_kGOST;
+ mask_a |= SSL_aGOST12;
+ }
+ cpk = &(c->pkeys[SSL_PKEY_GOST12_256]);
+ if (cpk->x509 != NULL && cpk->privatekey != NULL) {
+ mask_k |= SSL_kGOST;
+ mask_a |= SSL_aGOST12;
+ }
cpk = &(c->pkeys[SSL_PKEY_GOST01]);
if (cpk->x509 != NULL && cpk->privatekey != NULL) {
mask_k |= SSL_kGOST;
mask_a |= SSL_aGOST01;
}
+#endif
if (rsa_enc || (rsa_tmp && rsa_sign))
mask_k |= SSL_kRSA;
idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509)
idx = SSL_PKEY_RSA_SIGN;
+ if (idx == SSL_PKEY_GOST_EC) {
+ if (s->cert->pkeys[SSL_PKEY_GOST12_512].x509)
+ idx = SSL_PKEY_GOST12_512;
+ else if (s->cert->pkeys[SSL_PKEY_GOST12_256].x509)
+ idx = SSL_PKEY_GOST12_256;
+ else if (s->cert->pkeys[SSL_PKEY_GOST01].x509)
+ idx = SSL_PKEY_GOST01;
+ else
+ idx = -1;
+ }
if (idx == -1)
SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX, ERR_R_INTERNAL_ERROR);
return idx;
if ((i < 0) && SSL_want_x509_lookup(s)) {
return (SSL_ERROR_WANT_X509_LOOKUP);
}
+ if ((i < 0) && SSL_want_async(s)) {
+ return SSL_ERROR_WANT_ASYNC;
+ }
if (i == 0) {
if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
return (SSL_ERROR_SYSCALL);
}
+static int ssl_do_handshake_intern(void *vargs)
+{
+ struct ssl_async_args *args;
+ SSL *s;
+
+ args = (struct ssl_async_args *)vargs;
+ s = args->s;
+
+ return s->handshake_func(s);
+}
+
int SSL_do_handshake(SSL *s)
{
int ret = 1;
if (s->handshake_func == NULL) {
SSLerr(SSL_F_SSL_DO_HANDSHAKE, SSL_R_CONNECTION_TYPE_NOT_SET);
- return (-1);
+ return -1;
}
s->method->ssl_renegotiate_check(s);
if (SSL_in_init(s) || SSL_in_before(s)) {
- ret = s->handshake_func(s);
+ if((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ struct ssl_async_args args;
+
+ args.s = s;
+
+ ret = ssl_start_async_job(s, &args, ssl_do_handshake_intern);
+ } else {
+ ret = s->handshake_func(s);
+ }
}
- return (ret);
+ return ret;
}
void SSL_set_accept_state(SSL *s)
{
s->server = 1;
s->shutdown = 0;
- s->state = SSL_ST_ACCEPT | SSL_ST_BEFORE;
+ ossl_statem_clear(s);
s->handshake_func = s->method->ssl_accept;
clear_ciphers(s);
}
{
s->server = 0;
s->shutdown = 0;
- s->state = SSL_ST_CONNECT | SSL_ST_BEFORE;
+ ossl_statem_clear(s);
s->handshake_func = s->method->ssl_connect;
clear_ciphers(s);
}
int ssl_undefined_const_function(const SSL *s)
{
- SSLerr(SSL_F_SSL_UNDEFINED_CONST_FUNCTION,
- ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return (0);
}
return (NULL);
ret->version = s->version;
- ret->type = s->type;
ret->method = s->method;
if (s->session != NULL) {
ret->wbio = ret->rbio;
}
ret->rwstate = s->rwstate;
- ret->in_handshake = s->in_handshake;
ret->handshake_func = s->handshake_func;
ret->server = s->server;
ret->renegotiate = s->renegotiate;
ret->new_session = s->new_session;
ret->quiet_shutdown = s->quiet_shutdown;
ret->shutdown = s->shutdown;
- ret->state = s->state; /* SSL_dup does not really work at any state,
- * though */
+ ret->statem = s->statem; /* SSL_dup does not really work at any state,
+ * though */
RECORD_LAYER_dup(&ret->rlayer, &s->rlayer);
ret->init_num = 0; /* would have to copy ret->init_buf,
* ret->init_msg, ret->init_num,
* ret->init_off */
ret->hit = s->hit;
+ ret->default_passwd_callback = s->default_passwd_callback;
+ ret->default_passwd_callback_userdata = s->default_passwd_callback_userdata;
+
X509_VERIFY_PARAM_inherit(ret->param, s->param);
/* dup the cipher_list and cipher_list_by_id stacks */
return ssl->info_callback;
}
-int SSL_state(const SSL *ssl)
-{
- return (ssl->state);
-}
-
-void SSL_set_state(SSL *ssl, int state)
-{
- ssl->state = state;
-}
-
void SSL_set_verify_result(SSL *ssl, long arg)
{
ssl->verify_result = arg;
return outlen;
}
-int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
- CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
-{
- return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, argl, argp,
- new_func, dup_func, free_func);
-}
-
int SSL_set_ex_data(SSL *s, int idx, void *arg)
{
return (CRYPTO_set_ex_data(&s->ex_data, idx, arg));
return (CRYPTO_get_ex_data(&s->ex_data, idx));
}
-int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
- CRYPTO_EX_dup *dup_func,
- CRYPTO_EX_free *free_func)
-{
- return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, argl, argp,
- new_func, dup_func, free_func);
-}
-
int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, void *arg)
{
return (CRYPTO_set_ex_data(&s->ex_data, idx, arg));
{
ssl_clear_hash_ctx(hash);
*hash = EVP_MD_CTX_create();
- if (md)
- EVP_DigestInit_ex(*hash, md, NULL);
+ if (*hash == NULL || (md && EVP_DigestInit_ex(*hash, md, NULL) <= 0)) {
+ EVP_MD_CTX_destroy(*hash);
+ *hash = NULL;
+ return NULL;
+ }
return *hash;
}
/* Retrieve handshake hashes */
int ssl_handshake_hash(SSL *s, unsigned char *out, int outlen)
{
- unsigned char *p = out;
- int idx, ret = 0;
- long mask;
EVP_MD_CTX ctx;
- const EVP_MD *md;
+ EVP_MD_CTX *hdgst = s->s3->handshake_dgst;
+ int ret = EVP_MD_CTX_size(hdgst);
EVP_MD_CTX_init(&ctx);
- for (idx = 0; ssl_get_handshake_digest(idx, &mask, &md); idx++) {
- if (mask & ssl_get_algorithm2(s)) {
- int hashsize = EVP_MD_size(md);
- EVP_MD_CTX *hdgst = s->s3->handshake_dgst[idx];
- if (!hdgst || hashsize < 0 || hashsize > outlen)
- goto err;
- if (!EVP_MD_CTX_copy_ex(&ctx, hdgst))
- goto err;
- if (!EVP_DigestFinal_ex(&ctx, p, NULL))
- goto err;
- p += hashsize;
- outlen -= hashsize;
- }
+ if (ret < 0 || ret > outlen) {
+ ret = 0;
+ goto err;
}
- ret = p - out;
+ if (!EVP_MD_CTX_copy_ex(&ctx, hdgst)
+ || EVP_DigestFinal_ex(&ctx, out, NULL) <= 0)
+ ret = 0;
err:
EVP_MD_CTX_cleanup(&ctx);
return ret;