~ubuntu-branches/ubuntu/vivid/ecryptfs-utils/vivid

« back to all changes in this revision

Viewing changes to src/libecryptfs/packets.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2008-04-09 09:54:00 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20080409095400-cexrc09wzgqsk9bs
Tags: 43-1
* New upstream release.
* Removing watch file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Userspace side of communications with eCryptfs kernel module.
 
3
 *
 
4
 * Copyright (C) 2004-2006 International Business Machines Corp.
 
5
 *   Author(s): Trevor S. Highland <trevor.highland@gmail.com>
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU General Public License as
 
9
 * published by the Free Software Foundation; either version 2 of the
 
10
 * License, or (at your option) any later version.
 
11
 *
 
12
 * This program 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
 * General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
20
 * 02111-1307, USA.
 
21
 */
 
22
 
 
23
#include <errno.h>
 
24
#ifndef S_SPLINT_S
 
25
#include <syslog.h>
 
26
#include <stdio.h>
 
27
#endif
 
28
#include <string.h>
 
29
#include <gcrypt.h>
 
30
#include <keyutils.h>
 
31
#include <stdlib.h>
 
32
#include "config.h"
 
33
#include "../include/ecryptfs.h"
 
34
 
 
35
#define ECRYPTFS_PACKET_STATUS_GOOD 0
 
36
#define ECRYPTFS_PACKET_STATUS_BAD -1
 
37
 
 
38
/**
 
39
 * key_mod_encrypt
 
40
 * @encrypted_key: This function will allocate this memory and encrypt
 
41
 *                 the key into it
 
42
 * @encrypted_key_size: The size of the encrypted key; note that the
 
43
 *                      actual amount of memory allocated by this
 
44
 *                      function may be more than this
 
45
 * @ctx:
 
46
 * @auth_tok: The authentication token structure in the user session
 
47
 *            keyring; this contains the key module state blob
 
48
 * @decrypted_key:
 
49
 * @decrypted_key_size:
 
50
 *
 
51
 *
 
52
 *
 
53
 * Called from parse_packet()
 
54
 */
 
55
static int
 
56
key_mod_encrypt(char **encrypted_key, size_t *encrypted_key_size,
 
57
                struct ecryptfs_ctx *ctx, struct ecryptfs_auth_tok *auth_tok,
 
58
                char *decrypted_key, size_t decrypted_key_size)
 
59
{
 
60
        struct ecryptfs_key_mod *key_mod;
 
61
        int rc;
 
62
 
 
63
        if (ecryptfs_find_key_mod(&key_mod, ctx,
 
64
                                  auth_tok->token.private_key.key_mod_alias)) {
 
65
                rc = -EINVAL;
 
66
                syslog(LOG_ERR, "Failed to locate desired key module\n");
 
67
                goto out;
 
68
        }
 
69
        /* TODO: Include support for a hint rather than just a blob */
 
70
        if ((rc = key_mod->ops->encrypt(NULL, encrypted_key_size, decrypted_key,
 
71
                                        decrypted_key_size,
 
72
                                        auth_tok->token.private_key.data,
 
73
                                        ECRYPTFS_BLOB_TYPE_BLOB))) {
 
74
                syslog(LOG_ERR, "Error attempting to get encrypted key size "
 
75
                       "from key module; rc = [%d]\n", rc);
 
76
                goto out;
 
77
        }
 
78
        if ((*encrypted_key_size) == 0) {
 
79
                rc = -EINVAL;
 
80
                syslog(LOG_ERR, "Encrypted key size reported by key module "
 
81
                       "encrypt function is 0\n");
 
82
                goto out;
 
83
        }
 
84
        /* The first call just told us how much memory to
 
85
         * allocate. The actual key size may be less, so we don't
 
86
         * worry about ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES until the
 
87
         * second call. */
 
88
        if (((*encrypted_key) = malloc(*encrypted_key_size)) == NULL) {
 
89
                rc = -errno;
 
90
                syslog(LOG_ERR, "Failed to allocate memory: [%s]\n",
 
91
                       strerror(errno));
 
92
                goto out;
 
93
        }
 
94
        if ((rc = key_mod->ops->encrypt((*encrypted_key), encrypted_key_size,
 
95
                                        decrypted_key, decrypted_key_size,
 
96
                                        auth_tok->token.private_key.data,
 
97
                                        ECRYPTFS_BLOB_TYPE_BLOB))) {
 
98
                syslog(LOG_ERR, "Failed to encrypt key; rc = [%d]\n", rc);
 
99
                goto out;
 
100
        }
 
101
        if ((*encrypted_key_size) > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
 
102
                rc = -EINVAL;
 
103
                syslog(LOG_ERR, "Encrypted key size reported by key module "
 
104
                       "encrypt function is [%d]; max is [%d]\n",
 
105
                       (*encrypted_key_size), ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
 
106
                free(*encrypted_key);
 
107
                (*encrypted_key_size) = 0;
 
108
                goto out;
 
109
        }
 
110
out:
 
111
        return rc;
 
112
}
 
113
 
 
114
static int
 
115
key_mod_decrypt(char **decrypted_key, size_t *decrypted_key_size,
 
116
                struct ecryptfs_ctx *ctx, struct ecryptfs_auth_tok *auth_tok,
 
117
                char *encrypted_key, size_t encrypted_key_size)
 
118
{
 
119
        struct ecryptfs_key_mod *key_mod;
 
120
        int rc;
 
121
 
 
122
        if (ecryptfs_find_key_mod(&key_mod, ctx,
 
123
                                  auth_tok->token.private_key.key_mod_alias)) {
 
124
                rc = -EINVAL;
 
125
                syslog(LOG_ERR, "Failed to locate desired key module\n");
 
126
                goto out;
 
127
        }
 
128
        if ((rc = key_mod->ops->decrypt(NULL, decrypted_key_size,
 
129
                                        encrypted_key, encrypted_key_size,
 
130
                                        auth_tok->token.private_key.data,
 
131
                                        ECRYPTFS_BLOB_TYPE_BLOB))) {
 
132
                syslog(LOG_ERR, "Failed to get size for decrypted key\n");
 
133
                goto out;
 
134
        }
 
135
        if ((*decrypted_key_size) == 0) {
 
136
                rc = -EINVAL;
 
137
                syslog(LOG_ERR, "Decrypted key size reported by key module "
 
138
                       "decrypt function is 0\n");
 
139
                goto out;
 
140
        }
 
141
        /* The first call just told us how much memory to
 
142
         * allocate. The actual key size may be less, so we don't
 
143
         * worry about ECRYPTFS_MAX_KEY_BYTES until the second
 
144
         * call. */
 
145
        if (((*decrypted_key) = malloc(*decrypted_key_size)) == NULL) {
 
146
                rc = -ENOMEM;
 
147
                syslog(LOG_ERR, "Failed to allocate memory\n");
 
148
                goto out;
 
149
        }
 
150
        if ((rc = key_mod->ops->decrypt(*decrypted_key, decrypted_key_size,
 
151
                                        encrypted_key, encrypted_key_size,
 
152
                                        auth_tok->token.private_key.data,
 
153
                                        ECRYPTFS_BLOB_TYPE_BLOB))) {
 
154
                syslog(LOG_ERR, "Failed to decrypt key\n");
 
155
                goto out;
 
156
        }
 
157
        if ((*decrypted_key_size) > ECRYPTFS_MAX_KEY_BYTES) {
 
158
                rc = -EINVAL;
 
159
                syslog(LOG_ERR, "Decrypted key size reported by key module "
 
160
                       "decrypt function is [%d]; max is [%d]\n",
 
161
                       (*decrypted_key_size), ECRYPTFS_MAX_KEY_BYTES);
 
162
                free(*decrypted_key);
 
163
                (*decrypted_key_size) = 0;
 
164
                goto out;
 
165
        }
 
166
out:
 
167
        return rc;
 
168
}
 
169
 
 
170
static int write_failure_packet(size_t tag,
 
171
                                struct ecryptfs_message **reply)
 
172
{
 
173
        unsigned char *data;
 
174
        size_t i = 0;
 
175
        int rc = 0;
 
176
 
 
177
        *reply = malloc(sizeof(struct ecryptfs_message) + 2);
 
178
        if (!*reply) {
 
179
                rc = -errno;
 
180
                syslog(LOG_ERR, "Failed to allocate memory: %s\n",
 
181
                       strerror(errno));
 
182
                goto out;
 
183
        }
 
184
        data = (*reply)->data;
 
185
        data[i++] = tag;
 
186
        data[i++] = ECRYPTFS_PACKET_STATUS_BAD;
 
187
        (*reply)->data_len = i;
 
188
out:
 
189
        return rc;
 
190
}
 
191
 
 
192
static int write_tag_65_packet(unsigned char *key, size_t key_size,
 
193
                               struct ecryptfs_message **reply)
 
194
{
 
195
        unsigned char *data;
 
196
        size_t data_len;
 
197
        size_t length_size;
 
198
        size_t i = 0;
 
199
        int rc = 0;
 
200
 
 
201
        data_len = key_size + 4;
 
202
        *reply = malloc(sizeof(struct ecryptfs_message) + data_len);
 
203
        if (!*reply) {
 
204
                rc = -errno;
 
205
                syslog(LOG_ERR, "Failed to allocate memory: %s\n",
 
206
                       strerror(errno));
 
207
                goto out;
 
208
        }
 
209
        data = (*reply)->data;
 
210
        data[i++] = ECRYPTFS_TAG_65_PACKET;
 
211
        data[i++] = ECRYPTFS_PACKET_STATUS_GOOD;
 
212
        rc = ecryptfs_write_packet_length(&data[i], key_size, &length_size);
 
213
        if (rc) {
 
214
                syslog(LOG_ERR, "Invalid packet format\n");
 
215
                goto out;
 
216
        }
 
217
        i += length_size;
 
218
        memcpy(&data[i], key, key_size);
 
219
        i += key_size;
 
220
        (*reply)->data_len = i;
 
221
out:
 
222
        return rc;
 
223
}
 
224
 
 
225
static int
 
226
write_tag_67_packet(char *key, size_t key_size,
 
227
                    struct ecryptfs_message **reply)
 
228
{
 
229
        unsigned char *data;
 
230
        size_t data_len;
 
231
        size_t length_size;
 
232
        size_t i = 0;
 
233
        int rc = 0;
 
234
 
 
235
        data_len = key_size + 4;
 
236
        *reply = malloc(sizeof(struct ecryptfs_message) + data_len);
 
237
        if (!*reply) {
 
238
                rc = -errno;
 
239
                syslog(LOG_ERR, "Failed to allocate memory: %s\n",
 
240
                       strerror(errno));
 
241
                goto out;
 
242
        }
 
243
        data = (*reply)->data;
 
244
        data[i++] = ECRYPTFS_TAG_67_PACKET;
 
245
        data[i++] = ECRYPTFS_PACKET_STATUS_GOOD;
 
246
        rc = ecryptfs_write_packet_length(&data[i], key_size, &length_size);
 
247
        if (rc) {
 
248
                syslog(LOG_ERR, "Invalid packet format\n");
 
249
                goto out;
 
250
        }
 
251
        i += length_size;
 
252
        memcpy(&data[i], key, key_size);
 
253
        i += key_size;
 
254
        (*reply)->data_len = data_len;
 
255
out:
 
256
        return rc;
 
257
}
 
258
 
 
259
int parse_packet(struct ecryptfs_ctx *ctx,
 
260
                 struct ecryptfs_message *emsg,
 
261
                 struct ecryptfs_message **reply)
 
262
{
 
263
        struct ecryptfs_auth_tok *auth_tok = NULL;
 
264
        size_t i = 0;
 
265
        size_t data_size;
 
266
        size_t key_size;
 
267
        size_t length_size;
 
268
        size_t key_out_size;
 
269
        unsigned char *signature;
 
270
        unsigned char packet_type;
 
271
        char *key = NULL;
 
272
        char *key_out = NULL;
 
273
        key_serial_t key_sub;
 
274
        int rc;
 
275
 
 
276
        packet_type = emsg->data[i++];
 
277
        if ((rc = ecryptfs_parse_packet_length(&emsg->data[i], &data_size,
 
278
                                               &length_size))) {
 
279
                syslog(LOG_ERR, "Invalid packet format\n");
 
280
                goto write_failure;
 
281
        }
 
282
        i += length_size;
 
283
        signature = malloc(data_size + 1);
 
284
        if (!signature) {
 
285
                rc = -errno;
 
286
                syslog(LOG_ERR, "Failed to allocate memory: %s\n",
 
287
                       strerror(errno));
 
288
                goto write_failure;
 
289
        }
 
290
        memcpy(signature, &emsg->data[i], data_size);
 
291
        signature[data_size] = '\0';
 
292
        i += data_size;
 
293
        rc = ecryptfs_parse_packet_length(&emsg->data[i], &key_size,
 
294
                                          &length_size);
 
295
        if (rc) {
 
296
                syslog(LOG_ERR, "Invalid packet format\n");
 
297
                goto write_failure;
 
298
        }
 
299
        i += length_size;
 
300
        if ((key = malloc(key_size)) == NULL) {
 
301
                rc = -ENOMEM;
 
302
                syslog(LOG_ERR, "Failed to allocate memory\n");
 
303
                goto write_failure;
 
304
        }
 
305
        memcpy(key, &emsg->data[i], key_size);
 
306
        i += key_size;
 
307
        key_sub = request_key("user", signature, NULL, KEY_SPEC_USER_KEYRING);
 
308
        if (key_sub < 0) {
 
309
                syslog(LOG_ERR, "Could not find key with signature: "
 
310
                       "[%s]\n", signature);
 
311
                rc = -EINVAL;
 
312
                goto write_failure;
 
313
        }
 
314
        rc = keyctl_read_alloc(key_sub, (void **)(&auth_tok));
 
315
        switch (packet_type) {
 
316
        case ECRYPTFS_TAG_64_PACKET:
 
317
                if ((rc = key_mod_decrypt(&key_out, &key_out_size, ctx,
 
318
                                          auth_tok, key, key_size))) {
 
319
                        syslog(LOG_ERR, "Failed to decrypt key; rc = [%d]\n",
 
320
                               rc);
 
321
                        rc = write_failure_packet(ECRYPTFS_TAG_65_PACKET,
 
322
                                                  reply);
 
323
                        goto write_failure;
 
324
                }
 
325
                if ((rc = write_tag_65_packet(key_out, key_out_size, reply))) {
 
326
                        syslog(LOG_ERR, "Failed to write decrypted "
 
327
                               "key via tag 65 packet\n");
 
328
                        goto write_failure;
 
329
                }
 
330
                break;
 
331
        case ECRYPTFS_TAG_66_PACKET:
 
332
                rc = key_mod_encrypt(&key_out, &key_out_size, ctx, auth_tok,
 
333
                                     key, key_size);
 
334
                if (rc) {
 
335
                        syslog(LOG_ERR, "Failed to encrypt public "
 
336
                               "key\n");
 
337
                        goto write_failure;
 
338
                }
 
339
                rc = write_tag_67_packet(key_out, key_out_size, reply);
 
340
                if (rc) {
 
341
                        syslog(LOG_ERR, "Failed to write encrypted "
 
342
                               "key to tag 67 packet\n");
 
343
                        goto write_failure;
 
344
                }
 
345
                break;
 
346
        default:
 
347
                syslog(LOG_ERR, "Unrecognized packet type: [%d]\n",
 
348
                       packet_type);
 
349
                rc = -EINVAL;
 
350
                break;
 
351
        }
 
352
        free(key);
 
353
        free(signature);
 
354
        free(key_out);
 
355
        memset(auth_tok, 0, (sizeof(struct ecryptfs_auth_tok)
 
356
                             + auth_tok->token.private_key.data_len));
 
357
        free(auth_tok);
 
358
        return rc;
 
359
write_failure:
 
360
        if(packet_type == ECRYPTFS_TAG_66_PACKET)
 
361
                rc = write_failure_packet(ECRYPTFS_TAG_67_PACKET, reply);
 
362
        else
 
363
                rc = write_failure_packet(ECRYPTFS_TAG_65_PACKET, reply);
 
364
        free(key);
 
365
        free(signature);
 
366
        free(key_out);
 
367
        if (auth_tok) {
 
368
                memset(auth_tok, 0, (sizeof(struct ecryptfs_auth_tok)
 
369
                                     + auth_tok->token.private_key.data_len));
 
370
                free(auth_tok);
 
371
        }
 
372
        return rc;
 
373
}