(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 */
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)
int SSL_get_async_wait_fd(SSL *s)
{
if (!s->job)
- return 0;
+ return -1;
return ASYNC_get_wait_fd(s->job);
}
-static int ssl_accept_intern(void *vargs)
-{
- struct ssl_async_args *args;
- SSL *s;
-
- args = (struct ssl_async_args *)vargs;
- s = args->s;
-
- return s->method->ssl_accept(s);
-}
-
int SSL_accept(SSL *s)
{
- int ret;
- struct ssl_async_args args;
-
- if (s->handshake_func == 0)
+ if (s->handshake_func == 0) {
/* Not properly initialized yet */
SSL_set_accept_state(s);
-
- args.s = s;
-
- if((s->mode & SSL_MODE_ASYNC) && !ASYNC_in_job()) {
- switch(ASYNC_start_job(&s->job, &ret, ssl_accept_intern, &args,
- sizeof(struct ssl_async_args))) {
- case ASYNC_ERR:
- SSLerr(SSL_F_SSL_ACCEPT, SSL_R_FAILED_TO_INIT_ASYNC);
- return -1;
- case ASYNC_PAUSE:
- return -1;
- case ASYNC_FINISH:
- s->job = NULL;
- return ret;
- default:
- SSLerr(SSL_F_SSL_ACCEPT, ERR_R_INTERNAL_ERROR);
- /* Shouldn't happen */
- return -1;
- }
- } else {
- 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_read_intern(void *vargs)
+static int ssl_io_intern(void *vargs)
{
struct ssl_async_args *args;
SSL *s;
s = args->s;
buf = args->buf;
num = args->num;
-
- return s->method->ssl_read(s, buf, 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)
{
- int ret;
- struct ssl_async_args args;
-
if (s->handshake_func == 0) {
SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED);
return -1;
return (0);
}
- args.s = s;
- args.buf = buf;
- args.num = num;
-
- if((s->mode & SSL_MODE_ASYNC) && !ASYNC_in_job()) {
- switch(ASYNC_start_job(&s->job, &ret, ssl_read_intern, &args,
- sizeof(struct ssl_async_args))) {
- case ASYNC_ERR:
- s->rwstate = SSL_NOTHING;
- SSLerr(SSL_F_SSL_READ, 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_READ, ERR_R_INTERNAL_ERROR);
- /* Shouldn't happen */
- return -1;
- }
+ 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);
}
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
return (0);
}
- return (s->method->ssl_peek(s, buf, num));
-}
-
-static int ssl_write_intern(void *vargs)
-{
- struct ssl_async_args *args;
- SSL *s;
- const void *buf;
- int num;
+ if((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ struct ssl_async_args args;
- args = (struct ssl_async_args *)vargs;
- s = args->s;
- buf = args->buf;
- num = args->num;
+ args.s = s;
+ args.buf = buf;
+ args.num = num;
+ args.type = 1;
+ args.f.func1 = s->method->ssl_peek;
- return s->method->ssl_write(s, buf, num);
+ 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)
{
- int ret;
- struct ssl_async_args args;
-
if (s->handshake_func == 0) {
SSLerr(SSL_F_SSL_WRITE, SSL_R_UNINITIALIZED);
return -1;
return (-1);
}
- args.s = s;
- args.buf = (void *) buf;
- args.num = num;
-
- if((s->mode & SSL_MODE_ASYNC) && !ASYNC_in_job()) {
- switch(ASYNC_start_job(&s->job, &ret, ssl_write_intern, &args,
- sizeof(struct ssl_async_args))) {
- case ASYNC_ERR:
- s->rwstate = SSL_NOTHING;
- SSLerr(SSL_F_SSL_WRITE, 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_WRITE, ERR_R_INTERNAL_ERROR);
- /* Shouldn't happen */
- return -1;
- }
+ 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);
}
unsigned long mask_k, mask_a, emask_k, emask_a;
#ifndef OPENSSL_NO_EC
int have_ecc_cert, ecdsa_ok, ecc_pkey_size;
- int have_ecdh_tmp, ecdh_ok;
+ int ecdh_ok;
X509 *x = NULL;
EVP_PKEY *ecc_pkey = NULL;
int pk_nid = 0, md_nid = 0;
dh_tmp = dh_tmp_export = 0;
#endif
-#ifndef OPENSSL_NO_EC
- have_ecdh_tmp = (c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto);
-#endif
cpk = &(c->pkeys[SSL_PKEY_RSA_ENC]);
rsa_enc = pvalid[SSL_PKEY_RSA_ENC] & CERT_PKEY_VALID;
rsa_enc_export = (rsa_enc && EVP_PKEY_size(cpk->privatekey) * 8 <= kl);
#ifdef CIPHER_DEBUG
fprintf(stderr,
- "rt=%d rte=%d dht=%d ecdht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n",
- rsa_tmp, rsa_tmp_export, dh_tmp, have_ecdh_tmp, rsa_enc,
+ "rt=%d rte=%d dht=%d re=%d ree=%d rs=%d ds=%d dhr=%d dhd=%d\n",
+ rsa_tmp, rsa_tmp_export, dh_tmp, rsa_enc,
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;
#endif
#ifndef OPENSSL_NO_EC
- if (have_ecdh_tmp) {
- mask_k |= SSL_kECDHE;
- emask_k |= SSL_kECDHE;
- }
+ mask_k |= SSL_kECDHE;
+ emask_k |= SSL_kECDHE;
#endif
#ifndef OPENSSL_NO_PSK
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;
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)
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));
}
#endif
-#ifndef OPENSSL_NO_EC
-void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,
- EC_KEY *(*ecdh) (SSL *ssl, int is_export,
- int keylength))
-{
- SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_ECDH_CB,
- (void (*)(void))ecdh);
-}
-
-void SSL_set_tmp_ecdh_callback(SSL *ssl,
- EC_KEY *(*ecdh) (SSL *ssl, int is_export,
- int keylength))
-{
- SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_ECDH_CB, (void (*)(void))ecdh);
-}
-#endif
-
#ifndef OPENSSL_NO_PSK
int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
{
/* 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;