Imported Upstream version 3.4.11
[platform/upstream/gnutls.git] / lib / pkcs11_secret.c
1 /*
2  * GnuTLS PKCS#11 support
3  * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4  * 
5  * Author: Nikos Mavrogiannopoulos, Stef Walter
6  *
7  * The GnuTLS is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>
19  */
20
21 #include <gnutls_int.h>
22 #include <gnutls/pkcs11.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <gnutls_errors.h>
26 #include <gnutls_datum.h>
27 #include <pkcs11_int.h>
28 #include <random.h>
29
30 /**
31  * gnutls_pkcs11_copy_secret_key:
32  * @token_url: A PKCS #11 URL specifying a token
33  * @key: The raw key
34  * @label: A name to be used for the stored data
35  * @key_usage: One of GNUTLS_KEY_*
36  * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
37  *
38  * This function will copy a raw secret (symmetric) key into a PKCS #11 
39  * token specified by a URL. The key can be marked as sensitive or not.
40  *
41  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
42  *   negative error value.
43  *
44  * Since: 2.12.0
45  **/
46 int
47 gnutls_pkcs11_copy_secret_key(const char *token_url, gnutls_datum_t * key,
48                               const char *label,
49                               unsigned int key_usage, unsigned int flags
50                               /* GNUTLS_PKCS11_OBJ_FLAG_* */ )
51 {
52         int ret;
53         struct p11_kit_uri *info = NULL;
54         ck_rv_t rv;
55         struct ck_attribute a[12];
56         ck_object_class_t class = CKO_SECRET_KEY;
57         ck_object_handle_t obj;
58         ck_key_type_t keytype = CKK_GENERIC_SECRET;
59         ck_bool_t tval = 1;
60         int a_val;
61         uint8_t id[16];
62         struct pkcs11_session_info sinfo;
63         
64         PKCS11_CHECK_INIT;
65
66         memset(&sinfo, 0, sizeof(sinfo));
67
68         ret = pkcs11_url_to_info(token_url, &info, 0);
69         if (ret < 0) {
70                 gnutls_assert();
71                 return ret;
72         }
73
74         /* generate a unique ID */
75         ret = _gnutls_rnd(GNUTLS_RND_NONCE, id, sizeof(id));
76         if (ret < 0) {
77                 gnutls_assert();
78                 return ret;
79         }
80
81         ret =
82             pkcs11_open_session(&sinfo, NULL, info,
83                                 SESSION_WRITE |
84                                 pkcs11_obj_flags_to_int(flags));
85         p11_kit_uri_free(info);
86
87         if (ret < 0) {
88                 gnutls_assert();
89                 return ret;
90         }
91
92         /* FIXME: copy key usage flags */
93
94         a[0].type = CKA_CLASS;
95         a[0].value = &class;
96         a[0].value_len = sizeof(class);
97         a[1].type = CKA_VALUE;
98         a[1].value = key->data;
99         a[1].value_len = key->size;
100         a[2].type = CKA_TOKEN;
101         a[2].value = &tval;
102         a[2].value_len = sizeof(tval);
103         a[3].type = CKA_PRIVATE;
104         a[3].value = &tval;
105         a[3].value_len = sizeof(tval);
106         a[4].type = CKA_KEY_TYPE;
107         a[4].value = &keytype;
108         a[4].value_len = sizeof(keytype);
109         a[5].type = CKA_ID;
110         a[5].value = id;
111         a[5].value_len = sizeof(id);
112
113         a_val = 6;
114
115         if (label) {
116                 a[a_val].type = CKA_LABEL;
117                 a[a_val].value = (void *) label;
118                 a[a_val].value_len = strlen(label);
119                 a_val++;
120         }
121
122         if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
123                 tval = 1;
124         else
125                 tval = 0;
126
127         a[a_val].type = CKA_SENSITIVE;
128         a[a_val].value = &tval;
129         a[a_val].value_len = sizeof(tval);
130         a_val++;
131
132         rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &obj);
133         if (rv != CKR_OK) {
134                 gnutls_assert();
135                 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
136                 ret = pkcs11_rv_to_err(rv);
137                 goto cleanup;
138         }
139
140         /* generated! 
141          */
142
143         ret = 0;
144
145       cleanup:
146         pkcs11_close_session(&sinfo);
147
148         return ret;
149
150 }