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.


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.
+.It Fl E
+Switch the new domain key algorithm to ECDSA instead of RSA.
 .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 */

Reply via email to