Line data Source code
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 <gnutls/gnutls.h>
21 : #include <gnutls/crypto.h>
22 : #ifdef HAVE_GNUTLS_ABSTRACT_H
23 : # include <gnutls/abstract.h>
24 : #endif
25 :
26 : #if !defined(HAVE_NETTLE) || !defined(HAVE_GMP) || !defined(HAVE_GNUTLS_RND)
27 : # include <gcrypt.h>
28 : #endif
29 :
30 : #ifndef HAVE_NETTLE
31 : # include <libtasn1.h>
32 : #endif
33 :
34 : #ifdef HAVE_NETTLE
35 : # include <nettle/asn1.h>
36 : # include <nettle/rsa.h>
37 : # include <nettle/bignum.h>
38 : # include <nettle/version.h>
39 : #endif
40 :
41 : /**
42 : * \ingroup libtds
43 : * \defgroup auth Authentication
44 : * Functions for handling authentication.
45 : */
46 :
47 : /**
48 : * \addtogroup auth
49 : * @{
50 : */
51 :
52 : #ifndef HAVE_GNUTLS
53 : #error HAVE_GNUTLS not defined, this file should not be included
54 : #endif
55 :
56 : /* emulate GMP if not present */
57 : #ifndef HAVE_GMP
58 : #define HAVE_GMP 1
59 :
60 : typedef struct {
61 : gcry_mpi_t num;
62 : } mpz_t[1];
63 :
64 : #define mpz_powm(w,n,e,m) \
65 : gcry_mpi_powm((w)->num, (n)->num, (e)->num, (m)->num);
66 : #define mpz_init(n) do { (n)->num = NULL; } while(0)
67 : #define mpz_clear(n) gcry_mpi_release((n)->num)
68 :
69 : #endif
70 :
71 :
72 : /* emulate Nettle if not present */
73 : #ifndef HAVE_NETTLE
74 : #define HAVE_NETTLE 1
75 :
76 : typedef void nettle_random_func(void *ctx, size_t len, uint8_t *out);
77 :
78 : static inline void
79 : nettle_mpz_set_str_256_u(mpz_t x, unsigned length, const uint8_t *s)
80 : {
81 : gcry_mpi_scan(&x->num, GCRYMPI_FMT_USG, s, length, NULL);
82 : }
83 :
84 : static inline void
85 : nettle_mpz_get_str_256(unsigned length, uint8_t *s, const mpz_t x)
86 : {
87 : gcry_mpi_print(GCRYMPI_FMT_USG, s, length, NULL, x->num);
88 : }
89 :
90 : struct asn1_der_iterator {
91 : const unsigned char *data, *data_end;
92 : unsigned long length;
93 : unsigned long type;
94 : };
95 :
96 : enum asn1_iterator_result {
97 : ASN1_ITERATOR_ERROR,
98 : ASN1_ITERATOR_PRIMITIVE,
99 : ASN1_ITERATOR_CONSTRUCTED,
100 : ASN1_ITERATOR_END,
101 : };
102 :
103 : enum {
104 : ASN1_SEQUENCE = ASN1_TAG_SEQUENCE,
105 : };
106 :
107 : static enum asn1_iterator_result
108 : asn1_der_iterator_next(struct asn1_der_iterator *der)
109 : {
110 : unsigned char cls;
111 : unsigned long tag;
112 : int len;
113 : long l;
114 :
115 : if (asn1_get_tag_der(der->data, der->data_end - der->data, &cls, &len, &tag) != ASN1_SUCCESS)
116 : return ASN1_ITERATOR_ERROR;
117 : der->type = tag;
118 : der->data += len;
119 : l = asn1_get_length_der(der->data, der->data_end - der->data, &len);
120 : if (l < 0)
121 : return ASN1_ITERATOR_ERROR;
122 : der->data += len;
123 : der->length = l;
124 : if (cls == ASN1_CLASS_STRUCTURED)
125 : return ASN1_ITERATOR_CONSTRUCTED;
126 : return ASN1_ITERATOR_PRIMITIVE;
127 : }
128 :
129 : static enum asn1_iterator_result
130 : asn1_der_iterator_first(struct asn1_der_iterator *der, int size, const void *der_buf)
131 : {
132 : der->data = (const unsigned char *) der_buf;
133 : der->data_end = der->data + size;
134 :
135 : return asn1_der_iterator_next(der);
136 : }
137 :
138 : struct rsa_public_key {
139 : unsigned size;
140 : mpz_t n, e;
141 : };
142 :
143 : static void
144 : rsa_public_key_init(struct rsa_public_key *key)
145 : {
146 : key->size = 0;
147 : mpz_init(key->n);
148 : mpz_init(key->e);
149 : }
150 :
151 : static void
152 : rsa_public_key_clear(struct rsa_public_key *key)
153 : {
154 : mpz_clear(key->n);
155 : mpz_clear(key->e);
156 : }
157 :
158 : static int
159 : rsa_public_key_from_der_iterator(struct rsa_public_key *key, unsigned key_bits, struct asn1_der_iterator *der)
160 : {
161 : enum asn1_iterator_result ret;
162 :
163 : ret = asn1_der_iterator_next(der);
164 : if (ret != ASN1_ITERATOR_PRIMITIVE || der->type != ASN1_TAG_INTEGER)
165 : return 0;
166 : gcry_mpi_scan(&key->n->num, GCRYMPI_FMT_USG, der->data, der->length, NULL);
167 : key->size = (gcry_mpi_get_nbits(key->n->num)+7)/8;
168 : der->data += der->length;
169 :
170 : ret = asn1_der_iterator_next(der);
171 : if (ret != ASN1_ITERATOR_PRIMITIVE || der->type != ASN1_TAG_INTEGER)
172 : return 0;
173 : gcry_mpi_scan(&key->e->num, GCRYMPI_FMT_USG, der->data, der->length, NULL);
174 :
175 : return 1;
176 : }
177 :
178 : static void
179 : sha1(uint8_t *hash, const void *data, size_t len)
180 : {
181 : gcry_md_hash_buffer(GCRY_MD_SHA1, hash, data, len);
182 : }
183 : #else
184 : static void
185 0 : sha1(uint8_t *hash, const void *data, size_t len)
186 : {
187 : struct sha1_ctx ctx;
188 0 : sha1_init(&ctx);
189 0 : sha1_update(&ctx, len, (const uint8_t *) data);
190 : #if defined(NETTLE_VERSION_MAJOR) && NETTLE_VERSION_MAJOR >= 4
191 : sha1_digest(&ctx, hash);
192 : #else
193 0 : sha1_digest(&ctx, 20, hash);
194 : #endif
195 0 : }
196 : #endif
197 :
198 :
199 : #define dumpl(b,l) tdsdump_dump_buf(TDS_DBG_INFO1, #b, b, l)
200 : #ifndef dumpl
201 : #define dumpl(b,l) do {} while(0)
202 : #endif
203 : #define dump(b) dumpl(b, sizeof(b))
204 :
205 : /* OAEP configuration parameters */
206 : #define hash_func sha1
207 : enum { hash_len = 20 }; /* sha1 length */
208 : enum { key_size_max = 1024 }; /* max key in bytes */
209 : static const char label[] = "";
210 :
211 : static void
212 : memxor(uint8_t *dest, const uint8_t *src, size_t len)
213 : {
214 : size_t n;
215 0 : for (n = 0; n < len; ++n)
216 0 : dest[n] = dest[n] ^ src[n];
217 : }
218 :
219 : static void
220 0 : mgf_mask(uint8_t *dest, size_t dest_len, const uint8_t *mask, size_t mask_len)
221 0 : {
222 0 : unsigned n = 0;
223 : uint8_t hash[hash_len];
224 0 : uint8_t seed[mask_len + 4];
225 :
226 0 : memcpy(seed, mask, mask_len);
227 : /* we always have some data and check is done internally */
228 : for (;;) {
229 0 : TDS_PUT_UA4BE(seed+mask_len, n);
230 :
231 0 : hash_func(hash, seed, sizeof(seed));
232 0 : if (dest_len <= hash_len) {
233 0 : memxor(dest, hash, dest_len);
234 : break;
235 : }
236 :
237 0 : memxor(dest, hash, hash_len);
238 0 : dest += hash_len;
239 0 : dest_len -= hash_len;
240 0 : ++n;
241 : }
242 0 : }
243 :
244 : static int
245 0 : oaep_encrypt(size_t key_size, size_t length, const uint8_t *message, mpz_t m)
246 : {
247 : /* EM: 0x00 ROS (HASH 0x00.. 0x01 message) */
248 : struct {
249 : uint8_t all[1]; /* zero but used to access all data */
250 : uint8_t ros[hash_len];
251 : uint8_t db[key_size_max - hash_len - 1];
252 : } em;
253 0 : const unsigned db_len = key_size - hash_len - 1;
254 :
255 0 : if (length + hash_len * 2 + 2 > key_size)
256 : /* Message too long for this key. */
257 : return 0;
258 :
259 : /* create db */
260 0 : memset(&em, 0, sizeof(em));
261 0 : hash_func(em.db, label, strlen(label));
262 0 : em.all[key_size - length - 1] = 0x1;
263 0 : memcpy(em.all+(key_size - length), message, length);
264 0 : dumpl(em.db, db_len);
265 :
266 : /* create ros */
267 0 : tds_random_buffer(em.ros, hash_len);
268 0 : dump(em.ros);
269 :
270 : /* mask db */
271 0 : mgf_mask(em.db, db_len, em.ros, hash_len);
272 0 : dumpl(em.db, db_len);
273 :
274 : /* mask ros */
275 0 : mgf_mask(em.ros, hash_len, em.db, db_len);
276 0 : dump(em.ros);
277 :
278 0 : nettle_mpz_set_str_256_u(m, key_size, em.all);
279 :
280 0 : return 1;
281 : }
282 :
283 : static int
284 0 : rsa_encrypt_oaep(const struct rsa_public_key *key,
285 : size_t length, const uint8_t *message, mpz_t gibberish)
286 : {
287 0 : if (!oaep_encrypt(key->size, length, message, gibberish))
288 : return 0;
289 :
290 0 : mpz_powm(gibberish, gibberish, key->e, key->n);
291 0 : return 1;
292 : }
293 :
294 : static void*
295 0 : tds5_rsa_encrypt(const void *key, size_t key_len, const void *nonce, size_t nonce_len, const char *pwd, size_t *em_size)
296 : {
297 : int ret;
298 : mpz_t p;
299 0 : gnutls_datum_t pubkey_datum = { (unsigned char *) key, key_len };
300 : struct asn1_der_iterator der;
301 : struct rsa_public_key pubkey;
302 : uint8_t *message;
303 : size_t message_len, pwd_len;
304 0 : uint8_t *em = NULL;
305 : unsigned char der_buf[2048];
306 0 : size_t size = sizeof(der_buf);
307 :
308 0 : mpz_init(p);
309 0 : rsa_public_key_init(&pubkey);
310 :
311 0 : pwd_len = strlen(pwd);
312 0 : message_len = nonce_len + pwd_len;
313 0 : message = tds_new(uint8_t, message_len);
314 0 : if (!message)
315 : return NULL;
316 0 : memcpy(message, nonce, nonce_len);
317 0 : memcpy(message + nonce_len, pwd, pwd_len);
318 :
319 : /* use nettle directly */
320 : /* parse PEM, get DER */
321 0 : ret = gnutls_pem_base64_decode("RSA PUBLIC KEY", &pubkey_datum, der_buf, &size);
322 0 : if (ret) {
323 0 : tdsdump_log(TDS_DBG_ERROR, "Error %d decoding public key: %s\n", ret, gnutls_strerror(ret));
324 : goto error;
325 : }
326 :
327 : /* get key with nettle using DER */
328 0 : ret = asn1_der_iterator_first(&der, size, der_buf);
329 0 : if (ret != ASN1_ITERATOR_CONSTRUCTED || der.type != ASN1_SEQUENCE) {
330 0 : tdsdump_log(TDS_DBG_ERROR, "Invalid DER content\n");
331 : goto error;
332 : }
333 :
334 0 : ret = rsa_public_key_from_der_iterator(&pubkey, key_size_max * 8, &der);
335 0 : if (!ret) {
336 0 : tdsdump_log(TDS_DBG_ERROR, "Invalid DER content\n");
337 : goto error;
338 : }
339 :
340 : /* get password encrypted */
341 0 : ret = rsa_encrypt_oaep(&pubkey, message_len, message, p);
342 0 : if (!ret) {
343 0 : tdsdump_log(TDS_DBG_ERROR, "Error encrypting message\n");
344 : goto error;
345 : }
346 :
347 0 : em = tds_new(uint8_t, pubkey.size);
348 0 : *em_size = pubkey.size;
349 0 : if (!em)
350 : goto error;
351 :
352 0 : nettle_mpz_get_str_256(pubkey.size, em, p);
353 :
354 0 : tdsdump_dump_buf(TDS_DBG_INFO1, "em", em, pubkey.size);
355 :
356 0 : error:
357 0 : free(message);
358 0 : rsa_public_key_clear(&pubkey);
359 0 : mpz_clear(p);
360 0 : return em;
361 : }
362 :
363 : /** @} */
364 :
|