123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- #include <stdio.h>
- #include <string>
- #include <string.h>
- #include <memory>
- using std::unique_ptr;
- #include <openssl/err.h>
- #include <openssl/bn.h>
- #include <openssl/rsa.h>
- #include <openssl/evp.h>
- #include <openssl/pem.h>
- EVP_CIPHER_CTX *ctx;
- RSA* rsa;
- BIGNUM* bn;
- // assumes that the digest is at least of length 256/8 bytes.
- uint32_t generate_sha256_hash(const unsigned char *message, size_t message_len, unsigned char *digest)
- {
- EVP_MD_CTX *mdctx; unsigned int digest_len;
- if((mdctx = EVP_MD_CTX_create()) == NULL)
- {
- printf("EVP_MD_CTX_create returned NULL - could not create context\n"); fflush(stdout); return 0x1;
- }
- if(EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL) != 1)
- {
- printf("EVP_DigestInit_ex returned 0 - could not initialize hash with SHA256\n"); fflush(stdout); return 0x2;
- }
- if(EVP_DigestUpdate(mdctx, message, message_len) != 1)
- {
- printf("EVP_DigestUpdate returned 0 - could not compute SHA256 hash\n"); fflush(stdout); return 0x3;
- }
- if(1 != EVP_DigestFinal_ex(mdctx, digest, &digest_len))
- {
- printf("EVP_DigestFinal_ex returned 0 - could not finalize SHA256 hash\n"); fflush(stdout); return 0x4;
- }
- if(digest_len != 32)
- {
- printf("EVP_DigestFinal_ex returned a digest length of 0x%x instead of 0x20\n", digest_len); fflush(stdout); return 0x5;
- }
- EVP_MD_CTX_destroy(mdctx);
- return 0;
- }
- //////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////
- void crypto_cleanup()
- {
- RSA_free(rsa);
- BN_free(bn);
- EVP_CIPHER_CTX_free(ctx);
- }
- // Code adapted from here: https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
- int aes_gcm_128(int enc, unsigned char *key, unsigned char *iv, unsigned char* plaintext, uint32_t plaintext_len, unsigned char *ciphertext, uint32_t* op_ciphertext_len, unsigned char* tag)
- {
- int len;
- int ciphertext_len;
- int reset_return;
- if(ctx == NULL)
- {
- /* Create and initialise the context */
- if(!(ctx = EVP_CIPHER_CTX_new())) { ERR_print_errors_fp(stderr); fflush(stderr);return 0x1; }
- }
- /* Initialise the encryption operation. */
- if(1 != EVP_CipherInit_ex(ctx, EVP_aes_128_gcm(), NULL, key, iv, enc))
- {
- reset_return = EVP_CIPHER_CTX_reset(ctx);
- ERR_print_errors_fp(stderr);
- if(reset_return != 1)
- return 0xf2;
- return 0x2;
- }
- /* Provide the message to be encrypted, and obtain the encrypted output.
- * EVP_EncryptUpdate can be called multiple times if necessary
- */
- if(1 != EVP_CipherUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
- {
- reset_return = EVP_CIPHER_CTX_reset(ctx);
- ERR_print_errors_fp(stderr);
- if(1 != reset_return)
- return 0xF3;
- return 0x3;
- }
- ciphertext_len = len;
- if(enc == 0)
- {
- if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))
- {
- reset_return = EVP_CIPHER_CTX_reset(ctx);
- ERR_print_errors_fp(stderr); fflush(stderr);
- if(1 != reset_return)
- return 0xF5;
- return 0x5;
- }
- }
- /* Finalise the encryption. Normally ciphertext bytes may be written at
- * this stage, but this does not occur in GCM mode
- */
- // TODO: ^^^ Why the heck does it not occur in GCM mode ?
- if(1 != EVP_CipherFinal_ex(ctx, ciphertext + len, &len))
- {
- reset_return = EVP_CIPHER_CTX_reset(ctx);
- ERR_print_errors_fp(stderr); fflush(stderr);
- if(1 != reset_return)
- return 0xF4;
- return 0x4;
- }
- ciphertext_len += len;
- /* Get the tag */
- if(enc == 1)
- {
- if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
- {
- reset_return = EVP_CIPHER_CTX_reset(ctx);
- ERR_print_errors_fp(stderr); fflush(stderr);
- if(1 != reset_return)
- return 0xF5;
- return 0x5;
- }
- }
- /* Clean up */
- if(1 != EVP_CIPHER_CTX_reset(ctx))
- {
- ERR_print_errors_fp(stderr); fflush(stderr);
- return 0xF0;
- }
- *op_ciphertext_len=ciphertext_len;
- return 0;
- }
- uint32_t base64_encoding_wrapper(unsigned char* dest, unsigned char* src, uint32_t length)
- {
- return EVP_EncodeBlock(dest, src, length);
- }
- uint32_t base64_decoding_wrapper(unsigned char* dest, unsigned char* src, uint32_t length)
- {
- int length_with_padding = EVP_DecodeBlock(dest, src, length);
- if(length_with_padding == -1)
- return length_with_padding;
- char* first_equals_character = strstr((char*)src, "=");
- if(first_equals_character != NULL)
- {
- if(first_equals_character == (char*)src + length - 1) // the first equals character is also the last character in the string ==> Only one equals ==> 2 v$
- length_with_padding -= 1;
- else //if(first_equals_character == src + 38) // assuming that the base64 string is valid (EVP_DecodeBlock would have thrown an error in that case), the$
- length_with_padding -= 2;
- }
- return length_with_padding;
- }
|