1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "openssl-util.h"
#include "alloc-util.h"
#if HAVE_OPENSSL
int rsa_encrypt_bytes(
EVP_PKEY *pkey,
const void *decrypted_key,
size_t decrypted_key_size,
void **ret_encrypt_key,
size_t *ret_encrypt_key_size) {
_cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = NULL;
_cleanup_free_ void *b = NULL;
size_t l;
ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!ctx)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to allocate public key context");
if (EVP_PKEY_encrypt_init(ctx) <= 0)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to initialize public key context");
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to configure PKCS#1 padding");
if (EVP_PKEY_encrypt(ctx, NULL, &l, decrypted_key, decrypted_key_size) <= 0)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to determine encrypted key size");
b = malloc(l);
if (!b)
return -ENOMEM;
if (EVP_PKEY_encrypt(ctx, b, &l, decrypted_key, decrypted_key_size) <= 0)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to determine encrypted key size");
*ret_encrypt_key = TAKE_PTR(b);
*ret_encrypt_key_size = l;
return 0;
}
int rsa_pkey_to_suitable_key_size(
EVP_PKEY *pkey,
size_t *ret_suitable_key_size) {
size_t suitable_key_size;
RSA *rsa;
int bits;
assert_se(pkey);
assert_se(ret_suitable_key_size);
/* Analyzes the specified public key and that it is RSA. If so, will return a suitable size for a
* disk encryption key to encrypt with RSA for use in PKCS#11 security token schemes. */
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA)
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "X.509 certificate does not refer to RSA key.");
rsa = EVP_PKEY_get0_RSA(pkey);
if (!rsa)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to acquire RSA public key from X.509 certificate.");
bits = RSA_bits(rsa);
log_debug("Bits in RSA key: %i", bits);
/* We use PKCS#1 padding for the RSA cleartext, hence let's leave some extra space for it, hence only
* generate a random key half the size of the RSA length */
suitable_key_size = bits / 8 / 2;
if (suitable_key_size < 1)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Uh, RSA key size too short?");
*ret_suitable_key_size = suitable_key_size;
return 0;
}
#endif
|