From 73c5dcec5abe421ad173a008b5da699f0c03bc5d Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Thu, 14 Jan 2021 21:29:22 +0100 Subject: [PATCH] [airplay] Update pairing, change ciphering function return values --- src/outputs/pair-internal.h | 4 ++-- src/outputs/pair.c | 4 ++-- src/outputs/pair.h | 14 ++++++++++---- src/outputs/pair_homekit.c | 20 ++++++-------------- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/outputs/pair-internal.h b/src/outputs/pair-internal.h index 5dfba936..d86983e2 100644 --- a/src/outputs/pair-internal.h +++ b/src/outputs/pair-internal.h @@ -102,8 +102,8 @@ struct pair_definition struct pair_cipher_context *(*pair_cipher_new)(struct pair_definition *type, int channel, const uint8_t *shared_secret, size_t shared_secret_len); void (*pair_cipher_free)(struct pair_cipher_context *cctx); - int (*pair_encrypt)(uint8_t **ciphertext, size_t *ciphertext_len, uint8_t *plaintext, size_t plaintext_len, struct pair_cipher_context *cctx); - int (*pair_decrypt)(uint8_t **plaintext, size_t *plaintext_len, uint8_t *ciphertext, size_t ciphertext_len, struct pair_cipher_context *cctx); + ssize_t (*pair_encrypt)(uint8_t **ciphertext, size_t *ciphertext_len, uint8_t *plaintext, size_t plaintext_len, struct pair_cipher_context *cctx); + ssize_t (*pair_decrypt)(uint8_t **plaintext, size_t *plaintext_len, uint8_t *ciphertext, size_t ciphertext_len, struct pair_cipher_context *cctx); }; diff --git a/src/outputs/pair.c b/src/outputs/pair.c index ba5fd6f6..c0cd7ae1 100644 --- a/src/outputs/pair.c +++ b/src/outputs/pair.c @@ -547,7 +547,7 @@ pair_cipher_errmsg(struct pair_cipher_context *cctx) return cctx->errmsg; } -int +ssize_t pair_encrypt(uint8_t **ciphertext, size_t *ciphertext_len, uint8_t *plaintext, size_t plaintext_len, struct pair_cipher_context *cctx) { if (!cctx->type->pair_encrypt) @@ -556,7 +556,7 @@ pair_encrypt(uint8_t **ciphertext, size_t *ciphertext_len, uint8_t *plaintext, s return cctx->type->pair_encrypt(ciphertext, ciphertext_len, plaintext, plaintext_len, cctx); } -int +ssize_t pair_decrypt(uint8_t **plaintext, size_t *plaintext_len, uint8_t *ciphertext, size_t ciphertext_len, struct pair_cipher_context *cctx) { if (!cctx->type->pair_decrypt) diff --git a/src/outputs/pair.h b/src/outputs/pair.h index b2485207..95e09453 100644 --- a/src/outputs/pair.h +++ b/src/outputs/pair.h @@ -102,12 +102,18 @@ pair_cipher_free(struct pair_cipher_context *cctx); const char * pair_cipher_errmsg(struct pair_cipher_context *cctx); -/* Return 0 is success, -1 is general error, -2 is ciphertext_len shorter than - * blocklen in payload +/* The return value equals length of plaintext that was encrypted, so if the + * return value == plaintext_len then everything was encrypted. On error -1 is + * returned. */ -int +ssize_t pair_encrypt(uint8_t **ciphertext, size_t *ciphertext_len, uint8_t *plaintext, size_t plaintext_len, struct pair_cipher_context *cctx); -int + +/* The return value equals length of ciphertext that was decrypted, so if the + * return value == ciphertext_len then everything was decrypted. On error -1 is + * returned. + */ +ssize_t pair_decrypt(uint8_t **plaintext, size_t *plaintext_len, uint8_t *ciphertext, size_t ciphertext_len, struct pair_cipher_context *cctx); /* Rolls back the nonce diff --git a/src/outputs/pair_homekit.c b/src/outputs/pair_homekit.c index bc52ef68..a2e5afec 100644 --- a/src/outputs/pair_homekit.c +++ b/src/outputs/pair_homekit.c @@ -1729,7 +1729,7 @@ pair_cipher_new(struct pair_definition *type, int channel, const uint8_t *shared return NULL; } -static int +static ssize_t pair_encrypt(uint8_t **ciphertext, size_t *ciphertext_len, uint8_t *plaintext, size_t plaintext_len, struct pair_cipher_context *cctx) { uint8_t nonce[NONCE_LENGTH] = { 0 }; @@ -1778,17 +1778,14 @@ pair_encrypt(uint8_t **ciphertext, size_t *ciphertext_len, uint8_t *plaintext, s cctx->encryption_counter++; } - assert(plain_block == plaintext + plaintext_len); - assert(cipher_block == *ciphertext + *ciphertext_len); - #ifdef DEBUG_PAIR hexdump("Encrypted:\n", *ciphertext, *ciphertext_len); #endif - return 0; + return plain_block - plaintext; } -static int +static ssize_t pair_decrypt(uint8_t **plaintext, size_t *plaintext_len, uint8_t *ciphertext, size_t ciphertext_len, struct pair_cipher_context *cctx) { uint8_t nonce[NONCE_LENGTH] = { 0 }; @@ -1812,10 +1809,8 @@ pair_decrypt(uint8_t **plaintext, size_t *plaintext_len, uint8_t *ciphertext, si memcpy(&block_len, cipher_block, sizeof(block_len)); // TODO BE or LE? if (cipher_block + block_len + sizeof(block_len) + AUTHTAG_LENGTH > ciphertext + ciphertext_len) { - cctx->errmsg = "Insufficient encrypted data or corrupt block length"; - cctx->decryption_counter = cctx->decryption_counter_prev; - free(*plaintext); - return -2; // Corrupt block_len, stop before we read over the end + // The remaining ciphertext doesn't contain an entire block, so stop + break; } memcpy(tag, cipher_block + sizeof(block_len) + block_len, sizeof(tag)); @@ -1835,16 +1830,13 @@ pair_decrypt(uint8_t **plaintext, size_t *plaintext_len, uint8_t *ciphertext, si cctx->decryption_counter++; } - assert(plain_block < *plaintext + ciphertext_len); - assert(cipher_block == ciphertext + ciphertext_len); - *plaintext_len = plain_block - *plaintext; #ifdef DEBUG_PAIR hexdump("Decrypted:\n", *plaintext, *plaintext_len); #endif - return 0; + return cipher_block - ciphertext; } const struct pair_definition pair_homekit_normal =