LCOV - code coverage report
Current view: top level - pkcs11/gkm - gkm-sexp.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 88.0 % 183 161
Test Date: 2024-04-08 13:24:42 Functions: 93.3 % 15 14

            Line data    Source code
       1              : /*
       2              :  * gnome-keyring
       3              :  *
       4              :  * Copyright (C) 2008 Stefan Walter
       5              :  *
       6              :  * This program is free software; you can redistribute it and/or modify
       7              :  * it under the terms of the GNU Lesser General Public License as
       8              :  * published by the Free Software Foundation; either version 2.1 of
       9              :  * the License, or (at your option) any later version.
      10              :  *
      11              :  * This program is distributed in the hope that it will be useful, but
      12              :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              :  *
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this program; if not, see
      18              :  * <http://www.gnu.org/licenses/>.
      19              :  */
      20              : 
      21              : #include "config.h"
      22              : 
      23              : #include "gkm-sexp.h"
      24              : 
      25              : struct _GkmSexp {
      26              :         gint refs;
      27              :         gcry_sexp_t real;
      28              : };
      29              : 
      30              : GkmSexp*
      31           61 : gkm_sexp_new (gcry_sexp_t real)
      32              : {
      33              :         GkmSexp *sexp;
      34           61 :         g_return_val_if_fail (real, NULL);
      35           61 :         sexp = g_slice_new0 (GkmSexp);
      36           61 :         sexp->refs = 1;
      37           61 :         sexp->real = real;
      38           61 :         return sexp;
      39              : }
      40              : 
      41              : GkmSexp*
      42           68 : gkm_sexp_ref (GkmSexp *sexp)
      43              : {
      44           68 :         g_return_val_if_fail (sexp, NULL);
      45           68 :         ++(sexp->refs);
      46           68 :         return sexp;
      47              : }
      48              : 
      49              : void
      50          126 : gkm_sexp_unref (gpointer data)
      51              : {
      52          126 :         GkmSexp *sexp = data;
      53          126 :         g_return_if_fail (sexp);
      54          126 :         if (--(sexp->refs) == 0) {
      55           58 :                 g_assert (sexp->real);
      56           58 :                 gcry_sexp_release (sexp->real);
      57           58 :                 g_slice_free (GkmSexp, sexp);
      58              :         }
      59              : }
      60              : 
      61              : gcry_sexp_t
      62           76 : gkm_sexp_get (GkmSexp *sexp)
      63              : {
      64           76 :         g_return_val_if_fail (sexp, NULL);
      65           76 :         g_return_val_if_fail (sexp->real, NULL);
      66           76 :         return sexp->real;
      67              : }
      68              : 
      69              : GType
      70           12 : gkm_sexp_boxed_type (void)
      71              : {
      72              :         static GType type = 0;
      73           12 :         if (!type)
      74            9 :                 type = g_boxed_type_register_static ("GkmSexp",
      75              :                                                      (GBoxedCopyFunc)gkm_sexp_ref,
      76              :                                                      (GBoxedFreeFunc)gkm_sexp_unref);
      77           12 :         return type;
      78              : }
      79              : 
      80              : #define PUBLIC_KEY "public-key"
      81              : #define PUBLIC_KEY_L 10
      82              : #define PRIVATE_KEY "private-key"
      83              : #define PRIVATE_KEY_L 11
      84              : 
      85              : gboolean
      86           65 : gkm_sexp_parse_key (gcry_sexp_t s_key, int *algorithm, gboolean *is_private,
      87              :                     gcry_sexp_t *numbers)
      88              : {
      89           65 :         gboolean ret = FALSE;
      90           65 :         gcry_sexp_t child = NULL;
      91           65 :         gchar *str = NULL;
      92              :         const gchar *data;
      93              :         gsize n_data;
      94              :         gboolean priv;
      95              :         int algo;
      96              : 
      97           65 :         data = gcry_sexp_nth_data (s_key, 0, &n_data);
      98           65 :         if (!data)
      99            0 :                 goto done;
     100              : 
     101           65 :         if (n_data == PUBLIC_KEY_L && strncmp (data, PUBLIC_KEY, PUBLIC_KEY_L) == 0)
     102           11 :                 priv = FALSE;
     103           54 :         else if (n_data == PRIVATE_KEY_L && strncmp (data, PRIVATE_KEY, PRIVATE_KEY_L) == 0)
     104           54 :                 priv = TRUE;
     105              :         else
     106            0 :                 goto done;
     107              : 
     108           65 :         child = gcry_sexp_nth (s_key, 1);
     109           65 :         if (!child)
     110            0 :                 goto done;
     111              : 
     112           65 :         data = gcry_sexp_nth_data (child, 0, &n_data);
     113           65 :         if (!data)
     114            0 :                 goto done;
     115              : 
     116           65 :         str = g_alloca (n_data + 1);
     117           65 :         memcpy (str, data, n_data);
     118           65 :         str[n_data] = 0;
     119              : 
     120           65 :         algo = gcry_pk_map_name (str);
     121           65 :         if (!algo)
     122            0 :                 goto done;
     123              : 
     124              :         /* Yay all done */
     125           65 :         if (algorithm)
     126           56 :                 *algorithm = algo;
     127           65 :         if (numbers) {
     128           18 :                 *numbers = child;
     129           18 :                 child = NULL;
     130              :         }
     131           65 :         if (is_private)
     132           31 :                 *is_private = priv;
     133              : 
     134           65 :         ret = TRUE;
     135              : 
     136           65 : done:
     137           65 :         gcry_sexp_release (child);
     138           65 :         return ret;
     139              : }
     140              : 
     141              : static gcry_sexp_t
     142            4 : rsa_numbers_to_public (gcry_sexp_t rsa)
     143              : {
     144            4 :         gcry_sexp_t pubkey = NULL;
     145              :         gcry_mpi_t n, e;
     146              :         gcry_error_t gcry;
     147              : 
     148            4 :         n = e = NULL;
     149              : 
     150            8 :         if (!gkm_sexp_extract_mpi (rsa, &n, "n", NULL) ||
     151            4 :             !gkm_sexp_extract_mpi (rsa, &e, "e", NULL))
     152            0 :                 goto done;
     153              : 
     154            4 :         gcry = gcry_sexp_build (&pubkey, NULL, "(public-key (rsa (n %m) (e %m)))",
     155              :                                 n, e);
     156            4 :         if (gcry)
     157            0 :                 goto done;
     158            4 :         g_assert (pubkey);
     159              : 
     160            4 : done:
     161            4 :         gcry_mpi_release (n);
     162            4 :         gcry_mpi_release (e);
     163              : 
     164            4 :         return pubkey;
     165              : }
     166              : 
     167              : static gcry_sexp_t
     168            2 : dsa_numbers_to_public (gcry_sexp_t dsa)
     169              : {
     170              :         gcry_mpi_t p, q, g, y;
     171            2 :         gcry_sexp_t pubkey = NULL;
     172              :         gcry_error_t gcry;
     173              : 
     174            2 :         p = q = g = y = NULL;
     175              : 
     176            4 :         if (!gkm_sexp_extract_mpi (dsa, &p, "p", NULL) ||
     177            4 :             !gkm_sexp_extract_mpi (dsa, &q, "q", NULL) ||
     178            4 :             !gkm_sexp_extract_mpi (dsa, &g, "g", NULL) ||
     179            2 :             !gkm_sexp_extract_mpi (dsa, &y, "y", NULL))
     180            0 :                 goto done;
     181              : 
     182            2 :         gcry = gcry_sexp_build (&pubkey, NULL, "(public-key (dsa (p %m) (q %m) (g %m) (y %m)))",
     183              :                                 p, q, g, y);
     184            2 :         if (gcry)
     185            0 :                 goto done;
     186            2 :         g_assert (pubkey);
     187              : 
     188            2 : done:
     189            2 :         gcry_mpi_release (p);
     190            2 :         gcry_mpi_release (q);
     191            2 :         gcry_mpi_release (g);
     192            2 :         gcry_mpi_release (y);
     193              : 
     194            2 :         return pubkey;
     195              : }
     196              : 
     197              : static gcry_sexp_t
     198            2 : ecdsa_numbers_to_public (gcry_sexp_t ecdsa)
     199              : {
     200            2 :         gchar *curve_name = NULL, *q = NULL;
     201              :         gsize q_len;
     202            2 :         gcry_sexp_t pubkey = NULL;
     203              :         gcry_error_t gcry;
     204              : 
     205            4 :         if (!gkm_sexp_extract_string (ecdsa, &curve_name, "curve", NULL) ||
     206            2 :             !gkm_sexp_extract_buffer (ecdsa, &q, &q_len, "q", NULL))
     207            0 :                 goto done;
     208              : 
     209            2 :         gcry = gcry_sexp_build (&pubkey, NULL, "(public-key (ecdsa (curve %s) (q %b)))",
     210              :                                 curve_name, q_len, q);
     211            2 :         if (gcry)
     212            0 :                 goto done;
     213            2 :         g_assert (pubkey);
     214              : 
     215            2 : done:
     216            2 :         g_free (curve_name);
     217            2 :         g_free (q);
     218              : 
     219            2 :         return pubkey;
     220              : }
     221              : 
     222              : gboolean
     223            8 : gkm_sexp_key_to_public (gcry_sexp_t privkey, gcry_sexp_t *pubkey)
     224              : {
     225              :         gcry_sexp_t numbers;
     226              :         int algorithm;
     227              : 
     228            8 :         if (!gkm_sexp_parse_key (privkey, &algorithm, NULL, &numbers))
     229            0 :                 g_return_val_if_reached (FALSE);
     230              : 
     231            8 :         switch (algorithm) {
     232            4 :         case GCRY_PK_RSA:
     233            4 :                 *pubkey = rsa_numbers_to_public (numbers);
     234            4 :                 break;
     235            2 :         case GCRY_PK_DSA:
     236            2 :                 *pubkey = dsa_numbers_to_public (numbers);
     237            2 :                 break;
     238            2 :         case GCRY_PK_ECC:
     239            2 :                 *pubkey = ecdsa_numbers_to_public (numbers);
     240            2 :                 break;
     241            0 :         default:
     242            0 :                 g_return_val_if_reached (FALSE);
     243              :         }
     244              : 
     245            8 :         gcry_sexp_release (numbers);
     246            8 :         return *pubkey ? TRUE : FALSE;
     247              : }
     248              : 
     249              : gboolean
     250           91 : gkm_sexp_extract_mpi (gcry_sexp_t sexp, gcry_mpi_t *mpi, ...)
     251              : {
     252           91 :         gcry_sexp_t at = NULL;
     253              :         va_list va;
     254              : 
     255           91 :         g_assert (sexp);
     256           91 :         g_assert (mpi);
     257              : 
     258           91 :         va_start (va, mpi);
     259           91 :         at = gkm_sexp_get_childv (sexp, va);
     260           91 :         va_end (va);
     261              : 
     262           91 :         *mpi = NULL;
     263           91 :         if (at)
     264           91 :                 *mpi = gcry_sexp_nth_mpi (at ? at : sexp, 1, GCRYMPI_FMT_USG);
     265           91 :         if (at)
     266           91 :                 gcry_sexp_release (at);
     267              : 
     268           91 :         return (*mpi) ? TRUE : FALSE;
     269              : }
     270              : 
     271              : /* ECDSA s-exp lists the curve name as a string */
     272              : gboolean
     273            7 : gkm_sexp_extract_string (gcry_sexp_t sexp, gchar **buf, ...)
     274              : {
     275            7 :         gcry_sexp_t at = NULL;
     276              :         va_list va;
     277              : 
     278            7 :         g_assert (sexp);
     279            7 :         g_assert (buf);
     280              : 
     281            7 :         va_start (va, buf);
     282            7 :         at = gkm_sexp_get_childv (sexp, va);
     283            7 :         va_end (va);
     284              : 
     285            7 :         *buf = NULL;
     286            7 :         if (at) {
     287              :                 size_t len;
     288              :                 const char *data;
     289              : 
     290            7 :                 data = gcry_sexp_nth_data (at, 1, &len);
     291            7 :                 *buf = g_strndup (data, len);
     292            7 :                 gcry_sexp_release (at);
     293              :         }
     294              : 
     295            7 :         return (*buf) ? TRUE : FALSE;
     296              : }
     297              : 
     298              : gboolean
     299           10 : gkm_sexp_extract_buffer (gcry_sexp_t sexp, gchar **buf, gsize *bufsize, ...)
     300              : {
     301           10 :         gcry_sexp_t at = NULL;
     302              :         va_list va;
     303              : 
     304           10 :         g_assert (sexp);
     305           10 :         g_assert (buf);
     306              : 
     307           10 :         va_start (va, bufsize);
     308           10 :         at = gkm_sexp_get_childv (sexp, va);
     309           10 :         va_end (va);
     310              : 
     311           10 :         *buf = NULL;
     312           10 :         if (at) {
     313              :                 size_t len;
     314              :                 const char *data;
     315              : 
     316           10 :                 data = gcry_sexp_nth_data (at, 1, &len);
     317           10 :                 *buf = g_memdup (data, len);
     318           10 :                 *bufsize = len;
     319           10 :                 gcry_sexp_release (at);
     320              :         }
     321              : 
     322           10 :         return (*buf) ? TRUE : FALSE;
     323              : }
     324              : 
     325              : gcry_sexp_t
     326          113 : gkm_sexp_get_childv (gcry_sexp_t sexp, va_list va)
     327              : {
     328          113 :         gcry_sexp_t at = NULL;
     329              :         gcry_sexp_t child;
     330              :         const char *name;
     331              : 
     332          113 :         g_assert (sexp);
     333              : 
     334              :         for(;;) {
     335          301 :                 name = va_arg (va, const char*);
     336          301 :                 if (!name)
     337          113 :                         break;
     338              : 
     339          188 :                 child = gcry_sexp_find_token (at ? at : sexp, name, 0);
     340          188 :                 gcry_sexp_release (at);
     341          188 :                 at = child;
     342          188 :                 if (at == NULL)
     343            0 :                         break;
     344              :         }
     345              : 
     346          113 :         va_end (va);
     347              : 
     348          113 :         return at;
     349              : }
     350              : 
     351              : void
     352            0 : gkm_sexp_dump (gcry_sexp_t sexp)
     353              : {
     354              :         gsize len;
     355              :         gchar *buf;
     356              : 
     357            0 :         len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
     358            0 :         buf = g_malloc (len);
     359            0 :         gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, buf, len);
     360            0 :         g_printerr ("%s", buf);
     361            0 :         g_free (buf);
     362            0 : }
        

Generated by: LCOV version 2.0-1