Skip to content

The SSL_write and SSL_read return failed non-blocking when tls13 key update in any version #13729

@hou2gou

Description

@hou2gou

1> The client do key update, the server SSL_read may fail.
#8677 is one scene, and the other one. The PR #8773 does not solve the problem.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>

#define CHECK(expr)                                                            \
  do {                                                                         \
    if (!(expr)) {                                                             \
      fprintf(stderr, "Check failed at line %d: %s\n", __LINE__, #expr);       \
      ERR_print_errors_fp(stderr);                                             \
      abort();                                                                 \
    }                                                                          \
  } while (0)

static X509 *GetTestCertificate() {
  static const char kCertPEM[] =
      "-----BEGIN CERTIFICATE-----\n"
      "MIIBzzCCAXagAwIBAgIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC\n"
      "QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp\n"
      "dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ\n"
      "BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l\n"
      "dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni\n"
      "v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa\n"
      "HPUdfvGULUvPciLBo1AwTjAdBgNVHQ4EFgQUq4TSrKuV8IJOFngHVVdf5CaNgtEw\n"
      "HwYDVR0jBBgwFoAUq4TSrKuV8IJOFngHVVdf5CaNgtEwDAYDVR0TBAUwAwEB/zAJ\n"
      "BgcqhkjOPQQBA0gAMEUCIQDyoDVeUTo2w4J5m+4nUIWOcAZ0lVfSKXQA9L4Vh13E\n"
      "BwIgfB55FGohg/B6dGh5XxSZmmi08cueFV7mHzJSYV51yRQ=\n"
      "-----END CERTIFICATE-----\n";
  BIO *bio = BIO_new_mem_buf(kCertPEM, strlen(kCertPEM));
  CHECK(bio);
  X509 *ret = PEM_read_bio_X509(bio, NULL, NULL, NULL);
  CHECK(ret);
  BIO_free(bio);
  return ret;
}

static EVP_PKEY *GetTestKey() {
  static const char kKeyPEM[] =
      "-----BEGIN PRIVATE KEY-----\n"
      "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBw8IcnrUoEqc3VnJ\n"
      "TYlodwi1b8ldMHcO6NHJzgqLtGqhRANCAATmK2niv2Wfl74vHg2UikzVl2u3qR4N\n"
      "Rvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYaHPUdfvGULUvPciLB\n"
      "-----END PRIVATE KEY-----\n";
  BIO *bio = BIO_new_mem_buf(kKeyPEM, strlen(kKeyPEM));
  CHECK(bio);
  EVP_PKEY *ret = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
  CHECK(ret);
  BIO_free(bio);
  return ret;
}

int main(int argc, char **argv) {
  if (argc != 2) {
    fprintf(stderr,
            "Usage: %s [key_update_requested|key_update_not_requested]\n",
            argv[0]);
    return 1;
  }

  int key_update_type;
  if (strcmp(argv[1], "key_update_requested") == 0) {
    key_update_type = SSL_KEY_UPDATE_REQUESTED;
  } else if (strcmp(argv[1], "key_update_not_requested") == 0) {
    key_update_type = SSL_KEY_UPDATE_NOT_REQUESTED;
  } else {
    fprintf(stderr,
            "Usage: %s [key_update_requested|key_update_not_requested]\n",
            argv[0]);
    return 1;
  }

  SSL_CTX *ctx = SSL_CTX_new(TLS_method());
  CHECK(ctx);
  CHECK(SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION));
  CHECK(SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION));
  X509 *cert = GetTestCertificate();
  CHECK(SSL_CTX_use_certificate(ctx, cert));
  X509_free(cert);
  EVP_PKEY *key = GetTestKey();
  CHECK(SSL_CTX_use_PrivateKey(ctx, key));
  EVP_PKEY_free(key);

  SSL *client = SSL_new(ctx);
  CHECK(client);
  SSL_set_connect_state(client);

  SSL *server = SSL_new(ctx);
  CHECK(server);
  SSL_set_accept_state(server);

  BIO *bio1, *bio2;
  CHECK(BIO_new_bio_pair(&bio1, 1024, &bio2, 1024));
  SSL_set_bio(client, bio1, bio1);
  SSL_set_bio(server, bio2, bio2);

  // Drive both handshakes to completion.
  for (;;) {
    int client_ret = SSL_do_handshake(client);
    int client_err = SSL_get_error(client, client_ret);
    CHECK(client_err == SSL_ERROR_NONE ||
          client_err == SSL_ERROR_WANT_READ ||
          client_err == SSL_ERROR_WANT_WRITE);

    int server_ret = SSL_do_handshake(server);
    int server_err = SSL_get_error(server, server_ret);
    CHECK(server_err == SSL_ERROR_NONE ||
          server_err == SSL_ERROR_WANT_READ ||
          server_err == SSL_ERROR_WANT_WRITE);

    if (client_ret == 1 && server_ret == 1) {
      break;
    }
  }

  CHECK(SSL_key_update(client, key_update_type));

  char cwbuf[1025] = {0};
  CHECK(SSL_write(client, cwbuf, sizeof(cwbuf)) == -1);
  CHECK(SSL_get_error(client, -1) == SSL_ERROR_WANT_WRITE); 


  char srbuf[1024] = {0};
  CHECK(SSL_read(server, srbuf, sizeof(srbuf)) == -1);
  CHECK(SSL_get_error(server, -1) == SSL_ERROR_WANT_READ); 

  CHECK(SSL_write(server, "hello", 5) > 0);

  CHECK(SSL_write(client, cwbuf, sizeof(cwbuf)) > 0);
  CHECK(SSL_read(server,srbuf, sizeof(srbuf)) > 0);

  SSL_free(client);
  SSL_free(server);
  SSL_CTX_free(ctx);

  printf("OK\n");
  return 0;
}
Check failed at line 133: SSL_read(server,srbuf, sizeof(srbuf)) > 0
139705720121152:error:1408F119:SSL routines:ssl3_get_record:decryption failed or bad record mac:ssl/record/ssl3_record.c:677:

2> The client do key update, The client SSL_write/SSL_read may return fail.
#12485 have some discussion.
The commit kaduk@b653b50 only solve SSL_write,
and SSL_read also fail.

Metadata

Metadata

Assignees

No one assigned

    Labels

    triaged: bugThe issue/pr is/fixes a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions