FreeTDS API
sec_negotiate_gnutls.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 <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 
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 
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 
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 sha1(uint8_t *hash, const void *data, size_t len)
186 {
187  struct sha1_ctx ctx;
188  sha1_init(&ctx);
189  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  sha1_digest(&ctx, 20, hash);
194 #endif
195 }
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  for (n = 0; n < len; ++n)
216  dest[n] = dest[n] ^ src[n];
217 }
218 
219 static void
220 mgf_mask(uint8_t *dest, size_t dest_len, const uint8_t *mask, size_t mask_len)
221 {
222  unsigned n = 0;
223  uint8_t hash[hash_len];
224  uint8_t seed[mask_len + 4];
225 
226  memcpy(seed, mask, mask_len);
227  /* we always have some data and check is done internally */
228  for (;;) {
229  TDS_PUT_UA4BE(seed+mask_len, n);
230 
231  hash_func(hash, seed, sizeof(seed));
232  if (dest_len <= hash_len) {
233  memxor(dest, hash, dest_len);
234  break;
235  }
236 
237  memxor(dest, hash, hash_len);
238  dest += hash_len;
239  dest_len -= hash_len;
240  ++n;
241  }
242 }
243 
244 static int
245 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  const unsigned db_len = key_size - hash_len - 1;
254 
255  if (length + hash_len * 2 + 2 > key_size)
256  /* Message too long for this key. */
257  return 0;
258 
259  /* create db */
260  memset(&em, 0, sizeof(em));
261  hash_func(em.db, label, strlen(label));
262  em.all[key_size - length - 1] = 0x1;
263  memcpy(em.all+(key_size - length), message, length);
264  dumpl(em.db, db_len);
265 
266  /* create ros */
267  tds_random_buffer(em.ros, hash_len);
268  dump(em.ros);
269 
270  /* mask db */
271  mgf_mask(em.db, db_len, em.ros, hash_len);
272  dumpl(em.db, db_len);
273 
274  /* mask ros */
275  mgf_mask(em.ros, hash_len, em.db, db_len);
276  dump(em.ros);
277 
278  nettle_mpz_set_str_256_u(m, key_size, em.all);
279 
280  return 1;
281 }
282 
283 static int
284 rsa_encrypt_oaep(const struct rsa_public_key *key,
285  size_t length, const uint8_t *message, mpz_t gibberish)
286 {
287  if (!oaep_encrypt(key->size, length, message, gibberish))
288  return 0;
289 
290  mpz_powm(gibberish, gibberish, key->e, key->n);
291  return 1;
292 }
293 
294 static void*
295 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  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  uint8_t *em = NULL;
305  unsigned char der_buf[2048];
306  size_t size = sizeof(der_buf);
307 
308  mpz_init(p);
309  rsa_public_key_init(&pubkey);
310 
311  pwd_len = strlen(pwd);
312  message_len = nonce_len + pwd_len;
313  message = tds_new(uint8_t, message_len);
314  if (!message)
315  return NULL;
316  memcpy(message, nonce, nonce_len);
317  memcpy(message + nonce_len, pwd, pwd_len);
318 
319  /* use nettle directly */
320  /* parse PEM, get DER */
321  ret = gnutls_pem_base64_decode("RSA PUBLIC KEY", &pubkey_datum, der_buf, &size);
322  if (ret) {
323  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  ret = asn1_der_iterator_first(&der, size, der_buf);
329  if (ret != ASN1_ITERATOR_CONSTRUCTED || der.type != ASN1_SEQUENCE) {
330  tdsdump_log(TDS_DBG_ERROR, "Invalid DER content\n");
331  goto error;
332  }
333 
334  ret = rsa_public_key_from_der_iterator(&pubkey, key_size_max * 8, &der);
335  if (!ret) {
336  tdsdump_log(TDS_DBG_ERROR, "Invalid DER content\n");
337  goto error;
338  }
339 
340  /* get password encrypted */
341  ret = rsa_encrypt_oaep(&pubkey, message_len, message, p);
342  if (!ret) {
343  tdsdump_log(TDS_DBG_ERROR, "Error encrypting message\n");
344  goto error;
345  }
346 
347  em = tds_new(uint8_t, pubkey.size);
348  *em_size = pubkey.size;
349  if (!em)
350  goto error;
351 
352  nettle_mpz_get_str_256(pubkey.size, em, p);
353 
354  tdsdump_dump_buf(TDS_DBG_INFO1, "em", em, pubkey.size);
355 
356 error:
357  free(message);
358  rsa_public_key_clear(&pubkey);
359  mpz_clear(p);
360  return em;
361 }
362 
Definition: sec_negotiate_gnutls.h:90
Definition: sec_negotiate_gnutls.h:60
Definition: sec_negotiate_gnutls.h:138