LCOV - code coverage report
Current view: top level - pkcs11/gkm - gkm-data-der.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 84.8 % 928 787
Test Date: 2024-04-08 13:24:42 Functions: 100.0 % 43 43

            Line data    Source code
       1              : /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
       2              : /* gkm-data-der.c - parsing and serializing of common crypto DER structures
       3              : 
       4              :    Copyright (C) 2007 Stefan Walter
       5              : 
       6              :    The Gnome Keyring Library is free software; you can redistribute it and/or
       7              :    modify it under the terms of the GNU Library General Public License as
       8              :    published by the Free Software Foundation; either version 2 of the
       9              :    License, or (at your option) any later version.
      10              : 
      11              :    The Gnome Keyring Library is distributed in the hope that it will be useful,
      12              :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :    Library General Public License for more details.
      15              : 
      16              :    You should have received a copy of the GNU Library General Public
      17              :    License along with the Gnome Library; see the file COPYING.LIB.  If not,
      18              :    <http://www.gnu.org/licenses/>.
      19              : 
      20              :    Author: Stef Walter <stef@memberwebs.com>
      21              : */
      22              : 
      23              : #include "config.h"
      24              : 
      25              : #include "gkm-data-asn1.h"
      26              : #include "gkm-data-der.h"
      27              : #include "gkm-data-types.h"
      28              : #include "gkm-sexp.h"
      29              : 
      30              : #include "egg/egg-asn1x.h"
      31              : #include "egg/egg-asn1-defs.h"
      32              : #include "egg/egg-secure-memory.h"
      33              : #include "egg/egg-symkey.h"
      34              : 
      35              : #include <glib.h>
      36              : #include <gcrypt.h>
      37              : 
      38           77 : EGG_SECURE_DECLARE (data_der);
      39              : 
      40              : /* -----------------------------------------------------------------------------
      41              :  * QUARKS
      42              :  */
      43              : 
      44              : static GQuark OID_PKIX1_RSA;
      45              : static GQuark OID_PKIX1_DSA;
      46              : static GQuark OID_PKIX1_ECDSA;
      47              : static GQuark OID_PKCS12_PBE_3DES_SHA1;
      48              : static GQuark OID_ANSI_SECP256R1;
      49              : static GQuark OID_ANSI_SECP384R1;
      50              : static GQuark OID_ANSI_SECP521R1;
      51              : 
      52              : static void
      53          263 : init_quarks (void)
      54              : {
      55              :         static gsize quarks_inited = 0;
      56              : 
      57          263 :         if (g_once_init_enter (&quarks_inited)) {
      58              : 
      59              :                 #define QUARK(name, value) \
      60              :                         name = g_quark_from_static_string(value)
      61              : 
      62           11 :                 QUARK (OID_PKIX1_RSA, "1.2.840.113549.1.1.1");
      63           11 :                 QUARK (OID_PKIX1_DSA, "1.2.840.10040.4.1");
      64           11 :                 QUARK (OID_PKIX1_ECDSA, "1.2.840.10045.2.1");
      65           11 :                 QUARK (OID_PKCS12_PBE_3DES_SHA1, "1.2.840.113549.1.12.1.3");
      66           11 :                 QUARK (OID_ANSI_SECP256R1, "1.2.840.10045.3.1.7");
      67           11 :                 QUARK (OID_ANSI_SECP384R1, "1.3.132.0.34");
      68           11 :                 QUARK (OID_ANSI_SECP521R1, "1.3.132.0.35");
      69              : 
      70              :                 #undef QUARK
      71              : 
      72           11 :                 g_once_init_leave (&quarks_inited, 1);
      73              :         }
      74          263 : }
      75              : 
      76              : const gchar *
      77           11 : gkm_data_der_oid_to_curve (GQuark oid)
      78              : {
      79           11 :         if (oid == OID_ANSI_SECP256R1)
      80            7 :                 return "NIST P-256";
      81            4 :         else if (oid == OID_ANSI_SECP384R1)
      82            2 :                 return "NIST P-384";
      83            2 :         else if (oid == OID_ANSI_SECP521R1)
      84            2 :                 return "NIST P-521";
      85            0 :         return NULL;
      86              : }
      87              : 
      88              : /*
      89              :  * Convert ecc->curve values from libgcrypt representation to internal one.
      90              :  * Ignore duplicates and alternative names, since S-expressions are created
      91              :  * only by us throught this code.
      92              :  */
      93              : static GQuark
      94            5 : gkm_data_der_curve_to_oid (const gchar *curve)
      95              : {
      96            5 :         if (g_str_equal (curve, "NIST P-256"))
      97            3 :                 return OID_ANSI_SECP256R1;
      98            2 :         else if (g_str_equal (curve, "NIST P-384"))
      99            1 :                 return OID_ANSI_SECP384R1;
     100            1 :         else if (g_str_equal (curve, "NIST P-521"))
     101            1 :                 return OID_ANSI_SECP521R1;
     102            0 :         return 0;
     103              : }
     104              : 
     105              : 
     106              : GQuark
     107            1 : gkm_data_der_oid_from_ec_params (GBytes *params)
     108              : {
     109              :         GNode *asn;
     110              :         GQuark oid;
     111              : 
     112            1 :         init_quarks ();
     113              : 
     114            1 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "Parameters", params);
     115            1 :         if (!asn)
     116            0 :                 return 0;
     117              : 
     118            1 :         oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "namedCurve", NULL));
     119              : 
     120            1 :         egg_asn1x_destroy (asn);
     121            1 :         return oid;
     122              : }
     123              : 
     124              : GBytes *
     125            1 : gkm_data_der_get_ec_params (GQuark oid)
     126              : {
     127              :         GNode *asn;
     128            1 :         GBytes *params = NULL;
     129              :         GNode *named_curve;
     130              : 
     131            1 :         asn = egg_asn1x_create (pk_asn1_tab, "Parameters");
     132            1 :         if (!asn)
     133            0 :                 goto done;
     134              : 
     135            1 :         named_curve = egg_asn1x_node (asn, "namedCurve", NULL);
     136              : 
     137            1 :         if (!egg_asn1x_set_oid_as_quark (named_curve, oid))
     138            0 :                 goto done;
     139              : 
     140            1 :         if (!egg_asn1x_set_choice (asn, named_curve))
     141            0 :                 goto done;
     142              : 
     143            1 :         params = egg_asn1x_encode (asn, NULL);
     144              : 
     145            1 : done:
     146            1 :         egg_asn1x_destroy (asn);
     147            1 :         return params;
     148              : }
     149              : 
     150              : /* wrapper so we do not have to export the GQuark magic */
     151              : GBytes *
     152            1 : gkm_data_der_curve_to_ec_params (const gchar *curve_name)
     153              : {
     154              :         GQuark oid;
     155              : 
     156            1 :         init_quarks ();
     157              : 
     158            1 :         oid = gkm_data_der_curve_to_oid (curve_name);
     159            1 :         if (oid == 0)
     160            0 :                 return NULL;
     161              : 
     162            1 :         return gkm_data_der_get_ec_params (oid);
     163              : }
     164              : 
     165              : GBytes *
     166            1 : gkm_data_der_encode_ecdsa_q_str (const guchar *data, gsize data_len)
     167              : {
     168            1 :         GNode *asn = NULL;
     169            1 :         GBytes *bytes, *result = NULL;
     170              : 
     171            1 :         asn = egg_asn1x_create (pk_asn1_tab, "ECKeyQ");
     172            1 :         g_return_val_if_fail (asn, FALSE);
     173              : 
     174            1 :         bytes = g_bytes_new_static (data, data_len);
     175              : 
     176              :         /* "consumes" bytes */
     177            1 :         if (!gkm_data_asn1_write_string (asn, bytes))
     178            0 :                 goto done;
     179              : 
     180            1 :         result = egg_asn1x_encode (asn, g_realloc);
     181            1 :         if (result == NULL)
     182            0 :                 g_warning ("couldn't encode Q into the PKCS#11 structure: %s", egg_asn1x_message (asn));
     183            1 : done:
     184            1 :         egg_asn1x_destroy (asn);
     185            1 :         return result;
     186              : }
     187              : 
     188              : gboolean
     189            1 : gkm_data_der_encode_ecdsa_q (gcry_mpi_t q, GBytes **result)
     190              : {
     191              :         gcry_error_t gcry;
     192              :         guchar data[1024];
     193            1 :         gsize data_len = 1024;
     194            1 :         gboolean rv = TRUE;
     195              : 
     196            1 :         g_assert (q);
     197            1 :         g_assert (result);
     198              : 
     199            1 :         gcry = gcry_mpi_print (GCRYMPI_FMT_USG, data, data_len, &data_len, q);
     200            1 :         g_return_val_if_fail (gcry == 0, FALSE);
     201              : 
     202            1 :         *result = gkm_data_der_encode_ecdsa_q_str (data, data_len);
     203            1 :         if (*result == NULL)
     204            0 :                 rv = FALSE;
     205              : 
     206            1 :         return rv;
     207              : }
     208              : 
     209              : gboolean
     210            1 : gkm_data_der_decode_ecdsa_q (GBytes *data, GBytes **result)
     211              : {
     212            1 :         GNode *asn = NULL;
     213            1 :         gboolean rv = TRUE;
     214              : 
     215            1 :         g_assert (data);
     216            1 :         g_assert (result);
     217              : 
     218            1 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECKeyQ", data);
     219              :         /* workaround a bug in gcr (not DER encoding the MPI) */
     220            1 :         if (!asn) {
     221            0 :                 *result = data;
     222            0 :                 return rv;
     223              :         }
     224              : 
     225            1 :         rv = gkm_data_asn1_read_string (asn, result);
     226              : 
     227            1 :         egg_asn1x_destroy (asn);
     228            1 :         return rv;
     229              : }
     230              : 
     231              : /* -----------------------------------------------------------------------------
     232              :  * KEY PARSING
     233              :  */
     234              : 
     235              : #define SEXP_PUBLIC_RSA  \
     236              :         "(public-key"    \
     237              :         "  (rsa"         \
     238              :         "    (n %m)"     \
     239              :         "    (e %m)))"
     240              : 
     241              : GkmDataResult
     242          180 : gkm_data_der_read_public_key_rsa (GBytes *data,
     243              :                                   gcry_sexp_t *s_key)
     244              : {
     245          180 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
     246          180 :         GNode *asn = NULL;
     247              :         gcry_mpi_t n, e;
     248              :         int res;
     249              : 
     250          180 :         n = e = NULL;
     251              : 
     252          180 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPublicKey", data);
     253          180 :         if (!asn)
     254            2 :                 goto done;
     255              : 
     256          178 :         ret = GKM_DATA_FAILURE;
     257              : 
     258          356 :         if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "modulus", NULL), &n) ||
     259          178 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "publicExponent", NULL), &e))
     260            0 :                 goto done;
     261              : 
     262          178 :         res = gcry_sexp_build (s_key, NULL, SEXP_PUBLIC_RSA, n, e);
     263          178 :         if (res)
     264            0 :                 goto done;
     265              : 
     266          178 :         g_assert (*s_key);
     267          178 :         ret = GKM_DATA_SUCCESS;
     268              : 
     269          180 : done:
     270          180 :         egg_asn1x_destroy (asn);
     271          180 :         gcry_mpi_release (n);
     272          180 :         gcry_mpi_release (e);
     273              : 
     274          180 :         if (ret == GKM_DATA_FAILURE)
     275            0 :                 g_message ("invalid RSA public key");
     276              : 
     277          180 :         return ret;
     278              : }
     279              : 
     280              : #define SEXP_PRIVATE_RSA  \
     281              :         "(private-key"   \
     282              :         "  (rsa"         \
     283              :         "    (n %m)"     \
     284              :         "    (e %m)"     \
     285              :         "    (d %m)"     \
     286              :         "    (p %m)"     \
     287              :         "    (q %m)"     \
     288              :         "    (u %m)))"
     289              : 
     290              : GkmDataResult
     291           39 : gkm_data_der_read_private_key_rsa (GBytes *data,
     292              :                                    gcry_sexp_t *s_key)
     293              : {
     294           39 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
     295              :         gcry_mpi_t n, e, d, p, q, u;
     296              :         gcry_mpi_t tmp;
     297              :         gulong version;
     298           39 :         GNode *asn = NULL;
     299              :         int res;
     300              : 
     301           39 :         n = e = d = p = q = u = NULL;
     302              : 
     303           39 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPrivateKey", data);
     304           39 :         if (!asn)
     305           18 :                 goto done;
     306              : 
     307           21 :         ret = GKM_DATA_FAILURE;
     308              : 
     309           21 :         if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), &version))
     310            0 :                 goto done;
     311              : 
     312              :         /* We only support simple version */
     313           21 :         if (version != 0) {
     314            0 :                 ret = GKM_DATA_UNRECOGNIZED;
     315            0 :                 g_message ("unsupported version of RSA key: %lu", version);
     316            0 :                 goto done;
     317              :         }
     318              : 
     319           42 :         if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "modulus", NULL), &n) ||
     320           42 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "publicExponent", NULL), &e) ||
     321           42 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "privateExponent", NULL), &d) ||
     322           42 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "prime1", NULL), &p) ||
     323           42 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "prime2", NULL), &q) ||
     324           21 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "coefficient", NULL), &u))
     325            0 :                 goto done;
     326              : 
     327              :         /* Fix up the incoming key so gcrypt likes it */
     328           21 :         if (gcry_mpi_cmp (p, q) > 0) {
     329              :                 /* P shall be smaller then Q!  Swap primes.  iqmp becomes u.  */
     330           16 :                 tmp = p;
     331           16 :                 p = q;
     332           16 :                 q = tmp;
     333              :         } else {
     334              :                 /* U needs to be recomputed.  */
     335            5 :                 gcry_mpi_invm (u, p, q);
     336              :         }
     337              : 
     338           21 :         res = gcry_sexp_build (s_key, NULL, SEXP_PRIVATE_RSA, n, e, d, p, q, u);
     339           21 :         if (res)
     340            0 :                 goto done;
     341              : 
     342           21 :         g_assert (*s_key);
     343           21 :         ret = GKM_DATA_SUCCESS;
     344              : 
     345           39 : done:
     346           39 :         egg_asn1x_destroy (asn);
     347           39 :         gcry_mpi_release (n);
     348           39 :         gcry_mpi_release (e);
     349           39 :         gcry_mpi_release (d);
     350           39 :         gcry_mpi_release (p);
     351           39 :         gcry_mpi_release (q);
     352           39 :         gcry_mpi_release (u);
     353              : 
     354           39 :         if (ret == GKM_DATA_FAILURE)
     355            0 :                 g_message ("invalid RSA key");
     356              : 
     357           39 :         return ret;
     358              : }
     359              : 
     360              : #define SEXP_PUBLIC_DSA  \
     361              :         "(public-key"   \
     362              :         "  (dsa"         \
     363              :         "    (p %m)"     \
     364              :         "    (q %m)"     \
     365              :         "    (g %m)"     \
     366              :         "    (y %m)))"
     367              : 
     368              : GkmDataResult
     369            1 : gkm_data_der_read_public_key_dsa (GBytes *data,
     370              :                                   gcry_sexp_t *s_key)
     371              : {
     372            1 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
     373            1 :         GNode *asn = NULL;
     374              :         gcry_mpi_t p, q, g, y;
     375              :         int res;
     376              : 
     377            1 :         p = q = g = y = NULL;
     378              : 
     379            1 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPublicKey", data);
     380            1 :         if (!asn)
     381            0 :                 goto done;
     382              : 
     383            1 :         ret = GKM_DATA_FAILURE;
     384              : 
     385            2 :         if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "p", NULL), &p) ||
     386            2 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "q", NULL), &q) ||
     387            2 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "g", NULL), &g) ||
     388            1 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "Y", NULL), &y))
     389            0 :                 goto done;
     390              : 
     391            1 :         res = gcry_sexp_build (s_key, NULL, SEXP_PUBLIC_DSA, p, q, g, y);
     392            1 :         if (res)
     393            0 :                 goto done;
     394              : 
     395            1 :         g_assert (*s_key);
     396            1 :         ret = GKM_DATA_SUCCESS;
     397              : 
     398            1 : done:
     399            1 :         egg_asn1x_destroy (asn);
     400            1 :         gcry_mpi_release (p);
     401            1 :         gcry_mpi_release (q);
     402            1 :         gcry_mpi_release (g);
     403            1 :         gcry_mpi_release (y);
     404              : 
     405            1 :         if (ret == GKM_DATA_FAILURE)
     406            0 :                 g_message ("invalid public DSA key");
     407              : 
     408            1 :         return ret;
     409              : }
     410              : 
     411              : GkmDataResult
     412            1 : gkm_data_der_read_public_key_dsa_parts (GBytes *keydata,
     413              :                                         GBytes *params,
     414              :                                         gcry_sexp_t *s_key)
     415              : {
     416              :         gcry_mpi_t p, q, g, y;
     417            1 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
     418            1 :         GNode *asn_params = NULL;
     419            1 :         GNode *asn_key = NULL;
     420              :         int res;
     421              : 
     422            1 :         p = q = g = y = NULL;
     423              : 
     424            1 :         asn_params = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", params);
     425            1 :         asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPublicPart", keydata);
     426            1 :         if (!asn_params || !asn_key)
     427            0 :                 goto done;
     428              : 
     429            1 :         ret = GKM_DATA_FAILURE;
     430              : 
     431            2 :         if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "p", NULL), &p) ||
     432            2 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "q", NULL), &q) ||
     433            1 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "g", NULL), &g))
     434            0 :                 goto done;
     435              : 
     436            1 :         if (!gkm_data_asn1_read_mpi (asn_key, &y))
     437            0 :                 goto done;
     438              : 
     439            1 :         res = gcry_sexp_build (s_key, NULL, SEXP_PUBLIC_DSA, p, q, g, y);
     440            1 :         if (res)
     441            0 :                 goto done;
     442              : 
     443            1 :         g_assert (*s_key);
     444            1 :         ret = GKM_DATA_SUCCESS;
     445              : 
     446            1 : done:
     447            1 :         egg_asn1x_destroy (asn_key);
     448            1 :         egg_asn1x_destroy (asn_params);
     449            1 :         gcry_mpi_release (p);
     450            1 :         gcry_mpi_release (q);
     451            1 :         gcry_mpi_release (g);
     452            1 :         gcry_mpi_release (y);
     453              : 
     454            1 :         if (ret == GKM_DATA_FAILURE)
     455            0 :                 g_message ("invalid DSA key");
     456              : 
     457            1 :         return ret;
     458              : }
     459              : 
     460              : #define SEXP_PRIVATE_DSA  \
     461              :         "(private-key"   \
     462              :         "  (dsa"         \
     463              :         "    (p %m)"     \
     464              :         "    (q %m)"     \
     465              :         "    (g %m)"     \
     466              :         "    (y %m)"     \
     467              :         "    (x %m)))"
     468              : 
     469              : GkmDataResult
     470           21 : gkm_data_der_read_private_key_dsa (GBytes *data,
     471              :                                    gcry_sexp_t *s_key)
     472              : {
     473              :         gcry_mpi_t p, q, g, y, x;
     474           21 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
     475              :         int res;
     476           21 :         GNode *asn = NULL;
     477              : 
     478           21 :         p = q = g = y = x = NULL;
     479              : 
     480           21 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivateKey", data);
     481           21 :         if (!asn)
     482           16 :                 goto done;
     483              : 
     484            5 :         ret = GKM_DATA_FAILURE;
     485              : 
     486           10 :         if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "p", NULL), &p) ||
     487           10 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "q", NULL), &q) ||
     488           10 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "g", NULL), &g) ||
     489           10 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "Y", NULL), &y) ||
     490            5 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn, "priv", NULL), &x))
     491            0 :                 goto done;
     492              : 
     493            5 :         res = gcry_sexp_build (s_key, NULL, SEXP_PRIVATE_DSA, p, q, g, y, x);
     494            5 :         if (res)
     495            0 :                 goto done;
     496              : 
     497            5 :         g_assert (*s_key);
     498            5 :         ret = GKM_DATA_SUCCESS;
     499              : 
     500           21 : done:
     501           21 :         egg_asn1x_destroy (asn);
     502           21 :         gcry_mpi_release (p);
     503           21 :         gcry_mpi_release (q);
     504           21 :         gcry_mpi_release (g);
     505           21 :         gcry_mpi_release (y);
     506           21 :         gcry_mpi_release (x);
     507              : 
     508           21 :         if (ret == GKM_DATA_FAILURE)
     509            0 :                 g_message ("invalid DSA key");
     510              : 
     511           21 :         return ret;
     512              : }
     513              : 
     514              : GkmDataResult
     515            4 : gkm_data_der_read_private_key_dsa_parts (GBytes *keydata,
     516              :                                          GBytes *params,
     517              :                                          gcry_sexp_t *s_key)
     518              : {
     519              :         gcry_mpi_t p, q, g, y, x;
     520            4 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
     521              :         int res;
     522            4 :         GNode *asn_params = NULL;
     523            4 :         GNode *asn_key = NULL;
     524              : 
     525            4 :         p = q = g = y = x = NULL;
     526              : 
     527            4 :         asn_params = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", params);
     528            4 :         asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivatePart", keydata);
     529            4 :         if (!asn_params || !asn_key)
     530            0 :                 goto done;
     531              : 
     532            4 :         ret = GKM_DATA_FAILURE;
     533              : 
     534            8 :         if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "p", NULL), &p) ||
     535            8 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "q", NULL), &q) ||
     536            4 :             !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "g", NULL), &g))
     537            0 :                 goto done;
     538              : 
     539            4 :         if (!gkm_data_asn1_read_mpi (asn_key, &x))
     540            0 :                 goto done;
     541              : 
     542              :         /* Now we calculate y */
     543            4 :         y = gcry_mpi_snew (1024);
     544            4 :         gcry_mpi_powm (y, g, x, p);
     545              : 
     546            4 :         res = gcry_sexp_build (s_key, NULL, SEXP_PRIVATE_DSA, p, q, g, y, x);
     547            4 :         if (res)
     548            0 :                 goto done;
     549              : 
     550            4 :         g_assert (*s_key);
     551            4 :         ret = GKM_DATA_SUCCESS;
     552              : 
     553            4 : done:
     554            4 :         egg_asn1x_destroy (asn_key);
     555            4 :         egg_asn1x_destroy (asn_params);
     556            4 :         gcry_mpi_release (p);
     557            4 :         gcry_mpi_release (q);
     558            4 :         gcry_mpi_release (g);
     559            4 :         gcry_mpi_release (y);
     560            4 :         gcry_mpi_release (x);
     561              : 
     562            4 :         if (ret == GKM_DATA_FAILURE)
     563            0 :                 g_message ("invalid DSA key");
     564              : 
     565            4 :         return ret;
     566              : }
     567              : 
     568              : #define SEXP_PUBLIC_ECDSA  \
     569              :         "(public-key"   \
     570              :         "  (ecdsa"         \
     571              :         "    (curve %s)"     \
     572              :         "    (q %b)))"
     573              : 
     574              : GkmDataResult
     575            3 : gkm_data_der_read_public_key_ecdsa (GBytes *data,
     576              :                                      gcry_sexp_t *s_key)
     577              : {
     578            3 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
     579              :         int res;
     580            3 :         GNode *asn = NULL;
     581            3 :         GBytes *q = NULL;
     582              :         gsize q_bits;
     583              :         GQuark oid;
     584            3 :         const gchar *curve = NULL;
     585              : 
     586            3 :         init_quarks ();
     587              : 
     588            3 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECPublicKey", data);
     589            3 :         if (!asn)
     590            2 :                 goto done;
     591              : 
     592            1 :         ret = GKM_DATA_FAILURE;
     593              : 
     594            2 :         if (!gkm_data_asn1_read_oid (egg_asn1x_node (asn, "parameters", "namedCurve", NULL), &oid) ||
     595            1 :             !gkm_data_asn1_read_bit_string (egg_asn1x_node (asn, "q", NULL), &q, &q_bits))
     596            0 :                 goto done;
     597              : 
     598            1 :         curve = gkm_data_der_oid_to_curve (oid);
     599            1 :         if (curve == NULL)
     600            0 :                 goto done;
     601              : 
     602            1 :         res = gcry_sexp_build (s_key, NULL, SEXP_PUBLIC_ECDSA,
     603              :                                curve,
     604              :                                g_bytes_get_size(q), g_bytes_get_data(q, NULL));
     605            1 :         if (res)
     606            0 :                 goto done;
     607              : 
     608            1 :         g_assert (*s_key);
     609            1 :         ret = GKM_DATA_SUCCESS;
     610              : 
     611            3 : done:
     612            3 :         egg_asn1x_destroy (asn);
     613            3 :         g_bytes_unref (q);
     614              : 
     615            3 :         if (ret == GKM_DATA_FAILURE)
     616            0 :                 g_message ("invalid ECDSA key");
     617              : 
     618            3 :         return ret;
     619              : }
     620              : 
     621              : #define SEXP_PRIVATE_ECDSA  \
     622              :         "(private-key"   \
     623              :         "  (ecdsa"         \
     624              :         "    (curve %s)"     \
     625              :         "    (q %b)"     \
     626              :         "    (d %m)))"
     627              : 
     628              : GkmDataResult
     629           15 : gkm_data_der_read_private_key_ecdsa (GBytes *data,
     630              :                                      gcry_sexp_t *s_key)
     631              : {
     632           15 :         gcry_mpi_t d = NULL;
     633           15 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
     634              :         int res;
     635           15 :         GNode *asn = NULL;
     636           15 :         GBytes *q = NULL;
     637              :         gsize q_bits;
     638              :         GQuark oid;
     639           15 :         const gchar *curve = NULL;
     640              : 
     641           15 :         init_quarks ();
     642              : 
     643           15 :         asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECPrivateKey", data);
     644           15 :         if (!asn)
     645            6 :                 goto done;
     646              : 
     647            9 :         ret = GKM_DATA_FAILURE;
     648              : 
     649           18 :         if (!gkm_data_asn1_read_string_mpi (egg_asn1x_node (asn, "d", NULL), &d) ||
     650           18 :             !gkm_data_asn1_read_oid (egg_asn1x_node (asn, "parameters", "namedCurve", NULL), &oid) ||
     651            9 :             !gkm_data_asn1_read_bit_string (egg_asn1x_node (asn, "q", NULL), &q, &q_bits))
     652            0 :                 goto done;
     653              : 
     654            9 :         curve = gkm_data_der_oid_to_curve (oid);
     655            9 :         if (curve == NULL)
     656            0 :                 goto done;
     657              : 
     658            9 :         res = gcry_sexp_build (s_key, NULL, SEXP_PRIVATE_ECDSA,
     659              :                                curve,
     660              :                                g_bytes_get_size(q), g_bytes_get_data(q, NULL), d);
     661            9 :         if (res)
     662            0 :                 goto done;
     663              : 
     664            9 :         g_assert (*s_key);
     665            9 :         ret = GKM_DATA_SUCCESS;
     666              : 
     667           15 : done:
     668           15 :         egg_asn1x_destroy (asn);
     669           15 :         gcry_mpi_release (d);
     670           15 :         g_bytes_unref (q);
     671              : 
     672           15 :         if (ret == GKM_DATA_FAILURE)
     673            0 :                 g_message ("invalid ECDSA key");
     674              : 
     675           15 :         return ret;
     676              : }
     677              : 
     678              : GkmDataResult
     679            3 : gkm_data_der_read_public_key (GBytes *data, gcry_sexp_t *s_key)
     680              : {
     681              :         GkmDataResult res;
     682              : 
     683            3 :         res = gkm_data_der_read_public_key_rsa (data, s_key);
     684            3 :         if (res == GKM_DATA_UNRECOGNIZED)
     685            2 :                 res = gkm_data_der_read_public_key_ecdsa (data, s_key);
     686            3 :         if (res == GKM_DATA_UNRECOGNIZED)
     687            1 :                 res = gkm_data_der_read_public_key_dsa (data, s_key);
     688              : 
     689            3 :         return res;
     690              : }
     691              : 
     692              : GkmDataResult
     693          179 : gkm_data_der_read_public_key_info (GBytes *data,
     694              :                                    gcry_sexp_t* s_key)
     695              : {
     696          179 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
     697              :         GQuark oid;
     698          179 :         GNode *asn = NULL;
     699              :         GBytes *params;
     700          179 :         GBytes *key = NULL;
     701              :         guint n_bits;
     702              : 
     703          179 :         init_quarks ();
     704              : 
     705          179 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "SubjectPublicKeyInfo", data);
     706          179 :         if (!asn)
     707            0 :                 goto done;
     708              : 
     709          179 :         ret = GKM_DATA_FAILURE;
     710              : 
     711              :         /* Figure out the algorithm */
     712          179 :         oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "algorithm", "algorithm", NULL));
     713          179 :         if (!oid)
     714            0 :                 goto done;
     715              : 
     716              :         /* A bit string so we cannot process in place */
     717          179 :         key = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "subjectPublicKey", NULL), &n_bits);
     718          179 :         if (!key)
     719            0 :                 goto done;
     720          179 :         if (n_bits % 8 != 0) {
     721            0 :                 g_message ("invalid bit length for public key: %u", n_bits);
     722            0 :                 goto done;
     723              :         }
     724              : 
     725              :         /* An RSA key is simple */
     726          179 :         if (oid == OID_PKIX1_RSA) {
     727          177 :                 ret = gkm_data_der_read_public_key_rsa (key, s_key);
     728              : 
     729              :         /* A DSA key paramaters are stored separately */
     730            2 :         } else if (oid == OID_PKIX1_DSA) {
     731            1 :                 params = egg_asn1x_get_element_raw (egg_asn1x_node (asn, "algorithm", "parameters", NULL));
     732            1 :                 if (!params)
     733            0 :                         goto done;
     734            1 :                 ret = gkm_data_der_read_public_key_dsa_parts (key, params, s_key);
     735            1 :                 g_bytes_unref (params);
     736              : 
     737              :         /* A ECDSA key */
     738            1 :         } else if (oid == OID_PKIX1_ECDSA) {
     739            1 :                 ret = gkm_data_der_read_public_key_ecdsa (key, s_key);
     740              : 
     741              :         } else {
     742            0 :                 g_message ("unsupported key algorithm in certificate: %s", g_quark_to_string (oid));
     743            0 :                 ret = GKM_DATA_UNRECOGNIZED;
     744            0 :                 goto done;
     745              :         }
     746              : 
     747          179 : done:
     748          179 :         egg_asn1x_destroy (asn);
     749          179 :         if (key)
     750          179 :                 g_bytes_unref (key);
     751              : 
     752          179 :         if (ret == GKM_DATA_FAILURE)
     753            0 :                 g_message ("invalid subject public-key info");
     754              : 
     755          179 :         return ret;
     756              : }
     757              : 
     758              : GkmDataResult
     759           23 : gkm_data_der_read_private_key (GBytes *data,
     760              :                                gcry_sexp_t *s_key)
     761              : {
     762              :         GkmDataResult res;
     763              : 
     764           23 :         res = gkm_data_der_read_private_key_rsa (data, s_key);
     765           23 :         if (res == GKM_DATA_UNRECOGNIZED)
     766           18 :                 res = gkm_data_der_read_private_key_dsa (data, s_key);
     767           23 :         if (res == GKM_DATA_UNRECOGNIZED)
     768           13 :                 res = gkm_data_der_read_private_key_ecdsa (data, s_key);
     769              : 
     770           23 :         return res;
     771              : }
     772              : 
     773              : GkmDataResult
     774           25 : gkm_data_der_read_private_pkcs8_plain (GBytes *data,
     775              :                                        gcry_sexp_t *s_key)
     776              : {
     777           25 :         GNode *asn = NULL;
     778              :         GkmDataResult ret;
     779              :         int algorithm;
     780              :         GQuark key_algo;
     781           25 :         GBytes *keydata = NULL;
     782           25 :         GBytes *params = NULL;
     783              : 
     784           25 :         ret = GKM_DATA_UNRECOGNIZED;
     785              : 
     786           25 :         init_quarks ();
     787              : 
     788           25 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo", data);
     789           25 :         if (!asn)
     790            4 :                 goto done;
     791              : 
     792           21 :         ret = GKM_DATA_FAILURE;
     793           21 :         algorithm = 0;
     794              : 
     795           21 :         key_algo = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "privateKeyAlgorithm", "algorithm", NULL));
     796           21 :         if (!key_algo)
     797            0 :                 goto done;
     798           21 :         else if (key_algo == OID_PKIX1_RSA)
     799           16 :                 algorithm = GCRY_PK_RSA;
     800            5 :         else if (key_algo == OID_PKIX1_DSA)
     801            3 :                 algorithm = GCRY_PK_DSA;
     802            2 :         else if (key_algo == OID_PKIX1_ECDSA)
     803            2 :                 algorithm = GCRY_PK_ECC;
     804              : 
     805           21 :         if (!algorithm) {
     806            0 :                 ret = GKM_DATA_UNRECOGNIZED;
     807            0 :                 goto done;
     808              :         }
     809              : 
     810           21 :         keydata = egg_asn1x_get_string_as_bytes (egg_asn1x_node (asn, "privateKey", NULL));
     811           21 :         if (!keydata)
     812            0 :                 goto done;
     813              : 
     814           21 :         params = egg_asn1x_get_element_raw (egg_asn1x_node (asn, "privateKeyAlgorithm", "parameters", NULL));
     815              : 
     816           21 :         ret = GKM_DATA_SUCCESS;
     817              : 
     818           25 : done:
     819           25 :         if (ret == GKM_DATA_SUCCESS) {
     820           21 :                 switch (algorithm) {
     821           16 :                 case GCRY_PK_RSA:
     822           16 :                         ret = gkm_data_der_read_private_key_rsa (keydata, s_key);
     823           16 :                         break;
     824            3 :                 case GCRY_PK_DSA:
     825              :                         /* Try the normal one block format */
     826            3 :                         ret = gkm_data_der_read_private_key_dsa (keydata, s_key);
     827              : 
     828              :                         /* Otherwise try the two part format that everyone seems to like */
     829            3 :                         if (ret == GKM_DATA_UNRECOGNIZED && params)
     830            3 :                                 ret = gkm_data_der_read_private_key_dsa_parts (keydata, params, s_key);
     831            3 :                         break;
     832            2 :                 case GCRY_PK_ECC:
     833            2 :                         ret = gkm_data_der_read_private_key_ecdsa (keydata, s_key);
     834            2 :                         break;
     835            0 :                 default:
     836            0 :                         g_message ("invalid or unsupported key type in PKCS#8 key");
     837            0 :                         ret = GKM_DATA_UNRECOGNIZED;
     838            0 :                         break;
     839              :                 };
     840              : 
     841            4 :         } else if (ret == GKM_DATA_FAILURE) {
     842            0 :                 g_message ("invalid PKCS#8 key");
     843              :         }
     844              : 
     845           25 :         if (params)
     846           15 :                 g_bytes_unref (params);
     847           25 :         if (keydata)
     848           21 :                 g_bytes_unref (keydata);
     849           25 :         egg_asn1x_destroy (asn);
     850           25 :         return ret;
     851              : }
     852              : 
     853              : GkmDataResult
     854           21 : gkm_data_der_read_private_pkcs8_crypted (GBytes *data,
     855              :                                          const gchar *password,
     856              :                                          gsize n_password,
     857              :                                          gcry_sexp_t *s_key)
     858              : {
     859           21 :         GNode *asn = NULL;
     860           21 :         gcry_cipher_hd_t cih = NULL;
     861              :         gcry_error_t gcry;
     862              :         GkmDataResult ret, r;
     863              :         GQuark scheme;
     864           21 :         guchar *crypted = NULL;
     865              :         GNode *params;
     866              :         GBytes *bytes;
     867              :         gsize n_crypted;
     868              :         gint l;
     869              : 
     870           21 :         init_quarks ();
     871              : 
     872           21 :         ret = GKM_DATA_UNRECOGNIZED;
     873              : 
     874           21 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo", data);
     875           21 :         if (!asn)
     876            1 :                 goto done;
     877              : 
     878           20 :         ret = GKM_DATA_FAILURE;
     879              : 
     880              :         /* Figure out the type of encryption */
     881           20 :         scheme = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL));
     882           20 :         if (!scheme)
     883            0 :                 goto done;
     884              : 
     885           20 :         params = egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL);
     886           20 :         if (!params)
     887            0 :                 goto done;
     888              : 
     889              :         /*
     890              :          * Parse the encryption stuff into a cipher.
     891              :          */
     892           20 :         r = egg_symkey_read_cipher (scheme, password, n_password, params, &cih);
     893              : 
     894           20 :         if (r == GKM_DATA_UNRECOGNIZED) {
     895            0 :                 ret = GKM_DATA_FAILURE;
     896            0 :                 goto done;
     897           20 :         } else if (r != GKM_DATA_SUCCESS) {
     898            0 :                 ret = r;
     899            0 :                 goto done;
     900              :         }
     901              : 
     902           20 :         crypted = egg_asn1x_get_string_as_raw (egg_asn1x_node (asn, "encryptedData", NULL),
     903              :                                                egg_secure_realloc, &n_crypted);
     904           20 :         if (!crypted)
     905            0 :                 goto done;
     906              : 
     907           20 :         gcry = gcry_cipher_decrypt (cih, crypted, n_crypted, NULL, 0);
     908           20 :         gcry_cipher_close (cih);
     909           20 :         cih = NULL;
     910              : 
     911           20 :         if (gcry != 0) {
     912            0 :                 g_warning ("couldn't decrypt pkcs8 data: %s", gcry_strerror (gcry));
     913            0 :                 goto done;
     914              :         }
     915              : 
     916              :         /* Unpad the DER data */
     917           20 :         l = egg_asn1x_element_length (crypted, n_crypted);
     918           20 :         if (l <= 0 || l > n_crypted) {
     919            0 :                 ret = GKM_DATA_LOCKED;
     920            0 :                 goto done;
     921              :         }
     922           20 :         n_crypted = l;
     923              : 
     924           20 :         bytes = g_bytes_new_with_free_func (crypted, n_crypted, egg_secure_free, crypted);
     925           20 :         crypted = NULL;
     926              : 
     927              :         /* Try to parse the resulting key */
     928           20 :         ret = gkm_data_der_read_private_pkcs8_plain (bytes, s_key);
     929           20 :         g_bytes_unref (bytes);
     930              : 
     931              :         /* If unrecognized we assume bad password */
     932           20 :         if (ret == GKM_DATA_UNRECOGNIZED)
     933            4 :                 ret = GKM_DATA_LOCKED;
     934              : 
     935           16 : done:
     936           21 :         if (cih)
     937            0 :                 gcry_cipher_close (cih);
     938           21 :         egg_asn1x_destroy (asn);
     939           21 :         egg_secure_free (crypted);
     940              : 
     941           21 :         return ret;
     942              : }
     943              : 
     944              : GkmDataResult
     945           17 : gkm_data_der_read_private_pkcs8 (GBytes *data,
     946              :                                  const gchar *password,
     947              :                                  gsize n_password,
     948              :                                  gcry_sexp_t *s_key)
     949              : {
     950              :         GkmDataResult res;
     951              : 
     952           17 :         res = gkm_data_der_read_private_pkcs8_crypted (data, password, n_password, s_key);
     953           17 :         if (res == GKM_DATA_UNRECOGNIZED)
     954            1 :                 res = gkm_data_der_read_private_pkcs8_plain (data, s_key);
     955              : 
     956           17 :         return res;
     957              : }
     958              : 
     959              : GBytes *
     960            1 : gkm_data_der_write_public_key_rsa (gcry_sexp_t s_key)
     961              : {
     962            1 :         GNode *asn = NULL;
     963              :         gcry_mpi_t n, e;
     964            1 :         GBytes *result = NULL;
     965              : 
     966            1 :         n = e = NULL;
     967              : 
     968            1 :         asn = egg_asn1x_create (pk_asn1_tab, "RSAPublicKey");
     969            1 :         g_return_val_if_fail (asn, NULL);
     970              : 
     971            2 :         if (!gkm_sexp_extract_mpi (s_key, &n, "rsa", "n", NULL) ||
     972            1 :             !gkm_sexp_extract_mpi (s_key, &e, "rsa", "e", NULL))
     973            0 :                 goto done;
     974              : 
     975            2 :         if (!gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "modulus", NULL), n) ||
     976            1 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "publicExponent", NULL), e))
     977            0 :                 goto done;
     978              : 
     979            1 :         result = egg_asn1x_encode (asn, NULL);
     980            1 :         if (result == NULL)
     981            0 :                 g_warning ("couldn't encode public rsa key: %s", egg_asn1x_message (asn));
     982              : 
     983            1 : done:
     984            1 :         egg_asn1x_destroy (asn);
     985            1 :         gcry_mpi_release (n);
     986            1 :         gcry_mpi_release (e);
     987              : 
     988            1 :         return result;
     989              : }
     990              : 
     991              : GBytes *
     992            6 : gkm_data_der_write_private_key_rsa (gcry_sexp_t s_key)
     993              : {
     994            6 :         GNode *asn = NULL;
     995              :         gcry_mpi_t n, e, d, p, q, u, e1, e2, tmp;
     996            6 :         GBytes *result = NULL;
     997              : 
     998            6 :         n = e = d = p = q = u = e1 = e2 = tmp = NULL;
     999              : 
    1000            6 :         asn = egg_asn1x_create (pk_asn1_tab, "RSAPrivateKey");
    1001            6 :         g_return_val_if_fail (asn, NULL);
    1002              : 
    1003           12 :         if (!gkm_sexp_extract_mpi (s_key, &n, "rsa", "n", NULL) ||
    1004           12 :             !gkm_sexp_extract_mpi (s_key, &e, "rsa", "e", NULL) ||
    1005           12 :             !gkm_sexp_extract_mpi (s_key, &d, "rsa", "d", NULL) ||
    1006           12 :             !gkm_sexp_extract_mpi (s_key, &p, "rsa", "p", NULL) ||
    1007           12 :             !gkm_sexp_extract_mpi (s_key, &q, "rsa", "q", NULL) ||
    1008            6 :             !gkm_sexp_extract_mpi (s_key, &u, "rsa", "u", NULL))
    1009            0 :                 goto done;
    1010              : 
    1011           12 :         if (!gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "modulus", NULL), n) ||
    1012           12 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "publicExponent", NULL), e) ||
    1013           12 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "privateExponent", NULL), d) ||
    1014           12 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "prime1", NULL), p) ||
    1015           12 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "prime2", NULL), q) ||
    1016            6 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "coefficient", NULL), u))
    1017            0 :                 goto done;
    1018              : 
    1019              :         /* Calculate e1 and e2 */
    1020            6 :         tmp = gcry_mpi_snew (1024);
    1021            6 :         gcry_mpi_sub_ui (tmp, p, 1);
    1022            6 :         e1 = gcry_mpi_snew (1024);
    1023            6 :         gcry_mpi_mod (e1, d, tmp);
    1024            6 :         gcry_mpi_sub_ui (tmp, q, 1);
    1025            6 :         e2 = gcry_mpi_snew (1024);
    1026            6 :         gcry_mpi_mod (e2, d, tmp);
    1027              : 
    1028              :         /* Write out calculated */
    1029           12 :         if (!gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "exponent1", NULL), e1) ||
    1030            6 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "exponent2", NULL), e2))
    1031            0 :                 goto done;
    1032              : 
    1033              :         /* Write out the version */
    1034            6 :         egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), 0);
    1035              : 
    1036            6 :         result = egg_asn1x_encode (asn, egg_secure_realloc);
    1037            6 :         if (result == NULL)
    1038            0 :                 g_warning ("couldn't encode private rsa key: %s", egg_asn1x_message (asn));
    1039              : 
    1040            6 : done:
    1041            6 :         egg_asn1x_destroy (asn);
    1042            6 :         gcry_mpi_release (n);
    1043            6 :         gcry_mpi_release (e);
    1044            6 :         gcry_mpi_release (d);
    1045            6 :         gcry_mpi_release (p);
    1046            6 :         gcry_mpi_release (q);
    1047            6 :         gcry_mpi_release (u);
    1048              : 
    1049            6 :         gcry_mpi_release (tmp);
    1050            6 :         gcry_mpi_release (e1);
    1051            6 :         gcry_mpi_release (e2);
    1052              : 
    1053            6 :         return result;
    1054              : }
    1055              : 
    1056              : GBytes *
    1057            1 : gkm_data_der_write_public_key_dsa (gcry_sexp_t s_key)
    1058              : {
    1059            1 :         GNode *asn = NULL;
    1060              :         gcry_mpi_t p, q, g, y;
    1061            1 :         GBytes *result = NULL;
    1062              : 
    1063            1 :         p = q = g = y = NULL;
    1064              : 
    1065            1 :         asn = egg_asn1x_create (pk_asn1_tab, "DSAPublicKey");
    1066            1 :         g_return_val_if_fail (asn, NULL);
    1067              : 
    1068            2 :         if (!gkm_sexp_extract_mpi (s_key, &p, "dsa", "p", NULL) ||
    1069            2 :             !gkm_sexp_extract_mpi (s_key, &q, "dsa", "q", NULL) ||
    1070            2 :             !gkm_sexp_extract_mpi (s_key, &g, "dsa", "g", NULL) ||
    1071            1 :             !gkm_sexp_extract_mpi (s_key, &y, "dsa", "y", NULL))
    1072            0 :                 goto done;
    1073              : 
    1074            2 :         if (!gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "p", NULL), p) ||
    1075            2 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "q", NULL), q) ||
    1076            2 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "g", NULL), g) ||
    1077            1 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "Y", NULL), y))
    1078            0 :                 goto done;
    1079              : 
    1080            1 :         egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), 0);
    1081              : 
    1082            1 :         result = egg_asn1x_encode (asn, NULL);
    1083            1 :         if (result == NULL)
    1084            0 :                 g_warning ("couldn't encode public dsa key: %s", egg_asn1x_message (asn));
    1085              : 
    1086            1 : done:
    1087            1 :         egg_asn1x_destroy (asn);
    1088            1 :         gcry_mpi_release (p);
    1089            1 :         gcry_mpi_release (q);
    1090            1 :         gcry_mpi_release (g);
    1091            1 :         gcry_mpi_release (y);
    1092              : 
    1093            1 :         return result;
    1094              : }
    1095              : 
    1096              : GBytes *
    1097            3 : gkm_data_der_write_private_key_dsa_part (gcry_sexp_t skey)
    1098              : {
    1099            3 :         GNode *asn = NULL;
    1100              :         gcry_mpi_t x;
    1101            3 :         GBytes *result = NULL;
    1102              : 
    1103            3 :         x = NULL;
    1104              : 
    1105            3 :         asn = egg_asn1x_create (pk_asn1_tab, "DSAPrivatePart");
    1106            3 :         g_return_val_if_fail (asn, NULL);
    1107              : 
    1108            3 :         if (!gkm_sexp_extract_mpi (skey, &x, "dsa", "x", NULL))
    1109            0 :                 goto done;
    1110              : 
    1111            3 :         if (!gkm_data_asn1_write_mpi (asn, x))
    1112            0 :                 goto done;
    1113              : 
    1114            3 :         result = egg_asn1x_encode (asn, egg_secure_realloc);
    1115            3 :         if (result == NULL)
    1116            0 :                 g_warning ("couldn't encode private dsa key: %s", egg_asn1x_message (asn));
    1117              : 
    1118            3 : done:
    1119            3 :         egg_asn1x_destroy (asn);
    1120            3 :         gcry_mpi_release (x);
    1121              : 
    1122            3 :         return result;
    1123              : }
    1124              : 
    1125              : GBytes *
    1126            3 : gkm_data_der_write_private_key_dsa_params (gcry_sexp_t skey)
    1127              : {
    1128            3 :         GNode *asn = NULL;
    1129              :         gcry_mpi_t p, q, g;
    1130            3 :         GBytes *result = NULL;
    1131              : 
    1132            3 :         p = q = g = NULL;
    1133              : 
    1134            3 :         asn = egg_asn1x_create (pk_asn1_tab, "DSAParameters");
    1135            3 :         g_return_val_if_fail (asn, NULL);
    1136              : 
    1137            6 :         if (!gkm_sexp_extract_mpi (skey, &p, "dsa", "p", NULL) ||
    1138            6 :             !gkm_sexp_extract_mpi (skey, &q, "dsa", "q", NULL) ||
    1139            3 :             !gkm_sexp_extract_mpi (skey, &g, "dsa", "g", NULL))
    1140            0 :                 goto done;
    1141              : 
    1142            6 :         if (!gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "p", NULL), p) ||
    1143            6 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "q", NULL), q) ||
    1144            3 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "g", NULL), g))
    1145            0 :                 goto done;
    1146              : 
    1147            3 :         result = egg_asn1x_encode (asn, egg_secure_realloc);
    1148            3 :         if (result == NULL)
    1149            0 :                 g_warning ("couldn't encode private dsa params: %s", egg_asn1x_message (asn));
    1150              : 
    1151            3 : done:
    1152            3 :         egg_asn1x_destroy (asn);
    1153            3 :         gcry_mpi_release (p);
    1154            3 :         gcry_mpi_release (q);
    1155            3 :         gcry_mpi_release (g);
    1156              : 
    1157            3 :         return result;
    1158              : }
    1159              : 
    1160              : GBytes *
    1161            1 : gkm_data_der_write_private_key_dsa (gcry_sexp_t s_key)
    1162              : {
    1163            1 :         GNode *asn = NULL;
    1164              :         gcry_mpi_t p, q, g, y, x;
    1165            1 :         GBytes *result = NULL;
    1166              : 
    1167            1 :         p = q = g = y = x = NULL;
    1168              : 
    1169            1 :         asn = egg_asn1x_create (pk_asn1_tab, "DSAPrivateKey");
    1170            1 :         g_return_val_if_fail (asn, NULL);
    1171              : 
    1172            2 :         if (!gkm_sexp_extract_mpi (s_key, &p, "dsa", "p", NULL) ||
    1173            2 :             !gkm_sexp_extract_mpi (s_key, &q, "dsa", "q", NULL) ||
    1174            2 :             !gkm_sexp_extract_mpi (s_key, &g, "dsa", "g", NULL) ||
    1175            2 :             !gkm_sexp_extract_mpi (s_key, &y, "dsa", "y", NULL) ||
    1176            1 :             !gkm_sexp_extract_mpi (s_key, &x, "dsa", "x", NULL))
    1177            0 :                 goto done;
    1178              : 
    1179            2 :         if (!gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "p", NULL), p) ||
    1180            2 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "q", NULL), q) ||
    1181            2 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "g", NULL), g) ||
    1182            2 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "Y", NULL), y) ||
    1183            1 :             !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "priv", NULL), x))
    1184            0 :                 goto done;
    1185              : 
    1186            1 :         egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), 0);
    1187              : 
    1188            1 :         result = egg_asn1x_encode (asn, egg_secure_realloc);
    1189            1 :         if (result == NULL)
    1190            0 :                 g_warning ("couldn't encode private dsa key: %s", egg_asn1x_message (asn));
    1191              : 
    1192            1 : done:
    1193            1 :         egg_asn1x_destroy (asn);
    1194            1 :         gcry_mpi_release (p);
    1195            1 :         gcry_mpi_release (q);
    1196            1 :         gcry_mpi_release (g);
    1197            1 :         gcry_mpi_release (y);
    1198            1 :         gcry_mpi_release (x);
    1199              : 
    1200            1 :         return result;
    1201              : }
    1202              : 
    1203              : GBytes *
    1204            1 : gkm_data_der_write_public_key_ecdsa (gcry_sexp_t s_key)
    1205              : {
    1206            1 :         GNode *asn = NULL, *named_curve;
    1207            1 :         gcry_mpi_t d = NULL;
    1208            1 :         GBytes *result = NULL, *q = NULL;
    1209            1 :         gchar *q_data = NULL;
    1210              :         GQuark oid;
    1211            1 :         gchar *curve = NULL;
    1212              :         gsize q_size;
    1213              : 
    1214            1 :         init_quarks ();
    1215              : 
    1216            1 :         asn = egg_asn1x_create (pk_asn1_tab, "ECPublicKey");
    1217            1 :         g_return_val_if_fail (asn, NULL);
    1218              : 
    1219            2 :         if (!gkm_sexp_extract_buffer (s_key, &q_data, &q_size, "ecdsa", "q", NULL) ||
    1220            1 :             !gkm_sexp_extract_string (s_key, &curve, "ecdsa", "curve", NULL))
    1221            0 :                 goto done;
    1222              : 
    1223            1 :         oid = gkm_data_der_curve_to_oid (curve);
    1224            1 :         g_free (curve);
    1225            1 :         if (oid == 0)
    1226            0 :                 goto done;
    1227              : 
    1228            1 :         q = g_bytes_new_take (q_data, q_size);
    1229            1 :         if (q == NULL)
    1230            0 :                 goto done;
    1231              : 
    1232            1 :         named_curve = egg_asn1x_node (asn, "parameters", "namedCurve", NULL);
    1233              : 
    1234              :         /* XXX the bit size does not have to match byte size * 8 exactly
    1235              :          * it would be good to cover this with more tests
    1236              :          */
    1237            2 :         if (!gkm_data_asn1_write_bit_string (egg_asn1x_node (asn, "q", NULL), q, q_size*8) ||
    1238            1 :             !gkm_data_asn1_write_oid (named_curve, oid))
    1239            0 :                 goto done;
    1240              : 
    1241            1 :         if (!egg_asn1x_set_choice (egg_asn1x_node (asn, "parameters", NULL), named_curve))
    1242            0 :                 goto done;
    1243              : 
    1244            1 :         result = egg_asn1x_encode (asn, egg_secure_realloc);
    1245            1 :         if (result == NULL)
    1246            0 :                 g_warning ("couldn't encode public ecdsa key: %s", egg_asn1x_message (asn));
    1247              : 
    1248            1 : done:
    1249            1 :         egg_asn1x_destroy (asn);
    1250            1 :         gcry_mpi_release (d);
    1251            1 :         g_bytes_unref (q);
    1252              : 
    1253            1 :         return result;
    1254              : }
    1255              : 
    1256              : GBytes *
    1257            3 : gkm_data_der_write_private_key_ecdsa (gcry_sexp_t s_key)
    1258              : {
    1259            3 :         GNode *asn = NULL, *named_curve;
    1260            3 :         gcry_mpi_t d = NULL;
    1261            3 :         GBytes *result = NULL, *q = NULL;
    1262            3 :         gchar *q_data = NULL;
    1263              :         GQuark oid;
    1264            3 :         gchar *curve = NULL;
    1265              :         gsize q_size;
    1266              : 
    1267            3 :         init_quarks ();
    1268              : 
    1269            3 :         asn = egg_asn1x_create (pk_asn1_tab, "ECPrivateKey");
    1270            3 :         g_return_val_if_fail (asn, NULL);
    1271              : 
    1272            6 :         if (!gkm_sexp_extract_mpi (s_key, &d, "ecdsa", "d", NULL) ||
    1273            6 :             !gkm_sexp_extract_buffer (s_key, &q_data, &q_size, "ecdsa", "q", NULL) ||
    1274            3 :             !gkm_sexp_extract_string (s_key, &curve, "ecdsa", "curve", NULL))
    1275            0 :                 goto done;
    1276              : 
    1277            3 :         oid = gkm_data_der_curve_to_oid (curve);
    1278            3 :         g_free (curve);
    1279            3 :         if (oid == 0)
    1280            0 :                 goto done;
    1281              : 
    1282            3 :         q = g_bytes_new_take (q_data, q_size);
    1283            3 :         if (q == NULL)
    1284            0 :                 goto done;
    1285              : 
    1286            3 :         named_curve = egg_asn1x_node (asn, "parameters", "namedCurve", NULL);
    1287              : 
    1288            6 :         if (!gkm_data_asn1_write_string_mpi (egg_asn1x_node (asn, "d", NULL), d) ||
    1289            6 :             !gkm_data_asn1_write_bit_string (egg_asn1x_node (asn, "q", NULL), q, q_size*8) ||
    1290            3 :             !gkm_data_asn1_write_oid (named_curve, oid))
    1291            0 :                 goto done;
    1292              : 
    1293            3 :         if (!egg_asn1x_set_choice (egg_asn1x_node (asn, "parameters", NULL), named_curve))
    1294            0 :                 goto done;
    1295              : 
    1296            3 :         egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), 1);
    1297              : 
    1298            3 :         result = egg_asn1x_encode (asn, egg_secure_realloc);
    1299            3 :         if (result == NULL)
    1300            0 :                 g_warning ("couldn't encode private ecdsa key: %s", egg_asn1x_message (asn));
    1301              : 
    1302            3 : done:
    1303            3 :         egg_asn1x_destroy (asn);
    1304            3 :         gcry_mpi_release (d);
    1305            3 :         g_bytes_unref (q);
    1306              : 
    1307            3 :         return result;
    1308              : }
    1309              : 
    1310              : GBytes *
    1311            3 : gkm_data_der_write_public_key (gcry_sexp_t s_key)
    1312              : {
    1313              :         gboolean is_priv;
    1314              :         int algorithm;
    1315              : 
    1316            3 :         g_return_val_if_fail (s_key != NULL, NULL);
    1317              : 
    1318            3 :         if (!gkm_sexp_parse_key (s_key, &algorithm, &is_priv, NULL))
    1319            0 :                 g_return_val_if_reached (NULL);
    1320              : 
    1321            3 :         g_return_val_if_fail (!is_priv, NULL);
    1322              : 
    1323            3 :         switch (algorithm) {
    1324            1 :         case GCRY_PK_RSA:
    1325            1 :                 return gkm_data_der_write_public_key_rsa (s_key);
    1326            1 :         case GCRY_PK_DSA:
    1327            1 :                 return gkm_data_der_write_public_key_dsa (s_key);
    1328            1 :         case GCRY_PK_ECC:
    1329            1 :                 return gkm_data_der_write_public_key_ecdsa (s_key);
    1330            0 :         default:
    1331            0 :                 g_return_val_if_reached (NULL);
    1332              :         }
    1333              : }
    1334              : 
    1335              : GBytes *
    1336            3 : gkm_data_der_write_private_key (gcry_sexp_t s_key)
    1337              : {
    1338              :         gboolean is_priv;
    1339              :         int algorithm;
    1340              : 
    1341            3 :         g_return_val_if_fail (s_key != NULL, NULL);
    1342              : 
    1343            3 :         if (!gkm_sexp_parse_key (s_key, &algorithm, &is_priv, NULL))
    1344            0 :                 g_return_val_if_reached (NULL);
    1345              : 
    1346            3 :         g_return_val_if_fail (is_priv, NULL);
    1347              : 
    1348            3 :         switch (algorithm) {
    1349            1 :         case GCRY_PK_RSA:
    1350            1 :                 return gkm_data_der_write_private_key_rsa (s_key);
    1351            1 :         case GCRY_PK_DSA:
    1352            1 :                 return gkm_data_der_write_private_key_dsa (s_key);
    1353            1 :         case GCRY_PK_ECC:
    1354            1 :                 return gkm_data_der_write_private_key_ecdsa (s_key);
    1355            0 :         default:
    1356            0 :                 g_return_val_if_reached (NULL);
    1357              :         }
    1358              : }
    1359              : 
    1360              : static gcry_cipher_hd_t
    1361            5 : prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password,
    1362              :                                  gsize n_password, gsize *n_block)
    1363              : {
    1364            5 :         GNode *asn1_params = NULL;
    1365              :         gcry_cipher_hd_t cih;
    1366              :         guchar *salt;
    1367              :         gsize n_salt;
    1368              :         gcry_error_t gcry;
    1369              :         guchar *key, *iv;
    1370              :         gsize n_key;
    1371              :         int iterations;
    1372              : 
    1373            5 :         init_quarks ();
    1374              : 
    1375              :         /* Make sure the encryption algorithm works */
    1376            5 :         g_return_val_if_fail (gcry_cipher_algo_info (gcry_cipher_map_name (g_quark_to_string (OID_PKCS12_PBE_3DES_SHA1)),
    1377              :                                                      GCRYCTL_TEST_ALGO, NULL, 0) == 0, NULL);
    1378              : 
    1379              :         /* The encryption algorithm */
    1380            5 :         if(!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL),
    1381              :                                         OID_PKCS12_PBE_3DES_SHA1))
    1382            0 :                 g_return_val_if_reached (NULL);
    1383              : 
    1384              :         /* Randomize some input for the password based secret */
    1385            5 :         iterations = g_random_int_range (1000, 4096);
    1386            5 :         n_salt = 8;
    1387            5 :         salt = g_malloc (n_salt);
    1388            5 :         gcry_create_nonce (salt, n_salt);
    1389              : 
    1390              :         /* Allocate space for the key and iv */
    1391            5 :         n_key = gcry_cipher_get_algo_keylen (GCRY_CIPHER_3DES);
    1392            5 :         *n_block = gcry_cipher_get_algo_blklen (GCRY_MD_SHA1);
    1393            5 :         g_return_val_if_fail (n_key && *n_block, NULL);
    1394              : 
    1395            5 :         if (!egg_symkey_generate_pkcs12 (GCRY_CIPHER_3DES, GCRY_MD_SHA1,
    1396              :                                                 password, n_password, salt,
    1397              :                                                 sizeof (salt), iterations, &key, &iv))
    1398            0 :                 g_return_val_if_reached (NULL);
    1399              : 
    1400              :         /* Now write out the parameters */
    1401            5 :         asn1_params = egg_asn1x_create (pkix_asn1_tab, "pkcs-12-PbeParams");
    1402            5 :         g_return_val_if_fail (asn1_params, NULL);
    1403            5 :         egg_asn1x_set_string_as_raw (egg_asn1x_node (asn1_params, "salt", NULL), salt, n_salt, g_free);
    1404            5 :         egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn1_params, "iterations", NULL), iterations);
    1405            5 :         egg_asn1x_set_any_from (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), asn1_params);
    1406              : 
    1407              :         /* Now make a cipher that matches what we wrote out */
    1408            5 :         gcry = gcry_cipher_open (&cih, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0);
    1409            5 :         g_return_val_if_fail (gcry == 0, NULL);
    1410            5 :         g_return_val_if_fail (cih, NULL);
    1411              : 
    1412            5 :         gcry_cipher_setiv (cih, iv, *n_block);
    1413            5 :         gcry_cipher_setkey (cih, key, n_key);
    1414              : 
    1415            5 :         g_free (iv);
    1416            5 :         egg_secure_free (key);
    1417            5 :         egg_asn1x_destroy (asn1_params);
    1418              : 
    1419            5 :         return cih;
    1420              : }
    1421              : 
    1422              : GBytes *
    1423            9 : gkm_data_der_write_private_pkcs8_plain (gcry_sexp_t skey)
    1424              : {
    1425            9 :         GNode *asn = NULL;
    1426              :         int algorithm;
    1427              :         gboolean is_priv;
    1428              :         GQuark oid;
    1429              :         GBytes *params;
    1430              :         GBytes *key;
    1431              :         GBytes *data;
    1432              : 
    1433            9 :         init_quarks ();
    1434              : 
    1435              :         /* Parse and check that the key is for real */
    1436            9 :         if (!gkm_sexp_parse_key (skey, &algorithm, &is_priv, NULL))
    1437            0 :                 g_return_val_if_reached (NULL);
    1438            9 :         g_return_val_if_fail (is_priv == TRUE, NULL);
    1439              : 
    1440            9 :         asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo");
    1441            9 :         g_return_val_if_fail (asn, NULL);
    1442              : 
    1443              :         /* Write out the version */
    1444            9 :         egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), 0);
    1445              : 
    1446              :         /* Per algorithm differences */
    1447            9 :         switch (algorithm)
    1448              :         {
    1449              :         /* RSA gets encoded in a standard simple way */
    1450            5 :         case GCRY_PK_RSA:
    1451            5 :                 oid = OID_PKIX1_RSA;
    1452            5 :                 params = NULL;
    1453            5 :                 key = gkm_data_der_write_private_key_rsa (skey);
    1454            5 :                 break;
    1455              : 
    1456              :         /* DSA gets incoded with the params seperate */
    1457            2 :         case GCRY_PK_DSA:
    1458            2 :                 oid = OID_PKIX1_DSA;
    1459            2 :                 key = gkm_data_der_write_private_key_dsa_part (skey);
    1460            2 :                 params = gkm_data_der_write_private_key_dsa_params (skey);
    1461            2 :                 break;
    1462              : 
    1463            2 :         case GCRY_PK_ECC:
    1464            2 :                 oid = OID_PKIX1_ECDSA;
    1465            2 :                 params = NULL;
    1466            2 :                 key = gkm_data_der_write_private_key_ecdsa (skey);
    1467            2 :                 break;
    1468              : 
    1469            0 :         default:
    1470            0 :                 g_warning ("trying to serialize unsupported private key algorithm: %d", algorithm);
    1471            0 :                 return NULL;
    1472              :         };
    1473              : 
    1474              :         /* Write out the algorithm */
    1475            9 :         if (!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "privateKeyAlgorithm", "algorithm", NULL), oid))
    1476            0 :                 g_return_val_if_reached (NULL);
    1477              : 
    1478              :         /* Write out the parameters */
    1479            9 :         if (params) {
    1480            2 :                 egg_asn1x_set_any_raw (egg_asn1x_node (asn, "privateKeyAlgorithm", "parameters", NULL), params);
    1481            2 :                 g_bytes_unref (params);
    1482              :         }
    1483              : 
    1484              :         /* Write out the key portion */
    1485            9 :         egg_asn1x_set_string_as_bytes (egg_asn1x_node (asn, "privateKey", NULL), key);
    1486            9 :         g_bytes_unref (key);
    1487              : 
    1488            9 :         data = egg_asn1x_encode (asn, egg_secure_realloc);
    1489            9 :         if (data == NULL)
    1490            0 :                 g_warning ("couldn't encode private pkcs8 key: %s", egg_asn1x_message (asn));
    1491              : 
    1492            9 :         egg_asn1x_destroy (asn);
    1493            9 :         return data;
    1494              : }
    1495              : 
    1496              : GBytes *
    1497            5 : gkm_data_der_write_private_pkcs8_crypted (gcry_sexp_t skey,
    1498              :                                           const gchar *password,
    1499              :                                           gsize n_password)
    1500              : {
    1501              :         gcry_error_t gcry;
    1502              :         gcry_cipher_hd_t cih;
    1503            5 :         GNode *asn = NULL;
    1504              :         GBytes *key, *data;
    1505              :         guchar *raw;
    1506              :         gsize n_raw, n_key;
    1507            5 :         gsize block = 0;
    1508              : 
    1509              :         /* Encode the key in normal pkcs8 fashion */
    1510            5 :         key = gkm_data_der_write_private_pkcs8_plain (skey);
    1511            5 :         if (key == NULL)
    1512            0 :                 return NULL;
    1513              : 
    1514            5 :         asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo");
    1515            5 :         g_return_val_if_fail (asn, NULL);
    1516              : 
    1517              :         /* Create a and write out a cipher used for encryption */
    1518            5 :         cih = prepare_and_encode_pkcs8_cipher (asn, password, n_password, &block);
    1519            5 :         g_return_val_if_fail (cih, NULL);
    1520              : 
    1521            5 :         n_key = g_bytes_get_size (key);
    1522              : 
    1523              :         /* Pad the block of data */
    1524            5 :         if(block > 1) {
    1525            5 :                 gsize n_pad = block - (n_key % block);
    1526            5 :                 if (n_pad == 0)
    1527            0 :                         n_pad = block;
    1528            5 :                 raw = egg_secure_alloc (n_key + n_pad);
    1529            5 :                 memcpy (raw, g_bytes_get_data (key, NULL), n_key);
    1530            5 :                 memset (raw + n_key, (int)n_pad, n_pad);
    1531            5 :                 n_raw = n_key + n_pad;
    1532              : 
    1533              :         /* No padding, probably stream cipher */
    1534              :         } else {
    1535            0 :                 raw = egg_secure_alloc (n_key);
    1536            0 :                 memcpy (raw, g_bytes_get_data (key, NULL), n_key);
    1537            0 :                 n_raw = n_key;
    1538              :         }
    1539              : 
    1540            5 :         g_bytes_unref (key);
    1541              : 
    1542            5 :         gcry = gcry_cipher_encrypt (cih, raw, n_raw, NULL, 0);
    1543            5 :         g_return_val_if_fail (gcry == 0, NULL);
    1544              : 
    1545            5 :         gcry_cipher_close (cih);
    1546            5 :         key = g_bytes_new_with_free_func (raw, n_raw, egg_secure_free, raw);
    1547              : 
    1548            5 :         egg_asn1x_set_string_as_bytes (egg_asn1x_node (asn, "encryptedData", NULL), key);
    1549              : 
    1550            5 :         g_bytes_unref (key);
    1551              : 
    1552            5 :         data = egg_asn1x_encode (asn, NULL);
    1553            5 :         if (data == NULL)
    1554            0 :                 g_warning ("couldn't encode encrypted pkcs8 key: %s", egg_asn1x_message (asn));
    1555              : 
    1556            5 :         egg_asn1x_destroy (asn);
    1557            5 :         return data;
    1558              : }
    1559              : 
    1560              : /* -----------------------------------------------------------------------------
    1561              :  * CERTIFICATES
    1562              :  */
    1563              : 
    1564              : GkmDataResult
    1565          179 : gkm_data_der_read_certificate (GBytes *data,
    1566              :                                GNode **asn1)
    1567              : {
    1568          179 :         *asn1 = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", data);
    1569          179 :         if (!*asn1)
    1570            0 :                 return GKM_DATA_UNRECOGNIZED;
    1571              : 
    1572          179 :         return GKM_DATA_SUCCESS;
    1573              : }
    1574              : 
    1575              : GkmDataResult
    1576            1 : gkm_data_der_read_basic_constraints (GBytes *data,
    1577              :                                      gboolean *is_ca,
    1578              :                                      gint *path_len)
    1579              : {
    1580            1 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
    1581            1 :         GNode *asn = NULL;
    1582              :         GNode *node;
    1583              :         gulong value;
    1584              : 
    1585            1 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "BasicConstraints", data);
    1586            1 :         if (!asn)
    1587            0 :                 goto done;
    1588              : 
    1589            1 :         ret = GKM_DATA_FAILURE;
    1590              : 
    1591            1 :         if (path_len) {
    1592            1 :                 node = egg_asn1x_node (asn, "pathLenConstraint", NULL);
    1593            1 :                 if (!egg_asn1x_have (node))
    1594            1 :                         *path_len = -1;
    1595            0 :                 else if (!egg_asn1x_get_integer_as_ulong (node, &value))
    1596            0 :                         goto done;
    1597              :                 else
    1598            0 :                         *path_len = value;
    1599              :         }
    1600              : 
    1601            1 :         if (is_ca) {
    1602            1 :                 node = egg_asn1x_node (asn, "cA", NULL);
    1603            1 :                 if (!egg_asn1x_have (node))
    1604            0 :                         *is_ca = FALSE;
    1605            1 :                 else if (!egg_asn1x_get_boolean (node, is_ca))
    1606            0 :                         goto done;
    1607              :         }
    1608              : 
    1609            1 :         ret = GKM_DATA_SUCCESS;
    1610              : 
    1611            1 : done:
    1612            1 :         egg_asn1x_destroy (asn);
    1613            1 :         if (ret == GKM_DATA_FAILURE)
    1614            0 :                 g_message ("invalid basic constraints");
    1615              : 
    1616            1 :         return ret;
    1617              : }
    1618              : 
    1619              : GkmDataResult
    1620            1 : gkm_data_der_read_key_usage (GBytes *data,
    1621              :                              gulong *key_usage)
    1622              : {
    1623            1 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
    1624            1 :         GNode *asn = NULL;
    1625              :         guint n_bits;
    1626              : 
    1627            1 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "KeyUsage", data);
    1628            1 :         if (!asn)
    1629            0 :                 goto done;
    1630              : 
    1631            1 :         ret = GKM_DATA_FAILURE;
    1632              : 
    1633            1 :         if (!egg_asn1x_get_bits_as_ulong (asn, key_usage, &n_bits))
    1634            0 :                 goto done;
    1635              : 
    1636            1 :         ret = GKM_DATA_SUCCESS;
    1637              : 
    1638            1 : done:
    1639            1 :         egg_asn1x_destroy (asn);
    1640            1 :         return ret;
    1641              : }
    1642              : 
    1643              : GkmDataResult
    1644            1 : gkm_data_der_read_enhanced_usage (GBytes *data,
    1645              :                                   GQuark **usage_oids)
    1646              : {
    1647            1 :         GkmDataResult ret = GKM_DATA_UNRECOGNIZED;
    1648            1 :         GNode *asn = NULL;
    1649              :         GNode *node;
    1650              :         GArray *array;
    1651              :         GQuark oid;
    1652              :         int i;
    1653              : 
    1654            1 :         asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "ExtKeyUsageSyntax", data);
    1655            1 :         if (!asn)
    1656            0 :                 goto done;
    1657              : 
    1658            1 :         ret = GKM_DATA_FAILURE;
    1659              : 
    1660            1 :         array = g_array_new (TRUE, TRUE, sizeof (GQuark));
    1661            1 :         for (i = 0; TRUE; ++i) {
    1662            2 :                 node = egg_asn1x_node (asn, i + 1, NULL);
    1663            2 :                 if (node == NULL)
    1664            1 :                         break;
    1665              : 
    1666            1 :                 oid = egg_asn1x_get_oid_as_quark (node);
    1667            1 :                 g_array_append_val (array, oid);
    1668              :         }
    1669              : 
    1670            1 :         *usage_oids = (GQuark*)g_array_free (array, FALSE);
    1671            1 :         ret = GKM_DATA_SUCCESS;
    1672              : 
    1673            1 : done:
    1674            1 :         egg_asn1x_destroy (asn);
    1675            1 :         return ret;
    1676              : }
    1677              : 
    1678              : 
    1679              : GBytes *
    1680            1 : gkm_data_der_write_certificate (GNode *asn1)
    1681              : {
    1682              :         GBytes *result;
    1683              : 
    1684            1 :         g_return_val_if_fail (asn1, NULL);
    1685              : 
    1686            1 :         result = egg_asn1x_encode (asn1, NULL);
    1687            1 :         if (result == NULL)
    1688            0 :                 g_warning ("couldn't encode certificate: %s", egg_asn1x_message (asn1));
    1689              : 
    1690            1 :         return result;
    1691              : }
        

Generated by: LCOV version 2.0-1