Merge branch 'tls-session-ticket-aes256'
This commit is contained in:
commit
05d5c404e2
|
@ -91,6 +91,7 @@ OPTIONS = [
|
||||||
"header-field-buffer",
|
"header-field-buffer",
|
||||||
"max-header-fields",
|
"max-header-fields",
|
||||||
"include",
|
"include",
|
||||||
|
"tls-ticket-cipher",
|
||||||
"conf",
|
"conf",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,8 @@ int main(int argc, char *argv[]) {
|
||||||
shrpx::test_shrpx_config_parse_log_format) ||
|
shrpx::test_shrpx_config_parse_log_format) ||
|
||||||
!CU_add_test(pSuite, "config_read_tls_ticket_key_file",
|
!CU_add_test(pSuite, "config_read_tls_ticket_key_file",
|
||||||
shrpx::test_shrpx_config_read_tls_ticket_key_file) ||
|
shrpx::test_shrpx_config_read_tls_ticket_key_file) ||
|
||||||
|
!CU_add_test(pSuite, "config_read_tls_ticket_key_file_aes_256",
|
||||||
|
shrpx::test_shrpx_config_read_tls_ticket_key_file_aes_256) ||
|
||||||
!CU_add_test(pSuite, "config_match_downstream_addr_group",
|
!CU_add_test(pSuite, "config_match_downstream_addr_group",
|
||||||
shrpx::test_shrpx_config_match_downstream_addr_group) ||
|
shrpx::test_shrpx_config_match_downstream_addr_group) ||
|
||||||
!CU_add_test(pSuite, "util_streq", shrpx::test_util_streq) ||
|
!CU_add_test(pSuite, "util_streq", shrpx::test_util_streq) ||
|
||||||
|
|
50
src/shrpx.cc
50
src/shrpx.cc
|
@ -627,8 +627,21 @@ void renew_ticket_key_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
||||||
ticket_keys->keys.resize(1);
|
ticket_keys->keys.resize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RAND_bytes(reinterpret_cast<unsigned char *>(&ticket_keys->keys[0]),
|
auto &new_key = ticket_keys->keys[0];
|
||||||
sizeof(ticket_keys->keys[0])) == 0) {
|
new_key.cipher = get_config()->tls_ticket_cipher;
|
||||||
|
new_key.hmac = EVP_sha256();
|
||||||
|
new_key.hmac_keylen = EVP_MD_size(new_key.hmac);
|
||||||
|
|
||||||
|
assert(EVP_CIPHER_key_length(new_key.cipher) <= sizeof(new_key.data.enc_key));
|
||||||
|
assert(new_key.hmac_keylen <= sizeof(new_key.data.hmac_key));
|
||||||
|
|
||||||
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
LOG(INFO) << "enc_keylen=" << EVP_CIPHER_key_length(new_key.cipher)
|
||||||
|
<< ", hmac_keylen=" << new_key.hmac_keylen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RAND_bytes(reinterpret_cast<unsigned char *>(&new_key.data),
|
||||||
|
sizeof(new_key.data)) == 0) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
LOG(INFO) << "failed to renew ticket key";
|
LOG(INFO) << "failed to renew ticket key";
|
||||||
}
|
}
|
||||||
|
@ -638,7 +651,7 @@ void renew_ticket_key_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
LOG(INFO) << "ticket keys generation done";
|
LOG(INFO) << "ticket keys generation done";
|
||||||
for (auto &key : ticket_keys->keys) {
|
for (auto &key : ticket_keys->keys) {
|
||||||
LOG(INFO) << "name: " << util::format_hex(key.name, sizeof(key.name));
|
LOG(INFO) << "name: " << util::format_hex(key.data.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,8 +722,17 @@ int event_loop() {
|
||||||
if (!get_config()->upstream_no_tls) {
|
if (!get_config()->upstream_no_tls) {
|
||||||
bool auto_tls_ticket_key = true;
|
bool auto_tls_ticket_key = true;
|
||||||
if (!get_config()->tls_ticket_key_files.empty()) {
|
if (!get_config()->tls_ticket_key_files.empty()) {
|
||||||
auto ticket_keys =
|
if (!get_config()->tls_ticket_cipher_given) {
|
||||||
read_tls_ticket_key_file(get_config()->tls_ticket_key_files);
|
LOG(WARN) << "It is strongly recommended to specify "
|
||||||
|
"--tls-ticket-cipher=aes-128-cbc (or "
|
||||||
|
"tls-ticket-cipher=aes-128-cbc in configuration file) "
|
||||||
|
"when --tls-ticket-key-file is used for the smooth "
|
||||||
|
"transition when the default value of --tls-ticket-cipher "
|
||||||
|
"becomes aes-256-cbc";
|
||||||
|
}
|
||||||
|
auto ticket_keys = read_tls_ticket_key_file(
|
||||||
|
get_config()->tls_ticket_key_files, get_config()->tls_ticket_cipher,
|
||||||
|
EVP_sha256());
|
||||||
if (!ticket_keys) {
|
if (!ticket_keys) {
|
||||||
LOG(WARN) << "Use internal session ticket key generator";
|
LOG(WARN) << "Use internal session ticket key generator";
|
||||||
} else {
|
} else {
|
||||||
|
@ -967,6 +989,8 @@ void fill_default_config() {
|
||||||
mod_config()->header_field_buffer = 64_k;
|
mod_config()->header_field_buffer = 64_k;
|
||||||
mod_config()->max_header_fields = 100;
|
mod_config()->max_header_fields = 100;
|
||||||
mod_config()->downstream_addr_group_catch_all = 0;
|
mod_config()->downstream_addr_group_catch_all = 0;
|
||||||
|
mod_config()->tls_ticket_cipher = EVP_aes_128_cbc();
|
||||||
|
mod_config()->tls_ticket_cipher_given = false;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -1278,8 +1302,11 @@ SSL/TLS:
|
||||||
are treated as a part of protocol string.
|
are treated as a part of protocol string.
|
||||||
Default: )" << DEFAULT_TLS_PROTO_LIST << R"(
|
Default: )" << DEFAULT_TLS_PROTO_LIST << R"(
|
||||||
--tls-ticket-key-file=<PATH>
|
--tls-ticket-key-file=<PATH>
|
||||||
Path to file that contains 48 bytes random data to
|
Path to file that contains random data to construct TLS
|
||||||
construct TLS session ticket parameters. This options
|
session ticket parameters. If aes-128-cbc is given in
|
||||||
|
--tls-ticket-cipher, the file must contain exactly 48
|
||||||
|
bytes. If aes-256-cbc is given in --tls-ticket-cipher,
|
||||||
|
the file must contain exactly 80 bytes. This options
|
||||||
can be used repeatedly to specify multiple ticket
|
can be used repeatedly to specify multiple ticket
|
||||||
parameters. If several files are given, only the first
|
parameters. If several files are given, only the first
|
||||||
key is used to encrypt TLS session tickets. Other keys
|
key is used to encrypt TLS session tickets. Other keys
|
||||||
|
@ -1294,6 +1321,10 @@ SSL/TLS:
|
||||||
while opening or reading a file, key is generated
|
while opening or reading a file, key is generated
|
||||||
automatically and renewed every 12hrs. At most 2 keys
|
automatically and renewed every 12hrs. At most 2 keys
|
||||||
are stored in memory.
|
are stored in memory.
|
||||||
|
--tls-ticket-cipher=<TICKET_CIPHER>
|
||||||
|
Specify cipher to encrypt TLS session ticket. Specify
|
||||||
|
either aes-128-cbc or aes-256-cbc. By default,
|
||||||
|
aes-128-cbc is used.
|
||||||
--fetch-ocsp-response-file=<PATH>
|
--fetch-ocsp-response-file=<PATH>
|
||||||
Path to fetch-ocsp-response script file. It should be
|
Path to fetch-ocsp-response script file. It should be
|
||||||
absolute path.
|
absolute path.
|
||||||
|
@ -1660,6 +1691,7 @@ int main(int argc, char **argv) {
|
||||||
{SHRPX_OPT_MAX_HEADER_FIELDS, required_argument, &flag, 81},
|
{SHRPX_OPT_MAX_HEADER_FIELDS, required_argument, &flag, 81},
|
||||||
{SHRPX_OPT_ADD_REQUEST_HEADER, required_argument, &flag, 82},
|
{SHRPX_OPT_ADD_REQUEST_HEADER, required_argument, &flag, 82},
|
||||||
{SHRPX_OPT_INCLUDE, required_argument, &flag, 83},
|
{SHRPX_OPT_INCLUDE, required_argument, &flag, 83},
|
||||||
|
{SHRPX_OPT_TLS_TICKET_CIPHER, required_argument, &flag, 84},
|
||||||
{nullptr, 0, nullptr, 0}};
|
{nullptr, 0, nullptr, 0}};
|
||||||
|
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
@ -2026,6 +2058,10 @@ int main(int argc, char **argv) {
|
||||||
// --include
|
// --include
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_INCLUDE, optarg);
|
cmdcfgs.emplace_back(SHRPX_OPT_INCLUDE, optarg);
|
||||||
break;
|
break;
|
||||||
|
case 84:
|
||||||
|
// --tls-ticket-cipher
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_CIPHER, optarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,36 +144,72 @@ bool is_secure(const char *filename) {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::unique_ptr<TicketKeys>
|
std::unique_ptr<TicketKeys>
|
||||||
read_tls_ticket_key_file(const std::vector<std::string> &files) {
|
read_tls_ticket_key_file(const std::vector<std::string> &files,
|
||||||
|
const EVP_CIPHER *cipher, const EVP_MD *hmac) {
|
||||||
auto ticket_keys = make_unique<TicketKeys>();
|
auto ticket_keys = make_unique<TicketKeys>();
|
||||||
auto &keys = ticket_keys->keys;
|
auto &keys = ticket_keys->keys;
|
||||||
keys.resize(files.size());
|
keys.resize(files.size());
|
||||||
|
auto enc_keylen = EVP_CIPHER_key_length(cipher);
|
||||||
|
auto hmac_keylen = EVP_MD_size(hmac);
|
||||||
|
if (cipher == EVP_aes_128_cbc()) {
|
||||||
|
// backward compatibility, as a legacy of using same file format
|
||||||
|
// with nginx and apache.
|
||||||
|
hmac_keylen = 16;
|
||||||
|
}
|
||||||
|
auto expectedlen = sizeof(keys[0].data.name) + enc_keylen + hmac_keylen;
|
||||||
|
char buf[256];
|
||||||
|
assert(sizeof(buf) >= expectedlen);
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (auto &file : files) {
|
for (auto &file : files) {
|
||||||
|
struct stat fst {};
|
||||||
|
|
||||||
|
if (stat(file.c_str(), &fst) == -1) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(ERROR) << "tls-ticket-key-file: could not stat file " << file
|
||||||
|
<< ", errno=" << error;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fst.st_size != expectedlen) {
|
||||||
|
LOG(ERROR) << "tls-ticket-key-file: the expected file size is "
|
||||||
|
<< expectedlen << ", the actual file size is " << fst.st_size;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::ifstream f(file.c_str());
|
std::ifstream f(file.c_str());
|
||||||
if (!f) {
|
if (!f) {
|
||||||
LOG(ERROR) << "tls-ticket-key-file: could not open file " << file;
|
LOG(ERROR) << "tls-ticket-key-file: could not open file " << file;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
char buf[48];
|
|
||||||
f.read(buf, sizeof(buf));
|
f.read(buf, expectedlen);
|
||||||
if (f.gcount() != sizeof(buf)) {
|
if (f.gcount() != expectedlen) {
|
||||||
LOG(ERROR) << "tls-ticket-key-file: want to read 48 bytes but read "
|
LOG(ERROR) << "tls-ticket-key-file: want to read " << expectedlen
|
||||||
<< f.gcount() << " bytes from " << file;
|
<< " bytes but only read " << f.gcount() << " bytes from "
|
||||||
|
<< file;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &key = keys[i++];
|
auto &key = keys[i++];
|
||||||
auto p = buf;
|
key.cipher = cipher;
|
||||||
memcpy(key.name, p, sizeof(key.name));
|
key.hmac = hmac;
|
||||||
p += sizeof(key.name);
|
key.hmac_keylen = hmac_keylen;
|
||||||
memcpy(key.aes_key, p, sizeof(key.aes_key));
|
|
||||||
p += sizeof(key.aes_key);
|
|
||||||
memcpy(key.hmac_key, p, sizeof(key.hmac_key));
|
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
LOG(INFO) << "session ticket key: " << util::format_hex(key.name,
|
LOG(INFO) << "enc_keylen=" << enc_keylen
|
||||||
sizeof(key.name));
|
<< ", hmac_keylen=" << key.hmac_keylen;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto p = buf;
|
||||||
|
memcpy(key.data.name, p, sizeof(key.data.name));
|
||||||
|
p += sizeof(key.data.name);
|
||||||
|
memcpy(key.data.enc_key, p, enc_keylen);
|
||||||
|
p += enc_keylen;
|
||||||
|
memcpy(key.data.hmac_key, p, hmac_keylen);
|
||||||
|
|
||||||
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
LOG(INFO) << "session ticket key: " << util::format_hex(key.data.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ticket_keys;
|
return ticket_keys;
|
||||||
|
@ -668,6 +704,7 @@ enum {
|
||||||
SHRPX_OPTID_SUBCERT,
|
SHRPX_OPTID_SUBCERT,
|
||||||
SHRPX_OPTID_SYSLOG_FACILITY,
|
SHRPX_OPTID_SYSLOG_FACILITY,
|
||||||
SHRPX_OPTID_TLS_PROTO_LIST,
|
SHRPX_OPTID_TLS_PROTO_LIST,
|
||||||
|
SHRPX_OPTID_TLS_TICKET_CIPHER,
|
||||||
SHRPX_OPTID_TLS_TICKET_KEY_FILE,
|
SHRPX_OPTID_TLS_TICKET_KEY_FILE,
|
||||||
SHRPX_OPTID_USER,
|
SHRPX_OPTID_USER,
|
||||||
SHRPX_OPTID_VERIFY_CLIENT,
|
SHRPX_OPTID_VERIFY_CLIENT,
|
||||||
|
@ -959,6 +996,11 @@ int option_lookup_token(const char *name, size_t namelen) {
|
||||||
return SHRPX_OPTID_WORKER_WRITE_RATE;
|
return SHRPX_OPTID_WORKER_WRITE_RATE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'r':
|
||||||
|
if (util::strieq_l("tls-ticket-ciphe", name, 16)) {
|
||||||
|
return SHRPX_OPTID_TLS_TICKET_CIPHER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
if (util::strieq_l("max-header-field", name, 16)) {
|
if (util::strieq_l("max-header-field", name, 16)) {
|
||||||
return SHRPX_OPTID_MAX_HEADER_FIELDS;
|
return SHRPX_OPTID_MAX_HEADER_FIELDS;
|
||||||
|
@ -1805,6 +1847,19 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case SHRPX_OPTID_TLS_TICKET_CIPHER:
|
||||||
|
if (util::strieq(optarg, "aes-128-cbc")) {
|
||||||
|
mod_config()->tls_ticket_cipher = EVP_aes_128_cbc();
|
||||||
|
} else if (util::strieq(optarg, "aes-256-cbc")) {
|
||||||
|
mod_config()->tls_ticket_cipher = EVP_aes_256_cbc();
|
||||||
|
} else {
|
||||||
|
LOG(ERROR) << opt
|
||||||
|
<< ": unsupported cipher for ticket encryption: " << optarg;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mod_config()->tls_ticket_cipher_given = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
case SHRPX_OPTID_CONF:
|
case SHRPX_OPTID_CONF:
|
||||||
LOG(WARN) << "conf: ignored";
|
LOG(WARN) << "conf: ignored";
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,7 @@ constexpr char SHRPX_OPT_NO_OCSP[] = "no-ocsp";
|
||||||
constexpr char SHRPX_OPT_HEADER_FIELD_BUFFER[] = "header-field-buffer";
|
constexpr char SHRPX_OPT_HEADER_FIELD_BUFFER[] = "header-field-buffer";
|
||||||
constexpr char SHRPX_OPT_MAX_HEADER_FIELDS[] = "max-header-fields";
|
constexpr char SHRPX_OPT_MAX_HEADER_FIELDS[] = "max-header-fields";
|
||||||
constexpr char SHRPX_OPT_INCLUDE[] = "include";
|
constexpr char SHRPX_OPT_INCLUDE[] = "include";
|
||||||
|
constexpr char SHRPX_OPT_TLS_TICKET_CIPHER[] = "tls-ticket-cipher";
|
||||||
|
|
||||||
union sockaddr_union {
|
union sockaddr_union {
|
||||||
sockaddr_storage storage;
|
sockaddr_storage storage;
|
||||||
|
@ -224,9 +225,17 @@ struct DownstreamAddrGroup {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TicketKey {
|
struct TicketKey {
|
||||||
uint8_t name[16];
|
const EVP_CIPHER *cipher;
|
||||||
uint8_t aes_key[16];
|
const EVP_MD *hmac;
|
||||||
uint8_t hmac_key[16];
|
size_t hmac_keylen;
|
||||||
|
struct {
|
||||||
|
// name of this ticket configuration
|
||||||
|
uint8_t name[16];
|
||||||
|
// encryption key for |cipher|
|
||||||
|
uint8_t enc_key[32];
|
||||||
|
// hmac key for |hmac|
|
||||||
|
uint8_t hmac_key[32];
|
||||||
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TicketKeys {
|
struct TicketKeys {
|
||||||
|
@ -300,6 +309,7 @@ struct Config {
|
||||||
nghttp2_session_callbacks *http2_downstream_callbacks;
|
nghttp2_session_callbacks *http2_downstream_callbacks;
|
||||||
nghttp2_option *http2_option;
|
nghttp2_option *http2_option;
|
||||||
nghttp2_option *http2_client_option;
|
nghttp2_option *http2_client_option;
|
||||||
|
const EVP_CIPHER *tls_ticket_cipher;
|
||||||
char **argv;
|
char **argv;
|
||||||
char *cwd;
|
char *cwd;
|
||||||
size_t num_worker;
|
size_t num_worker;
|
||||||
|
@ -376,6 +386,8 @@ struct Config {
|
||||||
// true if host contains UNIX domain socket path
|
// true if host contains UNIX domain socket path
|
||||||
bool host_unix;
|
bool host_unix;
|
||||||
bool no_ocsp;
|
bool no_ocsp;
|
||||||
|
// true if --tls-ticket-cipher is used
|
||||||
|
bool tls_ticket_cipher_given;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Config *get_config();
|
const Config *get_config();
|
||||||
|
@ -447,10 +459,12 @@ int int_syslog_facility(const char *strfacility);
|
||||||
FILE *open_file_for_write(const char *filename);
|
FILE *open_file_for_write(const char *filename);
|
||||||
|
|
||||||
// Reads TLS ticket key file in |files| and returns TicketKey which
|
// Reads TLS ticket key file in |files| and returns TicketKey which
|
||||||
// stores read key data. This function returns TicketKey if it
|
// stores read key data. The given |cipher| and |hmac| determine the
|
||||||
|
// expected file size. This function returns TicketKey if it
|
||||||
// succeeds, or nullptr.
|
// succeeds, or nullptr.
|
||||||
std::unique_ptr<TicketKeys>
|
std::unique_ptr<TicketKeys>
|
||||||
read_tls_ticket_key_file(const std::vector<std::string> &files);
|
read_tls_ticket_key_file(const std::vector<std::string> &files,
|
||||||
|
const EVP_CIPHER *cipher, const EVP_MD *hmac);
|
||||||
|
|
||||||
// Selects group based on request's |hostport| and |path|. |hostport|
|
// Selects group based on request's |hostport| and |path|. |hostport|
|
||||||
// is the value taken from :authority or host header field, and may
|
// is the value taken from :authority or host header field, and may
|
||||||
|
|
|
@ -190,24 +190,62 @@ void test_shrpx_config_read_tls_ticket_key_file(void) {
|
||||||
|
|
||||||
close(fd1);
|
close(fd1);
|
||||||
close(fd2);
|
close(fd2);
|
||||||
auto ticket_keys = read_tls_ticket_key_file({file1, file2});
|
auto ticket_keys =
|
||||||
|
read_tls_ticket_key_file({file1, file2}, EVP_aes_128_cbc(), EVP_sha256());
|
||||||
unlink(file1);
|
unlink(file1);
|
||||||
unlink(file2);
|
unlink(file2);
|
||||||
CU_ASSERT(ticket_keys.get() != nullptr);
|
CU_ASSERT(ticket_keys.get() != nullptr);
|
||||||
CU_ASSERT(2 == ticket_keys->keys.size());
|
CU_ASSERT(2 == ticket_keys->keys.size());
|
||||||
auto key = &ticket_keys->keys[0];
|
auto key = &ticket_keys->keys[0];
|
||||||
CU_ASSERT(0 == memcmp("0..............1", key->name, sizeof(key->name)));
|
|
||||||
CU_ASSERT(0 ==
|
CU_ASSERT(0 ==
|
||||||
memcmp("2..............3", key->aes_key, sizeof(key->aes_key)));
|
memcmp("0..............1", key->data.name, sizeof(key->data.name)));
|
||||||
CU_ASSERT(0 ==
|
CU_ASSERT(0 == memcmp("2..............3", key->data.enc_key, 16));
|
||||||
memcmp("4..............5", key->hmac_key, sizeof(key->hmac_key)));
|
CU_ASSERT(0 == memcmp("4..............5", key->data.hmac_key, 16));
|
||||||
|
|
||||||
key = &ticket_keys->keys[1];
|
key = &ticket_keys->keys[1];
|
||||||
CU_ASSERT(0 == memcmp("6..............7", key->name, sizeof(key->name)));
|
|
||||||
CU_ASSERT(0 ==
|
CU_ASSERT(0 ==
|
||||||
memcmp("8..............9", key->aes_key, sizeof(key->aes_key)));
|
memcmp("6..............7", key->data.name, sizeof(key->data.name)));
|
||||||
|
CU_ASSERT(0 == memcmp("8..............9", key->data.enc_key, 16));
|
||||||
|
CU_ASSERT(0 == memcmp("a..............b", key->data.hmac_key, 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_shrpx_config_read_tls_ticket_key_file_aes_256(void) {
|
||||||
|
char file1[] = "/tmp/nghttpx-unittest.XXXXXX";
|
||||||
|
auto fd1 = mkstemp(file1);
|
||||||
|
assert(fd1 != -1);
|
||||||
|
assert(80 == write(fd1, "0..............12..............................34..."
|
||||||
|
"...........................5",
|
||||||
|
80));
|
||||||
|
char file2[] = "/tmp/nghttpx-unittest.XXXXXX";
|
||||||
|
auto fd2 = mkstemp(file2);
|
||||||
|
assert(fd2 != -1);
|
||||||
|
assert(80 == write(fd2, "6..............78..............................9a..."
|
||||||
|
"...........................b",
|
||||||
|
80));
|
||||||
|
|
||||||
|
close(fd1);
|
||||||
|
close(fd2);
|
||||||
|
auto ticket_keys =
|
||||||
|
read_tls_ticket_key_file({file1, file2}, EVP_aes_256_cbc(), EVP_sha256());
|
||||||
|
unlink(file1);
|
||||||
|
unlink(file2);
|
||||||
|
CU_ASSERT(ticket_keys.get() != nullptr);
|
||||||
|
CU_ASSERT(2 == ticket_keys->keys.size());
|
||||||
|
auto key = &ticket_keys->keys[0];
|
||||||
CU_ASSERT(0 ==
|
CU_ASSERT(0 ==
|
||||||
memcmp("a..............b", key->hmac_key, sizeof(key->hmac_key)));
|
memcmp("0..............1", key->data.name, sizeof(key->data.name)));
|
||||||
|
CU_ASSERT(0 ==
|
||||||
|
memcmp("2..............................3", key->data.enc_key, 32));
|
||||||
|
CU_ASSERT(0 ==
|
||||||
|
memcmp("4..............................5", key->data.hmac_key, 32));
|
||||||
|
|
||||||
|
key = &ticket_keys->keys[1];
|
||||||
|
CU_ASSERT(0 ==
|
||||||
|
memcmp("6..............7", key->data.name, sizeof(key->data.name)));
|
||||||
|
CU_ASSERT(0 ==
|
||||||
|
memcmp("8..............................9", key->data.enc_key, 32));
|
||||||
|
CU_ASSERT(0 ==
|
||||||
|
memcmp("a..............................b", key->data.hmac_key, 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_shrpx_config_match_downstream_addr_group(void) {
|
void test_shrpx_config_match_downstream_addr_group(void) {
|
||||||
|
|
|
@ -35,6 +35,7 @@ void test_shrpx_config_parse_config_str_list(void);
|
||||||
void test_shrpx_config_parse_header(void);
|
void test_shrpx_config_parse_header(void);
|
||||||
void test_shrpx_config_parse_log_format(void);
|
void test_shrpx_config_parse_log_format(void);
|
||||||
void test_shrpx_config_read_tls_ticket_key_file(void);
|
void test_shrpx_config_read_tls_ticket_key_file(void);
|
||||||
|
void test_shrpx_config_read_tls_ticket_key_file_aes_256(void);
|
||||||
void test_shrpx_config_match_downstream_addr_group(void);
|
void test_shrpx_config_match_downstream_addr_group(void);
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -213,21 +213,21 @@ int ticket_key_cb(SSL *ssl, unsigned char *key_name, unsigned char *iv,
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
CLOG(INFO, handler) << "encrypt session ticket key: "
|
CLOG(INFO, handler) << "encrypt session ticket key: "
|
||||||
<< util::format_hex(key.name, 16);
|
<< util::format_hex(key.data.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(key_name, key.name, sizeof(key.name));
|
memcpy(key_name, key.data.name, sizeof(key.data.name));
|
||||||
|
|
||||||
EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), nullptr, key.aes_key, iv);
|
EVP_EncryptInit_ex(ctx, get_config()->tls_ticket_cipher, nullptr,
|
||||||
HMAC_Init_ex(hctx, key.hmac_key, sizeof(key.hmac_key), EVP_sha256(),
|
key.data.enc_key, iv);
|
||||||
nullptr);
|
HMAC_Init_ex(hctx, key.data.hmac_key, key.hmac_keylen, key.hmac, nullptr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < keys.size(); ++i) {
|
for (i = 0; i < keys.size(); ++i) {
|
||||||
auto &key = keys[0];
|
auto &key = keys[0];
|
||||||
if (memcmp(key.name, key_name, sizeof(key.name)) == 0) {
|
if (memcmp(key_name, key.data.name, sizeof(key.data.name)) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,8 +246,8 @@ int ticket_key_cb(SSL *ssl, unsigned char *key_name, unsigned char *iv,
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &key = keys[i];
|
auto &key = keys[i];
|
||||||
HMAC_Init_ex(hctx, key.hmac_key, sizeof(key.hmac_key), EVP_sha256(), nullptr);
|
HMAC_Init_ex(hctx, key.data.hmac_key, key.hmac_keylen, key.hmac, nullptr);
|
||||||
EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), nullptr, key.aes_key, iv);
|
EVP_DecryptInit_ex(ctx, key.cipher, nullptr, key.data.enc_key, iv);
|
||||||
|
|
||||||
return i == 0 ? 1 : 2;
|
return i == 0 ? 1 : 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,10 @@ std::string quote_string(const std::string &target);
|
||||||
|
|
||||||
std::string format_hex(const unsigned char *s, size_t len);
|
std::string format_hex(const unsigned char *s, size_t len);
|
||||||
|
|
||||||
|
template <size_t N> std::string format_hex(const unsigned char (&s)[N]) {
|
||||||
|
return format_hex(s, N);
|
||||||
|
}
|
||||||
|
|
||||||
std::string http_date(time_t t);
|
std::string http_date(time_t t);
|
||||||
|
|
||||||
// Returns given time |t| from epoch in Common Log format (e.g.,
|
// Returns given time |t| from epoch in Common Log format (e.g.,
|
||||||
|
|
Loading…
Reference in New Issue