commit - 41815bccaee3b630bfc23a1a4764aa42f1aab87d
commit + 6bcbc7986fcc2a27f034b3cddaae5ee99ac00f23
blob - 45c6b476539f1fa5f8d9f7bf2c95826b04e0e76a
blob + 5772be376b91e12b68f710483131eb6da7209e5b
--- filter-dkimsign.8
+++ filter-dkimsign.8
The following flags are supported:
.Bl -tag -width Ds
.It Fl a Ar algorithm
-The algorithm to use.
-This implementation only supports rsa cryptography.
+The
+.Ar algorithm
+to use.
+Supported signing algorithms are
+.Em rsa
+and
+.Em ed25519 Pq when enabled at compile time .
Only sha256 should be used for hashing, since other algorithms are most likely
not supported by verifiers.
Defaults to
-.Em rsa-sha256 .
+.Cm rsa-sha256 .
.It Fl c Ar canonicalization
The canonicalization algorithm used to sign the message.
Defaults to
blob - 5d552f3936d3170a270cc6b9898fd013416caf6b
blob + 13e61d3659c3073073f0e2ff9aaef932b5feadcf
--- main.c
+++ main.c
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/sha.h>
int has_body;
struct dkim_signature signature;
int err;
- EVP_MD_CTX *b;
- EVP_MD_CTX *bh;
+ EVP_MD_CTX *dctx;
};
/* RFC 6376 section 5.4.1 */
static EVP_PKEY *pkey;
static const EVP_MD *hash_md;
+static int keyid = EVP_PKEY_RSA;
+static int sephash = 0;
#define DKIM_SIGNATURE_LINELEN 78
while ((ch = getopt(argc, argv, "a:c:d:h:k:s:tx:z")) != -1) {
switch (ch) {
case 'a':
- if (strncmp(optarg, "rsa-", 4) != 0)
- osmtpd_err(1, "invalid algorithm");
- hashalg = optarg + 4;
+ if (strncmp(optarg, "rsa-", 4) == 0) {
+ cryptalg = "rsa";
+ hashalg = optarg + 4;
+ keyid = EVP_PKEY_RSA;
+ sephash = 0;
+#ifdef HAVE_ED25519
+ } else if (strncmp(optarg, "ed25519-", 8) == 0) {
+ hashalg = optarg + 8;
+ cryptalg = "ed25519";
+ keyid = EVP_PKEY_ED25519;
+ sephash = 1;
+#endif
+ } else
+ osmtpd_errx(1, "invalid algorithm");
break;
case 'c':
if (strncmp(optarg, "simple", 6) == 0) {
pkey = PEM_read_PrivateKey(keyfile, NULL, NULL, NULL);
if (pkey == NULL)
osmtpd_errx(1, "Can't read key file");
- if (EVP_PKEY_get0_RSA(pkey) == NULL)
- osmtpd_err(1, "Key is not of type rsa");
fclose(keyfile);
break;
case 's':
}
OpenSSL_add_all_digests();
- if ((hash_md = EVP_get_digestbyname(hashalg)) == NULL)
- osmtpd_errx(1, "Can't find hash: %s", hashalg);
if (pledge("tmppath stdio", NULL) == -1)
osmtpd_err(1, "pledge");
+ if ((hash_md = EVP_get_digestbyname(hashalg)) == NULL)
+ osmtpd_errx(1, "Can't find hash: %s", hashalg);
+
if (domain == NULL || selector == NULL || pkey == NULL)
usage();
+ if (EVP_PKEY_id(pkey) != keyid)
+ osmtpd_errx(1, "Key is not of type %s", cryptalg);
+
osmtpd_register_filter_dataline(dkim_dataline);
osmtpd_register_filter_commit(dkim_commit);
osmtpd_local_message(dkim_message_new, dkim_message_free);
if (addheaders > 0 && !dkim_signature_printf(message, "z="))
goto fail;
- if ((message->b = EVP_MD_CTX_new()) == NULL ||
- (message->bh = EVP_MD_CTX_new()) == NULL) {
+ if ((message->dctx = EVP_MD_CTX_new()) == NULL) {
dkim_errx(message, "Failed to create hash context");
goto fail;
}
- if (EVP_DigestSignInit(message->b, NULL, hash_md, NULL, pkey) <= 0 ||
- EVP_DigestInit_ex(message->bh, hash_md, NULL) == 0) {
+ if (EVP_DigestInit_ex(message->dctx, hash_md, NULL) <= 0) {
dkim_errx(message, "Failed to initialize hash context");
goto fail;
}
return message;
fail:
free(message->headers);
- EVP_MD_CTX_free(message->b);
- EVP_MD_CTX_free(message->bh);
+ EVP_MD_CTX_free(message->dctx);
free(message);
return NULL;
}
size_t i;
fclose(message->origf);
- EVP_MD_CTX_free(message->b);
- EVP_MD_CTX_free(message->bh);
+ EVP_MD_CTX_free(message->dctx);
free(message->signature.signature);
for (i = 0; message->headers[i] != NULL; i++)
free(message->headers[i]);
}
while (message->body_whitelines--) {
- if (EVP_DigestUpdate(message->bh, "\r\n", 2) == 0) {
+ if (EVP_DigestUpdate(message->dctx, "\r\n", 2) == 0) {
dkim_errx(message, "Can't update hash context");
return;
}
message->body_whitelines = 0;
message->has_body = 1;
- if (EVP_DigestUpdate(message->bh, line, linelen) == 0 ||
- EVP_DigestUpdate(message->bh, "\r\n", 2) == 0) {
+ if (EVP_DigestUpdate(message->dctx, line, linelen) == 0 ||
+ EVP_DigestUpdate(message->dctx, "\r\n", 2) == 0) {
dkim_errx(message, "Can't update hash context");
return;
}
{
struct dkim_message *message = ctx->local_message;
/* Use largest hash size here */
- char bbh[EVP_MAX_MD_SIZE];
- char bh[(((sizeof(bbh) + 2) / 3) * 4) + 1];
+ char bdigest[EVP_MAX_MD_SIZE];
+ char digest[(((sizeof(bdigest) + 2) / 3) * 4) + 1];
char *b;
const char *sdomain = domain[0], *tsdomain;
time_t now;
ssize_t i;
- size_t linelen;
+ size_t linelen = 0;
char *tmp, *tmp2;
+ int digestsz;
if (addtime || addexpire)
now = time(NULL);
return;
if (canonbody == CANON_SIMPLE && !message->has_body) {
- if (EVP_DigestUpdate(message->bh, "\r\n", 2) <= 0) {
+ if (EVP_DigestUpdate(message->dctx, "\r\n", 2) <= 0) {
dkim_errx(message, "Can't update hash context");
return;
}
}
- if (EVP_DigestFinal_ex(message->bh, bbh, NULL) == 0) {
+ if (EVP_DigestFinal_ex(message->dctx, bdigest, &digestsz) == 0) {
dkim_errx(message, "Can't finalize hash context");
return;
}
- EVP_EncodeBlock(bh, bbh, EVP_MD_CTX_size(message->bh));
- if (!dkim_signature_printf(message, "bh=%s; h=", bh))
+ EVP_EncodeBlock(digest, bdigest, digestsz);
+ if (!dkim_signature_printf(message, "bh=%s; h=", digest))
return;
/* Reverse order for ease of use of RFC6367 section 5.4.2 */
for (i = 0; message->headers[i] != NULL; i++)
continue;
- for (i--; i >= 0; i--) {
- if (EVP_DigestSignUpdate(message->b,
- message->headers[i],
- strlen(message->headers[i])) <= 0 ||
- EVP_DigestSignUpdate(message->b, "\r\n", 2) <= 0) {
- dkim_errx(message, "Failed to update digest context");
+ EVP_MD_CTX_reset(message->dctx);
+ if (!sephash) {
+ if (EVP_DigestSignInit(message->dctx, NULL, hash_md, NULL,
+ pkey) != 1) {
+ dkim_errx(message, "Failed to initialize signature "
+ "context");
return;
}
+ } else {
+ if (EVP_DigestInit_ex(message->dctx, hash_md, NULL) != 1) {
+ dkim_errx(message, "Failed to initialize hash context");
+ return;
+ }
+ }
+ for (i--; i >= 0; i--) {
+ if (!sephash) {
+ if (EVP_DigestSignUpdate(message->dctx,
+ message->headers[i],
+ strlen(message->headers[i])) != 1 ||
+ EVP_DigestSignUpdate(message->dctx, "\r\n",
+ 2) <= 0) {
+ dkim_errx(message, "Failed to update signature "
+ "context");
+ return;
+ }
+ } else {
+ if (EVP_DigestUpdate(message->dctx, message->headers[i],
+ strlen(message->headers[i])) != 1 ||
+ EVP_DigestUpdate(message->dctx, "\r\n", 2) <= 0) {
+ dkim_errx(message, "Failed to update digest "
+ "context");
+ return;
+ }
+ }
if ((tsdomain = dkim_domain_select(message, message->headers[i])) != NULL)
sdomain = tsdomain;
/* We're done with the cached header after hashing */
return;
}
dkim_parse_header(message, tmp, 1);
- if (EVP_DigestSignUpdate(message->b, tmp, strlen(tmp)) <= 0) {
- dkim_errx(message, "Failed to update digest context");
- return;
+ if (!sephash) {
+ if (EVP_DigestSignUpdate(message->dctx, tmp,
+ strlen(tmp)) != 1) {
+ dkim_errx(message, "Failed to update signature "
+ "context");
+ return;
+ }
+ } else {
+ if (EVP_DigestUpdate(message->dctx, tmp, strlen(tmp)) != 1) {
+ dkim_errx(message, "Failed to update digest context");
+ return;
+ }
}
free(tmp);
- if (EVP_DigestSignFinal(message->b, NULL, &linelen) <= 0) {
- dkim_errx(message, "Failed to finalize digest");
- return;
+ if (!sephash) {
+ if (EVP_DigestSignFinal(message->dctx, NULL, &linelen) != 1) {
+ dkim_errx(message, "Can't finalize signature context");
+ return;
+ }
+#ifdef HAVE_ED25519
+ } else {
+ if (EVP_DigestFinal_ex(message->dctx, bdigest,
+ &digestsz) != 1) {
+ dkim_errx(message, "Can't finalize hash context");
+ return;
+ }
+ EVP_MD_CTX_reset(message->dctx);
+ if (EVP_DigestSignInit(message->dctx, NULL, NULL, NULL,
+ pkey) != 1) {
+ dkim_errx(message, "Failed to initialize signature "
+ "context");
+ return;
+ }
+ if (EVP_DigestSign(message->dctx, NULL, &linelen, bdigest,
+ digestsz) != 1) {
+ dkim_errx(message, "Failed to finalize signature");
+ return;
+ }
+#endif
}
if ((tmp = malloc(linelen)) == NULL) {
- dkim_err(message, "Can't allocate space for digest");
+ dkim_err(message, "Can't allocate space for signature");
return;
}
- if (EVP_DigestSignFinal(message->b, tmp, &linelen) <= 0) {
- dkim_errx(message, "Failed to finalize digest");
- return;
+ if (!sephash) {
+ if (EVP_DigestSignFinal(message->dctx, tmp, &linelen) != 1) {
+ dkim_errx(message, "Failed to finalize signature");
+ return;
+ }
+#ifdef HAVE_ED25519
+ } else {
+ if (EVP_DigestSign(message->dctx, tmp, &linelen, bdigest,
+ digestsz) != 1) {
+ dkim_errx(message, "Failed to finalize signature");
+ return;
+ }
+#endif
}
if ((b = malloc((((linelen + 2) / 3) * 4) + 1)) == NULL) {
dkim_err(message, "Can't create DKIM signature");