From 7c79d031a328b6c3ec3dffa8a7ea5da98bec32ef Mon Sep 17 00:00:00 2001 From: fduncanh Date: Thu, 11 Nov 2021 19:32:41 -0500 Subject: [PATCH] restore RPiPlay's crypto implementation, now they have fixed the aes-cbc bug. --- lib/crypto.c | 31 +++++++++++++++++-------------- lib/crypto.h | 3 +-- lib/mirror_buffer.c | 3 ++- lib/pairing.c | 4 ++-- lib/raop_buffer.c | 20 ++++---------------- 5 files changed, 26 insertions(+), 35 deletions(-) diff --git a/lib/crypto.c b/lib/crypto.c index c6cc109..30e9f14 100644 --- a/lib/crypto.c +++ b/lib/crypto.c @@ -68,25 +68,32 @@ aes_ctx_t *aes_init(const uint8_t *key, const uint8_t *iv, const EVP_CIPHER *typ memcpy(ctx->key, key, AES_128_BLOCK_SIZE); memcpy(ctx->iv, iv, AES_128_BLOCK_SIZE); + EVP_CIPHER_CTX_set_padding(ctx->cipher_ctx, 0); return ctx; } void aes_encrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int in_len) { - int out_len = 0; - if (!EVP_EncryptUpdate(ctx->cipher_ctx, out, &out_len, in, in_len)) { + int out_len_e = 0; + if (!EVP_EncryptUpdate(ctx->cipher_ctx, out, &out_len_e, in, in_len)) { handle_error(__func__); } - - assert(out_len <= in_len); + int out_len_f = in_len - out_len_e; + if (!EVP_EncryptFinal_ex(ctx->cipher_ctx, out + out_len_e, &out_len_f)) { + handle_error(__func__); + } + assert(out_len_e + out_len_f <= in_len); } void aes_decrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int in_len) { - int out_len = 0; - if (!EVP_DecryptUpdate(ctx->cipher_ctx, out, &out_len, in, in_len)) { + int out_len_d = 0; + if (!EVP_DecryptUpdate(ctx->cipher_ctx, out, &out_len_d, in, in_len)) { handle_error(__func__); } - - assert(out_len <= in_len); + int out_len_f = in_len - out_len_d; + if (!EVP_DecryptFinal_ex(ctx->cipher_ctx, out + out_len_d, &out_len_f)) { + handle_error(__func__); + } + assert(out_len_f + out_len_d <= in_len); } void aes_destroy(aes_ctx_t *ctx) { @@ -114,14 +121,10 @@ void aes_reset(aes_ctx_t *ctx, const EVP_CIPHER *type, aes_direction_t direction // AES CTR -aes_ctx_t *aes_ctr_encrypt_init(const uint8_t *key, const uint8_t *iv) { +aes_ctx_t *aes_ctr_init(const uint8_t *key, const uint8_t *iv) { return aes_init(key, iv, EVP_aes_128_ctr(), AES_ENCRYPT); } -aes_ctx_t *aes_ctr_decrypt_init(const uint8_t *key, const uint8_t *iv) { - return aes_init(key, iv, EVP_aes_128_ctr(), AES_DECRYPT); -} - void aes_ctr_encrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len) { aes_encrypt(ctx, in, out, len); ctx->block_offset = (ctx->block_offset + len) % AES_128_BLOCK_SIZE; @@ -134,7 +137,7 @@ void aes_ctr_start_fresh_block(aes_ctx_t *ctx) { } void aes_ctr_decrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len) { - aes_decrypt(ctx, in, out, len); + aes_encrypt(ctx, in, out, len); } void aes_ctr_reset(aes_ctx_t *ctx) { diff --git a/lib/crypto.h b/lib/crypto.h index 3f3a35a..13c5f28 100644 --- a/lib/crypto.h +++ b/lib/crypto.h @@ -41,8 +41,7 @@ typedef enum aes_direction_e { AES_DECRYPT, AES_ENCRYPT } aes_direction_t; typedef struct aes_ctx_s aes_ctx_t; -aes_ctx_t *aes_ctr_encrypt_init(const uint8_t *key, const uint8_t *iv); -aes_ctx_t *aes_ctr_decrypt_init(const uint8_t *key, const uint8_t *iv); +aes_ctx_t *aes_ctr_init(const uint8_t *key, const uint8_t *iv); void aes_ctr_reset(aes_ctx_t *ctx); void aes_ctr_encrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len); void aes_ctr_decrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len); diff --git a/lib/mirror_buffer.c b/lib/mirror_buffer.c index 84cd11d..faaa800 100755 --- a/lib/mirror_buffer.c +++ b/lib/mirror_buffer.c @@ -77,7 +77,7 @@ mirror_buffer_init_aes(mirror_buffer_t *mirror_buffer, uint64_t streamConnection fclose(keyfile); #endif // Need to be initialized externally - mirror_buffer->aes_ctx = aes_ctr_decrypt_init(decrypt_aeskey, decrypt_aesiv); + mirror_buffer->aes_ctx = aes_ctr_init(decrypt_aeskey, decrypt_aesiv); mirror_buffer->nextDecryptCount = 0; } @@ -97,6 +97,7 @@ mirror_buffer_init(logger_t *logger, memcpy(mirror_buffer->ecdh_secret, ecdh_secret, 32); mirror_buffer->logger = logger; mirror_buffer->nextDecryptCount = 0; + //mirror_buffer_init_aes(mirror_buffer, aeskey, ecdh_secret, streamConnectionID); return mirror_buffer; } diff --git a/lib/pairing.c b/lib/pairing.c index db03c83..11ce287 100755 --- a/lib/pairing.c +++ b/lib/pairing.c @@ -193,7 +193,7 @@ pairing_session_get_signature(pairing_session_t *session, unsigned char signatur derive_key_internal(session, (const unsigned char *) SALT_KEY, strlen(SALT_KEY), key, sizeof(key)); derive_key_internal(session, (const unsigned char *) SALT_IV, strlen(SALT_IV), iv, sizeof(iv)); - aes_ctx = aes_ctr_encrypt_init(key, iv); + aes_ctx = aes_ctr_init(key, iv); aes_ctr_encrypt(aes_ctx, signature, signature, PAIRING_SIG_SIZE); aes_ctr_destroy(aes_ctx); @@ -219,7 +219,7 @@ pairing_session_finish(pairing_session_t *session, const unsigned char signature derive_key_internal(session, (const unsigned char *) SALT_KEY, strlen(SALT_KEY), key, sizeof(key)); derive_key_internal(session, (const unsigned char *) SALT_IV, strlen(SALT_IV), iv, sizeof(iv)); - aes_ctx = aes_ctr_encrypt_init(key, iv); + aes_ctx = aes_ctr_init(key, iv); /* One fake round for the initial handshake encryption */ aes_ctr_encrypt(aes_ctx, sig_buffer, sig_buffer, PAIRING_SIG_SIZE); aes_ctr_encrypt(aes_ctx, signature, sig_buffer, PAIRING_SIG_SIZE); diff --git a/lib/raop_buffer.c b/lib/raop_buffer.c index 3b9feaa..1352e93 100755 --- a/lib/raop_buffer.c +++ b/lib/raop_buffer.c @@ -170,24 +170,12 @@ raop_buffer_decrypt(raop_buffer_t *raop_buffer, unsigned char *data, unsigned ch fwrite(&data[12], payloadsize, 1, file_source); } #endif - - /* Need to be initialized externally */ - aes_ctx_t *aes_ctx_audio = aes_cbc_init(raop_buffer->aeskey, raop_buffer->aesiv, AES_DECRYPT); - encryptedlen = (payload_size / 16) * 16; + encryptedlen = payload_size / 16*16; memset(output, 0, payload_size); - - /* Adding 15 to encryptedlen in the call to aes_cbc_decrypt is a fix (hack) to ensure that */ - /* all encryptedlen encrypted bytes are decrypted .*/ - /* The implementation of aes_cbc_decrypt in crypto.c calls OpenSSL function EVP_EncryptUpdate */ - /* but does not call EVP_EncryptFinal to finalize the decryption of the packet. */ - /* Instead the finalization of the < 16 remaining (unencrypted) bytes is done here. */ - /* Without the fix, the last 16 encrypted bytes are lost by EVP_EncryptUpdate; */ - /* with the fix all (encryptedlen + 15) /16 * 16 = encryptedlen decrypted encrypted-bytes are */ - /* written into output, with no risk of buffer overflow */ - - aes_cbc_decrypt(aes_ctx_audio, &data[12], output, encryptedlen + 15); - + // Need to be initialized internally + aes_ctx_t *aes_ctx_audio = aes_cbc_init(raop_buffer->aeskey, raop_buffer->aesiv, AES_DECRYPT); + aes_cbc_decrypt(aes_ctx_audio, &data[12], output, encryptedlen); aes_cbc_destroy(aes_ctx_audio); memcpy(output + encryptedlen, &data[12 + encryptedlen], payload_size - encryptedlen);