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

Reply via email to