crypto: only use gnutls crypto API, remove libgcrypt dependency (bgo #730294)
authorJiří Klimeš <jklimes@redhat.com>
Fri, 27 Mar 2015 23:20:55 +0000 (00:20 +0100)
committerJiří Klimeš <jklimes@redhat.com>
Wed, 1 Apr 2015 11:23:45 +0000 (13:23 +0200)
We don't need libgcrypt, because gnutls provides an API for encryption and
hashing. (Anyway gnutls itself now uses nettle instead of libgcrypt).

https://bugzilla.gnome.org/show_bug.cgi?id=730294

configure.ac
libnm-core/Makefile.am
libnm-core/crypto_gnutls.c
libnm-util/Makefile.am
libnm-util/crypto_gnutls.c

index 45ff815..0cb4b5a 100644 (file)
@@ -581,18 +581,11 @@ if test x"$ac_crypto" = xnss; then
   AC_DEFINE(HAVE_NSS, 1, [Define if you have NSS])
   with_nss=yes
 elif test x"$ac_crypto" = xgnutls; then
-  PKG_CHECK_MODULES(GNUTLS, [gnutls >= 1.2])
-  AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no)
-  if test x"$LIBGCRYPT_CONFIG" = xno; then
-    AC_MSG_ERROR([gnutls explicitly requested but gcrypt not found on system])
-  else
-    AC_DEFINE(HAVE_GNUTLS, 1, [Define if you have libgnutls])
-    LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags`
-    LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs`
-    AC_SUBST(LIBGCRYPT_CFLAGS)
-    AC_SUBST(LIBGCRYPT_LIBS)
-    with_gnutls=yes
-  fi
+  PKG_CHECK_MODULES(GNUTLS, [gnutls >= 2.12])
+  AC_DEFINE(HAVE_GNUTLS, 1, [Define if you have libgnutls])
+  AC_SUBST(GNUTLS_CFLAGS)
+  AC_SUBST(GNUTLS_LIBS)
+  with_gnutls=yes
 else
   AC_MSG_ERROR([Please choose either 'nss' or 'gnutls' for certificate and crypto operations])
 fi
index 8fab84b..73c5eac 100644 (file)
@@ -33,9 +33,9 @@ libnm_core_la_LIBADD =                        \
        $(UUID_LIBS)
 
 if WITH_GNUTLS
-AM_CPPFLAGS += $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
+AM_CPPFLAGS += $(GNUTLS_CFLAGS)
 libnm_core_la_SOURCES += crypto_gnutls.c
-libnm_core_la_LIBADD += $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
+libnm_core_la_LIBADD += $(GNUTLS_LIBS)
 endif
 
 if WITH_NSS
index 96dddb9..01291f0 100644 (file)
@@ -18,7 +18,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright 2007 - 2009 Red Hat, Inc.
+ * Copyright 2007 - 2015 Red Hat, Inc.
  */
 
 #include "config.h"
@@ -26,8 +26,8 @@
 #include <glib.h>
 #include <glib/gi18n-lib.h>
 
-#include <gcrypt.h>
 #include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
 #include <gnutls/x509.h>
 #include <gnutls/pkcs12.h>
 
@@ -68,8 +68,9 @@ crypto_decrypt (const char *cipher,
                 gsize *out_len,
                 GError **error)
 {
-       gcry_cipher_hd_t ctx;
-       gcry_error_t err;
+       gnutls_cipher_hd_t ctx;
+       gnutls_datum_t key_dt, iv_dt;
+       int err;
        int cipher_mech, i;
        char *output = NULL;
        gboolean success = FALSE;
@@ -79,13 +80,13 @@ crypto_decrypt (const char *cipher,
                return NULL;
 
        if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
-               cipher_mech = GCRY_CIPHER_3DES;
+               cipher_mech = GNUTLS_CIPHER_3DES_CBC;
                real_iv_len = SALT_LEN;
        } else if (!strcmp (cipher, CIPHER_DES_CBC)) {
-               cipher_mech = GCRY_CIPHER_DES;
+               cipher_mech = GNUTLS_CIPHER_DES_CBC;
                real_iv_len = SALT_LEN;
        } else if (!strcmp (cipher, CIPHER_AES_CBC)) {
-               cipher_mech = GCRY_CIPHER_AES;
+               cipher_mech = GNUTLS_CIPHER_AES_128_CBC;
                real_iv_len = 16;
        } else {
                g_set_error (error, NM_CRYPTO_ERROR,
@@ -105,39 +106,26 @@ crypto_decrypt (const char *cipher,
 
        output = g_malloc0 (data_len);
 
-       err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
-       if (err) {
-               g_set_error (error, NM_CRYPTO_ERROR,
-                            NM_CRYPTO_ERROR_DECRYPTION_FAILED,
-                            _("Failed to initialize the decryption cipher context: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
-               goto out;
-       }
-
-       err = gcry_cipher_setkey (ctx, key, key_len);
-       if (err) {
-               g_set_error (error, NM_CRYPTO_ERROR,
-                            NM_CRYPTO_ERROR_DECRYPTION_FAILED,
-                            _("Failed to set symmetric key for decryption: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
-               goto out;
-       }
+       key_dt.data = (unsigned char *) key;
+       key_dt.size = key_len;
+       iv_dt.data = (unsigned char *) iv;
+       iv_dt.size = iv_len;
 
-       err = gcry_cipher_setiv (ctx, iv, iv_len);
-       if (err) {
+       err = gnutls_cipher_init (&ctx, cipher_mech, &key_dt, &iv_dt);
+       if (err < 0) {
                g_set_error (error, NM_CRYPTO_ERROR,
                             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
-                            _("Failed to set IV for decryption: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
+                            _("Failed to initialize the decryption cipher context: %s (%s)"),
+                            gnutls_strerror_name (err), gnutls_strerror (err));
                goto out;
        }
 
-       err = gcry_cipher_decrypt (ctx, output, data_len, data, data_len);
-       if (err) {
+       err = gnutls_cipher_decrypt2 (ctx, data, data_len, output, data_len);
+       if (err < 0) {
                g_set_error (error, NM_CRYPTO_ERROR,
                             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
-                            _("Failed to decrypt the private key: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
+                            _("Failed to decrypt the private key: %s (%s)"),
+                            gnutls_strerror_name (err), gnutls_strerror (err));
                goto out;
        }
        pad_len = output[data_len - 1];
@@ -174,7 +162,7 @@ out:
                        output = NULL;
                }
        }
-       gcry_cipher_close (ctx);
+       gnutls_cipher_deinit (ctx);
        return output;
 }
 
@@ -189,8 +177,9 @@ crypto_encrypt (const char *cipher,
                 gsize *out_len,
                 GError **error)
 {
-       gcry_cipher_hd_t ctx;
-       gcry_error_t err;
+       gnutls_cipher_hd_t ctx;
+       gnutls_datum_t key_dt, iv_dt;
+       int err;
        int cipher_mech;
        char *output = NULL;
        gboolean success = FALSE;
@@ -203,10 +192,10 @@ crypto_encrypt (const char *cipher,
                return NULL;
 
        if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
-               cipher_mech = GCRY_CIPHER_3DES;
+               cipher_mech = GNUTLS_CIPHER_3DES_CBC;
                salt_len = SALT_LEN;
        } else if (!strcmp (cipher, CIPHER_AES_CBC)) {
-               cipher_mech = GCRY_CIPHER_AES;
+               cipher_mech = GNUTLS_CIPHER_AES_128_CBC;
                salt_len = iv_len;
        } else {
                g_set_error (error, NM_CRYPTO_ERROR,
@@ -229,40 +218,26 @@ crypto_encrypt (const char *cipher,
 
        output = g_malloc0 (output_len);
 
-       err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
-       if (err) {
-               g_set_error (error, NM_CRYPTO_ERROR,
-                            NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
-                            _("Failed to initialize the encryption cipher context: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
-               goto out;
-       }
-
-       err = gcry_cipher_setkey (ctx, key, key_len);
-       if (err) {
-               g_set_error (error, NM_CRYPTO_ERROR,
-                            NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
-                            _("Failed to set symmetric key for encryption: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
-               goto out;
-       }
+       key_dt.data = (unsigned char *) key;
+       key_dt.size = key_len;
+       iv_dt.data = (unsigned char *) iv;
+       iv_dt.size = iv_len;
 
-       /* gcrypt only wants 8 bytes of the IV (same as the DES block length) */
-       err = gcry_cipher_setiv (ctx, iv, salt_len);
-       if (err) {
+       err = gnutls_cipher_init (&ctx, cipher_mech, &key_dt, &iv_dt);
+       if (err < 0) {
                g_set_error (error, NM_CRYPTO_ERROR,
                             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
-                            _("Failed to set IV for encryption: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
+                            _("Failed to initialize the encryption cipher context: %s (%s)"),
+                            gnutls_strerror_name (err), gnutls_strerror (err));
                goto out;
        }
 
-       err = gcry_cipher_encrypt (ctx, output, output_len, padded_buf, padded_buf_len);
-       if (err) {
+       err = gnutls_cipher_encrypt2 (ctx, padded_buf, padded_buf_len, output, output_len);
+       if (err < 0) {
                g_set_error (error, NM_CRYPTO_ERROR,
                             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
-                            _("Failed to encrypt the data: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
+                            _("Failed to encrypt the data: %s (%s)"),
+                            gnutls_strerror_name (err), gnutls_strerror (err));
                goto out;
        }
 
@@ -284,7 +259,7 @@ out:
                        output = NULL;
                }
        }
-       gcry_cipher_close (ctx);
+       gnutls_cipher_deinit (ctx);
        return output;
 }
 
@@ -449,6 +424,6 @@ crypto_randomize (void *buffer, gsize buffer_len, GError **error)
        if (!crypto_init (error))
                return FALSE;
 
-       gcry_randomize (buffer, buffer_len, GCRY_STRONG_RANDOM);
+       gnutls_rnd (GNUTLS_RND_RANDOM, buffer, buffer_len);
        return TRUE;
 }
index 3fdc79e..f4f0057 100644 (file)
@@ -13,7 +13,7 @@ AM_CPPFLAGS = \
        $(UUID_CFLAGS)
 
 if WITH_GNUTLS
-AM_CPPFLAGS += $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
+AM_CPPFLAGS += $(GNUTLS_CFLAGS)
 endif
 
 if WITH_NSS
@@ -119,7 +119,7 @@ libnm_util_la_LDFLAGS = -Wl,--version-script=$(SYMBOL_VIS_FILE) \
 
 if WITH_GNUTLS
 libnm_util_la_SOURCES += crypto_gnutls.c
-libnm_util_la_LIBADD += $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
+libnm_util_la_LIBADD += $(GNUTLS_LIBS)
 endif
 
 if WITH_NSS
@@ -143,7 +143,7 @@ libtest_crypto_la_LIBADD = \
 
 if WITH_GNUTLS
 libtest_crypto_la_SOURCES += crypto_gnutls.c
-libtest_crypto_la_LIBADD += $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
+libtest_crypto_la_LIBADD += $(GNUTLS_LIBS)
 endif
 
 if WITH_NSS
index 3bec24a..f61ad86 100644 (file)
@@ -18,7 +18,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright 2007 - 2009 Red Hat, Inc.
+ * Copyright 2007 - 2015 Red Hat, Inc.
  */
 
 #include "config.h"
@@ -26,8 +26,8 @@
 #include <glib.h>
 #include <glib/gi18n-lib.h>
 
-#include <gcrypt.h>
 #include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
 #include <gnutls/x509.h>
 #include <gnutls/pkcs12.h>
 
@@ -65,8 +65,8 @@ crypto_md5_hash (const char *salt,
                  gsize buflen,
                  GError **error)
 {
-       gcry_md_hd_t ctx;
-       gcry_error_t err;
+       gnutls_hash_hd_t ctx;
+       int err;
        int nkey = buflen;
        const gsize digest_len = 16;
        int count = 0;
@@ -81,26 +81,27 @@ crypto_md5_hash (const char *salt,
        g_return_val_if_fail (buffer != NULL, FALSE);
        g_return_val_if_fail (buflen > 0, FALSE);
 
-       err = gcry_md_open (&ctx, GCRY_MD_MD5, 0);
-       if (err) {
+       if (gnutls_hash_get_len (GNUTLS_DIG_MD5) > MD5_HASH_LEN) {
                g_set_error (error, NM_CRYPTO_ERROR,
                             NM_CRYPTO_ERR_MD5_INIT_FAILED,
-                            _("Failed to initialize the MD5 engine: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
+                            _("Hash length too long (%d > %d)."),
+                            gnutls_hash_get_len (GNUTLS_DIG_MD5), MD5_HASH_LEN);
                return FALSE;
        }
 
        while (nkey > 0) {
                int i = 0;
 
+               err = gnutls_hash_init (&ctx, GNUTLS_DIG_MD5);
+               if (err < 0)
+                       goto error;
+
                if (count++)
-                       gcry_md_write (ctx, digest, digest_len);
-               gcry_md_write (ctx, password, password_len);
+                       gnutls_hash (ctx, digest, digest_len);
+               gnutls_hash (ctx, password, password_len);
                if (salt)
-                       gcry_md_write (ctx, salt, SALT_LEN); /* Only use 8 bytes of salt */
-               gcry_md_final (ctx);
-               memcpy (digest, gcry_md_read (ctx, 0), digest_len);
-               gcry_md_reset (ctx);
+                       gnutls_hash (ctx, salt, SALT_LEN); /* Only use 8 bytes of salt */
+               gnutls_hash_deinit (ctx, digest);
 
                while (nkey && (i < digest_len)) {
                        *(p++) = digest[i++];
@@ -109,8 +110,14 @@ crypto_md5_hash (const char *salt,
        }
 
        memset (digest, 0, sizeof (digest));
-       gcry_md_close (ctx);
        return TRUE;
+error:
+       memset (digest, 0, sizeof (digest));
+       g_set_error (error, NM_CRYPTO_ERROR,
+                    NM_CRYPTO_ERR_MD5_INIT_FAILED,
+                    _("Failed to initialize the MD5 engine: %s (%s)"),
+                    gnutls_strerror_name (err), gnutls_strerror (err));
+       return FALSE;
 }
 
 char *
@@ -124,21 +131,22 @@ crypto_decrypt (const char *cipher,
                 gsize *out_len,
                 GError **error)
 {
-       gcry_cipher_hd_t ctx;
-       gcry_error_t err;
+       gnutls_cipher_hd_t ctx;
+       gnutls_datum_t key_dt, iv_dt;
+       int err;
        int cipher_mech, i;
        char *output = NULL;
        gboolean success = FALSE;
        gsize pad_len, real_iv_len;
 
        if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
-               cipher_mech = GCRY_CIPHER_3DES;
+               cipher_mech = GNUTLS_CIPHER_3DES_CBC;
                real_iv_len = SALT_LEN;
        } else if (!strcmp (cipher, CIPHER_DES_CBC)) {
-               cipher_mech = GCRY_CIPHER_DES;
+               cipher_mech = GNUTLS_CIPHER_DES_CBC;
                real_iv_len = SALT_LEN;
        } else if (!strcmp (cipher, CIPHER_AES_CBC)) {
-               cipher_mech = GCRY_CIPHER_AES;
+               cipher_mech = GNUTLS_CIPHER_AES_128_CBC;
                real_iv_len = 16;
        } else {
                g_set_error (error, NM_CRYPTO_ERROR,
@@ -158,39 +166,26 @@ crypto_decrypt (const char *cipher,
 
        output = g_malloc0 (data->len);
 
-       err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
-       if (err) {
-               g_set_error (error, NM_CRYPTO_ERROR,
-                            NM_CRYPTO_ERR_CIPHER_INIT_FAILED,
-                            _("Failed to initialize the decryption cipher context: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
-               goto out;
-       }
-
-       err = gcry_cipher_setkey (ctx, key, key_len);
-       if (err) {
-               g_set_error (error, NM_CRYPTO_ERROR,
-                            NM_CRYPTO_ERR_CIPHER_SET_KEY_FAILED,
-                            _("Failed to set symmetric key for decryption: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
-               goto out;
-       }
+       key_dt.data = (unsigned char *) key;
+       key_dt.size = key_len;
+       iv_dt.data = (unsigned char *) iv;
+       iv_dt.size = iv_len;
 
-       err = gcry_cipher_setiv (ctx, iv, iv_len);
-       if (err) {
+       err = gnutls_cipher_init (&ctx, cipher_mech, &key_dt, &iv_dt);
+       if (err < 0) {
                g_set_error (error, NM_CRYPTO_ERROR,
-                            NM_CRYPTO_ERR_CIPHER_SET_IV_FAILED,
-                            _("Failed to set IV for decryption: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
+                            NM_CRYPTO_ERR_CIPHER_INIT_FAILED,
+                            _("Failed to initialize the decryption cipher context: %s (%s)"),
+                            gnutls_strerror_name (err), gnutls_strerror (err));
                goto out;
        }
 
-       err = gcry_cipher_decrypt (ctx, output, data->len, data->data, data->len);
-       if (err) {
+       err = gnutls_cipher_decrypt2 (ctx, data->data, data->len, output, data->len);
+       if (err < 0) {
                g_set_error (error, NM_CRYPTO_ERROR,
                             NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED,
-                            _("Failed to decrypt the private key: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
+                            _("Failed to decrypt the private key: %s (%s)"),
+                            gnutls_strerror_name (err), gnutls_strerror (err));
                goto out;
        }
        pad_len = output[data->len - 1];
@@ -227,7 +222,7 @@ out:
                        output = NULL;
                }
        }
-       gcry_cipher_close (ctx);
+       gnutls_cipher_deinit (ctx);
        return output;
 }
 
@@ -241,8 +236,9 @@ crypto_encrypt (const char *cipher,
                 gsize *out_len,
                 GError **error)
 {
-       gcry_cipher_hd_t ctx;
-       gcry_error_t err;
+       gnutls_cipher_hd_t ctx;
+       gnutls_datum_t key_dt, iv_dt;
+       int err;
        int cipher_mech;
        char *output = NULL;
        gboolean success = FALSE;
@@ -252,10 +248,10 @@ crypto_encrypt (const char *cipher,
        gsize salt_len;
 
        if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
-               cipher_mech = GCRY_CIPHER_3DES;
+               cipher_mech = GNUTLS_CIPHER_3DES_CBC;
                salt_len = SALT_LEN;
        } else if (!strcmp (cipher, CIPHER_AES_CBC)) {
-               cipher_mech = GCRY_CIPHER_AES;
+               cipher_mech = GNUTLS_CIPHER_AES_128_CBC;
                salt_len = iv_len;
        } else {
                g_set_error (error, NM_CRYPTO_ERROR,
@@ -278,40 +274,26 @@ crypto_encrypt (const char *cipher,
 
        output = g_malloc0 (output_len);
 
-       err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
-       if (err) {
-               g_set_error (error, NM_CRYPTO_ERROR,
-                            NM_CRYPTO_ERR_CIPHER_INIT_FAILED,
-                            _("Failed to initialize the encryption cipher context: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
-               goto out;
-       }
-
-       err = gcry_cipher_setkey (ctx, key, key_len);
-       if (err) {
-               g_set_error (error, NM_CRYPTO_ERROR,
-                            NM_CRYPTO_ERR_CIPHER_SET_KEY_FAILED,
-                            _("Failed to set symmetric key for encryption: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
-               goto out;
-       }
+       key_dt.data = (unsigned char *) key;
+       key_dt.size = key_len;
+       iv_dt.data = (unsigned char *) iv;
+       iv_dt.size = iv_len;
 
-       /* gcrypt only wants 8 bytes of the IV (same as the DES block length) */
-       err = gcry_cipher_setiv (ctx, iv, salt_len);
-       if (err) {
+       err = gnutls_cipher_init (&ctx, cipher_mech, &key_dt, &iv_dt);
+       if (err < 0) {
                g_set_error (error, NM_CRYPTO_ERROR,
-                            NM_CRYPTO_ERR_CIPHER_SET_IV_FAILED,
-                            _("Failed to set IV for encryption: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
+                            NM_CRYPTO_ERR_CIPHER_INIT_FAILED,
+                            _("Failed to initialize the encryption cipher context: %s (%s)"),
+                            gnutls_strerror_name (err), gnutls_strerror (err));
                goto out;
        }
 
-       err = gcry_cipher_encrypt (ctx, output, output_len, padded_buf, padded_buf_len);
-       if (err) {
+       err = gnutls_cipher_encrypt2 (ctx, padded_buf, padded_buf_len, output, output_len);
+       if (err < 0) {
                g_set_error (error, NM_CRYPTO_ERROR,
                             NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED,
-                            _("Failed to encrypt the data: %s / %s."),
-                            gcry_strsource (err), gcry_strerror (err));
+                            _("Failed to encrypt the data: %s (%s)"),
+                            gnutls_strerror_name (err), gnutls_strerror (err));
                goto out;
        }
 
@@ -333,7 +315,7 @@ out:
                        output = NULL;
                }
        }
-       gcry_cipher_close (ctx);
+       gnutls_cipher_deinit (ctx);
        return output;
 }
 
@@ -484,6 +466,6 @@ crypto_verify_pkcs8 (const GByteArray *data,
 gboolean
 crypto_randomize (void *buffer, gsize buffer_len, GError **error)
 {
-       gcry_randomize (buffer, buffer_len, GCRY_STRONG_RANDOM);
+       gnutls_rnd (GNUTLS_RND_RANDOM, buffer, buffer_len);
        return TRUE;
 }