LCOV - code coverage report
Current view: top level - src/tds - sec_negotiate_gnutls.h (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 0 75 0.0 %
Date: 2026-05-26 16:39:46 Functions: 0 5 0.0 %

          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             : 

Generated by: LCOV version 1.13