1 /*
2  * gnome-keyring
3  *
4  * Copyright (C) 2008 Stefan Walter
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include "pkcs11/pkcs11.h"
24 
25 #include "gkm-attributes.h"
26 #include "gkm-crypto.h"
27 #define DEBUG_FLAG GKM_DEBUG_OBJECT
28 #include "gkm-debug.h"
29 #include "gkm-factory.h"
30 #include "gkm-dh-private-key.h"
31 #include "gkm-session.h"
32 #include "gkm-transaction.h"
33 #include "gkm-util.h"
34 
35 struct _GkmDhPrivateKey {
36 	GkmDhKey parent;
37 	gcry_mpi_t value;
38 };
39 
40 G_DEFINE_TYPE (GkmDhPrivateKey, gkm_dh_private_key, GKM_TYPE_DH_KEY);
41 
42 /* -----------------------------------------------------------------------------
43  * INTERNAL
44  */
45 
46 static GkmObject*
factory_create_dh_private_key(GkmSession * session,GkmTransaction * transaction,CK_ATTRIBUTE_PTR attrs,CK_ULONG n_attrs)47 factory_create_dh_private_key (GkmSession *session, GkmTransaction *transaction,
48                                CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
49 {
50 	GkmManager *manager;
51 	gcry_mpi_t prime = NULL;
52 	gcry_mpi_t base = NULL;
53 	gcry_mpi_t value = NULL;
54 	CK_ATTRIBUTE_PTR idattr;
55 	GkmObject *object;
56 
57 	if (!gkm_attributes_find_mpi (attrs, n_attrs, CKA_PRIME, &prime) ||
58 	    !gkm_attributes_find_mpi (attrs, n_attrs, CKA_BASE, &base) ||
59 	    !gkm_attributes_find_mpi (attrs, n_attrs, CKA_VALUE, &value)) {
60 		gcry_mpi_release (prime);
61 		gcry_mpi_release (base);
62 		gcry_mpi_release (value);
63 		gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
64 		return NULL;
65 	}
66 
67 	manager = gkm_manager_for_template (attrs, n_attrs, session);
68 	idattr = gkm_attributes_find (attrs, n_attrs, CKA_ID);
69 
70 	object = GKM_OBJECT (gkm_dh_private_key_new (gkm_session_get_module (session),
71 	                                            manager, prime, base, value,
72 	                                            idattr ? g_memdup (idattr->pValue, idattr->ulValueLen) : NULL,
73 	                                            idattr ? idattr->ulValueLen : 0));
74 	gkm_attributes_consume (attrs, n_attrs, CKA_PRIME, CKA_BASE, CKA_VALUE, G_MAXULONG);
75 
76 	gkm_session_complete_object_creation (session, transaction, object,
77 	                                      TRUE, attrs, n_attrs);
78 	return object;
79 }
80 
81 /* -----------------------------------------------------------------------------
82  * DH_PRIVATE_KEY
83  */
84 
85 static CK_RV
gkm_dh_private_key_real_get_attribute(GkmObject * base,GkmSession * session,CK_ATTRIBUTE * attr)86 gkm_dh_private_key_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE* attr)
87 {
88 	GkmDhPrivateKey *self = GKM_DH_PRIVATE_KEY (base);
89 
90 	switch (attr->type)
91 	{
92 
93 	case CKA_CLASS:
94 		return gkm_attribute_set_ulong (attr, CKO_PRIVATE_KEY);
95 
96 	case CKA_PRIVATE:
97 		return gkm_attribute_set_bool (attr, TRUE);
98 
99 	case CKA_SENSITIVE:
100 		return gkm_attribute_set_bool (attr, FALSE);
101 
102 	case CKA_DECRYPT:
103 		return gkm_attribute_set_bool (attr, FALSE);
104 
105 	case CKA_SIGN:
106 		return gkm_attribute_set_bool (attr, FALSE);
107 
108 	case CKA_SIGN_RECOVER:
109 		return gkm_attribute_set_bool (attr, FALSE);
110 
111 	case CKA_DERIVE:
112 		return gkm_attribute_set_bool (attr, TRUE);
113 
114 	case CKA_UNWRAP:
115 		return gkm_attribute_set_bool (attr, FALSE);
116 
117 	case CKA_EXTRACTABLE:
118 		return gkm_attribute_set_bool (attr, TRUE);
119 
120 	case CKA_ALWAYS_SENSITIVE:
121 		return gkm_attribute_set_bool (attr, FALSE);
122 
123 	case CKA_NEVER_EXTRACTABLE:
124 		return gkm_attribute_set_bool (attr, FALSE);
125 
126 	case CKA_WRAP_WITH_TRUSTED:
127 		return gkm_attribute_set_bool (attr, FALSE);
128 
129 	case CKA_UNWRAP_TEMPLATE:
130 		gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: no CKA_UNWRAP_TEMPLATE attribute");
131 		return CKR_ATTRIBUTE_TYPE_INVALID;
132 
133 	case CKA_ALWAYS_AUTHENTICATE:
134 		return gkm_attribute_set_bool (attr, FALSE);
135 
136 	case CKA_VALUE:
137 		return gkm_attribute_set_mpi (attr, self->value);
138 
139 	case CKA_VALUE_BITS:
140 		return gkm_attribute_set_ulong (attr, gcry_mpi_get_nbits (self->value));
141 	};
142 
143 	return GKM_OBJECT_CLASS (gkm_dh_private_key_parent_class)->get_attribute (base, session, attr);
144 }
145 
146 static void
gkm_dh_private_key_init(GkmDhPrivateKey * self)147 gkm_dh_private_key_init (GkmDhPrivateKey *self)
148 {
149 
150 }
151 
152 static void
gkm_dh_private_key_finalize(GObject * obj)153 gkm_dh_private_key_finalize (GObject *obj)
154 {
155 	GkmDhPrivateKey *self = GKM_DH_PRIVATE_KEY (obj);
156 
157 	gcry_mpi_release (self->value);
158 	self->value = NULL;
159 
160 	G_OBJECT_CLASS (gkm_dh_private_key_parent_class)->finalize (obj);
161 }
162 
163 static void
gkm_dh_private_key_class_init(GkmDhPrivateKeyClass * klass)164 gkm_dh_private_key_class_init (GkmDhPrivateKeyClass *klass)
165 {
166 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
167 	GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
168 
169 	gkm_dh_private_key_parent_class = g_type_class_peek_parent (klass);
170 
171 	gobject_class->finalize = gkm_dh_private_key_finalize;
172 
173 	gkm_class->get_attribute = gkm_dh_private_key_real_get_attribute;
174 }
175 
176 /* -----------------------------------------------------------------------------
177  * PRIVATE
178  */
179 
180 GkmFactory*
gkm_dh_private_key_get_factory(void)181 gkm_dh_private_key_get_factory (void)
182 {
183 	static CK_OBJECT_CLASS klass = CKO_PRIVATE_KEY;
184 	static CK_KEY_TYPE type = CKK_DH;
185 
186 	static CK_ATTRIBUTE attributes[] = {
187 		{ CKA_CLASS, &klass, sizeof (klass) },
188 		{ CKA_KEY_TYPE, &type, sizeof (type) }
189 	};
190 
191 	static GkmFactory factory = {
192 		attributes,
193 		G_N_ELEMENTS (attributes),
194 		factory_create_dh_private_key
195 	};
196 
197 	return &factory;
198 }
199 
200 GkmDhPrivateKey*
gkm_dh_private_key_new(GkmModule * module,GkmManager * manager,gcry_mpi_t prime,gcry_mpi_t base,gcry_mpi_t value,gpointer id,gsize n_id)201 gkm_dh_private_key_new (GkmModule *module, GkmManager *manager,
202                         gcry_mpi_t prime, gcry_mpi_t base, gcry_mpi_t value,
203                         gpointer id, gsize n_id)
204 {
205 	GkmDhPrivateKey *key;
206 
207 	key = g_object_new (GKM_TYPE_DH_PRIVATE_KEY,
208 	                    "manager", manager,
209 	                    "module", module,
210 	                    NULL);
211 
212 	gkm_dh_key_initialize (GKM_DH_KEY (key), prime, base, id, n_id);
213 	key->value = value;
214 	return key;
215 }
216 
217 gcry_mpi_t
gkm_dh_private_key_get_value(GkmDhPrivateKey * self)218 gkm_dh_private_key_get_value (GkmDhPrivateKey *self)
219 {
220 	g_return_val_if_fail (GKM_IS_DH_PRIVATE_KEY (self), NULL);
221 	return self->value;
222 }
223