Skip to content

Commit

Permalink
@seba-aln you are a god of the C language
Browse files Browse the repository at this point in the history
  • Loading branch information
Xavrax committed Oct 5, 2023
1 parent 7583e9a commit 1bf3122
Show file tree
Hide file tree
Showing 9 changed files with 387 additions and 50 deletions.
96 changes: 96 additions & 0 deletions core/pbcc_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@

//#ifdef PUBNUB_CRYPTO_API

#include <stdint.h>
#include <stdio.h>
#include "pbcc_crypto.h"
#include "pbsha256.h"
#include "pbaes256.h"
#include "pubnub_crypto.h"
#include "pubnub_log.h"
#include "pubnub_memory_block.h"
#include "pubnub_assert.h"
#include <string.h>
#include <openssl/rand.h>

int pbcc_cipher_key_hash(const uint8_t* cipher_key, uint8_t* hash) {
uint8_t digest[32];
Expand Down Expand Up @@ -53,6 +58,7 @@ struct pubnub_byte_mem_block* pbcc_cryptor_header_v1_to_alloc_block(struct pubnu
uint8_t version = 1;
struct pubnub_byte_mem_block* result = (struct pubnub_byte_mem_block*)malloc(sizeof(struct pubnub_byte_mem_block));
if (NULL == result) {
PUBNUB_LOG_ERROR("pbcc_cryptor_header_v1_to_alloc_block: failed to allocate memory\n");
return NULL;
}

Expand All @@ -67,6 +73,7 @@ struct pubnub_byte_mem_block* pbcc_cryptor_header_v1_to_alloc_block(struct pubnu

result->ptr = (uint8_t*)malloc(header_size);
if (NULL == result->ptr) {
PUBNUB_LOG_ERROR("pbcc_cryptor_header_v1_to_alloc_block: failed to allocate memory\n");
free(result);
return NULL;
}
Expand Down Expand Up @@ -165,4 +172,93 @@ struct pubnub_cryptor_header_v1* pbcc_cryptor_header_v1_from_block(struct pubnub
return result;
}

pubnub_bymebl_t pbcc_legacy_encrypt(uint8_t const* cipher_key, pubnub_bymebl_t msg)
{
uint8_t key[33];
unsigned char iv[17] = "0123456789012345";
#if PUBNUB_RAND_INIT_VECTOR
int rand_status = RAND_bytes(iv, 16);
PUBNUB_ASSERT_OPT(rand_status == 1);
#endif

pbcc_cipher_key_hash((uint8_t*)cipher_key, key);
pubnub_bymebl_t result = pbaes256_encrypt_alloc(msg, key, iv);

#if PUBNUB_RAND_INIT_VECTOR
memmove(result.ptr + 16, result.ptr, result.size);
memcpy(result.ptr, iv, 16);
result.size += 16;
result.ptr[result.size] = '\0';
#endif

return result;
}

int pbcc_memory_encode(pubnub_bymebl_t buffer, char* base64_str, unsigned char* iv, size_t* n)
{
#if PUBNUB_RAND_INIT_VECTOR
memmove(buffer.ptr + 16, buffer.ptr, buffer.size);
memcpy(buffer.ptr, iv, 16);
buffer.size += 16;
buffer.ptr[buffer.size] = '\0';
#endif

#if PUBNUB_LOG_LEVEL >= PUBNUB_LOG_LEVEL_DEBUG
PUBNUB_LOG_DEBUG("\nbytes before encoding iv + encrypted msg = [");
for (int i = 0; i < (int)buffer.size; i++) {
PUBNUB_LOG_DEBUG("%d ", buffer.ptr[i]);
}
PUBNUB_LOG_DEBUG("]\n");
#endif

int max_size = base64_max_size(buffer.size);
if (*n + 1 < (size_t)max_size) {
PUBNUB_LOG_DEBUG("base64encode needs %d bytes but only %zu bytes are available\n", max_size, *n);
return -1;
}
char* base64_output = (char*)malloc(max_size);
if (base64encode(base64_output, max_size, buffer.ptr, buffer.size) != 0) {
PUBNUB_LOG_DEBUG("base64encode tried to use more than %d bytes to encode %zu bytes\n", max_size, buffer.size);
free(base64_output);
return -1;
}
int result = snprintf(base64_str, *n, "%s", base64_output);
*n = (size_t)strlen(base64_str);

free(base64_output);

return result >= 0 ? 0 : -1;
}

int pbcc_legacy_decrypt(uint8_t const* cipher_key, pubnub_bymebl_t *result, pubnub_bymebl_t to_decrypt) {
unsigned char iv[17] = "0123456789012345";
uint8_t key[33];

pbcc_cipher_key_hash(cipher_key, key);

#if PUBNUB_LOG_LEVEL >= PUBNUB_LOG_LEVEL_DEBUG
PUBNUB_LOG_DEBUG("\nbytes to decrypt = [");
for (size_t i = 0; i < to_decrypt.size; i++) {
PUBNUB_LOG_DEBUG("%d ", to_decrypt.ptr[i]);
}
PUBNUB_LOG_DEBUG("]\n");
#endif

if (to_decrypt.ptr != NULL) {

#if PUBNUB_RAND_INIT_VECTOR
memcpy(iv, to_decrypt.ptr, 16);
memmove(to_decrypt.ptr, to_decrypt.ptr + 16, to_decrypt.size - 16);
to_decrypt.size = to_decrypt.size - 16;
#endif
to_decrypt.ptr[to_decrypt.size] = '\0';

return pbaes256_decrypt(to_decrypt, key, iv, result);
}

return -1;
}



//#endif // PUBNUB_CRYPTO_API
55 changes: 55 additions & 0 deletions core/pbcc_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

#include "pubnub_memory_block.h"
#include <stdint.h>

/** @file pubnub_crypto.h
Expand Down Expand Up @@ -212,6 +213,60 @@ struct pubnub_byte_mem_block* pbcc_cryptor_header_v1_to_alloc_block(struct pubnu
*/
struct pubnub_cryptor_header_v1* pbcc_cryptor_header_v1_from_block(struct pubnub_byte_mem_block *cryptor_header);

/**
Encrypts data with legacy algorithm without encoding it to base64.
This function behaves the same as a old `pubnub_encrypt` function, but it doesn't
encode the encrypted data to base64. It allocates the memory for the encrypted data
and returns it to the user.
It is meant to be used within pubnub crypto module.
@pre cipher_key != NULL
@param cipher_key The key to use when encrypting
@param msg The memory block (pointer and size) of the data to encrypt
@param str String (allocated by the user) to write encrypted
@param n The size of the string
@return encrypted data block
*/
pubnub_bymebl_t pbcc_legacy_encrypt(uint8_t const* cipher_key, pubnub_bymebl_t msg);

/**
Decrypts data with legacy algorithm without decoding it from base64.
This function behaves the same as a old `pubnub_decrypt` function, but it doesn't
decode the encrypted data from base64. It allocates the memory for the decrypted data
and returns it to the user.
It is meant to be used within pubnub crypto module.
@pre cipher_key != NULL
@param cipher_key The key to use when decrypting
@param to_decrypt The memory block (pointer and size) of the data to decrypt
@return decrypted data block
*/
int pbcc_legacy_decrypt(uint8_t const* cipher_key, pubnub_bymebl_t *result, pubnub_bymebl_t to_decrypt);

/**
Encodes the encrypted data to base64.
This function behaves the same as an old second part of the
`pubnub_encrypt` function. It takes allocated encrypted data and
encodes it to base64.
It is meant to be used within pubnub crypto module.
@pre str != NULL
@param buffer The memory block (pointer and size) of the data to encode.
@param base64_str String (allocated by the user) to write encoded data,
@param n The size of the string,
@param iv The initialization vector.
@return 0: OK, -1: error
*/
//static int pbcc_memory_encode(pubnub_bymebl_t buffer, char* base64_str, unsigned char* iv, size_t* n);

#endif /* PBCC_CRYPTO_H */
//#endif /* PUBNUB_CRYPTO_API */
39 changes: 7 additions & 32 deletions core/pbcc_crypto_aes_cbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,48 +83,30 @@ static int aes_encrypt(

size_t enc_buffer_size = estimated_enc_buffer_size(to_encrypt.size);

pubnub_bymebl_t encrypted;
encrypted.ptr = (uint8_t *)malloc(enc_buffer_size);
if (encrypted.ptr == NULL) {
result->data.ptr = (uint8_t *)malloc(enc_buffer_size);
if (result->data.ptr == NULL) {
return -1;
}
encrypted.size = enc_buffer_size;
result->data.size = enc_buffer_size;

uint8_t iv[AES_IV_SIZE];
generate_init_vector(iv);

if (0 != pbaes256_encrypt(to_encrypt, key_hash, iv, &encrypted)) {
free(encrypted.ptr);
return -1;
};

size_t max_encoded_size = base64_max_size(encrypted.size);

result->data.ptr = (uint8_t *)malloc(max_encoded_size);
if (result->data.ptr == NULL) {
free(encrypted.ptr);
return -1;
}

if (0 != base64encode((char*)result->data.ptr, max_encoded_size, encrypted.ptr, encrypted.size)) {
if (0 != pbaes256_encrypt(to_encrypt, key_hash, iv, &result->data)) {
free(result->data.ptr);
free(encrypted.ptr);
return -1;
}
result->data.size = strlen((char*)result->data.ptr);
};

result->metadata.ptr = (uint8_t *)malloc(AES_IV_SIZE);
if (result->metadata.ptr == NULL) {
free(encrypted.ptr);
free(result->data.ptr);
free(result->data.ptr);
return -1;
}

memcpy(result->metadata.ptr, iv, AES_IV_SIZE);
result->metadata.size = AES_IV_SIZE;

free(encrypted.ptr);

return 0;
}

Expand All @@ -141,12 +123,6 @@ static int aes_decrypt(
return -1;
}

pubnub_bymebl_t decoded = pbbase64_decode_alloc_std((char*)to_decrypt.data.ptr, to_decrypt.data.size);
if (decoded.ptr == NULL) {
PUBNUB_LOG_ERROR("Failed to decode base64\n");
return -1;
}

size_t dec_buffer_size = estimated_dec_buffer_size(to_decrypt.data.size) + 5000; // TODO: Why do I need additional space?

result->ptr = (uint8_t *)malloc(dec_buffer_size);
Expand All @@ -158,14 +134,13 @@ static int aes_decrypt(
result->size = dec_buffer_size;

if (0 != pbaes256_decrypt(
decoded,
to_decrypt.data,
key_hash,
to_decrypt.metadata.ptr,
result
)) {
PUBNUB_LOG_ERROR("Failed to decrypt data\n");
free(result->ptr);
free(decoded.ptr);
return -1;
}

Expand Down
24 changes: 16 additions & 8 deletions core/pbcc_crypto_legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "pbcc_crypto.h"
#include "pubnub_crypto.h"
#include "pubnub_memory_block.h"
#include "pubnub_log.h"
#include <string.h>
#include <stdlib.h>

Expand Down Expand Up @@ -67,16 +68,18 @@ static int legacy_encrypt(
) {
struct legacy_context *ctx = (struct legacy_context *)algo->user_data;

size_t estimated_size = base64_max_size(estimated_enc_buffer_size(to_encrypt.size));
size_t estimated_size = estimated_enc_buffer_size(to_encrypt.size);
result->data.ptr = (uint8_t*)malloc(estimated_size);
memset(result->data.ptr, 0, estimated_size);
if (NULL == result->data.ptr) {
return -1;
}
result->data.size = estimated_size;

int res = pubnub_encrypt((char*)ctx->cipher_key, to_encrypt, (char*)result->data.ptr, &result->data.size);
if (0 != res) {
return res;
result->data = pbcc_legacy_encrypt(ctx->cipher_key, to_encrypt);
if (NULL == result->data.ptr) {
PUBNUB_LOG_ERROR("pbcc_legacy_encrypt() failed\n");
return -1;
}

result->metadata.ptr = NULL;
Expand All @@ -92,18 +95,23 @@ static int legacy_decrypt(
) {
struct legacy_context *ctx = (struct legacy_context *)algo->user_data;

size_t estimated_size = estimated_dec_buffer_size(to_decrypt.data.size) + 50000;
size_t estimated_size = estimated_dec_buffer_size(to_decrypt.data.size) + 100000; // TODO: WHY!?!?!?
result->ptr = (uint8_t*)malloc(estimated_size);
memset(result->ptr, 0, estimated_size);
if (NULL == result->ptr) {
return -1;
}
result->size = estimated_size;

int res = pubnub_decrypt((char*)ctx->cipher_key, (char*)to_decrypt.data.ptr, result);
if (0 != res) {
return res;
pbcc_legacy_decrypt(ctx->cipher_key, result, to_decrypt.data);
if (NULL == result->ptr) {
PUBNUB_LOG_ERROR("pubnub_decrypt() failed\n");
free(result->ptr);
return -1;
}

result->size = strlen((char*)result->ptr);

return 0;
}

Expand Down
4 changes: 4 additions & 0 deletions core/pubnub_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -851,3 +851,7 @@ static pubnub_bymebl_t *provider_decrypt(struct pubnub_crypto_provider_t const*
return result;
}

void pubnub_set_crypto_module(pubnub_t *pubnub, struct pubnub_crypto_provider_t *crypto_provider) {

}

14 changes: 13 additions & 1 deletion core/pubnub_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,23 @@ struct pubnub_crypto_provider_t *pubnub_crypto_legacy_module_init(const uint8_t*
@param default Pointer to the default crypto algorithm to use.
@param algorithms Pointer to the array of crypto algorithms to use.
@param n_algorithms Number of crypto algorithms in the array.
@param n_algorithms Number of crypto algorithms in the array. (omit the default one)
@return Pointer to the crypto module structure.
*/
struct pubnub_crypto_provider_t *pubnub_crypto_module_init(struct pubnub_cryptor_t *default_algorithm, struct pubnub_cryptor_t *algorithms, size_t n_algorithms);


/**
Set the crypto module to be used by the pubnub context.
This function sets the crypto module to be used by the pubnub context
for the encryption and decryption of the messages.
@param pubnub Pointer to the pubnub context.
@param crypto_provider Pointer to the crypto provider to use.
*/
void pubnub_set_crypto_module(pubnub_t *pubnub, struct pubnub_crypto_provider_t *crypto_provider);


#endif /* defined INC_PUBNUB_CRYPTO */
Loading

0 comments on commit 1bf3122

Please sign in to comment.