~ubuntu-branches/ubuntu/natty/gnome-keyring/natty

« back to all changes in this revision

Viewing changes to pkcs11/gck/gck-aes-key.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2010-02-16 19:00:06 UTC
  • mfrom: (1.1.58 upstream)
  • Revision ID: james.westby@ubuntu.com-20100216190006-cqpnic4zxlkmmi0o
Tags: 2.29.90git20100218-0ubuntu1
Updated to a git snapshot version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
19
 * 02111-1307, USA.
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include "pkcs11/pkcs11.h"
 
25
 
 
26
#include "gck-aes-mechanism.h"
 
27
#include "gck-attributes.h"
 
28
#include "gck-crypto.h"
 
29
#include "gck-aes-key.h"
 
30
#include "gck-session.h"
 
31
#include "gck-transaction.h"
 
32
#include "gck-util.h"
 
33
 
 
34
#include "egg/egg-secure-memory.h"
 
35
 
 
36
struct _GckAesKey {
 
37
        GckSecretKey parent;
 
38
        gpointer value;
 
39
        gsize n_value;
 
40
};
 
41
 
 
42
G_DEFINE_TYPE (GckAesKey, gck_aes_key, GCK_TYPE_SECRET_KEY);
 
43
 
 
44
/* -----------------------------------------------------------------------------
 
45
 * INTERNAL
 
46
 */
 
47
 
 
48
static int
 
49
algorithm_for_length (gsize length)
 
50
{
 
51
        switch (length) {
 
52
        case 16:
 
53
                return GCRY_CIPHER_AES128;
 
54
        case 24:
 
55
                return GCRY_CIPHER_AES192;
 
56
        case 32:
 
57
                return GCRY_CIPHER_AES256;
 
58
        default:
 
59
                return 0;
 
60
        }
 
61
}
 
62
 
 
63
static CK_RV
 
64
attribute_set_check_value (GckAesKey *self, CK_ATTRIBUTE *attr)
 
65
{
 
66
        gcry_cipher_hd_t cih;
 
67
        gcry_error_t gcry;
 
68
        gpointer data;
 
69
        CK_RV rv;
 
70
 
 
71
        g_assert (GCK_IS_AES_KEY (self));
 
72
        g_assert (attr);
 
73
 
 
74
        /* Just asking for the length */
 
75
        if (!attr->pValue) {
 
76
                attr->ulValueLen = 3;
 
77
                return CKR_OK;
 
78
        }
 
79
 
 
80
        cih = gck_aes_key_get_cipher (self, GCRY_CIPHER_MODE_ECB);
 
81
        if (cih == NULL)
 
82
                return CKR_FUNCTION_FAILED;
 
83
 
 
84
        /* Buffer of zeros */
 
85
        data = g_malloc0 (self->n_value);
 
86
 
 
87
        /* Encrypt it */
 
88
        gcry = gcry_cipher_encrypt (cih, data, self->n_value, NULL, 0);
 
89
        g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
 
90
 
 
91
        /* Use the first three bytes */
 
92
        g_assert (self->n_value > 3);
 
93
        rv = gck_attribute_set_data (attr, data, 3);
 
94
 
 
95
        gcry_cipher_close (cih);
 
96
        g_free (data);
 
97
 
 
98
        return rv;
 
99
}
 
100
 
 
101
static GckObject*
 
102
factory_create_aes_key (GckSession *session, GckTransaction *transaction,
 
103
                        CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
 
104
{
 
105
        GckAesKey *key;
 
106
        GckManager *manager;
 
107
        CK_ATTRIBUTE_PTR value;
 
108
 
 
109
        value = gck_attributes_find (attrs, n_attrs, CKA_VALUE);
 
110
        if (value == NULL) {
 
111
                gck_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
 
112
                return NULL;
 
113
        }
 
114
 
 
115
        if (algorithm_for_length (value->ulValueLen) == 0) {
 
116
                gck_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
 
117
                return NULL;
 
118
        }
 
119
 
 
120
        manager = gck_manager_for_template (attrs, n_attrs, session);
 
121
        key = g_object_new (GCK_TYPE_AES_KEY,
 
122
                            "module", gck_session_get_module (session),
 
123
                            "manager", manager,
 
124
                            NULL);
 
125
 
 
126
        key->value = egg_secure_alloc (value->ulValueLen);
 
127
        key->n_value = value->ulValueLen;
 
128
        memcpy (key->value, value->pValue, key->n_value);
 
129
 
 
130
        gck_attribute_consume (value);
 
131
 
 
132
        gck_session_complete_object_creation (session, transaction, GCK_OBJECT (key),
 
133
                                              TRUE, attrs, n_attrs);
 
134
        return GCK_OBJECT (key);
 
135
}
 
136
 
 
137
/* -----------------------------------------------------------------------------
 
138
 * OBJECT
 
139
 */
 
140
 
 
141
static CK_RV
 
142
gck_aes_key_real_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE *attr)
 
143
{
 
144
        GckAesKey *self = GCK_AES_KEY (base);
 
145
 
 
146
        switch (attr->type)
 
147
        {
 
148
        case CKA_KEY_TYPE:
 
149
                return gck_attribute_set_ulong (attr, CKK_AES);
 
150
 
 
151
        case CKA_UNWRAP:
 
152
        case CKA_WRAP:
 
153
                return gck_attribute_set_bool (attr, CK_TRUE);
 
154
 
 
155
        case CKA_VALUE:
 
156
                return gck_attribute_set_data (attr, self->value, self->n_value);
 
157
 
 
158
        case CKA_VALUE_LEN:
 
159
                return gck_attribute_set_ulong (attr, self->n_value);
 
160
 
 
161
        case CKA_CHECK_VALUE:
 
162
                return attribute_set_check_value (self, attr);
 
163
 
 
164
        case CKA_ALLOWED_MECHANISMS:
 
165
                return gck_attribute_set_data (attr, (CK_VOID_PTR)GCK_AES_MECHANISMS,
 
166
                                               sizeof (GCK_AES_MECHANISMS));
 
167
        };
 
168
 
 
169
        return GCK_OBJECT_CLASS (gck_aes_key_parent_class)->get_attribute (base, session, attr);
 
170
}
 
171
 
 
172
static void
 
173
gck_aes_key_init (GckAesKey *self)
 
174
{
 
175
 
 
176
}
 
177
 
 
178
static void
 
179
gck_aes_key_finalize (GObject *obj)
 
180
{
 
181
        GckAesKey *self = GCK_AES_KEY (obj);
 
182
 
 
183
        if (self->value) {
 
184
                egg_secure_clear (self->value, self->n_value);
 
185
                egg_secure_free (self->value);
 
186
                self->value = NULL;
 
187
                self->n_value = 0;
 
188
        }
 
189
 
 
190
        G_OBJECT_CLASS (gck_aes_key_parent_class)->finalize (obj);
 
191
}
 
192
 
 
193
static void
 
194
gck_aes_key_class_init (GckAesKeyClass *klass)
 
195
{
 
196
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
197
        GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
 
198
 
 
199
        gck_aes_key_parent_class = g_type_class_peek_parent (klass);
 
200
 
 
201
        gobject_class->finalize = gck_aes_key_finalize;
 
202
 
 
203
        gck_class->get_attribute = gck_aes_key_real_get_attribute;
 
204
}
 
205
 
 
206
/* -----------------------------------------------------------------------------
 
207
 * PUBLIC
 
208
 */
 
209
 
 
210
GckFactory*
 
211
gck_aes_key_get_factory (void)
 
212
{
 
213
        static CK_OBJECT_CLASS klass = CKO_SECRET_KEY;
 
214
        static CK_KEY_TYPE type = CKK_AES;
 
215
 
 
216
        static CK_ATTRIBUTE attributes[] = {
 
217
                { CKA_CLASS, &klass, sizeof (klass) },
 
218
                { CKA_KEY_TYPE, &type, sizeof (type) }
 
219
        };
 
220
 
 
221
        static GckFactory factory = {
 
222
                attributes,
 
223
                G_N_ELEMENTS (attributes),
 
224
                factory_create_aes_key
 
225
        };
 
226
 
 
227
        return &factory;
 
228
}
 
229
 
 
230
gsize
 
231
gck_aes_key_get_block_size (GckAesKey *self)
 
232
{
 
233
        int algorithm;
 
234
 
 
235
        g_return_val_if_fail (GCK_IS_AES_KEY (self), 0);
 
236
 
 
237
        algorithm = algorithm_for_length (self->n_value);
 
238
        g_return_val_if_fail (algorithm != 0, 0);
 
239
 
 
240
        return self->n_value;
 
241
}
 
242
 
 
243
gcry_cipher_hd_t
 
244
gck_aes_key_get_cipher (GckAesKey *self, int mode)
 
245
{
 
246
        gcry_cipher_hd_t cih;
 
247
        gcry_error_t gcry;
 
248
        int algorithm;
 
249
 
 
250
        g_return_val_if_fail (GCK_IS_AES_KEY (self), NULL);
 
251
 
 
252
        algorithm = algorithm_for_length (self->n_value);
 
253
        g_return_val_if_fail (algorithm != 0, NULL);
 
254
 
 
255
        gcry = gcry_cipher_open (&cih, algorithm, mode, 0);
 
256
        if (gcry != 0) {
 
257
                g_warning ("couldn't open %s cipher: %s",
 
258
                           gcry_cipher_algo_name (algorithm), gcry_strerror (gcry));
 
259
                return NULL;
 
260
        }
 
261
 
 
262
        /* Setup the key */
 
263
        gcry = gcry_cipher_setkey (cih, self->value, self->n_value);
 
264
        g_return_val_if_fail (gcry == 0, NULL);
 
265
 
 
266
        return cih;
 
267
}