From nobody Tue Sep 29 16:00:12 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hvNDY2Kxmz6tlT5 for ; Tue, 29 Sep 2026 16:00:13 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hvNDX5YBqz4gt0 for ; Tue, 29 Sep 2026 16:00:12 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790697612; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=P3ymAuFgmDiEa956w/iIoNKTYXz1W6HiT2tFT2OAU0A=; b=o3BiPHMPZMYqNTHp32Eg3qPsMgsYfJVxpyqf7TwrVejBSDlZp75cE/FTAlHIo4iDctuaS3 0JDOHH/ZqySvmTCKEoNNPgw/Qf+nyJ3Gd651dJQ93aJGGhQ4jz+ojbQ7q1n3260EGU8288 K2NG/512P0MUCNECK91rUzqf621l0ntMOIEY/ZHIaw52P6guKkAE9pAV1H6CPjPcNG7f8e t2d14UOOe7NSWifM72zTN9cEuGDArT59vk1DcLyiMPPZIzXuExj19wHQ1QL0AVxCOhoktJ STll0NHr+fu6aB9e2ATwWdpH/sz4ba6Gm+8U1E2jo159FE0sOdUpokw16Lpm1w== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1790697612; b=EpMxSzaBNeh4hV2lz8xY+lvS4O0XGPD7qMYw+DhVTmFTPRBMrshopFsz4C8nG9DsMplSPn ZHqi13WKjn9GrC7njHMq8xQApV222BbubaeVu22iYz3qx2RiLXsLOlRBxKt5iZ+wxYAUEl lHiJ/l/yb57D7uRDnAsfP6+NAnNhUG6pqGf3cLgh7+kA76FinAnuYQU/59egIjqWBcAlfM jdoXpXZVFKt1o+eMU0eaplu9Y/oG9N6MoE3/vga341AuVrJLYITCJHRDY2JvgoLSJuZsqP EUFichUEBjuQMlIHSXsr1YmF9ORVpoO1G55dbZefFq1Rq8T01TZKTuzYkYg8pw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1790697612; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=P3ymAuFgmDiEa956w/iIoNKTYXz1W6HiT2tFT2OAU0A=; b=D7fgfJwHYIX6ioz7f42Fpvg1DnsxScHxTdnw16iiZM42JG0VUVQo9/HIs4aFRXvTpCRFLQ u+lBCyAQhXVp1K69R5rbqYKbQzuiflFHfN6/Kg5aKA3BKmJwLINu0/qCIXZa3PaW2RmDwx r9eFWe8oiC8KNY3+pAvd5/18B7DkAW7xLYjlgbZuhc494zto1DOvh8Z5omaLnFvX72Ysvt d2cRUfr/sj0uhw+znnhKK3rUP8wZtPGkTn6c2zOjz1VONw3Hf8cbei/j9mFLBm6znTnOhD yMDWPcIgvEFTRvO/qK8Y6WBWHdCDDe7IKeVF8jlEBSi/6MiJ79sjUZuDARtxVQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hvNDX4cS7z1KPp for ; Tue, 29 Sep 2026 16:00:12 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 302db by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 29 Sep 2026 16:00:12 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Cc: Gordon Tetlow From: Mark Johnston Subject: git: f144a7164a1f - releng/15.1 - openssl: Fix CVE-2026-84782 List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/releng/15.1 X-Git-Reftype: branch X-Git-Commit: f144a7164a1f6fa7c2ac647465dc54f401a6072b Auto-Submitted: auto-generated Date: Tue, 29 Sep 2026 16:00:12 +0000 Message-Id: <6abbe08c.302db.1d3053d7@gitrepo.freebsd.org> The branch releng/15.1 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=f144a7164a1f6fa7c2ac647465dc54f401a6072b commit f144a7164a1f6fa7c2ac647465dc54f401a6072b Author: Gordon Tetlow AuthorDate: 2026-09-02 19:15:41 +0000 Commit: Mark Johnston CommitDate: 2026-09-29 01:01:48 +0000 openssl: Fix CVE-2026-84782 This is a commit from upstream to fix: dtls: reset init_off before retransmitting a message Approved by: so Security: FreeBSD-SA-26:68.openssl Security: CVE-2026-84782 --- crypto/openssl/ssl/d1_lib.c | 17 ++ crypto/openssl/ssl/statem/statem_dtls.c | 2 + crypto/openssl/test/dtlstest.c | 416 +++++++++++++++++++++++++++++++- 3 files changed, 433 insertions(+), 2 deletions(-) diff --git a/crypto/openssl/ssl/d1_lib.c b/crypto/openssl/ssl/d1_lib.c index ad1bc7d8c830..5e8f57f01a3a 100644 --- a/crypto/openssl/ssl/d1_lib.c +++ b/crypto/openssl/ssl/d1_lib.c @@ -406,6 +406,23 @@ int dtls1_handle_timeout(SSL_CONNECTION *s) } dtls1_start_timer(s); + + /* + * If write_state is anything other than WRITE_STATE_TRANSITION, a write + * is still parked mid-flight (WANT_WRITE) from a previous call into the + * state machine - the current flight hasn't actually finished going out + * yet, so there's nothing valid to retransmit. Retransmitting anyway + * would reconstruct an already-sent message from the retransmit queue + * into s->init_buf/s->init_off/s->init_num/s->d1->w_msg - the same + * fields the parked write is still using - corrupting that write's + * state out from under it. Leave it alone and let the next + * SSL_read()/SSL_write()/SSL_accept()/SSL_connect() call resume the + * parked write normally instead. + */ + if (s->statem.state == MSG_FLOW_WRITING + && s->statem.write_state != WRITE_STATE_TRANSITION) + return 0; + /* Calls SSLfatal() if required */ return dtls1_retransmit_buffered_messages(s); } diff --git a/crypto/openssl/ssl/statem/statem_dtls.c b/crypto/openssl/ssl/statem/statem_dtls.c index f62b757721fc..96ea03ab73cc 100644 --- a/crypto/openssl/ssl/statem/statem_dtls.c +++ b/crypto/openssl/ssl/statem/statem_dtls.c @@ -1218,6 +1218,8 @@ int dtls1_retransmit_message(SSL_CONNECTION *s, unsigned short seq, int *found) memcpy(s->init_buf->data, frag->fragment, frag->msg_header.msg_len + header_length); s->init_num = frag->msg_header.msg_len + header_length; + /* Always retransmit from the start, not wherever init_off was left */ + s->init_off = 0; dtls1_set_message_header_int(s, frag->msg_header.type, frag->msg_header.msg_len, diff --git a/crypto/openssl/test/dtlstest.c b/crypto/openssl/test/dtlstest.c index 725d7dc4f2b8..4e5ea51e9599 100644 --- a/crypto/openssl/test/dtlstest.c +++ b/crypto/openssl/test/dtlstest.c @@ -60,7 +60,6 @@ static int verify_cookie_cb(SSL *ssl, const unsigned char *cookie, static unsigned int timer_cb(SSL *s, unsigned int timer_us) { ++timer_cb_count; - if (timer_us == 0) return 50000; else @@ -681,6 +680,416 @@ end: return testresult; } +/* + * frag_bio and the four retransmit tests below need DTLS1.2 + */ +#ifndef OPENSSL_NO_DTLS1_2 + +/* + * Number of times the retransmit timer is fired while a write is parked, in + * each of the four tests below + */ +#define NUM_RETRANSMITS 3 + +typedef struct { + BIO *bio; + int allowed; /* number of fragment writes to let through before suspending */ + int write_calls; /* number of times frag_write() has been invoked at all */ +} frag_bio; + +/* + * Each call to this function corresponds to exactly one DTLS fragment being + * handed to the BIO by dtls1_do_write(). Once |allowed| fragments have been + * let through, every further write suspends (WANT_WRITE) until the test + * bumps |allowed| again. + */ +static int frag_write(BIO *bio, const char *buf, size_t len, size_t *written) +{ + frag_bio *f = BIO_get_data(bio); + + BIO_clear_retry_flags(bio); + + f->write_calls++; + + if (f->allowed <= 0) { + BIO_set_retry_write(bio); + *written = 0; + return 0; + } + f->allowed--; + + if (!BIO_write_ex(f->bio, buf, len, written)) { + fprintf(stderr, "Failed to send data via BIO_write_ex\n"); + return 0; + } + + return 1; +} + +static int frag_read(BIO *bio, char *buf, size_t buf_len, size_t *readbytes) +{ + frag_bio *f = BIO_get_data(bio); + return BIO_read_ex(f->bio, buf, buf_len, readbytes); +} + +static long frag_ctrl(BIO *bio, int cmd, long num, void *ptr) +{ + frag_bio *f = BIO_get_data(bio); + return BIO_ctrl(f->bio, cmd, num, ptr); +} + +static int frag_puts(BIO *bio, const char *str) +{ + size_t written; + return frag_write(bio, str, strlen(str), &written) ? (int)written : -1; +} + +static int frag_create(BIO *bio) +{ + frag_bio *f = OPENSSL_zalloc(sizeof(*f)); + if (f == NULL) + return 0; + BIO_set_data(bio, f); + BIO_set_init(bio, 1); + return 1; +} + +static int frag_destroy(BIO *bio) +{ + frag_bio *f = BIO_get_data(bio); + if (f == NULL) + return 1; + + BIO_free(f->bio); + OPENSSL_free(f); + BIO_set_data(bio, NULL); + BIO_set_init(bio, 0); + return 1; +} + +static BIO_METHOD *frag_method(void) +{ + static BIO_METHOD *m = NULL; + if (m == NULL) { + m = BIO_meth_new(BIO_TYPE_SOURCE_SINK | BIO_TYPE_FILTER, "fragment-limited dgram"); + BIO_meth_set_write_ex(m, frag_write); + BIO_meth_set_read_ex(m, frag_read); + BIO_meth_set_ctrl(m, frag_ctrl); + BIO_meth_set_puts(m, frag_puts); + BIO_meth_set_create(m, frag_create); + BIO_meth_set_destroy(m, frag_destroy); + } + return m; +} + +static BIO *frag_new(BIO *bio, int allowed) +{ + BIO *b = BIO_new(frag_method()); + frag_bio *f; + if (b == NULL) { + BIO_free(bio); + return NULL; + } + f = BIO_get_data(b); + f->bio = bio; + f->allowed = allowed; + return b; +} + +/* + * DTLS1.2 only. Exercises dtls1_handle_timeout()'s write_state guard (see + * d1_lib.c): while a write is parked mid-flight (WANT_WRITE, suspended here + * by a fragment-limiting BIO), a firing retransmit timer must not touch the + * retransmit queue at all - dtls1_retransmit_sent_messages() should never be + * entered, since retransmitting a message concurrently with the live write + * reusing the very same s->init_off/s->init_num/s->d1->w_msg fields would + * corrupt whichever write resumes second. + * + * Without the guard, letting that retransmit run ClientHello to completion + * while its own live write is still parked resets s->init_off/s->init_num + * to 0/0 out from under that write - so when the app resumes with + * SSL_connect(), dtls1_do_write() re-enters believing s->init_off == 0 means + * a brand new message is starting, when s->init_num no longer matches + * ClientHello's real length the way a fresh message's would - hitting an + * internal entry assertion and calling OPENSSL_die()/abort(). + * + * The client never calls SSL_connect() again until the very end, so the + * server is never driven far enough to respond - there's nothing to + * retransmit ClientHello against except the timer, driven purely by + * DTLSv1_get_timeout()/DTLSv1_handle_timeout(). + */ +static int test_dtls_client_retransmit(void) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + int testresult = 0; + int ret, err, i; + struct timeval tv; + static unsigned char alpn[750]; + size_t j, used = 0; + BIO *c_to_s_bio = NULL; + BIO *frag_wbio; + frag_bio *fb; + int write_calls_before; + + if (!TEST_true(create_ssl_ctx_pair(NULL, DTLS_server_method(), + DTLS_client_method(), + DTLS1_2_VERSION, DTLS1_2_VERSION, + &sctx, &cctx, cert, privkey))) + return 0; + + SSL_CTX_set_verify(cctx, SSL_VERIFY_NONE, NULL); + + /* Pad the ClientHello out via ALPN so it needs multiple fragments. */ + for (j = 0; j < 3; j++) { + char name[250]; + int n = snprintf(name, sizeof(name), + "proto-%04u-%s", (unsigned int)j, + "padpadpadpadpadpadpadpadpadpadpadpadpadpadpad" + "padpadpadpadpadpadpadpadpadpadpadpadpadpadpad" + "padpadpadpadpadpadpadpadpadpadpadpadpadpadpad" + "padpadpadpadpadpadpadpadpadpadpadpadpadpadpad" + "padpadpadpadpadpadpadpadpadpadpadpadpadpad"); + + if (!TEST_int_ge(n, 0) || !TEST_size_t_lt((size_t)n, sizeof(name))) + goto end; + if (!TEST_size_t_le(used + 1 + (size_t)n, sizeof(alpn))) + goto end; + + alpn[used++] = (unsigned char)n; + memcpy(alpn + used, name, (size_t)n); + used += (size_t)n; + } + if (!TEST_false(SSL_CTX_set_alpn_protos(cctx, alpn, (unsigned int)used))) + goto end; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + /* + * Pin the MTU so fragmentation of the ClientHello (padded out via ALPN + * above) is deterministic. SSL_OP_NO_QUERY_MTU stops dtls1_query_mtu() + * from overriding this with a value queried from the BIO. + */ + SSL_set_options(clientssl, SSL_OP_NO_QUERY_MTU); + if (!TEST_true(SSL_set_mtu(clientssl, 256))) + goto end; + + /* + * Wrap the client's write BIO in our fragment-limiting filter, initially + * allowing only the ClientHello's first fragment through. SSL_get_wbio() + * is a borrowed reference, and SSL_set0_wbio() will free whatever the old + * wbio pointer was as soon as we install the replacement - so we need our + * own ref on the underlying bio before frag_new() stores it internally, + * otherwise the wrapper is left holding a dangling pointer. + */ + c_to_s_bio = SSL_get_wbio(clientssl); + + if (!TEST_ptr(c_to_s_bio) || !TEST_true(BIO_up_ref(c_to_s_bio))) + goto end; + + frag_wbio = frag_new(c_to_s_bio, 1); + if (!TEST_ptr(frag_wbio)) { + BIO_free(c_to_s_bio); + goto end; + } + fb = BIO_get_data(frag_wbio); + + SSL_set0_wbio(clientssl, frag_wbio); + + DTLS_set_timer_cb(clientssl, timer_cb); + + /* + * Flight 1: frag_wbio's budget of 1 write buys exactly ClientHello's + * first fragment - that's all that goes out. The next write (its + * second fragment) is what actually suspends, leaving write_state + * parked at WRITE_STATE_SEND, waiting to resume ClientHello. + */ + ret = SSL_connect(clientssl); + if (!TEST_int_le(ret, 0) + || !TEST_int_eq(SSL_get_error(clientssl, ret), SSL_ERROR_WANT_WRITE)) + goto end; + + /* + * Let the retransmit timer fire, NUM_RETRANSMITS times, while the write + * above is still parked. fb->allowed = 100 so our custom BIO isn't what + * would block a retransmit, if one were sent. frag_write()'s call + * counter shouldn't move at all, round after round. + */ + fb->allowed = 100; + + for (i = 0; i < NUM_RETRANSMITS; i++) { + write_calls_before = fb->write_calls; + + if (!TEST_int_gt((int)DTLSv1_get_timeout(clientssl, &tv), 0)) + goto end; + + /* Wait for the retransmit timer to actually expire */ + OSSL_sleep((uint64_t)(tv.tv_sec * 1000 + tv.tv_usec / 1000) + 10); + + if (!TEST_int_ge((int)DTLSv1_handle_timeout(clientssl), 0)) + goto end; + + if (!TEST_int_eq(fb->write_calls, write_calls_before)) + goto end; + } + + /* + * Resume the original suspended write. This is the call expected to + * hit the entry assertion described above if the guard weren't there. + */ + ret = SSL_connect(clientssl); + err = SSL_get_error(clientssl, ret); + + /* + * If we get here at all (i.e. we didn't just abort()), the resume + * should look like an ordinary handshake continuation - WANT_READ or + * WANT_WRITE, not an internal failure. + */ + if (!TEST_false(err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL)) + goto end; + + testresult = 1; +end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + +/* + * DTLS1.2 only. Server-side counterpart to test_dtls_client_retransmit(): + * same write_state guard, but Certificate suspends mid-write during the + * server's flight instead of ClientHello. The cipher is pinned to a + * static-RSA suite so the flight is just ServerHello + Certificate + + * ServerHelloDone (no ServerKeyExchange); with a 256 byte MTU, ServerHello + * fits in a single fragment but Certificate does not. + * + * The client never calls SSL_accept() again until the very end, so the + * server is driven purely by DTLSv1_get_timeout()/DTLSv1_handle_timeout(). + */ +static int test_dtls_server_retransmit(void) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *serverssl = NULL, *clientssl = NULL; + int testresult = 0; + int ret, err, i; + struct timeval tv; + BIO *s_to_c_bio = NULL; + BIO *frag_wbio; + frag_bio *fb; + int write_calls_before; + + if (!TEST_true(create_ssl_ctx_pair(NULL, DTLS_server_method(), + DTLS_client_method(), + DTLS1_2_VERSION, DTLS1_2_VERSION, + &sctx, &cctx, cert, privkey))) + return 0; + + /* Static RSA cipher: no ServerKeyExchange, keeps the flight simple. */ + if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "AES128-SHA"))) + goto end; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL))) + goto end; + + /* + * Pin the server's MTU so its flight fragments deterministically. The + * client is left alone - its ClientHello is small and unfragmented. + */ + SSL_set_options(serverssl, SSL_OP_NO_QUERY_MTU); + if (!TEST_true(SSL_set_mtu(serverssl, 256))) + goto end; + + /* Wrap only the server's write BIO in our fragment-limiting filter. */ + s_to_c_bio = SSL_get_wbio(serverssl); + + if (!TEST_ptr(s_to_c_bio) || !TEST_true(BIO_up_ref(s_to_c_bio))) + goto end; + + /* Only let ServerHello and Certificate's first fragment out initially. */ + frag_wbio = frag_new(s_to_c_bio, 2); + if (!TEST_ptr(frag_wbio)) { + BIO_free(s_to_c_bio); + goto end; + } + fb = BIO_get_data(frag_wbio); + + SSL_set0_wbio(serverssl, frag_wbio); + + DTLS_set_timer_cb(serverssl, timer_cb); + + /* Flight 1: the client sends its ClientHello without any restriction. */ + if (!TEST_int_le(SSL_connect(clientssl), 0)) + goto end; + + /* + * Flight 2: frag_wbio's budget of 2 writes buys exactly ServerHello in + * full plus the first fragment of Certificate - that's all that goes + * out. The next write (Certificate's second fragment) is what actually + * suspends, leaving write_state parked at WRITE_STATE_SEND, waiting to + * resume Certificate specifically. + */ + ret = SSL_accept(serverssl); + if (!TEST_int_le(ret, 0) + || !TEST_int_eq(SSL_get_error(serverssl, ret), SSL_ERROR_WANT_WRITE)) + goto end; + + /* + * Let the retransmit timer fire, NUM_RETRANSMITS times, while the write + * above is still parked. fb->allowed = 100 so our custom BIO isn't what + * would block a retransmit, if one were sent. frag_write()'s call + * counter shouldn't move at all, round after round. + */ + fb->allowed = 100; + + for (i = 0; i < NUM_RETRANSMITS; i++) { + write_calls_before = fb->write_calls; + + if (!TEST_int_gt((int)DTLSv1_get_timeout(serverssl, &tv), 0)) + goto end; + + OSSL_sleep((uint64_t)(tv.tv_sec * 1000 + tv.tv_usec / 1000) + 10); + + if (!TEST_int_ge((int)DTLSv1_handle_timeout(serverssl), 0)) + goto end; + + if (!TEST_int_eq(fb->write_calls, write_calls_before)) + goto end; + } + + /* + * Resume the original suspended write. This is the call expected to + * hit the entry assertion described in test_dtls_client_retransmit() if + * the guard weren't there. + */ + ret = SSL_accept(serverssl); + err = SSL_get_error(serverssl, ret); + + /* + * If we get here at all (i.e. we didn't just abort()), the resume + * should look like an ordinary handshake continuation - WANT_READ or + * WANT_WRITE, not an internal failure. + */ + if (!TEST_false(err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL)) + goto end; + + testresult = 1; +end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + + return testresult; +} + +#endif + /* Confirm that we can create a connections using DTLSv1_listen() */ static int test_listen(void) { @@ -753,7 +1162,10 @@ int setup_tests(void) ADD_ALL_TESTS(test_swap_records, 4); ADD_TEST(test_listen); ADD_TEST(test_duplicate_app_data); - +#ifndef OPENSSL_NO_DTLS1_2 + ADD_TEST(test_dtls_client_retransmit); + ADD_TEST(test_dtls_server_retransmit); +#endif return 1; }