diff --git a/src/common.c b/src/common.c index ae07d51..13e93a3 100644 --- a/src/common.c +++ b/src/common.c @@ -58,17 +58,14 @@ typedef struct { size_t length; } Password; -Password base64_decode_string(const char *input) { - Password p; +void base64_decode_string(const char *input, unsigned char **outstring, size_t *outlen) { size_t input_len = strlen(input); size_t outmaxlen = input_len / 4 * 3; - p.string = malloc(outmaxlen); - int b64err = sodium_base642bin(p.string, outmaxlen, (const char *) input, input_len, - NULL, &p.length, NULL, sodium_base64_VARIANT_ORIGINAL); + *outstring = malloc(outmaxlen * sizeof(unsigned char)); + int b64err = sodium_base642bin(*outstring, outmaxlen, (const char *) input, input_len, + NULL, outlen, NULL, sodium_base64_VARIANT_ORIGINAL); if (b64err != 0) { fprintf(stderr, "[ERROR] Unable to base64-decode the password\n"); exit(EXIT_FAILURE); } - - return p; } \ No newline at end of file diff --git a/src/libexim-encrypt-dlfunc-decrypt-secretbox.c b/src/libexim-encrypt-dlfunc-decrypt-secretbox.c index f8d74b4..feeb95b 100644 --- a/src/libexim-encrypt-dlfunc-decrypt-secretbox.c +++ b/src/libexim-encrypt-dlfunc-decrypt-secretbox.c @@ -30,11 +30,11 @@ typedef enum { } seen_args; int main(int argc, char *argv[]) { - char* prog_basename = basename(argv[0]); + char *prog_basename = basename(argv[0]); int opt; char *cipherstring; - size_t pwlen; - char *b64password; + size_t password_len; + char *password; char *password_env; seen_args mode = NONE; @@ -57,9 +57,9 @@ int main(int argc, char *argv[]) { // check environment for LIBEXIM_PASSWORD password_env = getenv(ENVVAR_PASSWORD_NAME); if (password_env != NULL && strlen(password_env) > 0) { - pwlen = strlen(password_env); - b64password = malloc(pwlen + 1); - strncpy(b64password, password_env, pwlen); + password_len = strlen((const char *) password_env); + password = malloc(password_len + 1); + strncpy(password, password_env, password_len); mode |= PASSENV; } @@ -69,9 +69,9 @@ int main(int argc, char *argv[]) { long_options, &long_index)) != -1) { switch (opt) { case 'p': - pwlen = strlen(optarg); - b64password = malloc(pwlen + 1); - strncpy(b64password, optarg, pwlen); + password_len = strlen((const char *) optarg); + password = malloc(password_len + 1); + strncpy(password, optarg, password_len); mode |= PASSARG; break; case 'f': @@ -96,16 +96,45 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } - // fail if neither argument nor filename is present + // fail if neither argument nor filename for ciphertext is present if (input == NONE) { fprintf(stderr, "[ERROR] Please specify a ciphertext source.\n\n"); print_usage(prog_basename); exit(EXIT_FAILURE); } - // base64-decode password - Password p; - p = base64_decode_string(b64password); + // Derive key from the password. + unsigned char keybytes[crypto_secretbox_KEYBYTES]; + sodium_memzero(keybytes, crypto_secretbox_KEYBYTES); + crypto_generichash(keybytes, crypto_secretbox_KEYBYTES, + (unsigned char *) password, password_len, NULL, 0); - printf("»%s« [%zu]\n", p.string, p.length); + // base64-decode input + unsigned char *ciphertext; + size_t ciphertext_len; + base64_decode_string(cipherstring, &ciphertext, &ciphertext_len); + + // extract nonce + unsigned char nonce[crypto_secretbox_NONCEBYTES]; + memcpy(nonce, ciphertext, crypto_secretbox_NONCEBYTES); + + // prepare buffer for cleartext + if (ciphertext_len < crypto_secretbox_NONCEBYTES + crypto_secretbox_MACBYTES) { + fprintf(stderr, "[ERROR] Ciphertext is too small to contain any data.\n\n"); + exit(EXIT_FAILURE); + } + size_t cleartext_len = ciphertext_len - crypto_secretbox_NONCEBYTES - crypto_secretbox_MACBYTES; + unsigned char *cleartext = (unsigned char *) malloc(cleartext_len + 1); + sodium_memzero(cleartext, cleartext_len + 1); + + // decrypt + if (crypto_secretbox_open_easy(cleartext, &ciphertext[crypto_secretbox_NONCEBYTES], + ciphertext_len - crypto_secretbox_NONCEBYTES, nonce, keybytes) == 0) { + } else { + fprintf(stderr, "[ERROR] Unable to decrypt message.\n\n"); + exit(EXIT_FAILURE); + } + + // print cleartext to stdout + fprintf(stdout, "%s", (const char *) cleartext); } \ No newline at end of file