diff options
author | 2019-06-12 11:09:25 +0000 | |
---|---|---|
committer | 2019-06-12 11:09:25 +0000 | |
commit | 3e86e78b7c8081cdc2ce613b94fe4146b1d05588 (patch) | |
tree | 9549bdc98c90ca092939cce6c8742202a6fd0bf4 | |
parent | add missing backlinks to ssl(3) (diff) | |
download | wireguard-openbsd-3e86e78b7c8081cdc2ce613b94fe4146b1d05588.tar.xz wireguard-openbsd-3e86e78b7c8081cdc2ce613b94fe4146b1d05588.zip |
use acme-client to sign certificated with ecdsa keys
diff from Renaud Allard <renaud@allard.it>, ok to get in from florian@
-rw-r--r-- | usr.sbin/acme-client/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/acme-client/acctproc.c | 8 | ||||
-rw-r--r-- | usr.sbin/acme-client/acme-client.conf.5 | 8 | ||||
-rw-r--r-- | usr.sbin/acme-client/extern.h | 7 | ||||
-rw-r--r-- | usr.sbin/acme-client/key.c | 149 | ||||
-rw-r--r-- | usr.sbin/acme-client/key.h | 25 | ||||
-rw-r--r-- | usr.sbin/acme-client/keyproc.c | 20 | ||||
-rw-r--r-- | usr.sbin/acme-client/main.c | 7 | ||||
-rw-r--r-- | usr.sbin/acme-client/parse.h | 3 | ||||
-rw-r--r-- | usr.sbin/acme-client/parse.y | 19 | ||||
-rw-r--r-- | usr.sbin/acme-client/rsa.c | 88 | ||||
-rw-r--r-- | usr.sbin/acme-client/rsa.h | 23 |
12 files changed, 229 insertions, 132 deletions
diff --git a/usr.sbin/acme-client/Makefile b/usr.sbin/acme-client/Makefile index ea6c3ae6683..47f4bbac554 100644 --- a/usr.sbin/acme-client/Makefile +++ b/usr.sbin/acme-client/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.8 2017/07/03 22:21:47 espie Exp $ +# $OpenBSD: Makefile,v 1.9 2019/06/12 11:09:25 gilles Exp $ 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 diff --git a/usr.sbin/acme-client/acctproc.c b/usr.sbin/acme-client/acctproc.c index 760111339bc..52309b765d5 100644 --- a/usr.sbin/acme-client/acctproc.c +++ b/usr.sbin/acme-client/acctproc.c @@ -1,4 +1,4 @@ -/* $Id: acctproc.c,v 1.14 2019/06/08 07:52:55 florian Exp $ */ +/* $Id: acctproc.c,v 1.15 2019/06/12 11:09:25 gilles Exp $ */ /* * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -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 *acctkey) 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); } diff --git a/usr.sbin/acme-client/acme-client.conf.5 b/usr.sbin/acme-client/acme-client.conf.5 index 5f93cfcaba7..fdddcbd912d 100644 --- a/usr.sbin/acme-client/acme-client.conf.5 +++ b/usr.sbin/acme-client/acme-client.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: acme-client.conf.5,v 1.17 2019/01/08 06:46:29 florian Exp $ +.\" $OpenBSD: acme-client.conf.5,v 1.18 2019/06/12 11:09:25 gilles Exp $ .\" .\" Copyright (c) 2005 Esben Norby <norby@openbsd.org> .\" Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> @@ -17,7 +17,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 8 2019 $ +.Dd $Mdocdate: June 12 2019 $ .Dt ACME-CLIENT.CONF 5 .Os .Sh NAME @@ -109,8 +109,10 @@ Specify a list of alternative names for which the certificate will be valid. 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. +.Ar 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 diff --git a/usr.sbin/acme-client/extern.h b/usr.sbin/acme-client/extern.h index 86f2c3cfcf9..17c6aa54f18 100644 --- a/usr.sbin/acme-client/extern.h +++ b/usr.sbin/acme-client/extern.h @@ -1,4 +1,4 @@ -/* $Id: extern.h,v 1.12 2019/06/08 07:52:55 florian Exp $ */ +/* $Id: extern.h,v 1.13 2019/06/12 11:09:25 gilles Exp $ */ /* * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -276,6 +276,11 @@ char *json_fmt_signed(const char *, const char *, const char *); int verbose; /* + * Should we switch to ecdsa? + */ +int ecdsa; + +/* * What component is the process within (COMP__MAX for none)? */ enum comp proccomp; diff --git a/usr.sbin/acme-client/key.c b/usr.sbin/acme-client/key.c new file mode 100644 index 00000000000..02c04a03419 --- /dev/null +++ b/usr.sbin/acme-client/key.c @@ -0,0 +1,149 @@ +/* $Id: key.c,v 1.1 2019/06/12 11:09:25 gilles Exp $ */ +/* + * Copyright (c) 2019 Renaud Allard <renaud@allard.it> + * Copyright (c) 2016 Kristaps Dzonsons <kristaps@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; +} diff --git a/usr.sbin/acme-client/key.h b/usr.sbin/acme-client/key.h new file mode 100644 index 00000000000..272d36eb09a --- /dev/null +++ b/usr.sbin/acme-client/key.h @@ -0,0 +1,25 @@ +/* $Id: key.h,v 1.1 2019/06/12 11:09:25 gilles Exp $ */ +/* + * Copyright (c) 2019 Renaud Allard <renaud@allard.it> + * Copyright (c) 2016 Kristaps Dzonsons <kristaps@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 KEY_H +#define KEY_H + +EVP_PKEY *rsa_key_create(FILE *, const char *); +EVP_PKEY *ec_key_create(FILE *, const char *); +EVP_PKEY *key_load(FILE *, const char *); + +#endif /* ! KEY_H */ diff --git a/usr.sbin/acme-client/keyproc.c b/usr.sbin/acme-client/keyproc.c index 9e6b469c6fa..9c392a0f3f6 100644 --- a/usr.sbin/acme-client/keyproc.c +++ b/usr.sbin/acme-client/keyproc.c @@ -1,4 +1,4 @@ -/* $Id: keyproc.c,v 1.12 2019/06/08 07:52:55 florian Exp $ */ +/* $Id: keyproc.c,v 1.13 2019/06/12 11:09:25 gilles Exp $ */ /* * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -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); diff --git a/usr.sbin/acme-client/main.c b/usr.sbin/acme-client/main.c index 1bbecd3d989..ea8f7c5d348 100644 --- a/usr.sbin/acme-client/main.c +++ b/usr.sbin/acme-client/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.47 2019/06/08 07:52:55 florian Exp $ */ +/* $Id: main.c,v 1.48 2019/06/12 11:09:25 gilles Exp $ */ /* * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -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; @@ -147,6 +148,10 @@ main(int argc, char *argv[]) errx(EXIT_FAILURE, "authority %s not found", auth); } + if (domain->keytype == 1) { + ecdsa = 1; + } + acctkey = authority->account; if ((chngdir = domain->challengedir) == NULL) diff --git a/usr.sbin/acme-client/parse.h b/usr.sbin/acme-client/parse.h index 20a1de581bf..78405590568 100644 --- a/usr.sbin/acme-client/parse.h +++ b/usr.sbin/acme-client/parse.h @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.h,v 1.10 2019/06/08 07:52:55 florian Exp $ */ +/* $OpenBSD: parse.h,v 1.11 2019/06/12 11:09:25 gilles Exp $ */ /* * Copyright (c) 2016 Sebastian Benoit <benno@openbsd.org> * @@ -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; diff --git a/usr.sbin/acme-client/parse.y b/usr.sbin/acme-client/parse.y index 9063cc39531..994492706bb 100644 --- a/usr.sbin/acme-client/parse.y +++ b/usr.sbin/acme-client/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.34 2019/06/08 07:52:55 florian Exp $ */ +/* $OpenBSD: parse.y,v 1.35 2019/06/12 11:09:25 gilles Exp $ */ /* * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> @@ -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}, diff --git a/usr.sbin/acme-client/rsa.c b/usr.sbin/acme-client/rsa.c index 798badc7659..e69de29bb2d 100644 --- a/usr.sbin/acme-client/rsa.c +++ b/usr.sbin/acme-client/rsa.c @@ -1,88 +0,0 @@ -/* $Id: rsa.c,v 1.7 2018/07/28 15:25:23 tb Exp $ */ -/* - * Copyright (c) 2016 Kristaps Dzonsons <kristaps@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; -} diff --git a/usr.sbin/acme-client/rsa.h b/usr.sbin/acme-client/rsa.h index 8e4162808ca..e69de29bb2d 100644 --- a/usr.sbin/acme-client/rsa.h +++ b/usr.sbin/acme-client/rsa.h @@ -1,23 +0,0 @@ -/* $Id: rsa.h,v 1.1 2016/08/31 22:01:42 florian Exp $ */ -/* - * Copyright (c) 2016 Kristaps Dzonsons <kristaps@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 */ |