1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.h"
4 #include "ask-password-api.h"
9 #include "memory-util.h"
10 #include "memstream-util.h"
11 #include "openssl-util.h"
12 #include "random-util.h"
13 #include "string-util.h"
17 # include <openssl/ec.h>
18 # include <openssl/rsa.h>
20 # if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0)
21 # include <openssl/engine.h>
22 DISABLE_WARNING_DEPRECATED_DECLARATIONS
;
23 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ENGINE
*, ENGINE_free
, NULL
);
27 #ifndef OPENSSL_NO_UI_CONSOLE
28 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(UI_METHOD
*, UI_destroy_method
, NULL
);
31 /* For each error in the OpenSSL thread error queue, log the provided message and the OpenSSL error
32 * string. If there are no errors in the OpenSSL thread queue, this logs the message with "No OpenSSL
33 * errors." This logs at level debug. Returns -EIO (or -ENOMEM). */
34 #define log_openssl_errors(fmt, ...) _log_openssl_errors(UNIQ, fmt, ##__VA_ARGS__)
35 #define _log_openssl_errors(u, fmt, ...) \
37 size_t UNIQ_T(MAX, u) = 512 /* arbitrary, but openssl doc states it must be >= 256 */; \
38 _cleanup_free_ char *UNIQ_T(BUF, u) = malloc(UNIQ_T(MAX, u)); \
41 : __log_openssl_errors(u, UNIQ_T(BUF, u), UNIQ_T(MAX, u), fmt, ##__VA_ARGS__) \
42 ?: log_debug_errno(SYNTHETIC_ERRNO(EIO), fmt ": No OpenSSL errors.", ##__VA_ARGS__); \
44 #define __log_openssl_errors(u, buf, max, fmt, ...) \
46 int UNIQ_T(R, u) = 0; \
48 unsigned long UNIQ_T(E, u) = ERR_get_error(); \
49 if (UNIQ_T(E, u) == 0) \
51 ERR_error_string_n(UNIQ_T(E, u), buf, max); \
52 UNIQ_T(R, u) = log_debug_errno(SYNTHETIC_ERRNO(EIO), fmt ": %s", ##__VA_ARGS__, buf); \
57 int openssl_pubkey_from_pem(const void *pem
, size_t pem_size
, EVP_PKEY
**ret
) {
61 if (pem_size
== SIZE_MAX
)
62 pem_size
= strlen(pem
);
64 _cleanup_fclose_
FILE *f
= NULL
;
65 f
= fmemopen((void*) pem
, pem_size
, "r");
67 return log_oom_debug();
69 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= PEM_read_PUBKEY(f
, /* x= */ NULL
, /* pam_password_cb= */ NULL
, /* userdata= */ NULL
);
71 return log_openssl_errors("Failed to parse PEM");
73 *ret
= TAKE_PTR(pkey
);
77 int openssl_pubkey_to_pem(EVP_PKEY
*pkey
, char **ret
) {
81 _cleanup_(memstream_done
) MemStream m
= {};
82 FILE *f
= memstream_init(&m
);
86 if (PEM_write_PUBKEY(f
, pkey
) <= 0)
89 return memstream_finalize(&m
, ret
, /* ret_size= */ NULL
);
92 /* Returns the number of bytes generated by the specified digest algorithm. This can be used only for
93 * fixed-size algorithms, e.g. md5, sha1, sha256, etc. Do not use this for variable-sized digest algorithms,
94 * e.g. shake128. Returns 0 on success, -EOPNOTSUPP if the algorithm is not supported, or < 0 for any other
96 int openssl_digest_size(const char *digest_alg
, size_t *ret_digest_size
) {
98 assert(ret_digest_size
);
100 #if OPENSSL_VERSION_MAJOR >= 3
101 _cleanup_(EVP_MD_freep
) EVP_MD
*md
= EVP_MD_fetch(NULL
, digest_alg
, NULL
);
103 const EVP_MD
*md
= EVP_get_digestbyname(digest_alg
);
106 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
107 "Digest algorithm '%s' not supported.", digest_alg
);
110 #if OPENSSL_VERSION_MAJOR >= 3
111 digest_size
= EVP_MD_get_size(md
);
113 digest_size
= EVP_MD_size(md
);
115 if (digest_size
== 0)
116 return log_openssl_errors("Failed to get Digest size");
118 *ret_digest_size
= digest_size
;
123 /* Calculate the digest hash value for the provided data, using the specified digest algorithm. Returns 0 on
124 * success, -EOPNOTSUPP if the digest algorithm is not supported, or < 0 for any other error. */
125 int openssl_digest_many(
126 const char *digest_alg
,
127 const struct iovec data
[],
130 size_t *ret_digest_size
) {
135 assert(data
|| n_data
== 0);
137 /* ret_digest_size is optional, as caller may already know the digest size */
139 #if OPENSSL_VERSION_MAJOR >= 3
140 _cleanup_(EVP_MD_freep
) EVP_MD
*md
= EVP_MD_fetch(NULL
, digest_alg
, NULL
);
142 const EVP_MD
*md
= EVP_get_digestbyname(digest_alg
);
145 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
146 "Digest algorithm '%s' not supported.", digest_alg
);
148 _cleanup_(EVP_MD_CTX_freep
) EVP_MD_CTX
*ctx
= EVP_MD_CTX_new();
150 return log_openssl_errors("Failed to create new EVP_MD_CTX");
152 if (!EVP_DigestInit_ex(ctx
, md
, NULL
))
153 return log_openssl_errors("Failed to initialize EVP_MD_CTX");
155 for (size_t i
= 0; i
< n_data
; i
++)
156 if (!EVP_DigestUpdate(ctx
, data
[i
].iov_base
, data
[i
].iov_len
))
157 return log_openssl_errors("Failed to update Digest");
160 r
= openssl_digest_size(digest_alg
, &digest_size
);
164 _cleanup_free_
void *buf
= malloc(digest_size
);
166 return log_oom_debug();
169 if (!EVP_DigestFinal_ex(ctx
, buf
, &size
))
170 return log_openssl_errors("Failed to finalize Digest");
172 assert(size
== digest_size
);
174 *ret_digest
= TAKE_PTR(buf
);
176 *ret_digest_size
= size
;
181 /* Calculate the HMAC digest hash value for the provided data, using the provided key and specified digest
182 * algorithm. Returns 0 on success, -EOPNOTSUPP if the digest algorithm is not supported, or < 0 for any
184 int openssl_hmac_many(
185 const char *digest_alg
,
188 const struct iovec data
[],
191 size_t *ret_digest_size
) {
195 assert(data
|| n_data
== 0);
197 /* ret_digest_size is optional, as caller may already know the digest size */
199 #if OPENSSL_VERSION_MAJOR >= 3
200 _cleanup_(EVP_MD_freep
) EVP_MD
*md
= EVP_MD_fetch(NULL
, digest_alg
, NULL
);
202 const EVP_MD
*md
= EVP_get_digestbyname(digest_alg
);
205 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
206 "Digest algorithm '%s' not supported.", digest_alg
);
208 #if OPENSSL_VERSION_MAJOR >= 3
209 _cleanup_(EVP_MAC_freep
) EVP_MAC
*mac
= EVP_MAC_fetch(NULL
, "HMAC", NULL
);
211 return log_openssl_errors("Failed to create new EVP_MAC");
213 _cleanup_(EVP_MAC_CTX_freep
) EVP_MAC_CTX
*ctx
= EVP_MAC_CTX_new(mac
);
215 return log_openssl_errors("Failed to create new EVP_MAC_CTX");
217 _cleanup_(OSSL_PARAM_BLD_freep
) OSSL_PARAM_BLD
*bld
= OSSL_PARAM_BLD_new();
219 return log_openssl_errors("Failed to create new OSSL_PARAM_BLD");
221 if (!OSSL_PARAM_BLD_push_utf8_string(bld
, OSSL_MAC_PARAM_DIGEST
, (char*) digest_alg
, 0))
222 return log_openssl_errors("Failed to set HMAC OSSL_MAC_PARAM_DIGEST");
224 _cleanup_(OSSL_PARAM_freep
) OSSL_PARAM
*params
= OSSL_PARAM_BLD_to_param(bld
);
226 return log_openssl_errors("Failed to build HMAC OSSL_PARAM");
228 if (!EVP_MAC_init(ctx
, key
, key_size
, params
))
229 return log_openssl_errors("Failed to initialize EVP_MAC_CTX");
231 _cleanup_(HMAC_CTX_freep
) HMAC_CTX
*ctx
= HMAC_CTX_new();
233 return log_openssl_errors("Failed to create new HMAC_CTX");
235 if (!HMAC_Init_ex(ctx
, key
, key_size
, md
, NULL
))
236 return log_openssl_errors("Failed to initialize HMAC_CTX");
239 for (size_t i
= 0; i
< n_data
; i
++)
240 #if OPENSSL_VERSION_MAJOR >= 3
241 if (!EVP_MAC_update(ctx
, data
[i
].iov_base
, data
[i
].iov_len
))
243 if (!HMAC_Update(ctx
, data
[i
].iov_base
, data
[i
].iov_len
))
245 return log_openssl_errors("Failed to update HMAC");
248 #if OPENSSL_VERSION_MAJOR >= 3
249 digest_size
= EVP_MAC_CTX_get_mac_size(ctx
);
251 digest_size
= HMAC_size(ctx
);
253 if (digest_size
== 0)
254 return log_openssl_errors("Failed to get HMAC digest size");
256 _cleanup_free_
void *buf
= malloc(digest_size
);
258 return log_oom_debug();
260 #if OPENSSL_VERSION_MAJOR >= 3
262 if (!EVP_MAC_final(ctx
, buf
, &size
, digest_size
))
265 if (!HMAC_Final(ctx
, buf
, &size
))
267 return log_openssl_errors("Failed to finalize HMAC");
269 assert(size
== digest_size
);
271 *ret_digest
= TAKE_PTR(buf
);
273 *ret_digest_size
= size
;
278 /* Symmetric Cipher encryption using the alg-bits-mode cipher, e.g. AES-128-CFB. The key is required and must
279 * be at least the minimum required key length for the cipher. The IV is optional but, if provided, it must
280 * be at least the minimum iv length for the cipher. If no IV is provided and the cipher requires one, a
281 * buffer of zeroes is used. Returns 0 on success, -EOPNOTSUPP if the cipher algorithm is not supported, or <
282 * 0 on any other error. */
283 int openssl_cipher_many(
291 const struct iovec data
[],
300 assert(iv
|| iv_size
== 0);
301 assert(data
|| n_data
== 0);
305 _cleanup_free_
char *cipher_alg
= NULL
;
306 if (asprintf(&cipher_alg
, "%s-%zu-%s", alg
, bits
, mode
) < 0)
307 return log_oom_debug();
309 #if OPENSSL_VERSION_MAJOR >= 3
310 _cleanup_(EVP_CIPHER_freep
) EVP_CIPHER
*cipher
= EVP_CIPHER_fetch(NULL
, cipher_alg
, NULL
);
312 const EVP_CIPHER
*cipher
= EVP_get_cipherbyname(cipher_alg
);
315 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
316 "Cipher algorithm '%s' not supported.", cipher_alg
);
318 _cleanup_(EVP_CIPHER_CTX_freep
) EVP_CIPHER_CTX
*ctx
= EVP_CIPHER_CTX_new();
320 return log_openssl_errors("Failed to create new EVP_CIPHER_CTX");
322 /* Verify enough key data was provided. */
323 int cipher_key_length
= EVP_CIPHER_key_length(cipher
);
324 assert(cipher_key_length
>= 0);
325 if ((size_t) cipher_key_length
> key_size
)
326 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
327 "Not enough key bytes provided, require %d", cipher_key_length
);
329 /* Verify enough IV data was provided or, if no IV was provided, use a zeroed buffer for IV data. */
330 int cipher_iv_length
= EVP_CIPHER_iv_length(cipher
);
331 assert(cipher_iv_length
>= 0);
332 _cleanup_free_
void *zero_iv
= NULL
;
334 zero_iv
= malloc0(cipher_iv_length
);
336 return log_oom_debug();
339 iv_size
= (size_t) cipher_iv_length
;
341 if ((size_t) cipher_iv_length
> iv_size
)
342 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
343 "Not enough IV bytes provided, require %d", cipher_iv_length
);
345 if (!EVP_EncryptInit(ctx
, cipher
, key
, iv
))
346 return log_openssl_errors("Failed to initialize EVP_CIPHER_CTX.");
348 int cipher_block_size
= EVP_CIPHER_CTX_block_size(ctx
);
349 assert(cipher_block_size
> 0);
351 _cleanup_free_
uint8_t *buf
= NULL
;
354 for (size_t i
= 0; i
< n_data
; i
++) {
355 /* Cipher may produce (up to) input length + cipher block size of output. */
356 if (!GREEDY_REALLOC(buf
, size
+ data
[i
].iov_len
+ cipher_block_size
))
357 return log_oom_debug();
360 if (!EVP_EncryptUpdate(ctx
, &buf
[size
], &update_size
, data
[i
].iov_base
, data
[i
].iov_len
))
361 return log_openssl_errors("Failed to update Cipher.");
366 if (!GREEDY_REALLOC(buf
, size
+ cipher_block_size
))
367 return log_oom_debug();
370 if (!EVP_EncryptFinal_ex(ctx
, &buf
[size
], &final_size
))
371 return log_openssl_errors("Failed to finalize Cipher.");
373 *ret
= TAKE_PTR(buf
);
374 *ret_size
= size
+ final_size
;
379 /* Perform Single-Step (aka "Concat") KDF. Currently, this only supports using the digest for the auxiliary
380 * function. The derive_size parameter specifies how many bytes are derived.
382 * For more details see: https://www.openssl.org/docs/manmaster/man7/EVP_KDF-SS.html */
394 #if OPENSSL_VERSION_MAJOR >= 3
397 assert(derive_size
> 0);
400 _cleanup_(EVP_KDF_freep
) EVP_KDF
*kdf
= EVP_KDF_fetch(NULL
, "SSKDF", NULL
);
402 return log_openssl_errors("Failed to create new EVP_KDF");
404 _cleanup_(EVP_KDF_CTX_freep
) EVP_KDF_CTX
*ctx
= EVP_KDF_CTX_new(kdf
);
406 return log_openssl_errors("Failed to create new EVP_KDF_CTX");
408 _cleanup_(OSSL_PARAM_BLD_freep
) OSSL_PARAM_BLD
*bld
= OSSL_PARAM_BLD_new();
410 return log_openssl_errors("Failed to create new OSSL_PARAM_BLD");
412 _cleanup_free_
void *buf
= malloc(derive_size
);
414 return log_oom_debug();
416 if (!OSSL_PARAM_BLD_push_utf8_string(bld
, OSSL_KDF_PARAM_DIGEST
, (char*) digest
, 0))
417 return log_openssl_errors("Failed to add KDF-SS OSSL_KDF_PARAM_DIGEST");
419 if (!OSSL_PARAM_BLD_push_octet_string(bld
, OSSL_KDF_PARAM_KEY
, (char*) key
, key_size
))
420 return log_openssl_errors("Failed to add KDF-SS OSSL_KDF_PARAM_KEY");
423 if (!OSSL_PARAM_BLD_push_octet_string(bld
, OSSL_KDF_PARAM_SALT
, (char*) salt
, salt_size
))
424 return log_openssl_errors("Failed to add KDF-SS OSSL_KDF_PARAM_SALT");
427 if (!OSSL_PARAM_BLD_push_octet_string(bld
, OSSL_KDF_PARAM_INFO
, (char*) info
, info_size
))
428 return log_openssl_errors("Failed to add KDF-SS OSSL_KDF_PARAM_INFO");
430 _cleanup_(OSSL_PARAM_freep
) OSSL_PARAM
*params
= OSSL_PARAM_BLD_to_param(bld
);
432 return log_openssl_errors("Failed to build KDF-SS OSSL_PARAM");
434 if (EVP_KDF_derive(ctx
, buf
, derive_size
, params
) <= 0)
435 return log_openssl_errors("OpenSSL KDF-SS derive failed");
437 *ret
= TAKE_PTR(buf
);
441 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "KDF-SS requires OpenSSL >= 3.");
445 /* Perform Key-Based HMAC KDF. The mode must be "COUNTER" or "FEEDBACK". The parameter naming is from the
446 * OpenSSL api, and maps to SP800-108 naming as "...key, salt, info, and seed correspond to KI, Label,
447 * Context, and IV (respectively)...". The derive_size parameter specifies how many bytes are derived.
449 * For more details see: https://www.openssl.org/docs/manmaster/man7/EVP_KDF-KB.html */
450 int kdf_kb_hmac_derive(
464 #if OPENSSL_VERSION_MAJOR >= 3
466 assert(strcaseeq(mode
, "COUNTER") || strcaseeq(mode
, "FEEDBACK"));
468 assert(key
|| key_size
== 0);
469 assert(salt
|| salt_size
== 0);
470 assert(info
|| info_size
== 0);
471 assert(seed
|| seed_size
== 0);
472 assert(derive_size
> 0);
475 _cleanup_(EVP_KDF_freep
) EVP_KDF
*kdf
= EVP_KDF_fetch(NULL
, "KBKDF", NULL
);
477 return log_openssl_errors("Failed to create new EVP_KDF");
479 _cleanup_(EVP_KDF_CTX_freep
) EVP_KDF_CTX
*ctx
= EVP_KDF_CTX_new(kdf
);
481 return log_openssl_errors("Failed to create new EVP_KDF_CTX");
483 _cleanup_(OSSL_PARAM_BLD_freep
) OSSL_PARAM_BLD
*bld
= OSSL_PARAM_BLD_new();
485 return log_openssl_errors("Failed to create new OSSL_PARAM_BLD");
487 if (!OSSL_PARAM_BLD_push_utf8_string(bld
, OSSL_KDF_PARAM_MAC
, (char*) "HMAC", 0))
488 return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_MAC");
490 if (!OSSL_PARAM_BLD_push_utf8_string(bld
, OSSL_KDF_PARAM_MODE
, (char*) mode
, 0))
491 return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_MODE");
493 if (!OSSL_PARAM_BLD_push_utf8_string(bld
, OSSL_KDF_PARAM_DIGEST
, (char*) digest
, 0))
494 return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_DIGEST");
497 if (!OSSL_PARAM_BLD_push_octet_string(bld
, OSSL_KDF_PARAM_KEY
, (char*) key
, key_size
))
498 return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_KEY");
501 if (!OSSL_PARAM_BLD_push_octet_string(bld
, OSSL_KDF_PARAM_SALT
, (char*) salt
, salt_size
))
502 return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_SALT");
505 if (!OSSL_PARAM_BLD_push_octet_string(bld
, OSSL_KDF_PARAM_INFO
, (char*) info
, info_size
))
506 return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_INFO");
509 if (!OSSL_PARAM_BLD_push_octet_string(bld
, OSSL_KDF_PARAM_SEED
, (char*) seed
, seed_size
))
510 return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_SEED");
512 _cleanup_(OSSL_PARAM_freep
) OSSL_PARAM
*params
= OSSL_PARAM_BLD_to_param(bld
);
514 return log_openssl_errors("Failed to build KDF-KB OSSL_PARAM");
516 _cleanup_free_
void *buf
= malloc(derive_size
);
518 return log_oom_debug();
520 if (EVP_KDF_derive(ctx
, buf
, derive_size
, params
) <= 0)
521 return log_openssl_errors("OpenSSL KDF-KB derive failed");
523 *ret
= TAKE_PTR(buf
);
527 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "KDF-KB requires OpenSSL >= 3.");
531 int rsa_encrypt_bytes(
533 const void *decrypted_key
,
534 size_t decrypted_key_size
,
535 void **ret_encrypt_key
,
536 size_t *ret_encrypt_key_size
) {
538 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= NULL
;
539 _cleanup_free_
void *b
= NULL
;
542 ctx
= EVP_PKEY_CTX_new(pkey
, NULL
);
544 return log_openssl_errors("Failed to allocate public key context");
546 if (EVP_PKEY_encrypt_init(ctx
) <= 0)
547 return log_openssl_errors("Failed to initialize public key context");
549 if (EVP_PKEY_CTX_set_rsa_padding(ctx
, RSA_PKCS1_PADDING
) <= 0)
550 return log_openssl_errors("Failed to configure PKCS#1 padding");
552 if (EVP_PKEY_encrypt(ctx
, NULL
, &l
, decrypted_key
, decrypted_key_size
) <= 0)
553 return log_openssl_errors("Failed to determine encrypted key size");
559 if (EVP_PKEY_encrypt(ctx
, b
, &l
, decrypted_key
, decrypted_key_size
) <= 0)
560 return log_openssl_errors("Failed to determine encrypted key size");
562 *ret_encrypt_key
= TAKE_PTR(b
);
563 *ret_encrypt_key_size
= l
;
567 /* Encrypt the key data using RSA-OAEP with the provided label and specified digest algorithm. Returns 0 on
568 * success, -EOPNOTSUPP if the digest algorithm is not supported, or < 0 for any other error. */
569 int rsa_oaep_encrypt_bytes(
570 const EVP_PKEY
*pkey
,
571 const char *digest_alg
,
573 const void *decrypted_key
,
574 size_t decrypted_key_size
,
575 void **ret_encrypt_key
,
576 size_t *ret_encrypt_key_size
) {
581 assert(decrypted_key
);
582 assert(decrypted_key_size
> 0);
583 assert(ret_encrypt_key
);
584 assert(ret_encrypt_key_size
);
586 #if OPENSSL_VERSION_MAJOR >= 3
587 _cleanup_(EVP_MD_freep
) EVP_MD
*md
= EVP_MD_fetch(NULL
, digest_alg
, NULL
);
589 const EVP_MD
*md
= EVP_get_digestbyname(digest_alg
);
592 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
),
593 "Digest algorithm '%s' not supported.", digest_alg
);
595 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= EVP_PKEY_CTX_new((EVP_PKEY
*) pkey
, NULL
);
597 return log_openssl_errors("Failed to create new EVP_PKEY_CTX");
599 if (EVP_PKEY_encrypt_init(ctx
) <= 0)
600 return log_openssl_errors("Failed to initialize EVP_PKEY_CTX");
602 if (EVP_PKEY_CTX_set_rsa_padding(ctx
, RSA_PKCS1_OAEP_PADDING
) <= 0)
603 return log_openssl_errors("Failed to configure RSA-OAEP padding");
605 if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx
, md
) <= 0)
606 return log_openssl_errors("Failed to configure RSA-OAEP MD");
608 _cleanup_free_
char *duplabel
= strdup(label
);
610 return log_oom_debug();
612 if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx
, duplabel
, strlen(duplabel
) + 1) <= 0)
613 return log_openssl_errors("Failed to configure RSA-OAEP label");
614 /* ctx owns this now, don't free */
618 if (EVP_PKEY_encrypt(ctx
, NULL
, &size
, decrypted_key
, decrypted_key_size
) <= 0)
619 return log_openssl_errors("Failed to determine RSA-OAEP encrypted key size");
621 _cleanup_free_
void *buf
= malloc(size
);
623 return log_oom_debug();
625 if (EVP_PKEY_encrypt(ctx
, buf
, &size
, decrypted_key
, decrypted_key_size
) <= 0)
626 return log_openssl_errors("Failed to RSA-OAEP encrypt");
628 *ret_encrypt_key
= TAKE_PTR(buf
);
629 *ret_encrypt_key_size
= size
;
634 int rsa_pkey_to_suitable_key_size(
636 size_t *ret_suitable_key_size
) {
638 size_t suitable_key_size
;
642 assert(ret_suitable_key_size
);
644 /* Analyzes the specified public key and that it is RSA. If so, will return a suitable size for a
645 * disk encryption key to encrypt with RSA for use in PKCS#11 security token schemes. */
647 if (EVP_PKEY_base_id(pkey
) != EVP_PKEY_RSA
)
648 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG
), "X.509 certificate does not refer to RSA key.");
650 bits
= EVP_PKEY_bits(pkey
);
651 log_debug("Bits in RSA key: %i", bits
);
653 /* We use PKCS#1 padding for the RSA cleartext, hence let's leave some extra space for it, hence only
654 * generate a random key half the size of the RSA length */
655 suitable_key_size
= bits
/ 8 / 2;
657 if (suitable_key_size
< 1)
658 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Uh, RSA key size too short?");
660 *ret_suitable_key_size
= suitable_key_size
;
664 /* Generate RSA public key from provided "n" and "e" values. Numbers "n" and "e" must be provided here
665 * in big-endian format, e.g. wrap it with htobe32() for uint32_t. */
666 int rsa_pkey_from_n_e(const void *n
, size_t n_size
, const void *e
, size_t e_size
, EVP_PKEY
**ret
) {
667 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
675 #if OPENSSL_VERSION_MAJOR >= 3
676 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= EVP_PKEY_CTX_new_from_name(NULL
, "RSA", NULL
);
678 return log_openssl_errors("Failed to create new EVP_PKEY_CTX");
680 if (EVP_PKEY_fromdata_init(ctx
) <= 0)
681 return log_openssl_errors("Failed to initialize EVP_PKEY_CTX");
683 OSSL_PARAM params
[3];
685 #if __BYTE_ORDER == __BIG_ENDIAN
686 params
[0] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_N
, (void*)n
, n_size
);
687 params
[1] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_E
, (void*)e
, e_size
);
689 _cleanup_free_
void *native_n
= memdup_reverse(n
, n_size
);
691 return log_oom_debug();
693 _cleanup_free_
void *native_e
= memdup_reverse(e
, e_size
);
695 return log_oom_debug();
697 params
[0] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_N
, native_n
, n_size
);
698 params
[1] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_E
, native_e
, e_size
);
700 params
[2] = OSSL_PARAM_construct_end();
702 if (EVP_PKEY_fromdata(ctx
, &pkey
, EVP_PKEY_PUBLIC_KEY
, params
) <= 0)
703 return log_openssl_errors("Failed to create RSA EVP_PKEY");
705 _cleanup_(BN_freep
) BIGNUM
*bn_n
= BN_bin2bn(n
, n_size
, NULL
);
707 return log_openssl_errors("Failed to create BIGNUM for RSA n");
709 _cleanup_(BN_freep
) BIGNUM
*bn_e
= BN_bin2bn(e
, e_size
, NULL
);
711 return log_openssl_errors("Failed to create BIGNUM for RSA e");
713 _cleanup_(RSA_freep
) RSA
*rsa_key
= RSA_new();
715 return log_openssl_errors("Failed to create new RSA");
717 if (!RSA_set0_key(rsa_key
, bn_n
, bn_e
, NULL
))
718 return log_openssl_errors("Failed to set RSA n/e");
719 /* rsa_key owns these now, don't free */
723 pkey
= EVP_PKEY_new();
725 return log_openssl_errors("Failed to create new EVP_PKEY");
727 if (!EVP_PKEY_assign_RSA(pkey
, rsa_key
))
728 return log_openssl_errors("Failed to assign RSA key");
729 /* pkey owns this now, don't free */
733 *ret
= TAKE_PTR(pkey
);
738 /* Get the "n" and "e" values from the pkey. The values are returned in "bin" format, i.e. BN_bn2bin(). */
740 const EVP_PKEY
*pkey
,
744 size_t *ret_e_size
) {
752 #if OPENSSL_VERSION_MAJOR >= 3
753 _cleanup_(BN_freep
) BIGNUM
*bn_n
= NULL
;
754 if (!EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_RSA_N
, &bn_n
))
755 return log_openssl_errors("Failed to get RSA n");
757 _cleanup_(BN_freep
) BIGNUM
*bn_e
= NULL
;
758 if (!EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_RSA_E
, &bn_e
))
759 return log_openssl_errors("Failed to get RSA e");
761 const RSA
*rsa
= EVP_PKEY_get0_RSA((EVP_PKEY
*) pkey
);
763 return log_openssl_errors("Failed to get RSA key from public key");
765 const BIGNUM
*bn_n
= RSA_get0_n(rsa
);
767 return log_openssl_errors("Failed to get RSA n");
769 const BIGNUM
*bn_e
= RSA_get0_e(rsa
);
771 return log_openssl_errors("Failed to get RSA e");
774 size_t n_size
= BN_num_bytes(bn_n
), e_size
= BN_num_bytes(bn_e
);
775 _cleanup_free_
void *n
= malloc(n_size
), *e
= malloc(e_size
);
777 return log_oom_debug();
779 assert(BN_bn2bin(bn_n
, n
) == (int) n_size
);
780 assert(BN_bn2bin(bn_e
, e
) == (int) e_size
);
782 *ret_n
= TAKE_PTR(n
);
783 *ret_n_size
= n_size
;
784 *ret_e
= TAKE_PTR(e
);
785 *ret_e_size
= e_size
;
790 /* Generate ECC public key from provided curve ID and x/y points. */
791 int ecc_pkey_from_curve_x_y(
803 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= EVP_PKEY_CTX_new_id(EVP_PKEY_EC
, NULL
);
805 return log_openssl_errors("Failed to create new EVP_PKEY_CTX");
807 _cleanup_(BN_freep
) BIGNUM
*bn_x
= BN_bin2bn(x
, x_size
, NULL
);
809 return log_openssl_errors("Failed to create BIGNUM x");
811 _cleanup_(BN_freep
) BIGNUM
*bn_y
= BN_bin2bn(y
, y_size
, NULL
);
813 return log_openssl_errors("Failed to create BIGNUM y");
815 _cleanup_(EC_GROUP_freep
) EC_GROUP
*group
= EC_GROUP_new_by_curve_name(curve_id
);
817 return log_openssl_errors("ECC curve id %d not supported", curve_id
);
819 _cleanup_(EC_POINT_freep
) EC_POINT
*point
= EC_POINT_new(group
);
821 return log_openssl_errors("Failed to create new EC_POINT");
823 if (!EC_POINT_set_affine_coordinates(group
, point
, bn_x
, bn_y
, NULL
))
824 return log_openssl_errors("Failed to set ECC coordinates");
826 #if OPENSSL_VERSION_MAJOR >= 3
827 if (EVP_PKEY_fromdata_init(ctx
) <= 0)
828 return log_openssl_errors("Failed to initialize EVP_PKEY_CTX");
830 _cleanup_(OSSL_PARAM_BLD_freep
) OSSL_PARAM_BLD
*bld
= OSSL_PARAM_BLD_new();
832 return log_openssl_errors("Failed to create new OSSL_PARAM_BLD");
834 if (!OSSL_PARAM_BLD_push_utf8_string(bld
, OSSL_PKEY_PARAM_GROUP_NAME
, (char*) OSSL_EC_curve_nid2name(curve_id
), 0))
835 return log_openssl_errors("Failed to add ECC OSSL_PKEY_PARAM_GROUP_NAME");
837 _cleanup_(OPENSSL_freep
) void *pbuf
= NULL
;
839 pbuf_len
= EC_POINT_point2buf(group
, point
, POINT_CONVERSION_UNCOMPRESSED
, (unsigned char**) &pbuf
, NULL
);
841 return log_openssl_errors("Failed to convert ECC point to buffer");
843 if (!OSSL_PARAM_BLD_push_octet_string(bld
, OSSL_PKEY_PARAM_PUB_KEY
, pbuf
, pbuf_len
))
844 return log_openssl_errors("Failed to add ECC OSSL_PKEY_PARAM_PUB_KEY");
846 _cleanup_(OSSL_PARAM_freep
) OSSL_PARAM
*params
= OSSL_PARAM_BLD_to_param(bld
);
848 return log_openssl_errors("Failed to build ECC OSSL_PARAM");
850 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
851 if (EVP_PKEY_fromdata(ctx
, &pkey
, EVP_PKEY_PUBLIC_KEY
, params
) <= 0)
852 return log_openssl_errors("Failed to create ECC EVP_PKEY");
854 _cleanup_(EC_KEY_freep
) EC_KEY
*eckey
= EC_KEY_new();
856 return log_openssl_errors("Failed to create new EC_KEY");
858 if (!EC_KEY_set_group(eckey
, group
))
859 return log_openssl_errors("Failed to set ECC group");
861 if (!EC_KEY_set_public_key(eckey
, point
))
862 return log_openssl_errors("Failed to set ECC point");
864 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= EVP_PKEY_new();
866 return log_openssl_errors("Failed to create new EVP_PKEY");
868 if (!EVP_PKEY_assign_EC_KEY(pkey
, eckey
))
869 return log_openssl_errors("Failed to assign ECC key");
870 /* pkey owns this now, don't free */
874 *ret
= TAKE_PTR(pkey
);
879 int ecc_pkey_to_curve_x_y(
880 const EVP_PKEY
*pkey
,
885 size_t *ret_y_size
) {
887 _cleanup_(BN_freep
) BIGNUM
*bn_x
= NULL
, *bn_y
= NULL
;
892 #if OPENSSL_VERSION_MAJOR >= 3
894 if (!EVP_PKEY_get_utf8_string_param(pkey
, OSSL_PKEY_PARAM_GROUP_NAME
, NULL
, 0, &name_size
))
895 return log_openssl_errors("Failed to get ECC group name size");
897 _cleanup_free_
char *name
= new(char, name_size
+ 1);
899 return log_oom_debug();
901 if (!EVP_PKEY_get_utf8_string_param(pkey
, OSSL_PKEY_PARAM_GROUP_NAME
, name
, name_size
+ 1, NULL
))
902 return log_openssl_errors("Failed to get ECC group name");
904 curve_id
= OBJ_sn2nid(name
);
905 if (curve_id
== NID_undef
)
906 return log_openssl_errors("Failed to get ECC curve id");
908 if (!EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_EC_PUB_X
, &bn_x
))
909 return log_openssl_errors("Failed to get ECC point x");
911 if (!EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_EC_PUB_Y
, &bn_y
))
912 return log_openssl_errors("Failed to get ECC point y");
914 const EC_KEY
*eckey
= EVP_PKEY_get0_EC_KEY((EVP_PKEY
*) pkey
);
916 return log_openssl_errors("Failed to get EC_KEY");
918 const EC_GROUP
*group
= EC_KEY_get0_group(eckey
);
920 return log_openssl_errors("Failed to get EC_GROUP");
922 curve_id
= EC_GROUP_get_curve_name(group
);
923 if (curve_id
== NID_undef
)
924 return log_openssl_errors("Failed to get ECC curve id");
926 const EC_POINT
*point
= EC_KEY_get0_public_key(eckey
);
928 return log_openssl_errors("Failed to get EC_POINT");
933 return log_openssl_errors("Failed to create new BIGNUM");
935 if (!EC_POINT_get_affine_coordinates(group
, point
, bn_x
, bn_y
, NULL
))
936 return log_openssl_errors("Failed to get ECC x/y.");
939 size_t x_size
= BN_num_bytes(bn_x
), y_size
= BN_num_bytes(bn_y
);
940 _cleanup_free_
void *x
= malloc(x_size
), *y
= malloc(y_size
);
942 return log_oom_debug();
944 assert(BN_bn2bin(bn_x
, x
) == (int) x_size
);
945 assert(BN_bn2bin(bn_y
, y
) == (int) y_size
);
948 *ret_curve_id
= curve_id
;
950 *ret_x
= TAKE_PTR(x
);
952 *ret_x_size
= x_size
;
954 *ret_y
= TAKE_PTR(y
);
956 *ret_y_size
= y_size
;
961 /* Generate a new ECC key for the specified ECC curve id. */
962 int ecc_pkey_new(int curve_id
, EVP_PKEY
**ret
) {
965 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= EVP_PKEY_CTX_new_id(EVP_PKEY_EC
, NULL
);
967 return log_openssl_errors("Failed to create new EVP_PKEY_CTX");
969 if (EVP_PKEY_keygen_init(ctx
) <= 0)
970 return log_openssl_errors("Failed to initialize EVP_PKEY_CTX");
972 if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx
, curve_id
) <= 0)
973 return log_openssl_errors("Failed to set ECC curve %d", curve_id
);
975 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
976 if (EVP_PKEY_keygen(ctx
, &pkey
) <= 0)
977 return log_openssl_errors("Failed to generate ECC key");
979 *ret
= TAKE_PTR(pkey
);
984 /* Perform ECDH to derive an ECC shared secret between the provided private key and public peer key. For two
985 * keys, this will result in the same shared secret in either direction; ECDH using Alice's private key and
986 * Bob's public (peer) key will result in the same shared secret as ECDH using Bob's private key and Alice's
987 * public (peer) key. On success, this returns 0 and provides the shared secret; otherwise this returns an
989 int ecc_ecdh(const EVP_PKEY
*private_pkey
,
990 const EVP_PKEY
*peer_pkey
,
991 void **ret_shared_secret
,
992 size_t *ret_shared_secret_size
) {
994 assert(private_pkey
);
996 assert(ret_shared_secret
);
997 assert(ret_shared_secret_size
);
999 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= EVP_PKEY_CTX_new((EVP_PKEY
*) private_pkey
, NULL
);
1001 return log_openssl_errors("Failed to create new EVP_PKEY_CTX");
1003 if (EVP_PKEY_derive_init(ctx
) <= 0)
1004 return log_openssl_errors("Failed to initialize EVP_PKEY_CTX");
1006 if (EVP_PKEY_derive_set_peer(ctx
, (EVP_PKEY
*) peer_pkey
) <= 0)
1007 return log_openssl_errors("Failed to set ECC derive peer");
1009 size_t shared_secret_size
;
1010 if (EVP_PKEY_derive(ctx
, NULL
, &shared_secret_size
) <= 0)
1011 return log_openssl_errors("Failed to get ECC shared secret size");
1013 _cleanup_(erase_and_freep
) void *shared_secret
= malloc(shared_secret_size
);
1015 return log_oom_debug();
1017 if (EVP_PKEY_derive(ctx
, (unsigned char*) shared_secret
, &shared_secret_size
) <= 0)
1018 return log_openssl_errors("Failed to derive ECC shared secret");
1020 *ret_shared_secret
= TAKE_PTR(shared_secret
);
1021 *ret_shared_secret_size
= shared_secret_size
;
1026 int pubkey_fingerprint(EVP_PKEY
*pk
, const EVP_MD
*md
, void **ret
, size_t *ret_size
) {
1027 _cleanup_(EVP_MD_CTX_freep
) EVP_MD_CTX
* m
= NULL
;
1028 _cleanup_free_
void *d
= NULL
, *h
= NULL
;
1033 /* Calculates a message digest of the DER encoded public key */
1040 sz
= i2d_PublicKey(pk
, NULL
);
1042 return log_openssl_errors("Unable to convert public key to DER format");
1044 dd
= d
= malloc(sz
);
1046 return log_oom_debug();
1048 lsz
= i2d_PublicKey(pk
, &dd
);
1050 return log_openssl_errors("Unable to convert public key to DER format");
1052 m
= EVP_MD_CTX_new();
1054 return log_openssl_errors("Failed to create new EVP_MD_CTX");
1056 if (EVP_DigestInit_ex(m
, md
, NULL
) != 1)
1057 return log_openssl_errors("Failed to initialize %s context", EVP_MD_name(md
));
1059 if (EVP_DigestUpdate(m
, d
, lsz
) != 1)
1060 return log_openssl_errors("Failed to run %s context", EVP_MD_name(md
));
1062 msz
= EVP_MD_size(md
);
1067 return log_oom_debug();
1070 if (EVP_DigestFinal_ex(m
, h
, &umsz
) != 1)
1071 return log_openssl_errors("Failed to finalize hash context");
1073 assert(umsz
== (unsigned) msz
);
1081 int digest_and_sign(
1084 const void *data
, size_t size
,
1085 void **ret
, size_t *ret_size
) {
1094 data
= ""; /* make sure to pass a valid pointer to OpenSSL */
1098 if (size
== SIZE_MAX
) /* If SIZE_MAX input is a string whose size we determine automatically */
1099 size
= strlen(data
);
1102 _cleanup_(EVP_MD_CTX_freep
) EVP_MD_CTX
* mdctx
= EVP_MD_CTX_new();
1104 return log_openssl_errors("Failed to create new EVP_MD_CTX");
1106 if (EVP_DigestSignInit(mdctx
, NULL
, md
, NULL
, privkey
) != 1) {
1107 /* Distro security policies often disable support for SHA-1. Let's return a recognizable
1108 * error for that case. */
1109 bool invalid_digest
= ERR_GET_REASON(ERR_peek_last_error()) == EVP_R_INVALID_DIGEST
;
1110 r
= log_openssl_errors("Failed to initialize signature context");
1111 return invalid_digest
? -EADDRNOTAVAIL
: r
;
1114 /* Determine signature size */
1116 if (EVP_DigestSign(mdctx
, NULL
, &ss
, data
, size
) != 1)
1117 return log_openssl_errors("Failed to determine size of signature");
1119 _cleanup_free_
void *sig
= malloc(ss
);
1121 return log_oom_debug();
1123 if (EVP_DigestSign(mdctx
, sig
, &ss
, data
, size
) != 1)
1124 return log_openssl_errors("Failed to sign data");
1126 *ret
= TAKE_PTR(sig
);
1131 int pkcs7_new(X509
*certificate
, EVP_PKEY
*private_key
, const char *hash_algorithm
, PKCS7
**ret_p7
, PKCS7_SIGNER_INFO
**ret_si
) {
1132 assert(certificate
);
1135 /* This function sets up a new PKCS7 signing context. If a private key is provided, the context is
1136 * set up for "in-band" signing with PKCS7_dataFinal(). If a private key is not provided, the context
1137 * is set up for "out-of-band" signing, meaning the signature has to be provided by the user and
1138 * copied into the signer info's "enc_digest" field. If the signing hash algorithm is not provided,
1139 * SHA-256 is used. */
1141 _cleanup_(PKCS7_freep
) PKCS7
*p7
= PKCS7_new();
1145 if (PKCS7_set_type(p7
, NID_pkcs7_signed
) == 0)
1146 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to set PKCS7 type: %s",
1147 ERR_error_string(ERR_get_error(), NULL
));
1149 if (PKCS7_content_new(p7
, NID_pkcs7_data
) == 0)
1150 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to set PKCS7 content: %s",
1151 ERR_error_string(ERR_get_error(), NULL
));
1153 if (PKCS7_add_certificate(p7
, certificate
) == 0)
1154 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to set PKCS7 certificate: %s",
1155 ERR_error_string(ERR_get_error(), NULL
));
1158 if (X509_get_signature_info(certificate
, NULL
, &x509_pknid
, NULL
, NULL
) == 0)
1159 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to get X509 digest NID: %s",
1160 ERR_error_string(ERR_get_error(), NULL
));
1162 const EVP_MD
*md
= EVP_get_digestbyname(hash_algorithm
?: "SHA256");
1164 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to get digest algorithm '%s'",
1165 hash_algorithm
?: "SHA256");
1167 _cleanup_(PKCS7_SIGNER_INFO_freep
) PKCS7_SIGNER_INFO
*si
= PKCS7_SIGNER_INFO_new();
1172 if (PKCS7_SIGNER_INFO_set(si
, certificate
, private_key
, md
) <= 0)
1173 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to configure signer info: %s",
1174 ERR_error_string(ERR_get_error(), NULL
));
1176 if (ASN1_INTEGER_set(si
->version
, 1) == 0)
1177 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to set signer info version: %s",
1178 ERR_error_string(ERR_get_error(), NULL
));
1180 if (X509_NAME_set(&si
->issuer_and_serial
->issuer
, X509_get_issuer_name(certificate
)) == 0)
1181 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to set signer info issuer: %s",
1182 ERR_error_string(ERR_get_error(), NULL
));
1184 ASN1_INTEGER_free(si
->issuer_and_serial
->serial
);
1185 si
->issuer_and_serial
->serial
= ASN1_INTEGER_dup(X509_get0_serialNumber(certificate
));
1186 if (!si
->issuer_and_serial
->serial
)
1187 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to set signer info serial: %s",
1188 ERR_error_string(ERR_get_error(), NULL
));
1190 if (X509_ALGOR_set0(si
->digest_alg
, OBJ_nid2obj(EVP_MD_type(md
)), V_ASN1_NULL
, NULL
) == 0)
1191 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to set signer info digest algorithm: %s",
1192 ERR_error_string(ERR_get_error(), NULL
));
1194 if (X509_ALGOR_set0(si
->digest_enc_alg
, OBJ_nid2obj(x509_pknid
), V_ASN1_NULL
, NULL
) == 0)
1195 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to set signer info signing algorithm: %s",
1196 ERR_error_string(ERR_get_error(), NULL
));
1199 if (PKCS7_add_signer(p7
, si
) == 0)
1200 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to set PKCS7 signer info: %s",
1201 ERR_error_string(ERR_get_error(), NULL
));
1203 *ret_p7
= TAKE_PTR(p7
);
1205 /* We do not pass ownership here, 'si' object remains owned by 'p7' object. */
1216 const char *md_algorithm
,
1219 _cleanup_free_
void *hash
= NULL
;
1221 _cleanup_free_
char *enc
= NULL
;
1224 assert(s
|| len
== 0);
1225 assert(md_algorithm
);
1228 r
= openssl_digest(md_algorithm
, s
, len
, &hash
, &hash_size
);
1232 enc
= hexmem(hash
, hash_size
);
1236 *ret
= TAKE_PTR(enc
);
1240 static int ecc_pkey_generate_volume_keys(
1242 void **ret_decrypted_key
,
1243 size_t *ret_decrypted_key_size
,
1244 void **ret_saved_key
,
1245 size_t *ret_saved_key_size
) {
1247 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey_new
= NULL
;
1248 _cleanup_(erase_and_freep
) void *decrypted_key
= NULL
;
1249 _cleanup_free_
unsigned char *saved_key
= NULL
;
1250 size_t decrypted_key_size
, saved_key_size
;
1251 int nid
= NID_undef
;
1254 #if OPENSSL_VERSION_MAJOR >= 3
1255 _cleanup_free_
char *curve_name
= NULL
;
1258 if (EVP_PKEY_get_group_name(pkey
, NULL
, 0, &len
) != 1 || len
== 0)
1259 return log_openssl_errors("Failed to determine PKEY group name length");
1262 curve_name
= new(char, len
);
1264 return log_oom_debug();
1266 if (EVP_PKEY_get_group_name(pkey
, curve_name
, len
, &len
) != 1)
1267 return log_openssl_errors("Failed to get PKEY group name");
1269 nid
= OBJ_sn2nid(curve_name
);
1271 EC_KEY
*ec_key
= EVP_PKEY_get0_EC_KEY(pkey
);
1273 return log_openssl_errors("PKEY doesn't have EC_KEY associated");
1275 if (EC_KEY_check_key(ec_key
) != 1)
1276 return log_openssl_errors("EC_KEY associated with PKEY is not valid");
1278 nid
= EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key
));
1281 r
= ecc_pkey_new(nid
, &pkey_new
);
1283 return log_debug_errno(r
, "Failed to generate a new EC keypair: %m");
1285 r
= ecc_ecdh(pkey_new
, pkey
, &decrypted_key
, &decrypted_key_size
);
1287 return log_debug_errno(r
, "Failed to derive shared secret: %m");
1289 #if OPENSSL_VERSION_MAJOR >= 3
1290 /* EVP_PKEY_get1_encoded_public_key() always returns uncompressed format of EC points.
1291 See https://github.com/openssl/openssl/discussions/22835 */
1292 saved_key_size
= EVP_PKEY_get1_encoded_public_key(pkey_new
, &saved_key
);
1293 if (saved_key_size
== 0)
1294 return log_openssl_errors("Failed to convert the generated public key to SEC1 format");
1296 EC_KEY
*ec_key_new
= EVP_PKEY_get0_EC_KEY(pkey_new
);
1298 return log_openssl_errors("The generated key doesn't have associated EC_KEY");
1300 if (EC_KEY_check_key(ec_key_new
) != 1)
1301 return log_openssl_errors("EC_KEY associated with the generated key is not valid");
1303 saved_key_size
= EC_POINT_point2oct(EC_KEY_get0_group(ec_key_new
),
1304 EC_KEY_get0_public_key(ec_key_new
),
1305 POINT_CONVERSION_UNCOMPRESSED
,
1307 if (saved_key_size
== 0)
1308 return log_openssl_errors("Failed to determine size of the generated public key");
1310 saved_key
= malloc(saved_key_size
);
1312 return log_oom_debug();
1314 saved_key_size
= EC_POINT_point2oct(EC_KEY_get0_group(ec_key_new
),
1315 EC_KEY_get0_public_key(ec_key_new
),
1316 POINT_CONVERSION_UNCOMPRESSED
,
1317 saved_key
, saved_key_size
, NULL
);
1318 if (saved_key_size
== 0)
1319 return log_openssl_errors("Failed to convert the generated public key to SEC1 format");
1322 *ret_decrypted_key
= TAKE_PTR(decrypted_key
);
1323 *ret_decrypted_key_size
= decrypted_key_size
;
1324 *ret_saved_key
= TAKE_PTR(saved_key
);
1325 *ret_saved_key_size
= saved_key_size
;
1329 static int rsa_pkey_generate_volume_keys(
1331 void **ret_decrypted_key
,
1332 size_t *ret_decrypted_key_size
,
1333 void **ret_saved_key
,
1334 size_t *ret_saved_key_size
) {
1336 _cleanup_(erase_and_freep
) void *decrypted_key
= NULL
;
1337 _cleanup_free_
void *saved_key
= NULL
;
1338 size_t decrypted_key_size
, saved_key_size
;
1341 r
= rsa_pkey_to_suitable_key_size(pkey
, &decrypted_key_size
);
1343 return log_debug_errno(r
, "Failed to determine RSA public key size.");
1345 log_debug("Generating %zu bytes random key.", decrypted_key_size
);
1347 decrypted_key
= malloc(decrypted_key_size
);
1349 return log_oom_debug();
1351 r
= crypto_random_bytes(decrypted_key
, decrypted_key_size
);
1353 return log_debug_errno(r
, "Failed to generate random key: %m");
1355 r
= rsa_encrypt_bytes(pkey
, decrypted_key
, decrypted_key_size
, &saved_key
, &saved_key_size
);
1357 return log_debug_errno(r
, "Failed to encrypt random key: %m");
1359 *ret_decrypted_key
= TAKE_PTR(decrypted_key
);
1360 *ret_decrypted_key_size
= decrypted_key_size
;
1361 *ret_saved_key
= TAKE_PTR(saved_key
);
1362 *ret_saved_key_size
= saved_key_size
;
1366 int pkey_generate_volume_keys(
1368 void **ret_decrypted_key
,
1369 size_t *ret_decrypted_key_size
,
1370 void **ret_saved_key
,
1371 size_t *ret_saved_key_size
) {
1374 assert(ret_decrypted_key
);
1375 assert(ret_decrypted_key_size
);
1376 assert(ret_saved_key
);
1377 assert(ret_saved_key_size
);
1379 #if OPENSSL_VERSION_MAJOR >= 3
1380 int type
= EVP_PKEY_get_base_id(pkey
);
1382 int type
= EVP_PKEY_base_id(pkey
);
1387 return rsa_pkey_generate_volume_keys(pkey
, ret_decrypted_key
, ret_decrypted_key_size
, ret_saved_key
, ret_saved_key_size
);
1390 return ecc_pkey_generate_volume_keys(pkey
, ret_decrypted_key
, ret_decrypted_key_size
, ret_saved_key
, ret_saved_key_size
);
1393 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to determine a type of public key.");
1396 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Unsupported public key type: %s", OBJ_nid2sn(type
));
1400 static int load_key_from_provider(
1401 const char *provider
,
1402 const char *private_key_uri
,
1406 assert(private_key_uri
);
1409 #if OPENSSL_VERSION_MAJOR >= 3
1410 /* Load the provider so that this can work without any custom written configuration in /etc/.
1411 * Also load the 'default' as that seems to be the recommendation. */
1412 if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL
, provider
, /* retain_fallbacks= */ true))
1413 return log_openssl_errors("Failed to load OpenSSL provider '%s'", provider
);
1414 if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL
, "default", /* retain_fallbacks= */ true))
1415 return log_openssl_errors("Failed to load OpenSSL provider 'default'");
1417 _cleanup_(OSSL_STORE_closep
) OSSL_STORE_CTX
*store
= OSSL_STORE_open(
1419 /*ui_method=*/ NULL
,
1420 /*ui_method=*/ NULL
,
1421 /* post_process= */ NULL
,
1422 /* post_process_data= */ NULL
);
1424 return log_openssl_errors("Failed to open OpenSSL store via '%s'", private_key_uri
);
1426 if (OSSL_STORE_expect(store
, OSSL_STORE_INFO_PKEY
) == 0)
1427 return log_openssl_errors("Failed to filter store by private keys");
1429 _cleanup_(OSSL_STORE_INFO_freep
) OSSL_STORE_INFO
*info
= OSSL_STORE_load(store
);
1431 return log_openssl_errors("Failed to load OpenSSL store via '%s'", private_key_uri
);
1433 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*private_key
= OSSL_STORE_INFO_get1_PKEY(info
);
1435 return log_openssl_errors("Failed to load private key via '%s'", private_key_uri
);
1437 *ret
= TAKE_PTR(private_key
);
1445 static int load_key_from_engine(const char *engine
, const char *private_key_uri
, EVP_PKEY
**ret
) {
1447 assert(private_key_uri
);
1450 #if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0)
1451 DISABLE_WARNING_DEPRECATED_DECLARATIONS
;
1452 _cleanup_(ENGINE_freep
) ENGINE
*e
= ENGINE_by_id(engine
);
1454 return log_openssl_errors("Failed to load signing engine '%s'", engine
);
1456 if (ENGINE_init(e
) == 0)
1457 return log_openssl_errors("Failed to initialize signing engine '%s'", engine
);
1459 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*private_key
= ENGINE_load_private_key(e
, private_key_uri
, /*ui_method=*/ NULL
, /*callback_data=*/ NULL
);
1461 return log_openssl_errors("Failed to load private key from '%s'", private_key_uri
);
1464 *ret
= TAKE_PTR(private_key
);
1472 #ifndef OPENSSL_NO_UI_CONSOLE
1473 static int openssl_ask_password_ui_read(UI
*ui
, UI_STRING
*uis
) {
1476 switch(UI_get_string_type(uis
)) {
1478 /* If no ask password request was configured use the default openssl UI. */
1479 AskPasswordRequest
*req
= (AskPasswordRequest
*) UI_method_get_ex_data(UI_get_method(ui
), 0);
1481 return (UI_method_get_reader(UI_OpenSSL()))(ui
, uis
);
1483 req
->message
= UI_get0_output_string(uis
);
1485 _cleanup_strv_free_
char **l
= NULL
;
1486 r
= ask_password_auto(req
, ASK_PASSWORD_ACCEPT_CACHED
|ASK_PASSWORD_PUSH_CACHE
, &l
);
1488 log_error_errno(r
, "Failed to query for PIN: %m");
1492 if (strv_length(l
) != 1) {
1493 log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Expected only a single password/pin.");
1497 if (UI_set_result(ui
, uis
, *l
) != 0) {
1498 log_openssl_errors("Failed to set user interface result");
1505 return (UI_method_get_reader(UI_OpenSSL()))(ui
, uis
);
1510 static int openssl_load_private_key_from_file(const char *path
, EVP_PKEY
**ret
) {
1511 _cleanup_(erase_and_freep
) char *rawkey
= NULL
;
1512 _cleanup_(BIO_freep
) BIO
*kb
= NULL
;
1513 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pk
= NULL
;
1520 r
= read_full_file_full(
1521 AT_FDCWD
, path
, UINT64_MAX
, SIZE_MAX
,
1522 READ_FULL_FILE_SECURE
|READ_FULL_FILE_WARN_WORLD_READABLE
|READ_FULL_FILE_CONNECT_SOCKET
,
1524 &rawkey
, &rawkeysz
);
1526 return log_debug_errno(r
, "Failed to read key file '%s': %m", path
);
1528 kb
= BIO_new_mem_buf(rawkey
, rawkeysz
);
1530 return log_oom_debug();
1532 pk
= PEM_read_bio_PrivateKey(kb
, NULL
, NULL
, NULL
);
1534 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Failed to parse PEM private key: %s",
1535 ERR_error_string(ERR_get_error(), NULL
));
1538 *ret
= TAKE_PTR(pk
);
1543 static int openssl_ask_password_ui_new(const AskPasswordRequest
*request
, OpenSSLAskPasswordUI
**ret
) {
1546 #ifndef OPENSSL_NO_UI_CONSOLE
1547 _cleanup_(UI_destroy_methodp
) UI_METHOD
*method
= UI_create_method("systemd-ask-password");
1549 return log_openssl_errors("Failed to initialize openssl user interface");
1551 if (UI_method_set_reader(method
, openssl_ask_password_ui_read
) != 0)
1552 return log_openssl_errors("Failed to set openssl user interface reader");
1554 OpenSSLAskPasswordUI
*ui
= new(OpenSSLAskPasswordUI
, 1);
1556 return log_oom_debug();
1558 *ui
= (OpenSSLAskPasswordUI
) {
1559 .method
= TAKE_PTR(method
),
1560 .request
= *request
,
1563 UI_set_default_method(ui
->method
);
1565 if (UI_method_set_ex_data(ui
->method
, 0, &ui
->request
) == 0)
1566 return log_openssl_errors("Failed to set extra data for UI method");
1568 *ret
= TAKE_PTR(ui
);
1575 static int load_x509_certificate_from_file(const char *path
, X509
**ret
) {
1576 _cleanup_free_
char *rawcert
= NULL
;
1577 _cleanup_(X509_freep
) X509
*cert
= NULL
;
1578 _cleanup_(BIO_freep
) BIO
*cb
= NULL
;
1585 r
= read_full_file_full(
1586 AT_FDCWD
, path
, UINT64_MAX
, SIZE_MAX
,
1587 READ_FULL_FILE_CONNECT_SOCKET
,
1589 &rawcert
, &rawcertsz
);
1591 return log_debug_errno(r
, "Failed to read certificate file '%s': %m", path
);
1593 cb
= BIO_new_mem_buf(rawcert
, rawcertsz
);
1595 return log_oom_debug();
1597 cert
= PEM_read_bio_X509(cb
, NULL
, NULL
, NULL
);
1599 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG
), "Failed to parse X.509 certificate: %s",
1600 ERR_error_string(ERR_get_error(), NULL
));
1603 *ret
= TAKE_PTR(cert
);
1608 static int load_x509_certificate_from_provider(const char *provider
, const char *certificate_uri
, X509
**ret
) {
1610 assert(certificate_uri
);
1613 #if OPENSSL_VERSION_MAJOR >= 3
1614 /* Load the provider so that this can work without any custom written configuration in /etc/.
1615 * Also load the 'default' as that seems to be the recommendation. */
1616 if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL
, provider
, /* retain_fallbacks= */ true))
1617 return log_openssl_errors("Failed to load OpenSSL provider '%s'", provider
);
1618 if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL
, "default", /* retain_fallbacks= */ true))
1619 return log_openssl_errors("Failed to load OpenSSL provider 'default'");
1621 _cleanup_(OSSL_STORE_closep
) OSSL_STORE_CTX
*store
= OSSL_STORE_open(
1623 /*ui_method=*/ NULL
,
1624 /*ui_method=*/ NULL
,
1625 /* post_process= */ NULL
,
1626 /* post_process_data= */ NULL
);
1628 return log_openssl_errors("Failed to open OpenSSL store via '%s'", certificate_uri
);
1630 if (OSSL_STORE_expect(store
, OSSL_STORE_INFO_CERT
) == 0)
1631 return log_openssl_errors("Failed to filter store by X.509 certificates");
1633 _cleanup_(OSSL_STORE_INFO_freep
) OSSL_STORE_INFO
*info
= OSSL_STORE_load(store
);
1635 return log_openssl_errors("Failed to load OpenSSL store via '%s'", certificate_uri
);
1637 _cleanup_(X509_freep
) X509
*cert
= OSSL_STORE_INFO_get1_CERT(info
);
1639 return log_openssl_errors("Failed to load certificate via '%s'", certificate_uri
);
1641 *ret
= TAKE_PTR(cert
);
1650 OpenSSLAskPasswordUI
* openssl_ask_password_ui_free(OpenSSLAskPasswordUI
*ui
) {
1651 #if HAVE_OPENSSL && !defined(OPENSSL_NO_UI_CONSOLE)
1655 assert(UI_get_default_method() == ui
->method
);
1656 UI_set_default_method(UI_OpenSSL());
1657 UI_destroy_method(ui
->method
);
1665 int x509_fingerprint(X509
*cert
, uint8_t buffer
[static SHA256_DIGEST_SIZE
]) {
1667 _cleanup_free_
uint8_t *der
= NULL
;
1672 dersz
= i2d_X509(cert
, &der
);
1674 return log_openssl_errors("Unable to convert PEM certificate to DER format");
1676 sha256_direct(der
, dersz
, buffer
);
1679 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL is not supported, cannot calculate X509 fingerprint.");
1683 int openssl_load_x509_certificate(
1684 CertificateSourceType certificate_source_type
,
1685 const char *certificate_source
,
1686 const char *certificate
,
1691 assert(certificate
);
1693 switch (certificate_source_type
) {
1695 case OPENSSL_CERTIFICATE_SOURCE_FILE
:
1696 r
= load_x509_certificate_from_file(certificate
, ret
);
1698 case OPENSSL_CERTIFICATE_SOURCE_PROVIDER
:
1699 r
= load_x509_certificate_from_provider(certificate_source
, certificate
, ret
);
1702 assert_not_reached();
1705 return log_debug_errno(
1707 "Failed to load certificate '%s' from OpenSSL certificate source %s: %m",
1709 certificate_source
);
1713 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL is not supported, cannot load X509 certificate.");
1717 int openssl_load_private_key(
1718 KeySourceType private_key_source_type
,
1719 const char *private_key_source
,
1720 const char *private_key
,
1721 const AskPasswordRequest
*request
,
1722 EVP_PKEY
**ret_private_key
,
1723 OpenSSLAskPasswordUI
**ret_user_interface
) {
1727 assert(private_key
);
1730 if (private_key_source_type
== OPENSSL_KEY_SOURCE_FILE
) {
1731 r
= openssl_load_private_key_from_file(private_key
, ret_private_key
);
1735 *ret_user_interface
= NULL
;
1737 _cleanup_(openssl_ask_password_ui_freep
) OpenSSLAskPasswordUI
*ui
= NULL
;
1738 r
= openssl_ask_password_ui_new(request
, &ui
);
1740 return log_debug_errno(r
, "Failed to allocate ask-password user interface: %m");
1742 switch (private_key_source_type
) {
1744 case OPENSSL_KEY_SOURCE_ENGINE
:
1745 r
= load_key_from_engine(private_key_source
, private_key
, ret_private_key
);
1747 case OPENSSL_KEY_SOURCE_PROVIDER
:
1748 r
= load_key_from_provider(private_key_source
, private_key
, ret_private_key
);
1751 assert_not_reached();
1754 return log_debug_errno(
1756 "Failed to load key '%s' from OpenSSL private key source %s: %m",
1758 private_key_source
);
1760 *ret_user_interface
= TAKE_PTR(ui
);
1765 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "OpenSSL is not supported, cannot load private key.");
1769 int parse_openssl_certificate_source_argument(
1770 const char *argument
,
1771 char **certificate_source
,
1772 CertificateSourceType
*certificate_source_type
) {
1774 CertificateSourceType type
;
1775 const char *e
= NULL
;
1779 assert(certificate_source
);
1780 assert(certificate_source_type
);
1782 if (streq(argument
, "file"))
1783 type
= OPENSSL_CERTIFICATE_SOURCE_FILE
;
1784 else if ((e
= startswith(argument
, "provider:")))
1785 type
= OPENSSL_CERTIFICATE_SOURCE_PROVIDER
;
1787 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid certificate source '%s'", argument
);
1789 r
= free_and_strdup_warn(certificate_source
, e
);
1793 *certificate_source_type
= type
;
1798 int parse_openssl_key_source_argument(
1799 const char *argument
,
1800 char **private_key_source
,
1801 KeySourceType
*private_key_source_type
) {
1804 const char *e
= NULL
;
1808 assert(private_key_source
);
1809 assert(private_key_source_type
);
1811 if (streq(argument
, "file"))
1812 type
= OPENSSL_KEY_SOURCE_FILE
;
1813 else if ((e
= startswith(argument
, "engine:")))
1814 type
= OPENSSL_KEY_SOURCE_ENGINE
;
1815 else if ((e
= startswith(argument
, "provider:")))
1816 type
= OPENSSL_KEY_SOURCE_PROVIDER
;
1818 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Invalid private key source '%s'", argument
);
1820 r
= free_and_strdup_warn(private_key_source
, e
);
1824 *private_key_source_type
= type
;