FreeTDS API
Loading...
Searching...
No Matches
sec_negotiate_openssl.h
1/* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 * Copyright (C) 2015 Frediano Ziglio
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20#include <openssl/rand.h>
21#include <openssl/bio.h>
22#include <openssl/pem.h>
23#include <openssl/err.h>
24#include <openssl/rsa.h>
25
37#ifndef HAVE_OPENSSL
38#error HAVE_OPENSSL not defines, this file should not be included
39#endif
40
41static void *
42tds5_rsa_encrypt(const void *pem_key, size_t pem_key_len, const void *nonce, size_t nonce_len, const char *pwd, size_t *em_size)
43{
44 void *ret = NULL;
45 EVP_PKEY *key = NULL;
46 EVP_PKEY_CTX *ctx = NULL;
47 BIO *keybio;
48
49#if OPENSSL_VERSION_NUMBER < 0x3000000FL
50 RSA *rsa = NULL;
51#endif
52
53 uint8_t *message = NULL;
54 size_t message_len, pwd_len;
55 uint8_t *em = NULL;
56
57 keybio = BIO_new_mem_buf((void *) pem_key, pem_key_len);
58 if (keybio == NULL)
59 goto error;
60
61#if OPENSSL_VERSION_NUMBER < 0x3000000FL
62 /* Old OpenSSL versions seem to not like RSA public key format if PEM_read_bio_PUBKEY is used */
63 key = EVP_PKEY_new();
64 if (!key)
65 goto error;
66
67 rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL);
68 if (!rsa)
69 goto error;
70
71 EVP_PKEY_set1_RSA(key, rsa);
72#else
73 key = PEM_read_bio_PUBKEY(keybio, &key, NULL, NULL);
74 if (!key)
75 goto error;
76#endif
77
78 pwd_len = strlen(pwd);
79 message_len = nonce_len + pwd_len;
80 message = tds_new(uint8_t, message_len);
81 if (!message)
82 goto error;
83 memcpy(message, nonce, nonce_len);
84 memcpy(message + nonce_len, pwd, pwd_len);
85
86 *em_size = EVP_PKEY_size(key);
87 em = tds_new(uint8_t, *em_size);
88 if (!em)
89 goto error;
90
91 ctx = EVP_PKEY_CTX_new(key, NULL);
92 if (!ctx)
93 goto error;
94 if (EVP_PKEY_encrypt_init(ctx) <= 0
95 || EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, RSA_PKCS1_OAEP_PADDING, NULL) <= 0)
96 goto error;
97
98 if (EVP_PKEY_encrypt(ctx, em, em_size, message, message_len) <= 0)
99 goto error;
100
101 ret = em;
102
103 error:
104#if OPENSSL_VERSION_NUMBER < 0x3000000FL
105 RSA_free(rsa);
106#endif
107 EVP_PKEY_CTX_free(ctx);
108 free(message);
109 if (!ret)
110 free(em);
111 EVP_PKEY_free(key);
112 BIO_free(keybio);
113 return ret;
114}
115