On Tue, Jun 04, 2019 at 03:54:11PM +0200, Renaud Allard wrote: > > > On 6/3/19 11:53 AM, Renaud Allard wrote: > > > > > > > > On 5/29/19 9:58 AM, Florian Obser wrote: > > > > > On Wed, May 22, 2019 at 01:33:11PM +0200, Renaud Allard wrote: > > > > > > The key needs to be generated manually > > > > > > i.e.: openssl ecparam -genkey -name secp384r1 -out privkey.pem > > > > > > > > > > why not let acme-client generate the key? > > > > > > > > > > Here is a more complete diff where you can use the -E switch to > > > generate a ECDSA key instead of the RSA one. > > I refined a little bit the patch to not put ecdsa functions into rsa.c. So I > renamed rsa.c to key.c and removed the rsa references to functions which > apply to both rsa and ecdsa. >
reads, builds and works fine for me a couple comments inlined > Index: Makefile > =================================================================== > RCS file: /cvs/src/usr.sbin/acme-client/Makefile,v > retrieving revision 1.8 > diff -u -p -r1.8 Makefile > --- Makefile 3 Jul 2017 22:21:47 -0000 1.8 > +++ Makefile 4 Jun 2019 13:50:28 -0000 > @@ -2,7 +2,7 @@ > PROG= acme-client > SRCS= acctproc.c base64.c certproc.c chngproc.c dbg.c > dnsproc.c > SRCS+= fileproc.c http.c jsmn.c json.c keyproc.c main.c > netproc.c > -SRCS+= parse.y revokeproc.c rsa.c util.c > +SRCS+= parse.y revokeproc.c key.c util.c > > MAN= acme-client.1 acme-client.conf.5 > > Index: acctproc.c > =================================================================== > RCS file: /cvs/src/usr.sbin/acme-client/acctproc.c,v > retrieving revision 1.12 > diff -u -p -r1.12 acctproc.c > --- acctproc.c 28 Jul 2018 15:25:23 -0000 1.12 > +++ acctproc.c 4 Jun 2019 13:50:28 -0000 > @@ -82,8 +82,8 @@ op_thumb_rsa(EVP_PKEY *pkey) > warnx("bn2string"); > else if ((exp = bn2string(r->e)) == NULL) > warnx("bn2string"); > - else if ((json = json_fmt_thumb_rsa(exp, mod)) == NULL) > - warnx("json_fmt_thumb_rsa"); > + else if ((json = json_fmt_thumb_key(exp, mod)) == NULL) > + warnx("json_fmt_thumb_key"); > > free(exp); > free(mod); > @@ -175,10 +175,10 @@ op_sign_rsa(char **head, char **prot, EV > warnx("bn2string"); > else if ((exp = bn2string(r->e)) == NULL) > warnx("bn2string"); > - else if ((*head = json_fmt_header_rsa(exp, mod)) == NULL) > - warnx("json_fmt_header_rsa"); > - else if ((*prot = json_fmt_protected_rsa(exp, mod, nonce)) == NULL) > - warnx("json_fmt_protected_rsa"); > + else if ((*head = json_fmt_header_key(exp, mod)) == NULL) > + warnx("json_fmt_header_key"); > + else if ((*prot = json_fmt_protected_key(exp, mod, nonce)) == NULL) > + warnx("json_fmt_protected_key"); > else > rc = 1; > > @@ -338,7 +338,7 @@ acctproc(int netsock, const char *acctke > goto out; > dodbg("%s: generated RSA account key", acctkey); > } else { > - if ((pkey = rsa_key_load(f, acctkey)) == NULL) > + if ((pkey = key_load(f, acctkey)) == NULL) > goto out; > doddbg("%s: loaded RSA account key", acctkey); > } > Index: acme-client.1 > =================================================================== > RCS file: /cvs/src/usr.sbin/acme-client/acme-client.1,v > retrieving revision 1.29 > diff -u -p -r1.29 acme-client.1 > --- acme-client.1 3 Feb 2019 20:39:35 -0000 1.29 > +++ acme-client.1 4 Jun 2019 13:50:28 -0000 > @@ -79,7 +79,9 @@ The options are as follows: > .It Fl A > Create a new RSA account key if one does not already exist. > .It Fl D > -Create a new RSA domain key if one does not already exist. > +Create a new (RSA) domain key if one does not already exist. why is RSA in parenthesis here ? > +.It Fl E > +Switch the new domain key algorithm to ECDSA instead of RSA. the E option should be added to the SYNOPSIS too > .It Fl F > Force certificate renewal, even if it's too soon. > .It Fl f Ar configfile > Index: ecdsa.h > =================================================================== > RCS file: ecdsa.h > diff -N ecdsa.h > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ ecdsa.h 4 Jun 2019 13:50:28 -0000 > @@ -0,0 +1,22 @@ > +/* $Id: rsa.h,v 1.1 2016/08/31 22:01:42 florian Exp $ */ > +/* > + * Copyright (c) 2019 Renaud Allard <ren...@allard.it> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > +#ifndef ECDSA_H > +#define ECDSA_H > + > +EVP_PKEY *ec_key_create(FILE *, const char *); > + > +#endif /* ! ECDSA_H */ > Index: extern.h > =================================================================== > RCS file: /cvs/src/usr.sbin/acme-client/extern.h,v > retrieving revision 1.10 > diff -u -p -r1.10 extern.h > --- extern.h 31 Jan 2019 15:55:48 -0000 1.10 > +++ extern.h 4 Jun 2019 13:50:28 -0000 > @@ -18,6 +18,7 @@ > #define EXTERN_H > > #include "parse.h" > +#include "stdbool.h" > > #define MAX_SERVERS_DNS 8 > > @@ -240,11 +241,11 @@ char *json_fmt_challenge(const char *, > char *json_fmt_newauthz(const char *); > char *json_fmt_newcert(const char *); > char *json_fmt_newreg(const char *); > -char *json_fmt_protected_rsa(const char *, > +char *json_fmt_protected_key(const char *, > const char *, const char *); > char *json_fmt_revokecert(const char *); > -char *json_fmt_header_rsa(const char *, const char *); > -char *json_fmt_thumb_rsa(const char *, const char *); > +char *json_fmt_header_key(const char *, const char *); > +char *json_fmt_thumb_key(const char *, const char *); > char *json_fmt_signed(const char *, > const char *, const char *, const char *); > > @@ -252,6 +253,11 @@ char *json_fmt_signed(const char *, > * Should we print debugging messages? > */ > int verbose; > + > +/* > + * Should we switch to ecdsa? > + */ > +bool ecdsa; > > /* > * What component is the process within (COMP__MAX for none)? > Index: json.c > =================================================================== > RCS file: /cvs/src/usr.sbin/acme-client/json.c,v > retrieving revision 1.11 > diff -u -p -r1.11 json.c > --- json.c 31 Jan 2019 15:55:48 -0000 1.11 > +++ json.c 4 Jun 2019 13:50:28 -0000 > @@ -589,7 +589,7 @@ json_fmt_newcert(const char *cert) > * Header component of json_fmt_signed(). > */ > char * > -json_fmt_header_rsa(const char *exp, const char *mod) > +json_fmt_header_key(const char *exp, const char *mod) > { > int c; > char *p; > @@ -611,7 +611,7 @@ json_fmt_header_rsa(const char *exp, con > * Protected component of json_fmt_signed(). > */ > char * > -json_fmt_protected_rsa(const char *exp, const char *mod, const char *nce) > +json_fmt_protected_key(const char *exp, const char *mod, const char *nce) > { > int c; > char *p; > @@ -661,7 +661,7 @@ json_fmt_signed(const char *header, cons > * However, it's in the form of a JSON string, so do it here. > */ > char * > -json_fmt_thumb_rsa(const char *exp, const char *mod) > +json_fmt_thumb_key(const char *exp, const char *mod) > { > int c; > char *p; > Index: key.c > =================================================================== > RCS file: key.c > diff -N key.c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ key.c 4 Jun 2019 13:50:28 -0000 > @@ -0,0 +1,150 @@ > +/* $Id: rsa.c,v 1.7 2018/07/28 15:25:23 tb Exp $ */ > +/* > + * Copyright (c) 2019 Renaud Allard <ren...@allard.it> > + * Copyright (c) 2016 Kristaps Dzonsons <krist...@bsd.lv> > + * > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > + * > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#include <err.h> > +#include <stdlib.h> > +#include <unistd.h> > + > +#include <openssl/evp.h> > +#include <openssl/pem.h> > +#include <openssl/rsa.h> > +#include <openssl/ecdsa.h> > +#include <openssl/ec.h> > +#include <openssl/obj_mac.h> > + > +#include "rsa.h" > +#include "ecdsa.h" > + > +/* > + * Default number of bits when creating a new RSA key. > + */ > +#define KBITS 4096 > +#define ECCTYPE NID_secp384r1 > + > +/* > + * Create an RSA key with the default KBITS number of bits. > + */ > +EVP_PKEY * > +rsa_key_create(FILE *f, const char *fname) > +{ > + EVP_PKEY_CTX *ctx = NULL; > + EVP_PKEY *pkey = NULL; > + > + /* First, create the context and the key. */ > + > + if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) { > + warnx("EVP_PKEY_CTX_new_id"); > + goto err; > + } else if (EVP_PKEY_keygen_init(ctx) <= 0) { > + warnx("EVP_PKEY_keygen_init"); > + goto err; > + } else if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KBITS) <= 0) { > + warnx("EVP_PKEY_set_rsa_keygen_bits"); > + goto err; > + } else if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { > + warnx("EVP_PKEY_keygen"); > + goto err; > + } > + > + /* Serialise the key to the disc. */ > + > + if (PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) > + goto out; > + > + warnx("%s: PEM_write_PrivateKey", fname); > + > +err: > + EVP_PKEY_free(pkey); > + pkey = NULL; > +out: > + EVP_PKEY_CTX_free(ctx); > + return pkey; > +} > + > +EVP_PKEY * > +ec_key_create(FILE *f, const char *fname) > +{ > + EC_KEY *eckey = NULL; > + EVP_PKEY *pkey = NULL; > + > + if ((eckey = EC_KEY_new()) == NULL ) { > + warnx("EC_KEY_new"); > + goto err; > + } else if ((eckey = EC_KEY_new_by_curve_name(ECCTYPE)) == NULL ) { > + warnx("EC_GROUP_new_by_curve_name"); > + goto err; > + } > + > + if (!EC_KEY_generate_key(eckey)) { > + warnx("EC_KEY_generate_key"); > + goto err; > + } > + > + /* set OPENSSL_EC_NAMED_CURVE to be able to load the key */ > + > + EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); > + > + /* Serialise the key to the disc in EC format */ > + > + if (!PEM_write_ECPrivateKey(f, eckey, NULL, NULL, 0, NULL, NULL)) { > + warnx("PEM_write_ECPrivateKey"); > + goto err; > + } > + > + /* Convert the EC key into a PKEY structure */ > + > + if ((pkey=EVP_PKEY_new()) == NULL) { > + warnx("EVP_PKEY_new"); > + goto err; > + } > + if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { > + warnx("EVP_PKEY_assign_EC_KEY"); > + goto err; > + } > + > + goto out; > + > + warnx("%s: PEM_write_ECPrivateKey", fname); > + > +err: > + EC_KEY_free(eckey); > + EVP_PKEY_free(pkey); > + pkey = NULL; > +out: > + return pkey; > +} > + > + > + > +EVP_PKEY * > +key_load(FILE *f, const char *fname) > +{ > + EVP_PKEY *pkey; > + > + pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL); > + if (pkey == NULL) { > + warnx("%s: PEM_read_PrivateKey", fname); > + return NULL; > + } else if (EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA || > + EVP_PKEY_type(pkey->type) == EVP_PKEY_EC ) > + return pkey; > + > + warnx("%s: unsupported key type", fname); > + EVP_PKEY_free(pkey); > + return NULL; > +} > Index: keyproc.c > =================================================================== > RCS file: /cvs/src/usr.sbin/acme-client/keyproc.c,v > retrieving revision 1.11 > diff -u -p -r1.11 keyproc.c > --- keyproc.c 29 Jul 2018 20:22:02 -0000 1.11 > +++ keyproc.c 4 Jun 2019 13:50:28 -0000 > @@ -31,6 +31,7 @@ > > #include "extern.h" > #include "rsa.h" > +#include "ecdsa.h" > > /* > * This was lifted more or less directly from demos/x509/mkreq.c of the > @@ -114,11 +115,17 @@ keyproc(int netsock, const char *keyfile > } > > if (newkey) { > - if ((pkey = rsa_key_create(f, keyfile)) == NULL) > - goto out; > - dodbg("%s: generated RSA domain key", keyfile); > + if (ecdsa) { > + if ((pkey = ec_key_create(f, keyfile)) == NULL) > + goto out; > + dodbg("%s: generated ECDSA domain key", keyfile); > + } else { > + if ((pkey = rsa_key_create(f, keyfile)) == NULL) > + goto out; > + dodbg("%s: generated RSA domain key", keyfile); > + } > } else { > - if ((pkey = rsa_key_load(f, keyfile)) == NULL) > + if ((pkey = key_load(f, keyfile)) == NULL) > goto out; > doddbg("%s: loaded RSA domain key", keyfile); > } > Index: main.c > =================================================================== > RCS file: /cvs/src/usr.sbin/acme-client/main.c,v > retrieving revision 1.45 > diff -u -p -r1.45 main.c > --- main.c 9 Mar 2019 18:07:40 -0000 1.45 > +++ main.c 4 Jun 2019 13:50:28 -0000 > @@ -49,6 +49,7 @@ main(int argc, char *argv[]) > int popts = 0; > pid_t pids[COMP__MAX]; > extern int verbose; > + extern bool ecdsa; > extern enum comp proccomp; > size_t i, altsz, ne; > > @@ -57,7 +58,7 @@ main(int argc, char *argv[]) > struct domain_c *domain = NULL; > struct altname_c *ac; > > - while ((c = getopt(argc, argv, "ADFnrvf:")) != -1) > + while ((c = getopt(argc, argv, "ADEFnrvf:")) != -1) > switch (c) { > case 'A': > popts |= ACME_OPT_NEWACCT; > @@ -65,6 +66,10 @@ main(int argc, char *argv[]) > case 'D': > popts |= ACME_OPT_NEWDKEY; > break; > + case 'E': > + ecdsa = true; > + popts |= ACME_OPT_DKEYEC; > + break; > case 'F': > force = 1; > break; > @@ -180,6 +185,10 @@ main(int argc, char *argv[]) > != -1) { > dodbg("%s: domain key exists (not creating)", domain->key); > popts &= ~ACME_OPT_NEWDKEY; > + } > + > + if (popts & ACME_OPT_DKEYEC) { > + ecdsa = true; > } > > if (access(chngdir, R_OK) == -1) { > Index: parse.h > =================================================================== > RCS file: /cvs/src/usr.sbin/acme-client/parse.h,v > retrieving revision 1.9 > diff -u -p -r1.9 parse.h > --- parse.h 27 Nov 2017 16:53:04 -0000 1.9 > +++ parse.h 4 Jun 2019 13:50:28 -0000 > @@ -61,6 +61,7 @@ struct keyfile { > #define ACME_OPT_NEWACCT 0x00000002 > #define ACME_OPT_NEWDKEY 0x00000004 > #define ACME_OPT_CHECK 0x00000008 > +#define ACME_OPT_DKEYEC 0x00000016 > > struct acme_conf { > int opts; > Index: rsa.c > =================================================================== > RCS file: rsa.c > diff -N rsa.c > --- rsa.c 28 Jul 2018 15:25:23 -0000 1.7 > +++ /dev/null 1 Jan 1970 00:00:00 -0000 > @@ -1,88 +0,0 @@ > -/* $Id: rsa.c,v 1.7 2018/07/28 15:25:23 tb Exp $ */ > -/* > - * Copyright (c) 2016 Kristaps Dzonsons <krist...@bsd.lv> > - * > - * Permission to use, copy, modify, and distribute this software for any > - * purpose with or without fee is hereby granted, provided that the above > - * copyright notice and this permission notice appear in all copies. > - * > - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES > - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR > - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > - */ > - > -#include <err.h> > -#include <stdlib.h> > -#include <unistd.h> > - > -#include <openssl/evp.h> > -#include <openssl/pem.h> > -#include <openssl/rsa.h> > - > -#include "rsa.h" > - > -/* > - * Default number of bits when creating a new key. > - */ > -#define KBITS 4096 > - > -/* > - * Create an RSA key with the default KBITS number of bits. > - */ > -EVP_PKEY * > -rsa_key_create(FILE *f, const char *fname) > -{ > - EVP_PKEY_CTX *ctx = NULL; > - EVP_PKEY *pkey = NULL; > - > - /* First, create the context and the key. */ > - > - if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) { > - warnx("EVP_PKEY_CTX_new_id"); > - goto err; > - } else if (EVP_PKEY_keygen_init(ctx) <= 0) { > - warnx("EVP_PKEY_keygen_init"); > - goto err; > - } else if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KBITS) <= 0) { > - warnx("EVP_PKEY_set_rsa_keygen_bits"); > - goto err; > - } else if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { > - warnx("EVP_PKEY_keygen"); > - goto err; > - } > - > - /* Serialise the key to the disc. */ > - > - if (PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) > - goto out; > - > - warnx("%s: PEM_write_PrivateKey", fname); > -err: > - EVP_PKEY_free(pkey); > - pkey = NULL; > -out: > - EVP_PKEY_CTX_free(ctx); > - return pkey; > -} > - > - > -EVP_PKEY * > -rsa_key_load(FILE *f, const char *fname) > -{ > - EVP_PKEY *pkey; > - > - pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL); > - if (pkey == NULL) { > - warnx("%s: PEM_read_PrivateKey", fname); > - return NULL; > - } else if (EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA) > - return pkey; > - > - warnx("%s: unsupported key type", fname); > - EVP_PKEY_free(pkey); > - return NULL; > -} > Index: rsa.h > =================================================================== > RCS file: /cvs/src/usr.sbin/acme-client/rsa.h,v > retrieving revision 1.1 > diff -u -p -r1.1 rsa.h > --- rsa.h 31 Aug 2016 22:01:42 -0000 1.1 > +++ rsa.h 4 Jun 2019 13:50:28 -0000 > @@ -18,6 +18,6 @@ > #define RSA_H > > EVP_PKEY *rsa_key_create(FILE *, const char *); > -EVP_PKEY *rsa_key_load(FILE *, const char *); > +EVP_PKEY *key_load(FILE *, const char *); > > #endif /* ! RSA_H */ -- Gilles Chehade @poolpOrg https://www.poolp.org tip me: https://paypal.me/poolpOrg