Rename and reorder some of the pairing definitions and structures.

This commit is contained in:
Mike Brady
2022-06-25 14:15:56 +01:00
parent f39a42483c
commit d36decbd36
2 changed files with 63 additions and 59 deletions
+11 -7
View File
@@ -117,18 +117,22 @@ typedef enum { realtime_stream, buffered_stream } airplay_stream_t;
typedef struct {
uint8_t *data;
size_t len;
size_t length;
size_t size;
} ap2_buffer;
} sized_buffer;
typedef struct {
struct pair_cipher_context *cipher_ctx;
sized_buffer encrypted_read_buffer;
sized_buffer plaintext_read_buffer;
int is_encrypted;
} pair_cipher_bundle; // cipher context and buffers
typedef struct {
struct pair_setup_context *setup_ctx;
struct pair_verify_context *verify_ctx;
struct pair_cipher_context *cipher_ctx;
ap2_buffer encrypted_buf;
ap2_buffer plain_buf;
pair_cipher_bundle control_cipher_bundle;
} ap2_pairing;
// flush requests are stored in order of flushFromSeq
@@ -333,7 +337,7 @@ typedef struct {
int ap2_rate; // protect with flush mutex, 0 means don't play, 1 means play
int ap2_play_enabled; // protect with flush mutex
ap2_pairing ap2_control_pairing;
ap2_pairing ap2_pairing_context;
int event_socket;
int data_socket;
+52 -52
View File
@@ -1076,72 +1076,72 @@ void _debug_log_rtsp_message(const char *filename, const int linenumber, int lev
_debug_print_msg_headers(__FILE__, __LINE__, level, message)
#ifdef CONFIG_AIRPLAY_2
static void buf_add(ap2_buffer *buf, uint8_t *in, size_t in_len) {
if (buf->len + in_len > buf->size) {
buf->size = buf->len + in_len + 2048; // Extra legroom to avoid future memcpy's
static void buf_add(sized_buffer *buf, uint8_t *in, size_t in_len) {
if (buf->length + in_len > buf->size) {
buf->size = buf->length + in_len + 2048; // Extra legroom to avoid future memcpy's
uint8_t *new = malloc(buf->size);
memcpy(new, buf->data, buf->len);
memcpy(new, buf->data, buf->length);
free(buf->data);
buf->data = new;
}
memcpy(buf->data + buf->len, in, in_len);
buf->len += in_len;
memcpy(buf->data + buf->length, in, in_len);
buf->length += in_len;
}
static void buf_drain(ap2_buffer *buf, ssize_t len) {
if (len < 0 || (size_t)len >= buf->len) {
static void buf_drain(sized_buffer *buf, ssize_t len) {
if (len < 0 || (size_t)len >= buf->length) {
free(buf->data);
memset(buf, 0, sizeof(ap2_buffer));
memset(buf, 0, sizeof(sized_buffer));
return;
}
memmove(buf->data, buf->data + len, buf->len - len);
buf->len -= len;
memmove(buf->data, buf->data + len, buf->length - len);
buf->length -= len;
}
static size_t buf_remove(ap2_buffer *buf, uint8_t *out, size_t out_len) {
size_t bytes = (buf->len > out_len) ? out_len : buf->len;
static size_t buf_remove(sized_buffer *buf, uint8_t *out, size_t out_len) {
size_t bytes = (buf->length > out_len) ? out_len : buf->length;
memcpy(out, buf->data, bytes);
buf_drain(buf, bytes);
return bytes;
}
static ssize_t read_encrypted(int fd, ap2_pairing *ctx, void *buf, size_t count) {
static ssize_t read_encrypted(int fd, pair_cipher_bundle *ctx, void *buf, size_t count) {
uint8_t in[4096];
uint8_t *plain;
size_t plain_len;
// If there is leftover decoded content from the last pass just return that
if (ctx->plain_buf.len > 0) {
return buf_remove(&ctx->plain_buf, buf, count);
if (ctx->plaintext_read_buffer.length > 0) {
return buf_remove(&ctx->plaintext_read_buffer, buf, count);
}
do {
ssize_t got = read(fd, in, sizeof(in));
if (got <= 0)
return got;
buf_add(&ctx->encrypted_buf, in, got);
buf_add(&ctx->encrypted_read_buffer, in, got);
ssize_t consumed = pair_decrypt(&plain, &plain_len, ctx->encrypted_buf.data,
ctx->encrypted_buf.len, ctx->cipher_ctx);
ssize_t consumed = pair_decrypt(&plain, &plain_len, ctx->encrypted_read_buffer.data,
ctx->encrypted_read_buffer.length, ctx->cipher_ctx);
if (consumed < 0)
return -1;
buf_drain(&ctx->encrypted_buf, consumed);
buf_drain(&ctx->encrypted_read_buffer, consumed);
} while (plain_len == 0);
// Fast path, avoids some memcpy + allocs in case of the normal, small message
/* if (ctx->plain_buf.len == 0 && plain_len < count) {
/* if (ctx->plaintext_read_buffer.len == 0 && plain_len < count) {
memcpy(buf, plain, plain_len);
free(plain);
return plain_len;
}
*/
buf_add(&ctx->plain_buf, plain, plain_len);
buf_add(&ctx->plaintext_read_buffer, plain, plain_len);
free(plain);
return buf_remove(&ctx->plain_buf, buf, count);
return buf_remove(&ctx->plaintext_read_buffer, buf, count);
}
static ssize_t write_encrypted(int fd, ap2_pairing *ctx, const void *buf, size_t count) {
static ssize_t write_encrypted(int fd, pair_cipher_bundle *ctx, const void *buf, size_t count) {
uint8_t *encrypted;
size_t encrypted_len;
@@ -1170,9 +1170,9 @@ static ssize_t write_encrypted(rtsp_conn_info *conn, const void *buf, size_t cou
size_t encrypted_len;
ssize_t ret =
pair_encrypt(&encrypted, &encrypted_len, buf, count, conn->ap2_control_pairing.cipher_ctx);
pair_encrypt(&encrypted, &encrypted_len, buf, count, conn->ap2_pairing_context.cipher_ctx);
if (ret < 0) {
debug(1, pair_cipher_errmsg(conn->ap2_control_pairing.cipher_ctx));
debug(1, pair_cipher_errmsg(conn->ap2_pairing_context.cipher_ctx));
return -1;
}
@@ -1193,9 +1193,9 @@ static ssize_t write_encrypted(rtsp_conn_info *conn, const void *buf, size_t cou
ssize_t read_from_rtsp_connection(rtsp_conn_info *conn, void *buf, size_t count) {
#ifdef CONFIG_AIRPLAY_2
if (conn->ap2_control_pairing.cipher_ctx) {
conn->ap2_control_pairing.is_encrypted = 1;
return read_encrypted(conn->fd, &conn->ap2_control_pairing, buf, count);
if (conn->ap2_pairing_context.control_cipher_bundle.cipher_ctx) {
conn->ap2_pairing_context.control_cipher_bundle.is_encrypted = 1;
return read_encrypted(conn->fd, &conn->ap2_pairing_context.control_cipher_bundle, buf, count);
} else {
return read(conn->fd, buf, count);
}
@@ -1452,8 +1452,8 @@ int msg_write_response(rtsp_conn_info *conn, rtsp_message *resp) {
#ifdef CONFIG_AIRPLAY_2
ssize_t reply;
if (conn->ap2_control_pairing.is_encrypted) {
reply = write_encrypted(conn->fd, &conn->ap2_control_pairing, pkt, p - pkt);
if (conn->ap2_pairing_context.control_cipher_bundle.is_encrypted) {
reply = write_encrypted(conn->fd, &conn->ap2_pairing_context.control_cipher_bundle, pkt, p - pkt);
} else {
reply = write(conn->fd, pkt, p - pkt);
}
@@ -2062,29 +2062,29 @@ void handle_pair_verify(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *r
debug(2, "Connection %d: pair-verify Content-Length %d", conn->connection_number,
req->contentlength);
if (!conn->ap2_control_pairing.verify_ctx) {
conn->ap2_control_pairing.verify_ctx =
if (!conn->ap2_pairing_context.verify_ctx) {
conn->ap2_pairing_context.verify_ctx =
pair_verify_new(PAIR_SERVER_HOMEKIT, NULL, NULL, NULL, config.airplay_device_id);
if (!conn->ap2_control_pairing.verify_ctx) {
if (!conn->ap2_pairing_context.verify_ctx) {
debug(1, "Error creating verify context");
resp->respcode = 500; // Internal Server Error
goto out;
}
}
ret = pair_verify(&body, &body_len, conn->ap2_control_pairing.verify_ctx,
ret = pair_verify(&body, &body_len, conn->ap2_pairing_context.verify_ctx,
(const uint8_t *)req->content, req->contentlength);
if (ret < 0) {
debug(1, pair_verify_errmsg(conn->ap2_control_pairing.verify_ctx));
debug(1, pair_verify_errmsg(conn->ap2_pairing_context.verify_ctx));
resp->respcode = 470; // Connection Authorization Required
goto out;
}
ret = pair_verify_result(&result, conn->ap2_control_pairing.verify_ctx);
ret = pair_verify_result(&result, conn->ap2_pairing_context.verify_ctx);
if (ret == 0 && result->shared_secret_len > 0) {
conn->ap2_control_pairing.cipher_ctx =
conn->ap2_pairing_context.control_cipher_bundle.cipher_ctx =
pair_cipher_new(PAIR_SERVER_HOMEKIT, 2, result->shared_secret, result->shared_secret_len);
if (!conn->ap2_control_pairing.cipher_ctx) {
if (!conn->ap2_pairing_context.control_cipher_bundle.cipher_ctx) {
debug(1, "Error setting up rtsp control channel ciphering\n");
goto out;
}
@@ -2106,31 +2106,31 @@ void handle_pair_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *re
debug(2, "Connection %d: pair-setup Content-Length %d", conn->connection_number,
req->contentlength);
if (!conn->ap2_control_pairing.setup_ctx) {
conn->ap2_control_pairing.setup_ctx = pair_setup_new(PAIR_SERVER_HOMEKIT, config.airplay_pin,
if (!conn->ap2_pairing_context.setup_ctx) {
conn->ap2_pairing_context.setup_ctx = pair_setup_new(PAIR_SERVER_HOMEKIT, config.airplay_pin,
NULL, NULL, config.airplay_device_id);
if (!conn->ap2_control_pairing.setup_ctx) {
if (!conn->ap2_pairing_context.setup_ctx) {
debug(1, "Error creating setup context");
resp->respcode = 500; // Internal Server Error
goto out;
}
}
ret = pair_setup(&body, &body_len, conn->ap2_control_pairing.setup_ctx,
ret = pair_setup(&body, &body_len, conn->ap2_pairing_context.setup_ctx,
(const uint8_t *)req->content, req->contentlength);
if (ret < 0) {
debug(1, pair_setup_errmsg(conn->ap2_control_pairing.setup_ctx));
debug(1, pair_setup_errmsg(conn->ap2_pairing_context.setup_ctx));
resp->respcode = 470; // Connection Authorization Required
goto out;
}
ret = pair_setup_result(NULL, &result, conn->ap2_control_pairing.setup_ctx);
ret = pair_setup_result(NULL, &result, conn->ap2_pairing_context.setup_ctx);
if (ret == 0 && result->shared_secret_len > 0) {
// Transient pairing completed (pair-setup step 2), prepare encryption, but
// don't activate yet, the response to this request is still plaintext
conn->ap2_control_pairing.cipher_ctx =
conn->ap2_pairing_context.control_cipher_bundle.cipher_ctx =
pair_cipher_new(PAIR_SERVER_HOMEKIT, 2, result->shared_secret, result->shared_secret_len);
if (!conn->ap2_control_pairing.cipher_ctx) {
if (!conn->ap2_pairing_context.control_cipher_bundle.cipher_ctx) {
debug(1, "Error setting up rtsp control channel ciphering\n");
goto out;
}
@@ -4819,11 +4819,11 @@ void rtsp_conversation_thread_cleanup_function(void *arg) {
}
#ifdef CONFIG_AIRPLAY_2
buf_drain(&conn->ap2_control_pairing.plain_buf, -1);
buf_drain(&conn->ap2_control_pairing.encrypted_buf, -1);
pair_setup_free(conn->ap2_control_pairing.setup_ctx);
pair_verify_free(conn->ap2_control_pairing.verify_ctx);
pair_cipher_free(conn->ap2_control_pairing.cipher_ctx);
buf_drain(&conn->ap2_pairing_context.control_cipher_bundle.plaintext_read_buffer, -1);
buf_drain(&conn->ap2_pairing_context.control_cipher_bundle.encrypted_read_buffer, -1);
pair_cipher_free(conn->ap2_pairing_context.control_cipher_bundle.cipher_ctx);
pair_setup_free(conn->ap2_pairing_context.setup_ctx);
pair_verify_free(conn->ap2_pairing_context.verify_ctx);
if (conn->airplay_gid) {
free(conn->airplay_gid);
conn->airplay_gid = NULL;