1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include "openssl-util.h"
5 #include "alloc-util.h"
9 /* For each error in the the Openssl thread error queue, log the provided message and the Openssl error
10 * string. If there are no errors in the Openssl thread queue, this logs the message with "No openssl
11 * errors." This logs at level debug. Returns -EIO (or -ENOMEM). */
12 #define log_openssl_errors(fmt, ...) _log_openssl_errors(UNIQ, fmt, ##__VA_ARGS__)
13 #define _log_openssl_errors(u, fmt, ...) \
15 size_t UNIQ_T(MAX, u) = 512 /* arbitrary, but openssl doc states it must be >= 256 */; \
16 _cleanup_free_ char *UNIQ_T(BUF, u) = malloc(UNIQ_T(MAX, u)); \
19 : __log_openssl_errors(u, UNIQ_T(BUF, u), UNIQ_T(MAX, u), fmt, ##__VA_ARGS__) \
20 ?: log_debug_errno(SYNTHETIC_ERRNO(EIO), fmt ": No openssl errors.", ##__VA_ARGS__); \
22 #define __log_openssl_errors(u, buf, max, fmt, ...) \
24 int UNIQ_T(R, u) = 0; \
26 unsigned long UNIQ_T(E, u) = ERR_get_error(); \
27 if (UNIQ_T(E, u) == 0) \
29 ERR_error_string_n(UNIQ_T(E, u), buf, max); \
30 UNIQ_T(R, u) = log_debug_errno(SYNTHETIC_ERRNO(EIO), fmt ": %s", ##__VA_ARGS__, buf); \
35 int openssl_pkey_from_pem(const void *pem
, size_t pem_size
, EVP_PKEY
**ret
) {
39 _cleanup_fclose_
FILE *f
= NULL
;
40 f
= fmemopen((void*) pem
, pem_size
, "r");
42 return log_oom_debug();
44 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= PEM_read_PUBKEY(f
, NULL
, NULL
, NULL
);
46 return log_openssl_errors("Failed to parse PEM");
48 *ret
= TAKE_PTR(pkey
);
53 int openssl_hash(const EVP_MD
*alg
,
57 size_t *ret_hash_len
) {
59 _cleanup_(EVP_MD_CTX_freep
) EVP_MD_CTX
*ctx
= NULL
;
63 ctx
= EVP_MD_CTX_new();
65 /* This function just calls OPENSSL_zalloc, so failure
66 * here is almost certainly a failed allocation. */
69 /* The documentation claims EVP_DigestInit behaves just like
70 * EVP_DigestInit_ex if passed NULL, except it also calls
71 * EVP_MD_CTX_reset, which deinitializes the context. */
72 r
= EVP_DigestInit_ex(ctx
, alg
, NULL
);
76 r
= EVP_DigestUpdate(ctx
, msg
, msg_len
);
80 r
= EVP_DigestFinal_ex(ctx
, ret_hash
, &len
);
90 int rsa_encrypt_bytes(
92 const void *decrypted_key
,
93 size_t decrypted_key_size
,
94 void **ret_encrypt_key
,
95 size_t *ret_encrypt_key_size
) {
97 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= NULL
;
98 _cleanup_free_
void *b
= NULL
;
101 ctx
= EVP_PKEY_CTX_new(pkey
, NULL
);
103 return log_openssl_errors("Failed to allocate public key context");
105 if (EVP_PKEY_encrypt_init(ctx
) <= 0)
106 return log_openssl_errors("Failed to initialize public key context");
108 if (EVP_PKEY_CTX_set_rsa_padding(ctx
, RSA_PKCS1_PADDING
) <= 0)
109 return log_openssl_errors("Failed to configure PKCS#1 padding");
111 if (EVP_PKEY_encrypt(ctx
, NULL
, &l
, decrypted_key
, decrypted_key_size
) <= 0)
112 return log_openssl_errors("Failed to determine encrypted key size");
118 if (EVP_PKEY_encrypt(ctx
, b
, &l
, decrypted_key
, decrypted_key_size
) <= 0)
119 return log_openssl_errors("Failed to determine encrypted key size");
121 *ret_encrypt_key
= TAKE_PTR(b
);
122 *ret_encrypt_key_size
= l
;
127 int rsa_pkey_to_suitable_key_size(
129 size_t *ret_suitable_key_size
) {
131 size_t suitable_key_size
;
135 assert(ret_suitable_key_size
);
137 /* Analyzes the specified public key and that it is RSA. If so, will return a suitable size for a
138 * disk encryption key to encrypt with RSA for use in PKCS#11 security token schemes. */
140 if (EVP_PKEY_base_id(pkey
) != EVP_PKEY_RSA
)
141 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG
), "X.509 certificate does not refer to RSA key.");
143 bits
= EVP_PKEY_bits(pkey
);
144 log_debug("Bits in RSA key: %i", bits
);
146 /* We use PKCS#1 padding for the RSA cleartext, hence let's leave some extra space for it, hence only
147 * generate a random key half the size of the RSA length */
148 suitable_key_size
= bits
/ 8 / 2;
150 if (suitable_key_size
< 1)
151 return log_debug_errno(SYNTHETIC_ERRNO(EIO
), "Uh, RSA key size too short?");
153 *ret_suitable_key_size
= suitable_key_size
;
157 /* Generate RSA public key from provided "n" and "e" values. Note that if "e" is a number (e.g. uint32_t), it
158 * must be provided here big-endian, e.g. wrap it with htobe32(). */
159 int rsa_pkey_from_n_e(const void *n
, size_t n_size
, const void *e
, size_t e_size
, EVP_PKEY
**ret
) {
160 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
166 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= EVP_PKEY_CTX_new_id(EVP_PKEY_RSA
, NULL
);
168 return log_openssl_errors("Failed to create new EVP_PKEY_CTX");
170 _cleanup_(BN_freep
) BIGNUM
*bn_n
= BN_bin2bn(n
, n_size
, NULL
);
172 return log_openssl_errors("Failed to create BIGNUM for RSA n");
174 _cleanup_(BN_freep
) BIGNUM
*bn_e
= BN_bin2bn(e
, e_size
, NULL
);
176 return log_openssl_errors("Failed to create BIGNUM for RSA e");
178 #if OPENSSL_VERSION_MAJOR >= 3
179 if (EVP_PKEY_fromdata_init(ctx
) <= 0)
180 return log_openssl_errors("Failed to initialize EVP_PKEY_CTX");
182 _cleanup_(OSSL_PARAM_BLD_freep
) OSSL_PARAM_BLD
*bld
= OSSL_PARAM_BLD_new();
184 return log_openssl_errors("Failed to create new OSSL_PARAM_BLD");
186 if (!OSSL_PARAM_BLD_push_BN(bld
, OSSL_PKEY_PARAM_RSA_N
, bn_n
))
187 return log_openssl_errors("Failed to set RSA OSSL_PKEY_PARAM_RSA_N");
189 if (!OSSL_PARAM_BLD_push_BN(bld
, OSSL_PKEY_PARAM_RSA_E
, bn_e
))
190 return log_openssl_errors("Failed to set RSA OSSL_PKEY_PARAM_RSA_E");
192 _cleanup_(OSSL_PARAM_freep
) OSSL_PARAM
*params
= OSSL_PARAM_BLD_to_param(bld
);
194 return log_openssl_errors("Failed to build RSA OSSL_PARAM");
196 if (EVP_PKEY_fromdata(ctx
, &pkey
, EVP_PKEY_PUBLIC_KEY
, params
) <= 0)
197 return log_openssl_errors("Failed to create RSA EVP_PKEY");
199 _cleanup_(RSA_freep
) RSA
*rsa_key
= RSA_new();
201 return log_openssl_errors("Failed to create new RSA");
203 if (!RSA_set0_key(rsa_key
, bn_n
, bn_e
, NULL
))
204 return log_openssl_errors("Failed to set RSA n/e");
205 /* rsa_key owns these now, don't free */
209 pkey
= EVP_PKEY_new();
211 return log_openssl_errors("Failed to create new EVP_PKEY");
213 if (!EVP_PKEY_assign_RSA(pkey
, rsa_key
))
214 return log_openssl_errors("Failed to assign RSA key");
215 /* pkey owns this now, don't free */
219 *ret
= TAKE_PTR(pkey
);
224 /* Get the "n" and "e" values from the pkey. The values are returned in "bin" format, i.e. BN_bn2bin(). */
226 const EVP_PKEY
*pkey
,
230 size_t *ret_e_size
) {
238 #if OPENSSL_VERSION_MAJOR >= 3
239 _cleanup_(BN_freep
) BIGNUM
*bn_n
= NULL
;
240 if (!EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_RSA_N
, &bn_n
))
241 return log_openssl_errors("Failed to get RSA n");
243 _cleanup_(BN_freep
) BIGNUM
*bn_e
= NULL
;
244 if (!EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_RSA_E
, &bn_e
))
245 return log_openssl_errors("Failed to get RSA e");
247 const RSA
*rsa
= EVP_PKEY_get0_RSA((EVP_PKEY
*) pkey
);
249 return log_openssl_errors("Failed to get RSA key from public key");
251 const BIGNUM
*bn_n
= RSA_get0_n(rsa
);
253 return log_openssl_errors("Failed to get RSA n");
255 const BIGNUM
*bn_e
= RSA_get0_e(rsa
);
257 return log_openssl_errors("Failed to get RSA e");
260 size_t n_size
= BN_num_bytes(bn_n
), e_size
= BN_num_bytes(bn_e
);
261 _cleanup_free_
void *n
= malloc(n_size
), *e
= malloc(e_size
);
263 return log_oom_debug();
265 assert(BN_bn2bin(bn_n
, n
) == (int) n_size
);
266 assert(BN_bn2bin(bn_e
, e
) == (int) e_size
);
268 *ret_n
= TAKE_PTR(n
);
269 *ret_n_size
= n_size
;
270 *ret_e
= TAKE_PTR(e
);
271 *ret_e_size
= e_size
;
276 /* Generate a new RSA key with the specified number of bits. */
277 int rsa_pkey_new(size_t bits
, EVP_PKEY
**ret
) {
280 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= EVP_PKEY_CTX_new_id(EVP_PKEY_RSA
, NULL
);
282 return log_openssl_errors("Failed to create new EVP_PKEY_CTX");
284 if (EVP_PKEY_keygen_init(ctx
) <= 0)
285 return log_openssl_errors("Failed to initialize EVP_PKEY_CTX");
287 if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx
, (int) bits
) <= 0)
288 return log_openssl_errors("Failed to set RSA bits to %zu", bits
);
290 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
291 if (EVP_PKEY_keygen(ctx
, &pkey
) <= 0)
292 return log_openssl_errors("Failed to generate ECC key");
294 *ret
= TAKE_PTR(pkey
);
299 /* Generate ECC public key from provided curve ID and x/y points. */
300 int ecc_pkey_from_curve_x_y(
312 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= EVP_PKEY_CTX_new_id(EVP_PKEY_EC
, NULL
);
314 return log_openssl_errors("Failed to create new EVP_PKEY_CTX");
316 _cleanup_(BN_freep
) BIGNUM
*bn_x
= BN_bin2bn(x
, x_size
, NULL
);
318 return log_openssl_errors("Failed to create BIGNUM x");
320 _cleanup_(BN_freep
) BIGNUM
*bn_y
= BN_bin2bn(y
, y_size
, NULL
);
322 return log_openssl_errors("Failed to create BIGNUM y");
324 _cleanup_(EC_GROUP_freep
) EC_GROUP
*group
= EC_GROUP_new_by_curve_name(curve_id
);
326 return log_openssl_errors("ECC curve id %d not supported", curve_id
);
328 _cleanup_(EC_POINT_freep
) EC_POINT
*point
= EC_POINT_new(group
);
330 return log_openssl_errors("Failed to create new EC_POINT");
332 if (!EC_POINT_set_affine_coordinates(group
, point
, bn_x
, bn_y
, NULL
))
333 return log_openssl_errors("Failed to set ECC coordinates");
335 #if OPENSSL_VERSION_MAJOR >= 3
336 if (EVP_PKEY_fromdata_init(ctx
) <= 0)
337 return log_openssl_errors("Failed to initialize EVP_PKEY_CTX");
339 _cleanup_(OSSL_PARAM_BLD_freep
) OSSL_PARAM_BLD
*bld
= OSSL_PARAM_BLD_new();
341 return log_openssl_errors("Failed to create new OSSL_PARAM_BLD");
343 if (!OSSL_PARAM_BLD_push_utf8_string(bld
, OSSL_PKEY_PARAM_GROUP_NAME
, (char*) OSSL_EC_curve_nid2name(curve_id
), 0))
344 return log_openssl_errors("Failed to add ECC OSSL_PKEY_PARAM_GROUP_NAME");
346 _cleanup_(OPENSSL_freep
) void *pbuf
= NULL
;
348 pbuf_len
= EC_POINT_point2buf(group
, point
, POINT_CONVERSION_UNCOMPRESSED
, (unsigned char**) &pbuf
, NULL
);
350 return log_openssl_errors("Failed to convert ECC point to buffer");
352 if (!OSSL_PARAM_BLD_push_octet_string(bld
, OSSL_PKEY_PARAM_PUB_KEY
, pbuf
, pbuf_len
))
353 return log_openssl_errors("Failed to add ECC OSSL_PKEY_PARAM_PUB_KEY");
355 _cleanup_(OSSL_PARAM_freep
) OSSL_PARAM
*params
= OSSL_PARAM_BLD_to_param(bld
);
357 return log_openssl_errors("Failed to build ECC OSSL_PARAM");
359 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
360 if (EVP_PKEY_fromdata(ctx
, &pkey
, EVP_PKEY_PUBLIC_KEY
, params
) <= 0)
361 return log_openssl_errors("Failed to create ECC EVP_PKEY");
363 _cleanup_(EC_KEY_freep
) EC_KEY
*eckey
= EC_KEY_new();
365 return log_openssl_errors("Failed to create new EC_KEY");
367 if (!EC_KEY_set_group(eckey
, group
))
368 return log_openssl_errors("Failed to set ECC group");
370 if (!EC_KEY_set_public_key(eckey
, point
))
371 return log_openssl_errors("Failed to set ECC point");
373 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= EVP_PKEY_new();
375 return log_openssl_errors("Failed to create new EVP_PKEY");
377 if (!EVP_PKEY_assign_EC_KEY(pkey
, eckey
))
378 return log_openssl_errors("Failed to assign ECC key");
379 /* pkey owns this now, don't free */
383 *ret
= TAKE_PTR(pkey
);
388 int ecc_pkey_to_curve_x_y(
389 const EVP_PKEY
*pkey
,
394 size_t *ret_y_size
) {
396 _cleanup_(BN_freep
) BIGNUM
*bn_x
= NULL
, *bn_y
= NULL
;
401 #if OPENSSL_VERSION_MAJOR >= 3
403 if (!EVP_PKEY_get_utf8_string_param(pkey
, OSSL_PKEY_PARAM_GROUP_NAME
, NULL
, 0, &name_size
))
404 return log_openssl_errors("Failed to get ECC group name size");
406 _cleanup_free_
char *name
= new(char, name_size
+ 1);
408 return log_oom_debug();
410 if (!EVP_PKEY_get_utf8_string_param(pkey
, OSSL_PKEY_PARAM_GROUP_NAME
, name
, name_size
+ 1, NULL
))
411 return log_openssl_errors("Failed to get ECC group name");
413 curve_id
= OBJ_sn2nid(name
);
414 if (curve_id
== NID_undef
)
415 return log_openssl_errors("Failed to get ECC curve id");
417 if (!EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_EC_PUB_X
, &bn_x
))
418 return log_openssl_errors("Failed to get ECC point x");
420 if (!EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_EC_PUB_Y
, &bn_y
))
421 return log_openssl_errors("Failed to get ECC point y");
423 const EC_KEY
*eckey
= EVP_PKEY_get0_EC_KEY((EVP_PKEY
*) pkey
);
425 return log_openssl_errors("Failed to get EC_KEY");
427 const EC_GROUP
*group
= EC_KEY_get0_group(eckey
);
429 return log_openssl_errors("Failed to get EC_GROUP");
431 curve_id
= EC_GROUP_get_curve_name(group
);
432 if (curve_id
== NID_undef
)
433 return log_openssl_errors("Failed to get ECC curve id");
435 const EC_POINT
*point
= EC_KEY_get0_public_key(eckey
);
437 return log_openssl_errors("Failed to get EC_POINT");
442 return log_openssl_errors("Failed to create new BIGNUM");
444 if (!EC_POINT_get_affine_coordinates(group
, point
, bn_x
, bn_y
, NULL
))
445 return log_openssl_errors("Failed to get ECC x/y.");
448 size_t x_size
= BN_num_bytes(bn_x
), y_size
= BN_num_bytes(bn_y
);
449 _cleanup_free_
void *x
= malloc(x_size
), *y
= malloc(y_size
);
451 return log_oom_debug();
453 assert(BN_bn2bin(bn_x
, x
) == (int) x_size
);
454 assert(BN_bn2bin(bn_y
, y
) == (int) y_size
);
457 *ret_curve_id
= curve_id
;
459 *ret_x
= TAKE_PTR(x
);
461 *ret_x_size
= x_size
;
463 *ret_y
= TAKE_PTR(y
);
465 *ret_y_size
= y_size
;
470 /* Generate a new ECC key for the specified ECC curve id. */
471 int ecc_pkey_new(int curve_id
, EVP_PKEY
**ret
) {
474 _cleanup_(EVP_PKEY_CTX_freep
) EVP_PKEY_CTX
*ctx
= EVP_PKEY_CTX_new_id(EVP_PKEY_EC
, NULL
);
476 return log_openssl_errors("Failed to create new EVP_PKEY_CTX");
478 if (EVP_PKEY_keygen_init(ctx
) <= 0)
479 return log_openssl_errors("Failed to initialize EVP_PKEY_CTX");
481 if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx
, curve_id
) <= 0)
482 return log_openssl_errors("Failed to set ECC curve %d", curve_id
);
484 _cleanup_(EVP_PKEY_freep
) EVP_PKEY
*pkey
= NULL
;
485 if (EVP_PKEY_keygen(ctx
, &pkey
) <= 0)
486 return log_openssl_errors("Failed to generate ECC key");
488 *ret
= TAKE_PTR(pkey
);
493 int pubkey_fingerprint(EVP_PKEY
*pk
, const EVP_MD
*md
, void **ret
, size_t *ret_size
) {
494 _cleanup_(EVP_MD_CTX_freep
) EVP_MD_CTX
* m
= NULL
;
495 _cleanup_free_
void *d
= NULL
, *h
= NULL
;
500 /* Calculates a message digest of the DER encoded public key */
507 sz
= i2d_PublicKey(pk
, NULL
);
509 return log_openssl_errors("Unable to convert public key to DER format");
513 return log_oom_debug();
515 lsz
= i2d_PublicKey(pk
, &dd
);
517 return log_openssl_errors("Unable to convert public key to DER format");
519 m
= EVP_MD_CTX_new();
521 return log_openssl_errors("Failed to create new EVP_MD_CTX");
523 if (EVP_DigestInit_ex(m
, md
, NULL
) != 1)
524 return log_openssl_errors("Failed to initialize %s context", EVP_MD_name(md
));
526 if (EVP_DigestUpdate(m
, d
, lsz
) != 1)
527 return log_openssl_errors("Failed to run %s context", EVP_MD_name(md
));
529 msz
= EVP_MD_size(md
);
534 return log_oom_debug();
537 if (EVP_DigestFinal_ex(m
, h
, &umsz
) != 1)
538 return log_openssl_errors("Failed to finalize hash context");
540 assert(umsz
== (unsigned) msz
);
552 const EVP_MD
*md_algorithm
,
555 uint8_t hash
[EVP_MAX_MD_SIZE
];
560 hash_size
= EVP_MD_size(md_algorithm
);
561 assert(hash_size
> 0);
563 r
= openssl_hash(md_algorithm
, s
, len
, hash
, NULL
);
567 enc
= hexmem(hash
, hash_size
);
578 int x509_fingerprint(X509
*cert
, uint8_t buffer
[static SHA256_DIGEST_SIZE
]) {
580 _cleanup_free_
uint8_t *der
= NULL
;
585 dersz
= i2d_X509(cert
, &der
);
587 return log_openssl_errors("Unable to convert PEM certificate to DER format");
589 sha256_direct(der
, dersz
, buffer
);
592 return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "openssl is not supported, cannot calculate X509 fingerprint: %m");