Imported Upstream version 2.34.0
[platform/upstream/glib-networking.git] / tls / gnutls / gtlscertificate-gnutls-pkcs11.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright © 2011 Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Stef Walter <stefw@collabora.co.uk>
21  */
22
23 #include "config.h"
24
25 #include <gnutls/gnutls.h>
26 #include <gnutls/pkcs11.h>
27 #include <string.h>
28
29 #include "gtlscertificate-gnutls.h"
30 #include "gtlscertificate-gnutls-pkcs11.h"
31
32 G_DEFINE_TYPE (GTlsCertificateGnutlsPkcs11, g_tls_certificate_gnutls_pkcs11,
33                G_TYPE_TLS_CERTIFICATE_GNUTLS);
34
35 enum
36 {
37   PROP_0,
38
39   PROP_CERTIFICATE_URI,
40   PROP_PRIVATE_KEY_URI
41 };
42
43 struct _GTlsCertificateGnutlsPkcs11Private
44 {
45   gchar *certificate_uri;
46   gchar *private_key_uri;
47 };
48
49 static void
50 g_tls_certificate_gnutls_pkcs11_finalize (GObject *object)
51 {
52   GTlsCertificateGnutlsPkcs11 *self = G_TLS_CERTIFICATE_GNUTLS_PKCS11 (object);
53
54   g_free (self->priv->certificate_uri);
55   g_free (self->priv->private_key_uri);
56
57   G_OBJECT_CLASS (g_tls_certificate_gnutls_pkcs11_parent_class)->finalize (object);
58 }
59
60 static void
61 g_tls_certificate_gnutls_pkcs11_get_property (GObject    *object,
62                                               guint       prop_id,
63                                               GValue     *value,
64                                               GParamSpec *pspec)
65 {
66   GTlsCertificateGnutlsPkcs11 *self = G_TLS_CERTIFICATE_GNUTLS_PKCS11 (object);
67
68   switch (prop_id)
69     {
70     case PROP_CERTIFICATE_URI:
71       g_value_set_string (value, self->priv->certificate_uri);
72       break;
73     case PROP_PRIVATE_KEY_URI:
74       g_value_set_string (value, self->priv->private_key_uri);
75       break;
76     default:
77       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
78     }
79 }
80
81 static void
82 g_tls_certificate_gnutls_pkcs11_set_property (GObject      *object,
83                                               guint         prop_id,
84                                               const GValue *value,
85                                               GParamSpec   *pspec)
86 {
87   GTlsCertificateGnutlsPkcs11 *self = G_TLS_CERTIFICATE_GNUTLS_PKCS11 (object);
88
89   switch (prop_id)
90     {
91     case PROP_CERTIFICATE_URI:
92       g_free (self->priv->certificate_uri);
93       self->priv->certificate_uri = g_value_dup_string (value);
94       break;
95     case PROP_PRIVATE_KEY_URI:
96       g_free (self->priv->private_key_uri);
97       self->priv->private_key_uri = g_value_dup_string (value);
98       break;
99     default:
100       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
101     }
102 }
103
104 static void
105 g_tls_certificate_gnutls_pkcs11_init (GTlsCertificateGnutlsPkcs11 *self)
106 {
107   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
108                                             G_TYPE_TLS_CERTIFICATE_GNUTLS_PKCS11,
109                                             GTlsCertificateGnutlsPkcs11Private);
110 }
111
112 static void
113 g_tls_certificate_gnutls_pkcs11_copy (GTlsCertificateGnutls    *gnutls,
114                                       const gchar              *interaction_id,
115                                       gnutls_retr2_st          *st)
116 {
117   GTlsCertificateGnutlsPkcs11 *self = G_TLS_CERTIFICATE_GNUTLS_PKCS11 (gnutls);
118   gchar *uri;
119
120   st->key.x509 = NULL;
121
122   /* Let the base class copy certificate in */
123   G_TLS_CERTIFICATE_GNUTLS_CLASS (g_tls_certificate_gnutls_pkcs11_parent_class)->copy (gnutls,
124                                                                                        interaction_id,
125                                                                                        st);
126
127   /* This is the allocation behavior we expect from base class */
128   g_assert (st->deinit_all);
129
130   /* If the base class somehow put a key in, then respect that */
131   if (st->key.x509 == NULL)
132     {
133       uri = g_tls_certificate_gnutls_pkcs11_build_private_key_uri (self, interaction_id);
134       if (uri != NULL)
135         {
136           gnutls_pkcs11_privkey_init (&st->key.pkcs11);
137           gnutls_pkcs11_privkey_import_url (st->key.pkcs11, uri, GNUTLS_PKCS11_URL_GENERIC);
138           st->key_type = GNUTLS_PRIVKEY_PKCS11;
139           g_free (uri);
140         }
141     }
142 }
143
144 static void
145 g_tls_certificate_gnutls_pkcs11_class_init (GTlsCertificateGnutlsPkcs11Class *klass)
146 {
147   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
148   GTlsCertificateGnutlsClass *gnutls_class = G_TLS_CERTIFICATE_GNUTLS_CLASS (klass);
149
150   g_type_class_add_private (klass, sizeof (GTlsCertificateGnutlsPkcs11Private));
151
152   gobject_class->get_property = g_tls_certificate_gnutls_pkcs11_get_property;
153   gobject_class->set_property = g_tls_certificate_gnutls_pkcs11_set_property;
154   gobject_class->finalize     = g_tls_certificate_gnutls_pkcs11_finalize;
155
156   gnutls_class->copy = g_tls_certificate_gnutls_pkcs11_copy;
157
158   g_object_class_install_property (gobject_class, PROP_CERTIFICATE_URI,
159                   g_param_spec_string ("certificate-uri", "Certificate URI",
160                                        "PKCS#11 URI of Certificate", NULL,
161                                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
162
163   g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY_URI,
164                   g_param_spec_string ("private-key-uri", "Private Key URI",
165                                        "PKCS#11 URI of Private Key", NULL,
166                                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
167 }
168
169 GTlsCertificate *
170 g_tls_certificate_gnutls_pkcs11_new (gpointer certificate_data,
171                                      gsize certificate_data_length,
172                                      const gchar *certificate_uri,
173                                      const gchar *private_key_uri,
174                                      GTlsCertificate    *issuer)
175 {
176   GTlsCertificate *certificate;
177   gnutls_datum_t datum;
178
179   g_return_val_if_fail (certificate_data, NULL);
180   g_return_val_if_fail (certificate_uri, NULL);
181
182   datum.data = certificate_data;
183   datum.size = certificate_data_length;
184
185   certificate = g_object_new (G_TYPE_TLS_CERTIFICATE_GNUTLS_PKCS11,
186                               "issuer", issuer,
187                               "certificate-uri", certificate_uri,
188                               "private-key-uri", private_key_uri,
189                               NULL);
190
191   g_tls_certificate_gnutls_set_data (G_TLS_CERTIFICATE_GNUTLS (certificate), &datum);
192
193   return certificate;
194 }
195
196 gchar *
197 g_tls_certificate_gnutls_pkcs11_build_certificate_uri (GTlsCertificateGnutlsPkcs11 *self,
198                                                        const gchar *interaction_id)
199 {
200   g_return_val_if_fail (G_IS_TLS_CERTIFICATE_GNUTLS_PKCS11 (self), NULL);
201   if (self->priv->certificate_uri == NULL)
202     return NULL;
203   else if (interaction_id)
204     return g_strdup_printf ("%s;pinfile=%s", self->priv->certificate_uri, interaction_id);
205   else
206     return g_strdup (self->priv->certificate_uri);
207 }
208
209 gchar *
210 g_tls_certificate_gnutls_pkcs11_build_private_key_uri (GTlsCertificateGnutlsPkcs11 *self,
211                                                        const gchar *interaction_id)
212 {
213   if (self->priv->private_key_uri == NULL)
214     return NULL;
215   else if (interaction_id)
216     return g_strdup_printf ("%s;pinfile=%s", self->priv->private_key_uri, interaction_id);
217   else
218     return g_strdup (self->priv->private_key_uri);
219 }