summaryrefslogtreecommitdiff
path: root/src/core/crypto_openssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/crypto_openssl.c')
-rw-r--r--src/core/crypto_openssl.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/core/crypto_openssl.c b/src/core/crypto_openssl.c
new file mode 100644
index 0000000..551ea83
--- /dev/null
+++ b/src/core/crypto_openssl.c
@@ -0,0 +1,142 @@
+#include "hybbx/types.h"
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+#include <stdio.h>
+#include <string.h>
+
+void hybbx_openssl_sha256_hex(const char *data, size_t len, char hex[65])
+{
+ unsigned char digest[32];
+ unsigned int digest_len = sizeof(digest);
+ EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+
+ if (ctx == NULL) {
+ hex[0] = '\0';
+ return;
+ }
+
+ if (EVP_DigestInit_ex(ctx, EVP_sha256(), NULL) != 1 ||
+ EVP_DigestUpdate(ctx, data, len) != 1 ||
+ EVP_DigestFinal_ex(ctx, digest, &digest_len) != 1) {
+ EVP_MD_CTX_free(ctx);
+ hex[0] = '\0';
+ return;
+ }
+
+ EVP_MD_CTX_free(ctx);
+
+ for (size_t i = 0; i < digest_len; i++) {
+ snprintf(hex + i * 2, 3, "%02x", digest[i]);
+ }
+}
+
+static int openssl_gcm_crypt(int encrypt, const uint8_t key[32],
+ const uint8_t nonce[12], const uint8_t *aad,
+ size_t aad_len, const uint8_t *in, size_t in_len,
+ uint8_t *out, const uint8_t tag_in[16],
+ uint8_t tag_out[16])
+{
+ EVP_CIPHER_CTX *ctx = NULL;
+ int out_len = 0;
+ int total = 0;
+ int rc = -1;
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (ctx == NULL) {
+ return -1;
+ }
+
+ if (EVP_CipherInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL, encrypt) !=
+ 1 ||
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) != 1 ||
+ EVP_CipherInit_ex(ctx, NULL, NULL, key, nonce, encrypt) != 1) {
+ goto done;
+ }
+
+ if (aad_len > 0 && aad != NULL) {
+ if (EVP_CipherUpdate(ctx, NULL, &out_len, aad, (int)aad_len) != 1) {
+ goto done;
+ }
+ }
+
+ if (in_len > 0) {
+ if (EVP_CipherUpdate(ctx, out, &out_len, in, (int)in_len) != 1) {
+ goto done;
+ }
+ total = out_len;
+ }
+
+ if (encrypt) {
+ if (EVP_EncryptFinal_ex(ctx, out + total, &out_len) != 1) {
+ goto done;
+ }
+ if (tag_out == NULL ||
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag_out) != 1) {
+ goto done;
+ }
+ rc = 0;
+ goto done;
+ }
+
+ if (tag_in == NULL ||
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16,
+ (void *)(uintptr_t)tag_in) != 1) {
+ goto done;
+ }
+
+ if (EVP_DecryptFinal_ex(ctx, out + total, &out_len) != 1) {
+ goto done;
+ }
+
+ rc = 0;
+done:
+ EVP_CIPHER_CTX_free(ctx);
+ return rc;
+}
+
+int hybbx_openssl_aes256gcm_encrypt(
+ const uint8_t key[32], const uint8_t nonce[12], const uint8_t *aad,
+ size_t aad_len, const uint8_t *plaintext, size_t plaintext_len,
+ uint8_t *ciphertext, uint8_t tag[16])
+{
+ if (key == NULL || nonce == NULL || tag == NULL) {
+ return -1;
+ }
+ if (plaintext_len > 0 && (plaintext == NULL || ciphertext == NULL)) {
+ return -1;
+ }
+
+ return openssl_gcm_crypt(1, key, nonce, aad, aad_len, plaintext,
+ plaintext_len, ciphertext, NULL, tag);
+}
+
+int hybbx_openssl_aes256gcm_decrypt(
+ const uint8_t key[32], const uint8_t nonce[12], const uint8_t *aad,
+ size_t aad_len, const uint8_t *ciphertext, size_t ciphertext_len,
+ uint8_t *plaintext, const uint8_t tag[16])
+{
+ if (key == NULL || nonce == NULL || tag == NULL) {
+ return -1;
+ }
+ if (ciphertext_len > 0 && (ciphertext == NULL || plaintext == NULL)) {
+ return -1;
+ }
+
+ return openssl_gcm_crypt(0, key, nonce, aad, aad_len, ciphertext,
+ ciphertext_len, plaintext, tag, NULL);
+}
+
+hybbx_result_t hybbx_openssl_random(uint8_t *buf, size_t len)
+{
+ if (buf == NULL || len == 0) {
+ return HYBBX_ERR_INVALID;
+ }
+
+ if (RAND_bytes(buf, (int)len) == 1) {
+ return HYBBX_OK;
+ }
+
+ return HYBBX_ERR_IO;
+}
git clone -b <branch> https://cgit.mode42.com/<repo>.git
git clone -b <branch> git://cgit.mode42.com/<repo>.git

info@mode42.com