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-public-key.h"
31 #include "gkm-session.h"
32 #include "gkm-transaction.h"
33 #include "gkm-util.h"
34 
35 struct _GkmDhPublicKey {
36 	GkmDhKey parent;
37 	gcry_mpi_t value;
38 };
39 
40 G_DEFINE_TYPE (GkmDhPublicKey, gkm_dh_public_key, GKM_TYPE_DH_KEY);
41 
42 /* -----------------------------------------------------------------------------
43  * INTERNAL
44  */
45 
46 static GkmObject*
factory_create_dh_public_key(GkmSession * session,GkmTransaction * transaction,CK_ATTRIBUTE_PTR attrs,CK_ULONG n_attrs)47 factory_create_dh_public_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_public_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_PUBLIC_KEY
83  */
84 
85 static CK_RV
gkm_dh_public_key_real_get_attribute(GkmObject * base,GkmSession * session,CK_ATTRIBUTE * attr)86 gkm_dh_public_key_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE* attr)
87 {
88 	GkmDhPublicKey *self = GKM_DH_PUBLIC_KEY (base);
89 
90 	switch (attr->type)
91 	{
92 
93 	case CKA_CLASS:
94 		return gkm_attribute_set_ulong (attr, CKO_PUBLIC_KEY);
95 
96 	case CKA_DERIVE:
97 		return gkm_attribute_set_bool (attr, FALSE);
98 
99 	case CKA_ENCRYPT:
100 		return gkm_attribute_set_bool (attr, FALSE);
101 
102 	case CKA_VERIFY:
103 		return gkm_attribute_set_bool (attr, FALSE);
104 
105 	case CKA_VERIFY_RECOVER:
106 		return gkm_attribute_set_bool (attr, FALSE);
107 
108 	case CKA_WRAP:
109 		return gkm_attribute_set_bool (attr, FALSE);
110 
111 	case CKA_TRUSTED:
112 		return gkm_attribute_set_bool (attr, FALSE);
113 
114 	case CKA_WRAP_TEMPLATE:
115 		gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: no CKA_WRAP_TEMPLATE attribute");
116 		return CKR_ATTRIBUTE_TYPE_INVALID;
117 
118 	case CKA_VALUE:
119 		return gkm_attribute_set_mpi (attr, self->value);
120 	};
121 
122 	return GKM_OBJECT_CLASS (gkm_dh_public_key_parent_class)->get_attribute (base, session, attr);
123 }
124 
125 static void
gkm_dh_public_key_init(GkmDhPublicKey * self)126 gkm_dh_public_key_init (GkmDhPublicKey *self)
127 {
128 
129 }
130 
131 static void
gkm_dh_public_key_finalize(GObject * obj)132 gkm_dh_public_key_finalize (GObject *obj)
133 {
134 	GkmDhPublicKey *self = GKM_DH_PUBLIC_KEY (obj);
135 
136 	gcry_mpi_release (self->value);
137 	self->value = NULL;
138 
139 	G_OBJECT_CLASS (gkm_dh_public_key_parent_class)->finalize (obj);
140 }
141 
142 static void
gkm_dh_public_key_class_init(GkmDhPublicKeyClass * klass)143 gkm_dh_public_key_class_init (GkmDhPublicKeyClass *klass)
144 {
145 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
146 	GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
147 
148 	gkm_dh_public_key_parent_class = g_type_class_peek_parent (klass);
149 
150 	gobject_class->finalize = gkm_dh_public_key_finalize;
151 
152 	gkm_class->get_attribute = gkm_dh_public_key_real_get_attribute;
153 }
154 
155 /* -----------------------------------------------------------------------------
156  * PUBLIC
157  */
158 
159 GkmFactory*
gkm_dh_public_key_get_factory(void)160 gkm_dh_public_key_get_factory (void)
161 {
162 	static CK_OBJECT_CLASS klass = CKO_PUBLIC_KEY;
163 	static CK_KEY_TYPE type = CKK_DH;
164 
165 	static CK_ATTRIBUTE attributes[] = {
166 		{ CKA_CLASS, &klass, sizeof (klass) },
167 		{ CKA_KEY_TYPE, &type, sizeof (type) }
168 	};
169 
170 	static GkmFactory factory = {
171 		attributes,
172 		G_N_ELEMENTS (attributes),
173 		factory_create_dh_public_key
174 	};
175 
176 	return &factory;
177 }
178 
179 GkmDhPublicKey*
gkm_dh_public_key_new(GkmModule * module,GkmManager * manager,gcry_mpi_t prime,gcry_mpi_t base,gcry_mpi_t value,gpointer id,gsize n_id)180 gkm_dh_public_key_new (GkmModule *module, GkmManager *manager,
181                        gcry_mpi_t prime, gcry_mpi_t base, gcry_mpi_t value,
182                        gpointer id, gsize n_id)
183 {
184 	GkmDhPublicKey *key;
185 
186 	key = g_object_new (GKM_TYPE_DH_PUBLIC_KEY,
187 	                    "manager", manager,
188 	                    "module", module,
189 	                    NULL);
190 
191 	key->value = value;
192 	gkm_dh_key_initialize (GKM_DH_KEY (key), prime, base, id, n_id);
193 	return key;
194 }
195