Skip to content

Commit 0778f4d

Browse files
committed
Merge pull request trusteddomainproject#208 from futatuki/issue-183-libopendkim-dkim_test_key-ed25519-support
2 parents daf493a + 51f2c1c commit 0778f4d

File tree

4 files changed

+166
-40
lines changed

4 files changed

+166
-40
lines changed

RELEASE_NOTES

+6
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,14 @@ release, and a summary of the changes in that release.
5353
were not being properly handled.
5454
LIBOPENDKIM: Expose conversion table between internal code already
5555
provided as DKIM_ macros and their literal name in C string.
56+
LIBOPENDKIM: Extend dkim_test_key() to allow testing a ed25519 key,
57+
as dkim_test_key2(). For API compatibility, function interface
58+
of dkim_test_key() is not changed, but it only calls
59+
dkim_test_key2(). Patch from Yasuhito Futatsuki.
5660
TOOLS: Feature requrest #187: Add option to match subdomains when
5761
generating zone files. Patch from Andreas Schulze.
62+
TOOLS: issue #183: On opendkim-testkey, add support for ed25519 keys.
63+
Patch from Yasuhito Futatsuki.
5864

5965
2.10.3 2015/05/12
6066
LIBOPENDKIM: Make strict header checking non-destructive. The last

libopendkim/dkim-test.c

+108-34
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,8 @@ dkim_test_dns_get(DKIM *dkim, u_char *buf, size_t buflen)
267267
}
268268

269269
/*
270-
** DKIM_TEST_KEY -- retrieve a public key and verify it against a provided
271-
** private key
270+
** DKIM_TEST_KEY2 -- retrieve a public key and verify it against a provided
271+
** private key
272272
**
273273
** Parameters:
274274
** lib -- DKIM library handle
@@ -277,6 +277,7 @@ dkim_test_dns_get(DKIM *dkim, u_char *buf, size_t buflen)
277277
** key -- private key to verify (PEM format)
278278
** keylen -- size of private key
279279
** dnssec -- DNSSEC result (may be NULL)
280+
** alg -- signing algorithm
280281
** err -- error buffer (may be NULL)
281282
** errlen -- size of error buffer
282283
**
@@ -287,8 +288,9 @@ dkim_test_dns_get(DKIM *dkim, u_char *buf, size_t buflen)
287288
*/
288289

289290
int
290-
dkim_test_key(DKIM_LIB *lib, char *selector, char *domain,
291-
char *key, size_t keylen, int *dnssec, char *err, size_t errlen)
291+
dkim_test_key2(DKIM_LIB *lib, char *selector, char *domain,
292+
char *key, size_t keylen, dkim_alg_t alg,
293+
int *dnssec, char *err, size_t errlen)
292294
{
293295
int status = 0;
294296
DKIM_STAT stat;
@@ -300,10 +302,12 @@ dkim_test_key(DKIM_LIB *lib, char *selector, char *domain,
300302
#else /* USE_GNUTLS */
301303
BIO *keybuf;
302304
BIO *outkey;
305+
size_t outkey_len;
303306
#endif /* USE_GNUTLS */
304307
void *ptr;
305308
struct dkim_crypto *crypto;
306309
char buf[BUFRSZ];
310+
const char *algstr;
307311

308312
assert(lib != NULL);
309313
assert(selector != NULL);
@@ -317,8 +321,10 @@ dkim_test_key(DKIM_LIB *lib, char *selector, char *domain,
317321
return -1;
318322
}
319323

320-
snprintf(buf, sizeof buf, "v=1; d=%s; s=%s; h=x; b=x; a=x",
321-
domain, selector);
324+
algstr = dkim_code_to_name(dkim_table_algorithms, alg);
325+
326+
snprintf(buf, sizeof buf, "v=1; d=%s; s=%s; h=x; b=x; a=%s",
327+
domain, selector, algstr);
322328

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

410416
sig->sig_signature = (void *) crypto;
411-
sig->sig_keytype = DKIM_KEYTYPE_RSA;
417+
switch(alg)
418+
{
419+
case DKIM_SIGN_RSASHA1:
420+
case DKIM_SIGN_RSASHA256:
421+
sig->sig_keytype = DKIM_KEYTYPE_RSA;
422+
break;
423+
case DKIM_SIGN_ED25519SHA256:
424+
sig->sig_keytype = DKIM_KEYTYPE_ED25519;
425+
break;
426+
default:
427+
return -1;
428+
}
412429

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

435-
crypto->crypto_keysize = EVP_PKEY_size(crypto->crypto_pkey);
436-
437-
outkey = BIO_new(BIO_s_mem());
438-
if (outkey == NULL)
439-
{
440-
BIO_free(keybuf);
441-
(void) dkim_free(dkim);
442-
if (err != NULL)
443-
strlcpy(err, "BIO_new() failed", errlen);
444-
return -1;
445-
}
446-
447-
status = i2d_PUBKEY_bio(outkey, crypto->crypto_pkey);
448-
if (status == 0)
452+
if (sig->sig_keytype == DKIM_KEYTYPE_ED25519)
449453
{
450-
BIO_free(keybuf);
451-
BIO_free(outkey);
452-
(void) dkim_free(dkim);
453-
if (err != NULL)
454+
outkey_len = sizeof(buf);
455+
if (! EVP_PKEY_get_raw_public_key(crypto->crypto_pkey,
456+
buf, &outkey_len))
454457
{
455-
strlcpy(err, "i2d_RSA_PUBKEY_bio() failed",
458+
strlcpy(err,
459+
"EVP_PKEY_get_raw_public_key() failed",
456460
errlen);
461+
return -1;
457462
}
458-
return -1;
463+
ptr = buf;
459464
}
465+
else
466+
{
467+
crypto->crypto_keysize = EVP_PKEY_size(crypto->crypto_pkey);
460468

461-
(void) BIO_get_mem_data(outkey, &ptr);
469+
outkey = BIO_new(BIO_s_mem());
470+
if (outkey == NULL)
471+
{
472+
BIO_free(keybuf);
473+
(void) dkim_free(dkim);
474+
if (err != NULL)
475+
strlcpy(err, "BIO_new() failed", errlen);
476+
return -1;
477+
}
462478

463-
if (BIO_number_written(outkey) == sig->sig_keylen)
479+
status = i2d_PUBKEY_bio(outkey, crypto->crypto_pkey);
480+
if (status == 0)
481+
{
482+
BIO_free(keybuf);
483+
BIO_free(outkey);
484+
(void) dkim_free(dkim);
485+
if (err != NULL)
486+
{
487+
strlcpy(err, "i2d_RSA_PUBKEY_bio() failed",
488+
errlen);
489+
}
490+
return -1;
491+
}
492+
(void) BIO_get_mem_data(outkey, &ptr);
493+
494+
outkey_len = BIO_number_written(outkey);
495+
496+
}
497+
498+
if (outkey_len == sig->sig_keylen)
499+
{
464500
status = memcmp(ptr, sig->sig_key, sig->sig_keylen);
501+
if (status != 0)
502+
{
503+
strlcpy(err, "keys do not match", errlen);
504+
}
505+
}
465506
else
507+
{
466508
status = 1;
509+
snprintf(err, errlen,
510+
"key do not match: local = %zd, remote = %zd",
511+
outkey_len, sig->sig_keylen);
512+
}
467513

468-
if (status != 0)
469-
strlcpy(err, "keys do not match", errlen);
470-
471-
BIO_free(keybuf);
472-
BIO_free(outkey);
514+
if (sig->sig_keytype != DKIM_KEYTYPE_ED25519)
515+
{
516+
BIO_free(keybuf);
517+
BIO_free(outkey);
518+
}
473519
#endif /* USE_GNUTLS */
474520
}
475521

476522
(void) dkim_free(dkim);
477523

478524
return (status == 0 ? 0 : 1);
479525
}
526+
527+
/*
528+
** DKIM_TEST_KEY -- retrieve a public key and verify it against a provided
529+
** private key
530+
**
531+
** Parameters:
532+
** lib -- DKIM library handle
533+
** selector -- selector
534+
** domain -- domain name
535+
** key -- private key to verify (PEM format)
536+
** keylen -- size of private key
537+
** dnssec -- DNSSEC result (may be NULL)
538+
** err -- error buffer (may be NULL)
539+
** errlen -- size of error buffer
540+
**
541+
** Return value:
542+
** 1 -- keys don't match
543+
** 0 -- keys match (or no key provided)
544+
** -1 -- error
545+
*/
546+
547+
int
548+
dkim_test_key(DKIM_LIB *lib, char *selector, char *domain,
549+
char *key, size_t keylen, int *dnssec, char *err, size_t errlen)
550+
{
551+
return dkim_test_key2(lib, selector, domain, key, keylen,
552+
DKIM_SIGN_RSASHA256, dnssec, err, errlen);
553+
}

libopendkim/dkim.h

+24
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,30 @@ extern uint32_t dkim_libversion __P((void));
14521452
extern DKIM_STAT dkim_get_sigsubstring __P((DKIM *, DKIM_SIGINFO *,
14531453
char *, size_t *));
14541454

1455+
/*
1456+
** DKIM_TEST_KEY2 -- retrieve a public key and verify it against a provided
1457+
** private key
1458+
**
1459+
** Parameters:
1460+
** lib -- DKIM library handle
1461+
** selector -- selector
1462+
** domain -- domain name
1463+
** key -- private key to verify (PEM format)
1464+
** keylen -- size of private key
1465+
** alg -- signing algorithm
1466+
** dnssec -- DNSSEC result (may be NULL)
1467+
** err -- error buffer (may be NULL)
1468+
** errlen -- size of error buffer
1469+
**
1470+
** Return value:
1471+
** 1 -- keys don't match
1472+
** 0 -- keys match (or no key provided)
1473+
** -1 -- error
1474+
*/
1475+
1476+
extern int dkim_test_key2 __P((DKIM_LIB *, char *, char *, char *, size_t,
1477+
dkim_alg_t, int *, char *, size_t));
1478+
14551479
/*
14561480
** DKIM_TEST_KEY -- retrieve a public key and verify it against a provided
14571481
** private key

opendkim/opendkim-testkey.c

+28-6
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ main(int argc, char **argv)
237237
char selector[BUFRSZ];
238238
char keypath[MAXBUFRSZ];
239239
char signalgstr[BUFRSZ];
240+
dkim_alg_t default_signalg;
240241
dkim_alg_t signalg;
241242

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

348+
p = NULL;
349+
(void) config_get(cfg, "SignatureAlgorithm", &p, sizeof p);
350+
if (p != NULL)
351+
{
352+
default_signalg = (dkim_alg_t)
353+
dkim_name_to_code(dkim_table_algorithms,
354+
p);
355+
if (default_signalg == -1)
356+
{
357+
fprintf(stderr,
358+
"%s: %s: Unknown SignatureAlgorithm %s\n",
359+
progname, path, p);
360+
return EX_CONFIG;
361+
}
362+
}
363+
else
364+
{
365+
default_signalg = DKIM_SIGN_RSASHA256;
366+
}
367+
347368
#ifdef USE_LDAP
348369
(void) config_get(cfg, "LDAPUseTLS",
349370
&ldap_usetls, sizeof ldap_usetls);
@@ -550,6 +571,10 @@ main(int argc, char **argv)
550571
progname, keyname, signalgstr);
551572
}
552573
}
574+
else
575+
{
576+
signalg = default_signalg;
577+
}
553578

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

602-
/* To do: check consistency of the key and algorithm.
603-
It is needed to extend dkim_test_key() for it */
604-
605627
dnssec = DKIM_DNSSEC_UNKNOWN;
606628

607-
status = dkim_test_key(lib, selector, domain,
608-
keypath, keylen, &dnssec,
609-
err, sizeof err);
629+
status = dkim_test_key2(lib, selector, domain,
630+
keypath, keylen, signalg,
631+
&dnssec, err, sizeof err);
610632

611633
switch (status)
612634
{

0 commit comments

Comments
 (0)