On 6/7/19 2:38 PM, Renaud Allard wrote:


On 6/7/19 2:28 PM, Florian Obser wrote:
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.



Hello,

Here is a patch with ecdsa and rsa in %token after the domain key name

OK? comments?
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	11 Jun 2019 08:15:13 -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.14
diff -u -p -r1.14 acctproc.c
--- acctproc.c	8 Jun 2019 07:52:55 -0000	1.14
+++ acctproc.c	11 Jun 2019 08:15:13 -0000
@@ -29,7 +29,7 @@
 #include <openssl/err.h>
 
 #include "extern.h"
-#include "rsa.h"
+#include "key.h"
 
 /*
  * Converts a BIGNUM to the form used in JWK.
@@ -352,7 +352,9 @@ 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;
+		if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) 
 			goto out;
 		doddbg("%s: loaded RSA account key", acctkey);
 	}
Index: acme-client.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/acme-client/acme-client.conf.5,v
retrieving revision 1.17
diff -u -p -r1.17 acme-client.conf.5
--- acme-client.conf.5	8 Jan 2019 06:46:29 -0000	1.17
+++ acme-client.conf.5	11 Jun 2019 08:15:13 -0000
@@ -109,8 +109,9 @@ Specify a list of alternative names for 
 The common name is included automatically if this option is present,
 but there is no automatic conversion/inclusion between "www." and
 plain domain name forms.
-.It Ic domain key Ar file
+.It Ic domain key Ar file Op Ar keytype
 The private key file for which the certificate will be obtained.
+keytype can be rsa or ecdsa. Defaults to rsa.
 .It Ic domain certificate Ar file
 The filename of the certificate that will be issued.
 This is optional if
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/acme-client/extern.h,v
retrieving revision 1.12
diff -u -p -r1.12 extern.h
--- extern.h	8 Jun 2019 07:52:55 -0000	1.12
+++ extern.h	11 Jun 2019 08:15:13 -0000
@@ -276,6 +276,11 @@ char		*json_fmt_signed(const char *, con
 int		 verbose;
 
 /*
+ * Should we switch to ecdsa?
+ */
+int		ecdsa;
+
+/*
  * What component is the process within (COMP__MAX for none)?
  */
 enum comp	 proccomp;
Index: key.c
===================================================================
RCS file: key.c
diff -N key.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ key.c	11 Jun 2019 08:15:14 -0000
@@ -0,0 +1,149 @@
+/*	$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 "key.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;
+	}
+
+	warnx("%s: PEM_write_ECPrivateKey", fname);
+
+	goto out;
+
+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: key.h
===================================================================
RCS file: key.h
diff -N key.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ key.h	11 Jun 2019 08:15:14 -0000
@@ -0,0 +1,31 @@
+/*	$Id: rsa.h,v 1.1 2016/08/31 22:01:42 florian 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.
+ */
+#ifndef RSA_H
+#define RSA_H
+
+EVP_PKEY	*rsa_key_create(FILE *, const char *);
+EVP_PKEY	*key_load(FILE *, const char *);
+
+#endif /* ! RSA_H */
+
+#ifndef ECDSA_H
+#define ECDSA_H
+
+EVP_PKEY	*ec_key_create(FILE *, const char *);
+
+#endif /* ! ECDSA_H */
Index: keyproc.c
===================================================================
RCS file: /cvs/src/usr.sbin/acme-client/keyproc.c,v
retrieving revision 1.12
diff -u -p -r1.12 keyproc.c
--- keyproc.c	8 Jun 2019 07:52:55 -0000	1.12
+++ keyproc.c	11 Jun 2019 08:15:14 -0000
@@ -30,7 +30,7 @@
 #include <openssl/x509v3.h>
 
 #include "extern.h"
-#include "rsa.h"
+#include "key.h"
 
 /*
  * This was lifted more or less directly from demos/x509/mkreq.c of the
@@ -117,13 +117,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.47
diff -u -p -r1.47 main.c
--- main.c	8 Jun 2019 07:52:55 -0000	1.47
+++ main.c	11 Jun 2019 08:15:14 -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;
 
@@ -145,6 +146,10 @@ main(int argc, char *argv[])
 		authority = authority_find(conf, auth);
 		if (authority == NULL)
 			errx(EXIT_FAILURE, "authority %s not found", auth);
+	}
+
+	if (domain->keytype == 1) {
+		ecdsa = 1;
 	}
 
 	acctkey = authority->account;
Index: parse.h
===================================================================
RCS file: /cvs/src/usr.sbin/acme-client/parse.h,v
retrieving revision 1.10
diff -u -p -r1.10 parse.h
--- parse.h	8 Jun 2019 07:52:55 -0000	1.10
+++ parse.h	11 Jun 2019 08:15:14 -0000
@@ -38,6 +38,7 @@ struct domain_c {
 	TAILQ_ENTRY(domain_c)	 entry;
 	TAILQ_HEAD(, altname_c)	altname_list;
 	int			altname_count;
+	int		       	keytype;
 	char		       	*domain;
 	char		       	*key;
 	char		       	*cert;
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/acme-client/parse.y,v
retrieving revision 1.34
diff -u -p -r1.34 parse.y
--- parse.y	8 Jun 2019 07:52:55 -0000	1.34
+++ parse.y	11 Jun 2019 08:15:14 -0000
@@ -38,6 +38,7 @@
 #include <unistd.h>
 
 #include "parse.h"
+#include "extern.h"
 
 TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
 static struct file {
@@ -99,10 +100,11 @@ typedef struct {
 %}
 
 %token	AUTHORITY URL API ACCOUNT
-%token	DOMAIN ALTERNATIVE NAMES CERT FULL CHAIN KEY SIGN WITH CHALLENGEDIR
+%token	DOMAIN ALTERNATIVE NAMES CERT FULL CHAIN KEY SIGN WITH CHALLENGEDIR KEYTYPE
 %token	YES NO
 %token	INCLUDE
 %token	ERROR
+%token	RSA ECDSA
 %token	<v.string>	STRING
 %token	<v.number>	NUMBER
 %type	<v.string>	string
@@ -258,12 +260,21 @@ domain		: DOMAIN STRING {
 		}
 		;
 
+keytype		: RSA { 
+			domain->keytype = 0;
+		}
+		| ECDSA {
+			domain->keytype = 1;
+		}
+		| /* nothing */
+		;
+
 domainopts_l	: domainopts_l domainoptsl nl
 		| domainoptsl optnl
 		;
 
 domainoptsl	: ALTERNATIVE NAMES '{' altname_l '}'
-		| DOMAIN KEY STRING {
+		| DOMAIN KEY STRING keytype {
 			char *s;
 			if (domain->key != NULL) {
 				yyerror("duplicate key");
@@ -427,10 +438,12 @@ lookup(char *s)
 		{"chain",		CHAIN},
 		{"challengedir",	CHALLENGEDIR},
 		{"domain",		DOMAIN},
+		{"ecdsa",		ECDSA},
 		{"full",		FULL},
 		{"include",		INCLUDE},
 		{"key",			KEY},
 		{"names",		NAMES},
+		{"rsa",			RSA},
 		{"sign",		SIGN},
 		{"url",			URL},
 		{"with",		WITH},
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: rsa.h
diff -N rsa.h
--- rsa.h	31 Aug 2016 22:01:42 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,23 +0,0 @@
-/*	$Id: rsa.h,v 1.1 2016/08/31 22:01:42 florian 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.
- */
-#ifndef RSA_H
-#define RSA_H
-
-EVP_PKEY	*rsa_key_create(FILE *, const char *);
-EVP_PKEY	*rsa_key_load(FILE *, const char *);
-
-#endif /* ! RSA_H */

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

Reply via email to