crypto.cpp 4.2 KB

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