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.

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");
 
 	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");
 	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)
 			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.
 .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 *,
 			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 *);
 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,
     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)
 {
 	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);
+
+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;
 			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 */

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to