From: Theo Buehler Subject: acme-client: align RSA and EC key generation To: tech@openbsd.org Cc: wolf@wolfsden.cz Date: Tue, 7 May 2024 20:57:17 +0200 rsa_key_create() and ec_key_create() currently use different approaches for key generation. Obviously, the key types need to be distinct, and RSA needs setting the bit size whereas for EC we need to set the curve. That's all the differences there need to be. Also, we can do with fewer elses and exit paths. This way both key types use PEM-encoded PKCS#8 (RFC 5208) private keys as on-disk format. Currently, EC keys use a somewhat weird format. The old key format will keep working. This only changes how newly generated keys are stored. Another benefit is that this avoids a patch in wolf's portable version since key.c no longer uses "deprecated API". Index: key.c =================================================================== RCS file: /cvs/src/usr.sbin/acme-client/key.c,v diff -u -p -r1.8 key.c --- key.c 29 Aug 2023 14:44:53 -0000 1.8 +++ key.c 5 May 2024 19:24:14 -0000 @@ -42,79 +42,76 @@ rsa_key_create(FILE *f, const char *fnam 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) { + } + 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) { + } + 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) { + } + 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; + if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) { + warnx("%s: PEM_write_PrivateKey", fname); + goto err; + } - warnx("%s: PEM_write_PrivateKey", fname); + EVP_PKEY_CTX_free(ctx); + return pkey; err: EVP_PKEY_free(pkey); - pkey = NULL; -out: EVP_PKEY_CTX_free(ctx); - return pkey; + return NULL; } EVP_PKEY * ec_key_create(FILE *f, const char *fname) { - EC_KEY *eckey = NULL; + EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *pkey = NULL; - if ((eckey = EC_KEY_new_by_curve_name(NID_secp384r1)) == NULL) { - warnx("EC_KEY_new_by_curve_name"); + if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL) { + warnx("EVP_PKEY_CTX_new_id"); goto err; } - - if (!EC_KEY_generate_key(eckey)) { - warnx("EC_KEY_generate_key"); + if (EVP_PKEY_keygen_init(ctx) <= 0) { + warnx("EVP_PKEY_keygen_init"); goto err; } - - /* Serialise the key to the disc in EC format */ - - if (!PEM_write_ECPrivateKey(f, eckey, NULL, NULL, 0, NULL, NULL)) { - warnx("%s: PEM_write_ECPrivateKey", fname); + if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_secp384r1) <= 0) { + warnx("EVP_PKEY_CTX_set_ec_paramgen_curve_nid"); goto err; } - - /* Convert the EC key into a PKEY structure */ - - if ((pkey = EVP_PKEY_new()) == NULL) { - warnx("EVP_PKEY_new"); + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { + warnx("EVP_PKEY_keygen"); goto err; } - if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { - warnx("EVP_PKEY_set1_EC_KEY"); + + /* Serialise the key to the disc. */ + + if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) { + warnx("%s: PEM_write_PrivateKey", fname); goto err; } - goto out; + EVP_PKEY_CTX_free(ctx); + return pkey; err: EVP_PKEY_free(pkey); - pkey = NULL; -out: - EC_KEY_free(eckey); - return pkey; + EVP_PKEY_CTX_free(ctx); + return NULL; } EVP_PKEY *