Skip to content

Commit

Permalink
Merge pull request trusteddomainproject#208 from futatuki/issue-183-l…
Browse files Browse the repository at this point in the history
…ibopendkim-dkim_test_key-ed25519-support
  • Loading branch information
futatuki committed Mar 24, 2024
2 parents 23ade73 + 51f2c1c commit 248dbce
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 40 deletions.
6 changes: 6 additions & 0 deletions RELEASE_NOTES
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,14 @@ release, and a summary of the changes in that release.
were not being properly handled.
LIBOPENDKIM: Expose conversion table between internal code already
provided as DKIM_ macros and their literal name in C string.
LIBOPENDKIM: Extend dkim_test_key() to allow testing a ed25519 key,
as dkim_test_key2(). For API compatibility, function interface
of dkim_test_key() is not changed, but it only calls
dkim_test_key2(). Patch from Yasuhito Futatsuki.
TOOLS: Feature requrest #187: Add option to match subdomains when
generating zone files. Patch from Andreas Schulze.
TOOLS: issue #183: On opendkim-testkey, add support for ed25519 keys.
Patch from Yasuhito Futatsuki.

2.10.3 2015/05/12
LIBOPENDKIM: Make strict header checking non-destructive. The last
Expand Down
142 changes: 108 additions & 34 deletions libopendkim/dkim-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ dkim_test_dns_get(DKIM *dkim, u_char *buf, size_t buflen)
}

/*
** DKIM_TEST_KEY -- retrieve a public key and verify it against a provided
** private key
** DKIM_TEST_KEY2 -- retrieve a public key and verify it against a provided
** private key
**
** Parameters:
** lib -- DKIM library handle
Expand All @@ -277,6 +277,7 @@ dkim_test_dns_get(DKIM *dkim, u_char *buf, size_t buflen)
** key -- private key to verify (PEM format)
** keylen -- size of private key
** dnssec -- DNSSEC result (may be NULL)
** alg -- signing algorithm
** err -- error buffer (may be NULL)
** errlen -- size of error buffer
**
Expand All @@ -287,8 +288,9 @@ dkim_test_dns_get(DKIM *dkim, u_char *buf, size_t buflen)
*/

int
dkim_test_key(DKIM_LIB *lib, char *selector, char *domain,
char *key, size_t keylen, int *dnssec, char *err, size_t errlen)
dkim_test_key2(DKIM_LIB *lib, char *selector, char *domain,
char *key, size_t keylen, dkim_alg_t alg,
int *dnssec, char *err, size_t errlen)
{
int status = 0;
DKIM_STAT stat;
Expand All @@ -300,10 +302,12 @@ dkim_test_key(DKIM_LIB *lib, char *selector, char *domain,
#else /* USE_GNUTLS */
BIO *keybuf;
BIO *outkey;
size_t outkey_len;
#endif /* USE_GNUTLS */
void *ptr;
struct dkim_crypto *crypto;
char buf[BUFRSZ];
const char *algstr;

assert(lib != NULL);
assert(selector != NULL);
Expand All @@ -317,8 +321,10 @@ dkim_test_key(DKIM_LIB *lib, char *selector, char *domain,
return -1;
}

snprintf(buf, sizeof buf, "v=1; d=%s; s=%s; h=x; b=x; a=x",
domain, selector);
algstr = dkim_code_to_name(dkim_table_algorithms, alg);

snprintf(buf, sizeof buf, "v=1; d=%s; s=%s; h=x; b=x; a=%s",
domain, selector, algstr);

stat = dkim_process_set(dkim, DKIM_SETTYPE_SIGNATURE, (u_char *) buf,
strlen(buf), NULL, FALSE, NULL);
Expand Down Expand Up @@ -408,7 +414,18 @@ dkim_test_key(DKIM_LIB *lib, char *selector, char *domain,
#endif /* USE_GNUTLS */

sig->sig_signature = (void *) crypto;
sig->sig_keytype = DKIM_KEYTYPE_RSA;
switch(alg)
{
case DKIM_SIGN_RSASHA1:
case DKIM_SIGN_RSASHA256:
sig->sig_keytype = DKIM_KEYTYPE_RSA;
break;
case DKIM_SIGN_ED25519SHA256:
sig->sig_keytype = DKIM_KEYTYPE_ED25519;
break;
default:
return -1;
}

#ifdef USE_GNUTLS
if (err != NULL)
Expand All @@ -432,48 +449,105 @@ dkim_test_key(DKIM_LIB *lib, char *selector, char *domain,
return -1;
}

crypto->crypto_keysize = EVP_PKEY_size(crypto->crypto_pkey);

outkey = BIO_new(BIO_s_mem());
if (outkey == NULL)
{
BIO_free(keybuf);
(void) dkim_free(dkim);
if (err != NULL)
strlcpy(err, "BIO_new() failed", errlen);
return -1;
}

status = i2d_PUBKEY_bio(outkey, crypto->crypto_pkey);
if (status == 0)
if (sig->sig_keytype == DKIM_KEYTYPE_ED25519)
{
BIO_free(keybuf);
BIO_free(outkey);
(void) dkim_free(dkim);
if (err != NULL)
outkey_len = sizeof(buf);
if (! EVP_PKEY_get_raw_public_key(crypto->crypto_pkey,
buf, &outkey_len))
{
strlcpy(err, "i2d_RSA_PUBKEY_bio() failed",
strlcpy(err,
"EVP_PKEY_get_raw_public_key() failed",
errlen);
return -1;
}
return -1;
ptr = buf;
}
else
{
crypto->crypto_keysize = EVP_PKEY_size(crypto->crypto_pkey);

(void) BIO_get_mem_data(outkey, &ptr);
outkey = BIO_new(BIO_s_mem());
if (outkey == NULL)
{
BIO_free(keybuf);
(void) dkim_free(dkim);
if (err != NULL)
strlcpy(err, "BIO_new() failed", errlen);
return -1;
}

if (BIO_number_written(outkey) == sig->sig_keylen)
status = i2d_PUBKEY_bio(outkey, crypto->crypto_pkey);
if (status == 0)
{
BIO_free(keybuf);
BIO_free(outkey);
(void) dkim_free(dkim);
if (err != NULL)
{
strlcpy(err, "i2d_RSA_PUBKEY_bio() failed",
errlen);
}
return -1;
}
(void) BIO_get_mem_data(outkey, &ptr);

outkey_len = BIO_number_written(outkey);

}

if (outkey_len == sig->sig_keylen)
{
status = memcmp(ptr, sig->sig_key, sig->sig_keylen);
if (status != 0)
{
strlcpy(err, "keys do not match", errlen);
}
}
else
{
status = 1;
snprintf(err, errlen,
"key do not match: local = %zd, remote = %zd",
outkey_len, sig->sig_keylen);
}

if (status != 0)
strlcpy(err, "keys do not match", errlen);

BIO_free(keybuf);
BIO_free(outkey);
if (sig->sig_keytype != DKIM_KEYTYPE_ED25519)
{
BIO_free(keybuf);
BIO_free(outkey);
}
#endif /* USE_GNUTLS */
}

(void) dkim_free(dkim);

return (status == 0 ? 0 : 1);
}

/*
** DKIM_TEST_KEY -- retrieve a public key and verify it against a provided
** private key
**
** Parameters:
** lib -- DKIM library handle
** selector -- selector
** domain -- domain name
** key -- private key to verify (PEM format)
** keylen -- size of private key
** dnssec -- DNSSEC result (may be NULL)
** err -- error buffer (may be NULL)
** errlen -- size of error buffer
**
** Return value:
** 1 -- keys don't match
** 0 -- keys match (or no key provided)
** -1 -- error
*/

int
dkim_test_key(DKIM_LIB *lib, char *selector, char *domain,
char *key, size_t keylen, int *dnssec, char *err, size_t errlen)
{
return dkim_test_key2(lib, selector, domain, key, keylen,
DKIM_SIGN_RSASHA256, dnssec, err, errlen);
}
24 changes: 24 additions & 0 deletions libopendkim/dkim.h
Original file line number Diff line number Diff line change
Expand Up @@ -1452,6 +1452,30 @@ extern uint32_t dkim_libversion __P((void));
extern DKIM_STAT dkim_get_sigsubstring __P((DKIM *, DKIM_SIGINFO *,
char *, size_t *));

/*
** DKIM_TEST_KEY2 -- retrieve a public key and verify it against a provided
** private key
**
** Parameters:
** lib -- DKIM library handle
** selector -- selector
** domain -- domain name
** key -- private key to verify (PEM format)
** keylen -- size of private key
** alg -- signing algorithm
** dnssec -- DNSSEC result (may be NULL)
** err -- error buffer (may be NULL)
** errlen -- size of error buffer
**
** Return value:
** 1 -- keys don't match
** 0 -- keys match (or no key provided)
** -1 -- error
*/

extern int dkim_test_key2 __P((DKIM_LIB *, char *, char *, char *, size_t,
dkim_alg_t, int *, char *, size_t));

/*
** DKIM_TEST_KEY -- retrieve a public key and verify it against a provided
** private key
Expand Down
34 changes: 28 additions & 6 deletions opendkim/opendkim-testkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ main(int argc, char **argv)
char selector[BUFRSZ];
char keypath[MAXBUFRSZ];
char signalgstr[BUFRSZ];
dkim_alg_t default_signalg;
dkim_alg_t signalg;

progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1;
Expand Down Expand Up @@ -344,6 +345,26 @@ main(int argc, char **argv)
strlcpy(keypath, p, sizeof keypath);
}

p = NULL;
(void) config_get(cfg, "SignatureAlgorithm", &p, sizeof p);
if (p != NULL)
{
default_signalg = (dkim_alg_t)
dkim_name_to_code(dkim_table_algorithms,
p);
if (default_signalg == -1)
{
fprintf(stderr,
"%s: %s: Unknown SignatureAlgorithm %s\n",
progname, path, p);
return EX_CONFIG;
}
}
else
{
default_signalg = DKIM_SIGN_RSASHA256;
}

#ifdef USE_LDAP
(void) config_get(cfg, "LDAPUseTLS",
&ldap_usetls, sizeof ldap_usetls);
Expand Down Expand Up @@ -550,6 +571,10 @@ main(int argc, char **argv)
progname, keyname, signalgstr);
}
}
else
{
signalg = default_signalg;
}

if (keypath[0] == '/' ||
strncmp(keypath, "./", 2) == 0 ||
Expand Down Expand Up @@ -599,14 +624,11 @@ main(int argc, char **argv)
progname, keyname);
}

/* To do: check consistency of the key and algorithm.
It is needed to extend dkim_test_key() for it */

dnssec = DKIM_DNSSEC_UNKNOWN;

status = dkim_test_key(lib, selector, domain,
keypath, keylen, &dnssec,
err, sizeof err);
status = dkim_test_key2(lib, selector, domain,
keypath, keylen, signalg,
&dnssec, err, sizeof err);

switch (status)
{
Expand Down

0 comments on commit 248dbce

Please sign in to comment.