2 rsa.c -- RSA key handling
3 Copyright (C) 2007-2022 Guus Sliepen <guus@tinc-vpn.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "../system.h"
22 #include <openssl/pem.h>
23 #include <openssl/rsa.h>
25 #define TINC_RSA_INTERNAL
27 #if OPENSSL_VERSION_MAJOR < 3
30 #include <openssl/encoder.h>
31 #include <openssl/decoder.h>
32 #include <openssl/core_names.h>
33 #include <openssl/param_build.h>
36 typedef EVP_PKEY rsa_t;
40 #include "../logger.h"
45 #if OPENSSL_VERSION_MAJOR >= 3
46 static EVP_PKEY *build_rsa_key(int selection, const BIGNUM *bn_n, const BIGNUM *bn_e, const BIGNUM *bn_d) {
50 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
53 openssl_err("initialize key context");
57 OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
58 OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, bn_n);
59 OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, bn_e);
62 OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_D, bn_d);
65 OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld);
68 bool ok = EVP_PKEY_fromdata_init(ctx) > 0
69 && EVP_PKEY_fromdata(ctx, &key, selection, params) > 0;
71 OSSL_PARAM_free(params);
72 OSSL_PARAM_BLD_free(bld);
73 EVP_PKEY_CTX_free(ctx);
79 openssl_err("build key");
84 static bool hex_to_bn(BIGNUM **bn, const char *hex) {
85 return (size_t)BN_hex2bn(bn, hex) == strlen(hex);
88 static rsa_t *rsa_set_hex_key(const char *n, const char *e, const char *d) {
94 if(!hex_to_bn(&bn_n, n) || !hex_to_bn(&bn_e, e) || (d && !hex_to_bn(&bn_d, d))) {
98 #if OPENSSL_VERSION_MAJOR < 3
102 RSA_set0_key(rsa, bn_n, bn_e, bn_d);
106 int selection = bn_d ? EVP_PKEY_KEYPAIR : EVP_PKEY_PUBLIC_KEY;
107 rsa = build_rsa_key(selection, bn_n, bn_e, bn_d);
111 #if OPENSSL_VERSION_MAJOR < 3
124 rsa_t *rsa_set_hex_public_key(const char *n, const char *e) {
125 return rsa_set_hex_key(n, e, NULL);
128 rsa_t *rsa_set_hex_private_key(const char *n, const char *e, const char *d) {
129 return rsa_set_hex_key(n, e, d);
134 #if OPENSSL_VERSION_MAJOR >= 3
135 static rsa_t *read_key_from_pem(FILE *fp, int selection) {
137 OSSL_DECODER_CTX *ctx = OSSL_DECODER_CTX_new_for_pkey(&rsa, "PEM", NULL, "RSA", selection, NULL, NULL);
140 openssl_err("initialize decoder");
144 bool ok = OSSL_DECODER_from_fp(ctx, fp);
145 OSSL_DECODER_CTX_free(ctx);
149 openssl_err("read RSA key from file");
156 rsa_t *rsa_read_pem_public_key(FILE *fp) {
159 #if OPENSSL_VERSION_MAJOR < 3
160 rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL);
164 rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
168 rsa = read_key_from_pem(fp, OSSL_KEYMGMT_SELECT_PUBLIC_KEY);
172 openssl_err("read RSA public key");
178 rsa_t *rsa_read_pem_private_key(FILE *fp) {
181 #if OPENSSL_VERSION_MAJOR < 3
182 rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
184 rsa = read_key_from_pem(fp, OSSL_KEYMGMT_SELECT_PRIVATE_KEY);
188 openssl_err("read RSA private key");
194 size_t rsa_size(const rsa_t *rsa) {
195 #if OPENSSL_VERSION_MAJOR < 3
196 return RSA_size(rsa);
198 return EVP_PKEY_get_size(rsa);
202 #if OPENSSL_VERSION_MAJOR >= 3
203 // Initialize encryption or decryption context. Must return >0 on success, ≤0 on failure.
204 typedef int (enc_init_t)(EVP_PKEY_CTX *ctx);
206 // Encrypt or decrypt data. Must return >0 on success, ≤0 on failure.
207 typedef int (enc_process_t)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen);
209 static bool rsa_encrypt_decrypt(rsa_t *rsa, const void *in, size_t len, void *out,
210 enc_init_t init, enc_process_t process) {
211 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(rsa, NULL);
216 bool ok = init(ctx) > 0
217 && EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) > 0
218 && process(ctx, out, &outlen, in, len) > 0
221 EVP_PKEY_CTX_free(ctx);
232 bool rsa_public_encrypt(rsa_t *rsa, const void *in, size_t len, void *out) {
233 #if OPENSSL_VERSION_MAJOR < 3
235 if((size_t)RSA_public_encrypt((int) len, in, out, rsa, RSA_NO_PADDING) == len) {
238 if(rsa_encrypt_decrypt(rsa, in, len, out, EVP_PKEY_encrypt_init, EVP_PKEY_encrypt)) {
243 openssl_err("perform RSA encryption");
247 bool rsa_private_decrypt(rsa_t *rsa, const void *in, size_t len, void *out) {
248 #if OPENSSL_VERSION_MAJOR < 3
250 if((size_t)RSA_private_decrypt((int) len, in, out, rsa, RSA_NO_PADDING) == len) {
253 if(rsa_encrypt_decrypt(rsa, in, len, out, EVP_PKEY_decrypt_init, EVP_PKEY_decrypt)) {
258 openssl_err("perform RSA decryption");
262 void rsa_free(rsa_t *rsa) {
264 #if OPENSSL_VERSION_MAJOR < 3