mirror of
https://gitlab.kit.edu/kit/scc/sys/mail/exim-encrypt-dlfunc.git
synced 2025-12-06 08:33:56 +01:00
…
This commit is contained in:
34
src/genkey.c
34
src/genkey.c
@ -32,11 +32,15 @@ void
|
|||||||
dump_key_as_exim_config(FILE * f, const char *name, unsigned char *key,
|
dump_key_as_exim_config(FILE * f, const char *name, unsigned char *key,
|
||||||
unsigned int keylen)
|
unsigned int keylen)
|
||||||
{
|
{
|
||||||
fprintf(f, "%s = \"", name);
|
// encode with base64
|
||||||
for (int i = 0; i < keylen; i++) {
|
unsigned int b64len = sodium_base64_ENCODED_LEN(keylen, sodium_base64_VARIANT_ORIGINAL);
|
||||||
fprintf(f, "\\x%02x", key[i]);
|
unsigned char *b64string = malloc(b64len);
|
||||||
}
|
sodium_bin2base64((char *const) b64string, b64len,
|
||||||
fprintf(f, "\"\n");
|
key, keylen,
|
||||||
|
sodium_base64_VARIANT_ORIGINAL);
|
||||||
|
fprintf(f, "%s = \"%s\"\n", name, b64string);
|
||||||
|
|
||||||
|
free(b64string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -52,21 +56,6 @@ write_key_files(const char *filebase, const char *varname,
|
|||||||
sprintf(exim_filename, "%s_exim.conf", filebase);
|
sprintf(exim_filename, "%s_exim.conf", filebase);
|
||||||
sprintf(raw_filename, "%s.raw", filebase);
|
sprintf(raw_filename, "%s.raw", filebase);
|
||||||
|
|
||||||
/*
|
|
||||||
// open header file
|
|
||||||
f = fopen(header_filename, "w+");
|
|
||||||
if (f == NULL) {
|
|
||||||
fprintf(stderr, "Unable to open %s for writing",
|
|
||||||
header_filename);
|
|
||||||
exit(129);
|
|
||||||
}
|
|
||||||
// write key as C header
|
|
||||||
dump_key_as_c_code(f, varname, key, keylen);
|
|
||||||
|
|
||||||
// close header file
|
|
||||||
fclose(f);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// open exim config snippet file
|
// open exim config snippet file
|
||||||
f = fopen(exim_filename, "w+");
|
f = fopen(exim_filename, "w+");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
@ -100,11 +89,6 @@ void create_cryptobox_keys(const char *filebase, const char *varname)
|
|||||||
unsigned char recipient_pk[crypto_box_PUBLICKEYBYTES];
|
unsigned char recipient_pk[crypto_box_PUBLICKEYBYTES];
|
||||||
unsigned char recipient_sk[crypto_box_SECRETKEYBYTES];
|
unsigned char recipient_sk[crypto_box_SECRETKEYBYTES];
|
||||||
|
|
||||||
while (key_contains_zero(recipient_pk, crypto_box_PUBLICKEYBYTES) &
|
|
||||||
key_contains_zero(recipient_sk, crypto_box_SECRETKEYBYTES)) {
|
|
||||||
crypto_box_keypair(recipient_pk, recipient_sk);
|
|
||||||
}
|
|
||||||
|
|
||||||
char pk_filename[4096];
|
char pk_filename[4096];
|
||||||
char pk_varname[4096];
|
char pk_varname[4096];
|
||||||
char sk_filename[4096];
|
char sk_filename[4096];
|
||||||
|
|||||||
@ -6,9 +6,23 @@
|
|||||||
/* Exim4 dlfunc API header */
|
/* Exim4 dlfunc API header */
|
||||||
#include <local_scan.h>
|
#include <local_scan.h>
|
||||||
|
|
||||||
|
int b64decode(unsigned char * const input, const size_t input_len, unsigned char * output) {
|
||||||
|
unsigned int output_len = input_len / 4 * 3;
|
||||||
|
output = store_get(output_len);
|
||||||
|
sodium_memzero(output, output_len);
|
||||||
|
int b64err = sodium_base642bin(output, output_len, (const char *) input, input_len, NULL, NULL, NULL, sodium_base64_VARIANT_ORIGINAL);
|
||||||
|
if (b64err != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return output_len;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Encrypt the second argument with password string from the first argument
|
* Encrypt message using crypto_secretbox_easy().
|
||||||
* using crypto_secretbox_easy().
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 1. password
|
||||||
|
* 2. cleartext message
|
||||||
*/
|
*/
|
||||||
int sodium_crypto_secretbox_encrypt_password(uschar **yield, int argc, uschar *argv[]) {
|
int sodium_crypto_secretbox_encrypt_password(uschar **yield, int argc, uschar *argv[]) {
|
||||||
// ensure libsodium is initialized
|
// ensure libsodium is initialized
|
||||||
@ -48,11 +62,14 @@ int sodium_crypto_secretbox_encrypt_password(uschar **yield, int argc, uschar *a
|
|||||||
// encrypt message
|
// encrypt message
|
||||||
unsigned char nonce[crypto_secretbox_NONCEBYTES];
|
unsigned char nonce[crypto_secretbox_NONCEBYTES];
|
||||||
randombytes_buf(nonce, sizeof nonce);
|
randombytes_buf(nonce, sizeof nonce);
|
||||||
crypto_secretbox_easy(ciphertext, message, messagelen, nonce, keybytes);
|
if (crypto_secretbox_easy(ciphertext, message, messagelen, nonce, keybytes) != 0) {
|
||||||
|
*yield = string_copy((unsigned char *) "Encryption error after crypto_secretbox_easy()");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// combine nonce and ciphertext
|
// combine nonce and ciphertext
|
||||||
size_t combined_message_len = crypto_secretbox_NONCEBYTES + cipherlen;
|
size_t combined_message_len = crypto_secretbox_NONCEBYTES + cipherlen;
|
||||||
unsigned char * combined_message = store_get(combined_message_len);
|
unsigned char *combined_message = store_get(combined_message_len);
|
||||||
memcpy(combined_message, nonce, crypto_secretbox_NONCEBYTES);
|
memcpy(combined_message, nonce, crypto_secretbox_NONCEBYTES);
|
||||||
memcpy(&combined_message[crypto_secretbox_NONCEBYTES], ciphertext, cipherlen);
|
memcpy(&combined_message[crypto_secretbox_NONCEBYTES], ciphertext, cipherlen);
|
||||||
|
|
||||||
@ -60,7 +77,7 @@ int sodium_crypto_secretbox_encrypt_password(uschar **yield, int argc, uschar *a
|
|||||||
unsigned int outputsize = sodium_base64_ENCODED_LEN(combined_message_len,
|
unsigned int outputsize = sodium_base64_ENCODED_LEN(combined_message_len,
|
||||||
sodium_base64_VARIANT_ORIGINAL);
|
sodium_base64_VARIANT_ORIGINAL);
|
||||||
unsigned char *outstring = (unsigned char *) store_get(outputsize);
|
unsigned char *outstring = (unsigned char *) store_get(outputsize);
|
||||||
sodium_memzero(outstring, outputsize);
|
//sodium_memzero(outstring, outputsize);
|
||||||
sodium_bin2base64((char *const) outstring, outputsize,
|
sodium_bin2base64((char *const) outstring, outputsize,
|
||||||
combined_message, combined_message_len,
|
combined_message, combined_message_len,
|
||||||
sodium_base64_VARIANT_ORIGINAL);
|
sodium_base64_VARIANT_ORIGINAL);
|
||||||
@ -71,26 +88,27 @@ int sodium_crypto_secretbox_encrypt_password(uschar **yield, int argc, uschar *a
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decrypt the second argument with password string from the first argument
|
* Decrypt message encrypted by sodium_crypto_secretbox_encrypt_password(). Arguments:
|
||||||
* using crypto_secretbox_open_easy().
|
* 1. password string
|
||||||
|
* 2. encrypted message
|
||||||
*/
|
*/
|
||||||
int sodium_crypto_secretbox_decrypt_password(uschar ** yield, int argc, uschar * argv[])
|
int sodium_crypto_secretbox_decrypt_password(uschar **yield, int argc, uschar *argv[]) {
|
||||||
{
|
|
||||||
// ensure libsodium is initialized
|
// ensure libsodium is initialized
|
||||||
if (sodium_init() == -1) {
|
if (sodium_init() == -1) {
|
||||||
*yield = string_copy(US "Unable to initialize libsodium");
|
*yield = string_copy(US
|
||||||
|
"Unable to initialize libsodium");
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
// check argument count
|
// check argument count
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
*yield =
|
*yield =
|
||||||
string_sprintf
|
string_sprintf
|
||||||
("Wrong number of arguments (got %i, expected 2)", argc);
|
("Wrong number of arguments (got %i, expected 2)", argc);
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
// get password
|
// get password
|
||||||
unsigned char *password = argv[0];
|
unsigned char *password = argv[0];
|
||||||
size_t passwordlen = strlen((const char *)password);
|
size_t passwordlen = strlen((const char *) password);
|
||||||
|
|
||||||
// Derive key from the password.
|
// Derive key from the password.
|
||||||
unsigned char keybytes[crypto_secretbox_KEYBYTES];
|
unsigned char keybytes[crypto_secretbox_KEYBYTES];
|
||||||
@ -106,10 +124,14 @@ int sodium_crypto_secretbox_decrypt_password(uschar ** yield, int argc, uschar *
|
|||||||
unsigned int combined_message_len = ciphertextb64len / 4 * 3;
|
unsigned int combined_message_len = ciphertextb64len / 4 * 3;
|
||||||
unsigned char *combined_message = (unsigned char *) store_get(combined_message_len);
|
unsigned char *combined_message = (unsigned char *) store_get(combined_message_len);
|
||||||
sodium_memzero(combined_message, combined_message_len);
|
sodium_memzero(combined_message, combined_message_len);
|
||||||
sodium_base642bin(combined_message, combined_message_len,
|
int b64err = sodium_base642bin(combined_message, combined_message_len,
|
||||||
(const char *) ciphertextb64, ciphertextb64len,
|
(const char *) ciphertextb64, ciphertextb64len,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
sodium_base64_VARIANT_ORIGINAL);
|
sodium_base64_VARIANT_ORIGINAL);
|
||||||
|
if (b64err != 0) {
|
||||||
|
*yield = string_copy((unsigned char *) "Error decoding base64 encoded ciphertext");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
// extract nonce
|
// extract nonce
|
||||||
unsigned char nonce[crypto_secretbox_NONCEBYTES];
|
unsigned char nonce[crypto_secretbox_NONCEBYTES];
|
||||||
@ -117,17 +139,142 @@ int sodium_crypto_secretbox_decrypt_password(uschar ** yield, int argc, uschar *
|
|||||||
|
|
||||||
// prepare buffer for cleartext
|
// prepare buffer for cleartext
|
||||||
unsigned int cleartextlen = combined_message_len - crypto_secretbox_NONCEBYTES - crypto_secretbox_MACBYTES;
|
unsigned int cleartextlen = combined_message_len - crypto_secretbox_NONCEBYTES - crypto_secretbox_MACBYTES;
|
||||||
unsigned char *cleartext = (unsigned char *) store_get(cleartextlen+1);
|
unsigned char *cleartext = (unsigned char *) store_get(cleartextlen + 1);
|
||||||
sodium_memzero(cleartext, cleartextlen+1);
|
sodium_memzero(cleartext, cleartextlen + 1);
|
||||||
|
|
||||||
// decrypt message
|
// decrypt message
|
||||||
if (crypto_secretbox_open_easy(cleartext, &combined_message[crypto_secretbox_NONCEBYTES],
|
if (crypto_secretbox_open_easy(cleartext, &combined_message[crypto_secretbox_NONCEBYTES],
|
||||||
combined_message_len - crypto_secretbox_NONCEBYTES, nonce, keybytes) != 0) {
|
combined_message_len - crypto_secretbox_NONCEBYTES, nonce, keybytes) != 0) {
|
||||||
*yield = string_copy((unsigned char *) "Unable to decrypt.");
|
*yield = string_copy((unsigned char *) "Decryption error after crypto_secretbox_open_easy()");
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return base64-encoded ciphertext
|
// return cleartext
|
||||||
*yield = string_copy(cleartext);
|
*yield = string_copy(cleartext);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encrypt message using crypto_box_seal().
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 1. public key
|
||||||
|
* 2. cleartext message
|
||||||
|
*/
|
||||||
|
int sodium_crypto_box_seal(uschar **yield, int argc, uschar *argv[]) {
|
||||||
|
if (sodium_init() == -1) {
|
||||||
|
*yield = string_copy(US
|
||||||
|
"Unable to initialize libsodium");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
if (argc != 2) {
|
||||||
|
*yield = string_sprintf("Wrong number of arguments (got %i, expected 2)", argc);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get key, check size
|
||||||
|
unsigned char *key = argv[0];
|
||||||
|
size_t keylen = strlen((const char *) key);
|
||||||
|
if (keylen != crypto_box_PUBLICKEYBYTES) {
|
||||||
|
*yield = string_sprintf("Public key has wrong size (got %d, expected %d)", keylen, crypto_box_PUBLICKEYBYTES);
|
||||||
|
return ERROR;
|
||||||
|
};
|
||||||
|
|
||||||
|
// get cleartext message
|
||||||
|
unsigned char *message = argv[1];
|
||||||
|
size_t messagelen = strlen((const char *) message);
|
||||||
|
|
||||||
|
// prepare buffer for ciphertext
|
||||||
|
unsigned int cipherlen = messagelen + crypto_box_SEALBYTES;
|
||||||
|
unsigned char *ciphertext = store_get(cipherlen);
|
||||||
|
sodium_memzero(ciphertext, cipherlen);
|
||||||
|
|
||||||
|
// encrypt message
|
||||||
|
if (crypto_box_seal(ciphertext, message, messagelen, key) == -1) {
|
||||||
|
*yield = string_copy((unsigned char *) "Encryption error after crypto_box_seal()");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// base64-encode the ciphertext
|
||||||
|
unsigned int outputsize = sodium_base64_ENCODED_LEN(cipherlen,
|
||||||
|
sodium_base64_VARIANT_ORIGINAL);
|
||||||
|
unsigned char *outstring = store_get(outputsize);
|
||||||
|
sodium_bin2base64((char *const) outstring, outputsize,
|
||||||
|
ciphertext, cipherlen,
|
||||||
|
sodium_base64_VARIANT_ORIGINAL);
|
||||||
|
|
||||||
|
// return base64-encoded ciphertext
|
||||||
|
*yield = string_copy(outstring);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decrypt message encrypted by sodium_crypto_box_seal().
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* 1. private key
|
||||||
|
* 2. public key
|
||||||
|
* 3. encrypted message
|
||||||
|
*/
|
||||||
|
int sodium_crypto_box_seal_open(uschar **yield, int argc, uschar *argv[]) {
|
||||||
|
if (sodium_init() == -1) {
|
||||||
|
*yield = string_copy(US
|
||||||
|
"Unable to initialize libsodium");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
if (argc != 3) {
|
||||||
|
*yield = string_sprintf("Wrong number of arguments (got %i, expected 2)", argc);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check private key
|
||||||
|
unsigned char *sk = argv[0];
|
||||||
|
size_t sk_len = strlen((const char *)sk);
|
||||||
|
if (sk_len != crypto_box_SECRETKEYBYTES) {
|
||||||
|
*yield = string_sprintf("Private key has wrong size (got %d, expected %d)", sk_len, crypto_box_SECRETKEYBYTES);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check public key
|
||||||
|
unsigned char *pk = argv[1];
|
||||||
|
size_t pk_len = strlen((const char *)pk);
|
||||||
|
if (pk_len != crypto_box_PUBLICKEYBYTES) {
|
||||||
|
*yield = string_sprintf("Private key has wrong size (got %d, expected %d)", pk_len, crypto_box_PUBLICKEYBYTES);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get encrypted message
|
||||||
|
unsigned char *ciphertextb64 = argv[2];
|
||||||
|
size_t ciphertextb64len = strlen((const char *) ciphertextb64);
|
||||||
|
|
||||||
|
// base64-decode the ciphertext
|
||||||
|
unsigned int ciphertextlen = ciphertextb64len / 4 * 3;
|
||||||
|
unsigned char *ciphertext = (unsigned char *) store_get(ciphertextlen);
|
||||||
|
sodium_memzero(ciphertext, ciphertextlen);
|
||||||
|
int b64err = sodium_base642bin(ciphertext, ciphertextlen,
|
||||||
|
(const char *) ciphertextb64, ciphertextb64len,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
sodium_base64_VARIANT_ORIGINAL);
|
||||||
|
if (b64err != 0) {
|
||||||
|
*yield = string_copy((unsigned char *) "Error decoding base64 encoded ciphertext");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare buffer for cleartext
|
||||||
|
unsigned int cleartextlen = ciphertextlen - crypto_box_SEALBYTES;
|
||||||
|
unsigned char *cleartext = (unsigned char *) store_get(cleartextlen + 1);
|
||||||
|
sodium_memzero(cleartext, cleartextlen + 1);
|
||||||
|
|
||||||
|
// decrypt message
|
||||||
|
if (crypto_box_seal_open(cleartext, ciphertext, ciphertextlen, pk, sk) != 0) {
|
||||||
|
*yield = string_copy((unsigned char *) "Decryption error after crypto_box_seal_open()");
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return cleartext
|
||||||
|
*yield = string_copy(cleartext);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
@ -1,61 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <sodium.h>
|
|
||||||
|
|
||||||
/* Exim4 dlfunc API header */
|
|
||||||
#include <local_scan.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Encrypt the second argument with the public key from the first argument
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
int sodium_crypto_box_seal(uschar ** yield, int argc, uschar * argv[])
|
|
||||||
{
|
|
||||||
size_t messagelen;
|
|
||||||
unsigned char *message, *key;
|
|
||||||
|
|
||||||
if (sodium_init() == -1) {
|
|
||||||
*yield = string_copy(US "Unable to initialize libsodium");
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
if (argc != 2) {
|
|
||||||
*yield =
|
|
||||||
string_sprintf
|
|
||||||
("Wrong number of arguments (got %i, expected 2)", argc);
|
|
||||||
return ERROR;
|
|
||||||
}
|
|
||||||
// get cleartext message
|
|
||||||
message = argv[0];
|
|
||||||
messagelen = strlen((const char *)message);
|
|
||||||
|
|
||||||
// get key
|
|
||||||
key = argv[1];
|
|
||||||
|
|
||||||
// prepare buffer for ciphertext
|
|
||||||
unsigned int cipherlen = messagelen + crypto_box_SEALBYTES;
|
|
||||||
unsigned char *ciphertext = malloc(cipherlen);
|
|
||||||
sodium_memzero(ciphertext, cipherlen);
|
|
||||||
|
|
||||||
// encrypt message
|
|
||||||
crypto_box_seal(ciphertext, message, messagelen, recipient_pk);
|
|
||||||
|
|
||||||
// base64-encode the ciphertext
|
|
||||||
unsigned int outputsize = sodium_base64_ENCODED_LEN(cipherlen,
|
|
||||||
sodium_base64_VARIANT_ORIGINAL);
|
|
||||||
unsigned char *outstring = malloc(outputsize);
|
|
||||||
sodium_memzero(outstring, outputsize);
|
|
||||||
|
|
||||||
sodium_bin2base64((char *const)outstring, outputsize,
|
|
||||||
ciphertext, cipherlen,
|
|
||||||
sodium_base64_VARIANT_ORIGINAL);
|
|
||||||
free(ciphertext);
|
|
||||||
|
|
||||||
// return base64-encoded ciphertext
|
|
||||||
*yield = string_copy(outstring);
|
|
||||||
free(outstring);
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@ -8,3 +8,8 @@ CIPHERTEXT=$(exim -be "\${dlfunc{${LIB}}{sodium_crypto_secretbox_encrypt_passwor
|
|||||||
DECRYPTED=$(exim -be "\${dlfunc{${LIB}}{sodium_crypto_secretbox_decrypt_password}{${PASSWORD}}{${CIPHERTEXT}}}")
|
DECRYPTED=$(exim -be "\${dlfunc{${LIB}}{sodium_crypto_secretbox_decrypt_password}{${PASSWORD}}{${CIPHERTEXT}}}")
|
||||||
|
|
||||||
if [ "${CLEARTEXT}" == "${DECRYPTED}" ] ; then echo "Test successful"; fi
|
if [ "${CLEARTEXT}" == "${DECRYPTED}" ] ; then echo "Test successful"; fi
|
||||||
|
|
||||||
|
|
||||||
|
exim -be "cryptobox_recipient_pk = \"\xa0\x32\xf6\xa8\x2a\x6c\x7b\x41\xf4\xfc\xc8\x7c\xa8\x79\x46\x24\x9c\x03\xf7\x47\xf4\x6f\x6c\xea\x90\xcb\xed\x4c\x48\x4d\x57\x63\" \\
|
||||||
|
cryptobox_recipient_sk = \"\xf7\x4d\x7d\x26\x90\x6a\x63\xc3\xfa\xcd\xed\x2f\xd4\xd0\x6a\x76\xf5\xc4\xe6\xd8\xcb\xcf\x4c\x0e\x2d\x7c\x99\xfd\xcb\x0b\xf5\xfe\" \\
|
||||||
|
\${dlfunc{${LIB}}{sodium_crypto_box_seal}{cryptobox_recipient_pk}{${CLEARTEXT}}}"
|
||||||
|
|||||||
Reference in New Issue
Block a user