diff --git a/sbin/dumpon/dumpon.c b/sbin/dumpon/dumpon.c --- a/sbin/dumpon/dumpon.c +++ b/sbin/dumpon/dumpon.c @@ -76,11 +76,14 @@ #include #ifdef HAVE_CRYPTO +#include #include #include #include +#if OPENSSL_VERSION_NUMBER < 0x30000000L #include #endif +#endif static int verbose; @@ -232,8 +235,15 @@ static void _genkey(const char *pubkeyfile, struct diocskerneldump_arg *kdap) { - FILE *fp; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY_CTX *pubkey_ctx = NULL; + EVP_PKEY *pubkey; +#else RSA *pubkey; +#endif + FILE *fp; + int encrypt_result; + int pubkey_bits; assert(pubkeyfile != NULL); assert(kdap != NULL); @@ -245,34 +255,41 @@ if (fp == NULL) err(1, "Unable to open %s", pubkeyfile); - /* - * Obsolescent OpenSSL only knows about /dev/random, and needs to - * pre-seed before entering cap mode. For whatever reason, - * RSA_pub_encrypt uses the internal PRNG. - */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L - { - unsigned char c[1]; - RAND_bytes(c, 1); - } -#endif - if (caph_enter() < 0) err(1, "Unable to enter capability mode"); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + pubkey = EVP_PKEY_new(); +#else pubkey = RSA_new(); +#endif if (pubkey == NULL) { errx(1, "Unable to allocate an RSA structure: %s", ERR_error_string(ERR_get_error(), NULL)); } +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + pubkey = PEM_read_PUBKEY(fp, &pubkey, NULL, NULL); +#else pubkey = PEM_read_RSA_PUBKEY(fp, &pubkey, NULL, NULL); +#endif fclose(fp); fp = NULL; if (pubkey == NULL) errx(1, "Unable to read data from %s: %s", pubkeyfile, ERR_error_string(ERR_get_error(), NULL)); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + pubkey_ctx = EVP_PKEY_CTX_new(pubkey, NULL); + if (pubkey_ctx == NULL) + errx(1, "Unable to allocate an public key context structure: %s", + ERR_error_string(ERR_get_error(), NULL)); + + if (EVP_PKEY_encrypt_init(pubkey_ctx) <= 0) + errx(1, "EVP_PKEY_encrypt_init failed: %s", + ERR_error_string(ERR_get_error(), NULL)); +#endif + /* * RSA keys under ~1024 bits are trivially factorable (2018). OpenSSL * provides an API for RSA keys to estimate the symmetric-cipher @@ -288,16 +305,21 @@ * of 'd' (i.e., the supplied key is a public key rather than a full * keypair). */ -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - if (RSA_security_bits(pubkey) < 112) +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + pubkey_bits = EVP_PKEY_security_bits(pubkey); #else - if (RSA_size(pubkey) * 8 < 2048) + pubkey_bits = RSA_security_bits(pubkey); #endif + if (pubkey_bits < 112) errx(1, "Small RSA keys (you provided: %db) can be " "factored cheaply. Please generate a larger key.", - RSA_size(pubkey) * 8); + pubkey_bits * 8); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + kdap->kda_encryptedkeysize = EVP_PKEY_get_size(pubkey); +#else kdap->kda_encryptedkeysize = RSA_size(pubkey); +#endif if (kdap->kda_encryptedkeysize > KERNELDUMP_ENCKEY_MAX_SIZE) { errx(1, "Public key has to be at most %db long.", 8 * KERNELDUMP_ENCKEY_MAX_SIZE); @@ -318,13 +340,34 @@ "with compression."); arc4random_buf(kdap->kda_key, sizeof(kdap->kda_key)); - if (RSA_public_encrypt(sizeof(kdap->kda_key), kdap->kda_key, - kdap->kda_encryptedkey, pubkey, - RSA_PKCS1_OAEP_PADDING) != (int)kdap->kda_encryptedkeysize) { + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + size_t outlen; + + if (EVP_PKEY_CTX_set_rsa_padding(pubkey_ctx, RSA_PKCS1_OAEP_PADDING) <= 0) { + errx(1, "Could not set encryption padding: %s", + ERR_error_string(ERR_get_error(), NULL)); + } + outlen = kdap->kda_encryptedkeysize; + + encrypt_result = EVP_PKEY_encrypt(pubkey_ctx, kdap->kda_encryptedkey, &outlen, + kdap->kda_key, sizeof(kdap->kda_key)); +#else + encrypt_result = RSA_public_encrypt(sizeof(kdap->kda_key), kdap->kda_key, + kdap->kda_encryptedkey, pubkey, RSA_PKCS1_OAEP_PADDING); +#endif + if (encrypt_result < 0) { errx(1, "Unable to encrypt the one-time key: %s", ERR_error_string(ERR_get_error(), NULL)); } +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + kdap->kda_encryptedkeysize = outlen; + + EVP_PKEY_free(pubkey); + EVP_PKEY_CTX_free(pubkey_ctx); +#else RSA_free(pubkey); +#endif } /*