crypto.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #include <stdio.h>
  2. #include <string>
  3. #include <string.h>
  4. #include <memory>
  5. using std::unique_ptr;
  6. #include <openssl/err.h>
  7. #include <openssl/bn.h>
  8. #include <openssl/rsa.h>
  9. #include <openssl/evp.h>
  10. #include <openssl/pem.h>
  11. EVP_CIPHER_CTX *ctx;
  12. RSA* rsa;
  13. BIGNUM* bn;
  14. // assumes that the digest is at least of length 256/8 bytes.
  15. uint32_t generate_sha256_hash(const unsigned char *message, size_t message_len, unsigned char *digest)
  16. {
  17. EVP_MD_CTX *mdctx; unsigned int digest_len;
  18. if((mdctx = EVP_MD_CTX_create()) == NULL)
  19. {
  20. printf("EVP_MD_CTX_create returned NULL - could not create context\n"); fflush(stdout); return 0x1;
  21. }
  22. if(EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL) != 1)
  23. {
  24. printf("EVP_DigestInit_ex returned 0 - could not initialize hash with SHA256\n"); fflush(stdout); return 0x2;
  25. }
  26. if(EVP_DigestUpdate(mdctx, message, message_len) != 1)
  27. {
  28. printf("EVP_DigestUpdate returned 0 - could not compute SHA256 hash\n"); fflush(stdout); return 0x3;
  29. }
  30. if(1 != EVP_DigestFinal_ex(mdctx, digest, &digest_len))
  31. {
  32. printf("EVP_DigestFinal_ex returned 0 - could not finalize SHA256 hash\n"); fflush(stdout); return 0x4;
  33. }
  34. if(digest_len != 32)
  35. {
  36. printf("EVP_DigestFinal_ex returned a digest length of 0x%x instead of 0x20\n", digest_len); fflush(stdout); return 0x5;
  37. }
  38. EVP_MD_CTX_destroy(mdctx);
  39. return 0;
  40. }
  41. //////////////////////////////////////////////////////////////////////////
  42. //////////////////////////////////////
  43. void crypto_cleanup()
  44. {
  45. RSA_free(rsa);
  46. BN_free(bn);
  47. EVP_CIPHER_CTX_free(ctx);
  48. }
  49. // Code adapted from here: https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
  50. 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)
  51. {
  52. int len;
  53. int ciphertext_len;
  54. if(ctx == NULL)
  55. {
  56. /* Create and initialise the context */
  57. if(!(ctx = EVP_CIPHER_CTX_new())) { ERR_print_errors_fp(stderr); fflush(stderr);return 0x1; }
  58. }
  59. /* Initialise the encryption operation. */
  60. if(1 != EVP_CipherInit_ex(ctx, EVP_aes_128_gcm(), NULL, key, iv, enc))
  61. {
  62. EVP_CIPHER_CTX_init(ctx);
  63. ERR_print_errors_fp(stderr);
  64. return 0x2;
  65. }
  66. /* Provide the message to be encrypted, and obtain the encrypted output.
  67. * EVP_EncryptUpdate can be called multiple times if necessary
  68. */
  69. if(1 != EVP_CipherUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
  70. {
  71. EVP_CIPHER_CTX_init(ctx);
  72. ERR_print_errors_fp(stderr);
  73. return 0x3;
  74. }
  75. ciphertext_len = len;
  76. if(enc == 0)
  77. {
  78. if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))
  79. {
  80. EVP_CIPHER_CTX_init(ctx);
  81. ERR_print_errors_fp(stderr); fflush(stderr);
  82. return 0x5;
  83. }
  84. }
  85. /* Finalise the encryption. Normally ciphertext bytes may be written at
  86. * this stage, but this does not occur in GCM mode
  87. */
  88. // TODO: ^^^ Why the heck does it not occur in GCM mode ?
  89. if(1 != EVP_CipherFinal_ex(ctx, ciphertext + len, &len))
  90. {
  91. EVP_CIPHER_CTX_init(ctx);
  92. ERR_print_errors_fp(stderr); fflush(stderr);
  93. return 0x4;
  94. }
  95. ciphertext_len += len;
  96. /* Get the tag */
  97. if(enc == 1)
  98. {
  99. if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
  100. {
  101. EVP_CIPHER_CTX_init(ctx);
  102. ERR_print_errors_fp(stderr); fflush(stderr);
  103. return 0x5;
  104. }
  105. }
  106. /* Clean up */
  107. EVP_CIPHER_CTX_init(ctx);
  108. *op_ciphertext_len=ciphertext_len;
  109. return 0;
  110. }
  111. uint32_t base64_encoding_wrapper(unsigned char* src, uint32_t length, unsigned char* dest)
  112. {
  113. return EVP_EncodeBlock(dest, src, length);
  114. }
  115. uint32_t base64_decoding_wrapper(const char* src, uint32_t length, unsigned char* dest)
  116. {
  117. int length_with_padding = EVP_DecodeBlock(dest, (const unsigned char*) src, length);
  118. if(length_with_padding == -1)
  119. return length_with_padding;
  120. char* first_equals_character = strstr((char*)src, "=");
  121. if(first_equals_character != NULL)
  122. {
  123. if(first_equals_character == (char*)src + length - 1) // the first equals character is also the last character in the string ==> Only one equals
  124. length_with_padding -= 1;
  125. else // assuming that the base64 string is valid (EVP_DecodeBlock would have thrown an error in that case).
  126. length_with_padding -= 2;
  127. }
  128. return length_with_padding;
  129. }