On Fri, Jun 07, 2019 at 10:40:36AM +0200, Renaud Allard wrote:
> 
> 
> On 6/6/19 10:46 AM, Renaud Allard wrote:
> > 
> > 
> > On 6/6/19 10:10 AM, Florian Obser wrote:
> > 
> > > I currently don't have time to review this. I'm busy switching
> > > acme-client to the rfc 8555 / letsencrypt v2 api. Doesn't look like
> > > this conflicts too badly with my work, but I'd appreciate it if we
> > > could hold this off for a bit and rebase it ontop of the v2 work.
> > 
> > OK, let's wait till your v2 is done. People have the patch already if
> > they want to try out ecdsa in the meantime.
> > 
> 
> Here is the patch after the v2 change.
> I also changed ecdsa to int instead of bool as requested.
> 

you forgot to include ecdsa.h this time around, but I found it in one
of the earlier diffs.

It is a bit silly though, just skip it, rename rsa.h to key.h and add
your ecdsa.h content there.


> 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  7 Jun 2019 08:37:56 -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.13
> diff -u -p -r1.13 acctproc.c
> --- acctproc.c        7 Jun 2019 08:07:52 -0000       1.13
> +++ acctproc.c        7 Jun 2019 08:37:56 -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");

keep the _rsa name, this is the account key, not the domain key.

>  
>       free(exp);
>       free(mod);
> @@ -173,8 +173,8 @@ op_sign_rsa(char **prot, EVP_PKEY *pkey,
>               warnx("bn2string");
>       else if ((exp = bn2string(r->e)) == NULL)
>               warnx("bn2string");
> -     else if ((*prot = json_fmt_protected_rsa(exp, mod, nonce, url)) == NULL)
> -             warnx("json_fmt_protected_rsa");
> +     else if ((*prot = json_fmt_protected_key(exp, mod, nonce, url)) == NULL)
> +             warnx("json_fmt_protected_key");

keep the _rsa name, this is the account key, not the domain key.

>       else
>               rc = 1;
>  
> @@ -349,7 +349,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)

we need a check here that this is an RSA key for now since we don't
support ECDSA account keys yet

>                       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.30
> diff -u -p -r1.30 acme-client.1
> --- acme-client.1     7 Jun 2019 08:07:52 -0000       1.30
> +++ acme-client.1     7 Jun 2019 08:37:56 -0000
> @@ -22,7 +22,7 @@
>  .Nd ACME client
>  .Sh SYNOPSIS
>  .Nm acme-client
> -.Op Fl ADFnrv
> +.Op Fl ADEFnrv
>  .Op Fl f Ar configfile
>  .Ar domain
>  .Sh DESCRIPTION
> @@ -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 domain key if one does not already exist. Defaults to RSA.
> +.It Fl E
> +Switch the new domain key algorithm to ECDSA instead of RSA.

could you try to tackle moving this to the config file instead of a flag?

>  .It Fl F
>  Force certificate renewal, even if it's too soon.
>  .It Fl f Ar configfile
> Index: extern.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/acme-client/extern.h,v
> retrieving revision 1.11
> diff -u -p -r1.11 extern.h
> --- extern.h  7 Jun 2019 08:07:52 -0000       1.11
> +++ extern.h  7 Jun 2019 08:37:57 -0000
> @@ -263,18 +263,23 @@ char            *json_fmt_newcert(const char *);
>  char         *json_fmt_chkacc(void);
>  char         *json_fmt_newacc(void);
>  char         *json_fmt_neworder(const char *const *, size_t);
> -char         *json_fmt_protected_rsa(const char *,
> +char         *json_fmt_protected_key(const char *,

keep the _rsa name, this is the account key, not the domain key.

>                       const char *, const char *, const char *);
>  char         *json_fmt_protected_kid(const char *, const char *,
>                       const char *);
>  char         *json_fmt_revokecert(const char *);
> -char         *json_fmt_thumb_rsa(const char *, const char *);
> +char         *json_fmt_thumb_key(const char *, const char *);

keep the _rsa name, this is the account key, not the domain key.

>  char         *json_fmt_signed(const char *, const char *, const char *);
>  
>  /*
>   * Should we print debugging messages?
>   */
>  int           verbose;
> +
> +/*
> + * Should we switch to ecdsa?
> + */
> +int           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.12
> diff -u -p -r1.12 json.c
> --- json.c    7 Jun 2019 08:07:52 -0000       1.12
> +++ json.c    7 Jun 2019 08:37:57 -0000
> @@ -708,7 +708,7 @@ json_fmt_newcert(const char *cert)
>   * 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,

keep the _rsa name, this is the account key, not the domain key.

>      const char *url)
>  {
>       int      c;
> @@ -781,7 +781,7 @@ json_fmt_signed(const char *protected, c
>   * 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)

keep the _rsa name, this is the account key, not the domain key.

>  {
>       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     7 Jun 2019 08:37:57 -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);

this is unreachable

> +
> +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 7 Jun 2019 08:37:57 -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,13 +115,19 @@ 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);
> +             doddbg("%s: loaded domain key", keyfile);
>       }
>  
>       fclose(f);
> Index: main.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/acme-client/main.c,v
> retrieving revision 1.46
> diff -u -p -r1.46 main.c
> --- main.c    7 Jun 2019 08:07:52 -0000       1.46
> +++ main.c    7 Jun 2019 08:37:57 -0000
> @@ -49,6 +49,7 @@ main(int argc, char *argv[])
>       int               popts = 0;
>       pid_t             pids[COMP__MAX];
>       extern int        verbose;
> +     extern int        ecdsa;
>       extern enum comp  proccomp;
>       size_t            i, altsz, ne;
>  
> @@ -57,13 +58,16 @@ 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;
>                       break;
>               case 'D':
>                       popts |= ACME_OPT_NEWDKEY;
> +                     break;
> +             case 'E':
> +                     ecdsa = 1;

it would be awesome to have this in the config file.
I can help you if you get stuck there.

I would add it to the end for "domain key", with rsa the default.

So this would be rsa:

domain example.com {
        alternative names { secure.example.com }
        domain key "/etc/ssl/private/example.com.key"
        domain full chain certificate "/etc/ssl/example.com.fullchain.pem"
        sign with letsencrypt
}

so would this:

        domain key "/etc/ssl/private/example.com.key" RSA

and ecdsa:

        domain key "/etc/ssl/private/example.com.key" ECDSA

make RSA/ECDSA proper tokens in parse.y, don't try to strcmp it.

>                       break;
>               case 'F':
>                       force = 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   7 Jun 2019 08:37:57 -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     7 Jun 2019 08:37:57 -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 */




-- 
I'm not entirely sure you are real.

Reply via email to