~siretart/cryptsetup/debian

« back to all changes in this revision

Viewing changes to luks/keyencryption.c

  • Committer: Reinhard Tartler
  • Date: 2008-05-25 17:39:22 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: siretart@tauware.de-20080525173922-popbnh1gtbt3rxis
merge new upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include <fcntl.h>
29
29
#include <unistd.h>
30
30
#include <errno.h>
 
31
#include <signal.h>
31
32
 
32
33
#include "luks.h"
33
34
#include "../lib/libcryptsetup.h"
34
35
#include "../lib/internal.h"
35
36
#include "../lib/blockdev.h"
36
37
 
37
 
#define div_round_up(a,b) ({           \
 
38
#define div_round_up(a,b) ({          \
38
39
        typeof(a) __a = (a);          \
39
40
        typeof(b) __b = (b);          \
40
 
        (__a - 1) / __b + 1;        \
 
41
        (__a - 1) / __b + 1;          \
41
42
})
42
43
 
 
44
static inline int round_up_modulo(int x, int m) {
 
45
        return div_round_up(x, m) * m;
 
46
}
43
47
 
44
48
static int setup_mapping(const char *cipher, const char *name, 
45
49
                         const char *device, unsigned int payloadOffset,
58
62
         * device's sector size, otherwise the mapping will be refused.
59
63
         */
60
64
        if(device_sector_size < 0) {
61
 
                fprintf(stderr,_("Unable to obtain sector size for %s"),device);
 
65
                set_error(_("Unable to obtain sector size for %s"),device);
62
66
                return -EINVAL;
63
67
        }
64
68
        options->size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
90
94
        return backend->remove(&options);
91
95
}
92
96
 
 
97
/* I miss closures in C! */
 
98
static struct setup_backend *cleaner_backend=NULL;
 
99
static const char *cleaner_name=NULL; 
 
100
static int devfd=0;
 
101
 
 
102
static void sigint_handler(int sig)
 
103
{
 
104
        if(devfd)
 
105
                close(devfd);
 
106
        if(cleaner_backend && cleaner_name) 
 
107
                clear_mapping(cleaner_name, cleaner_backend);
 
108
        signal(SIGINT, SIG_DFL);
 
109
        kill(getpid(), SIGINT);
 
110
}
 
111
 
 
112
/* This function is not reentrant safe, as it installs a signal
 
113
   handler and global vars for cleaning */
93
114
static int LUKS_endec_template(char *src, size_t srcLength, 
94
115
                               struct luks_phdr *hdr, 
95
116
                               char *key, size_t keyLength, 
98
119
                               ssize_t (*func)(int, void *, size_t),
99
120
                               int mode)
100
121
{
101
 
        int devfd;
102
122
        char *name = NULL;
103
123
        char *fullpath = NULL;
104
124
        char *dmCipherSpec = NULL;
115
135
                r = -ENOMEM;
116
136
                goto out1;
117
137
        }
 
138
        
 
139
        signal(SIGINT, sigint_handler);
 
140
        cleaner_name = name;
 
141
        cleaner_backend = backend;
118
142
 
119
143
        r = setup_mapping(dmCipherSpec,name,device,hdr->payloadOffset,key,keyLength,sector,srcLength,backend,mode);
120
144
        if(r < 0) {
121
 
                fprintf(stderr,"Failed to setup dm-crypt key mapping.\nCheck kernel for support for the %s cipher spec and verify that %s contains at least %d sectors.\n",
 
145
                if(!get_error())
 
146
                        set_error("Failed to setup dm-crypt key mapping.\nCheck kernel for support for the %s cipher spec and verify that %s contains at least %d sectors",
122
147
                        dmCipherSpec, 
123
148
                        device, 
124
149
                        sector + div_round_up(srcLength,SECTOR_SIZE));
126
151
                goto out1;
127
152
        }
128
153
 
129
 
        devfd = open(fullpath, mode | O_DIRECT | O_SYNC);
 
154
        devfd = open(fullpath, mode | O_DIRECT | O_SYNC);  /* devfd is a global var */
130
155
        if(devfd == -1) { r = -EIO; goto out2; }
131
156
 
132
157
        r = func(devfd,src,srcLength);
135
160
        r = 0;
136
161
 out3:
137
162
        close(devfd);
 
163
        devfd = 0;
138
164
 out2:
139
165
        clear_mapping(name,backend);
140
166
 out1:
 
167
        signal(SIGINT, SIG_DFL);
 
168
        cleaner_name = NULL;
 
169
        cleaner_backend = NULL;
141
170
        free(dmCipherSpec);
142
171
        free(fullpath); 
143
172
        free(name); 
152
181
{
153
182
        
154
183
        return LUKS_endec_template(src,srcLength,hdr,key,keyLength, device, sector, backend,    
155
 
                                   (ssize_t (*)(int, void *, size_t)) write_blockwise, O_RDWR);
 
184
                                   (ssize_t (*)(int, void *, size_t)) write_blockwise, O_RDWR | O_EXCL);
156
185
}       
157
186
 
158
187
int LUKS_decrypt_from_storage(char *dst, size_t dstLength, 
163
192
{
164
193
        return LUKS_endec_template(dst,dstLength,hdr,key,keyLength, device, sector, backend, read_blockwise, O_RDONLY);
165
194
}
 
195
 
 
196
// Local Variables:
 
197
// c-basic-offset: 8
 
198
// indent-tabs-mode: nil
 
199
// End: