Line data Source code
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 "gkm-attributes.h"
24 : #include "gkm-crypto.h"
25 : #include "gkm-hkdf-mechanism.h"
26 : #include "gkm-secret-key.h"
27 : #include "gkm-session.h"
28 : #include "gkm-transaction.h"
29 :
30 : #include "egg/egg-hkdf.h"
31 : #include "egg/egg-libgcrypt.h"
32 : #include "egg/egg-secure-memory.h"
33 :
34 1 : EGG_SECURE_DECLARE (hkdf_mechanism);
35 :
36 : CK_RV
37 1 : gkm_hkdf_mechanism_derive (GkmSession *session, const char *algo,
38 : CK_MECHANISM_PTR mech, GkmObject *base,
39 : CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs,
40 : GkmObject **derived)
41 : {
42 : CK_ATTRIBUTE attr;
43 : GArray *array;
44 : gconstpointer value;
45 : gpointer output;
46 : gsize n_value;
47 1 : CK_ULONG n_output = 0;
48 : GkmTransaction *transaction;
49 : CK_KEY_TYPE type;
50 :
51 1 : g_return_val_if_fail (GKM_IS_SECRET_KEY (base), CKR_GENERAL_ERROR);
52 :
53 : /* Get the value of the original key */
54 1 : value = gkm_secret_key_get_key_value (GKM_SECRET_KEY (base), &n_value);
55 1 : g_return_val_if_fail (value, CKR_GENERAL_ERROR);
56 :
57 : /* What length should we truncate to? */
58 1 : if (!gkm_attributes_find_ulong (attrs, n_attrs, CKA_VALUE_LEN, &n_output)) {
59 0 : if (gkm_attributes_find_ulong (attrs, n_attrs, CKA_KEY_TYPE, &type))
60 0 : n_output = gkm_crypto_secret_key_length (type);
61 : }
62 :
63 : /* Default to input length */
64 1 : if (n_output == 0)
65 0 : n_output = n_value;
66 :
67 1 : output = egg_secure_alloc (n_output);
68 1 : if (!egg_hkdf_perform ("sha256", value, n_value, mech->pParameter,
69 : mech->ulParameterLen, NULL, 0, output, n_output)) {
70 0 : egg_secure_free (output);
71 0 : return CKR_FUNCTION_FAILED;
72 : }
73 :
74 : /* Now setup the attributes with our new value */
75 1 : array = g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE));
76 :
77 : /* Prepend the value */
78 1 : attr.type = CKA_VALUE;
79 1 : attr.pValue = output;
80 1 : attr.ulValueLen = n_output;
81 :
82 1 : g_array_append_val (array, attr);
83 :
84 : /* Add the remainder of the attributes */
85 1 : g_array_append_vals (array, attrs, n_attrs);
86 :
87 1 : transaction = gkm_transaction_new ();
88 :
89 : /* Now create an object with these attributes */
90 2 : *derived = gkm_session_create_object_for_attributes (session, transaction,
91 1 : (CK_ATTRIBUTE_PTR)array->data, array->len);
92 :
93 1 : egg_secure_free (output);
94 1 : g_array_free (array, TRUE);
95 :
96 1 : return gkm_transaction_complete_and_unref (transaction);
97 : }
|