~ecryptfs/ecryptfs/trunk

« back to all changes in this revision

Viewing changes to src/libecryptfs/main.c

  • Committer: Dustin Kirkland
  • Date: 2009-01-22 00:58:21 UTC
  • Revision ID: git-v1:d0d0782ff84bd0c8deead3c695a7e13f7874b175
filename encryption userspace support

Recent changes to the ecryptfs kernel code has added support for
filename encryption.

The basic userspace support was a added a few weeks ago.  You can
specify the key in the kernel keyring to use as a mount parameter,
with:
  ecryptfs_fnek_sig=0000000000000000

This patch adds a couple of conveniences, mainly in support of using
encrypting filenames easily with the encrypted-home and
encrypted-private features of ecryptfs.

In these scenarios, the filename encryption key is dynamically
(but programmatically) generated using the mount passphrase.

The mount passphrase is salted, hashed 65536 times using sha512,
converted to hex, and truncated to 16 digits long (128 bits).  This
value is used as the filename encryption passphrase.

Should the filename encryption password be compromised, one would
have to reverse this process.  We have designed this to be
cryptographically very difficult.

The signature of the filename encryption key (often abbreviated
"fnek") should be specified in ~/.ecryptfs/Private_fnek.sig.

If this file exists and contains a valid signature, the
mount.ecryptfs_private helper will specify this key in the mount
options as described above.

The pam_ecryptfs modules will continue to insert the wrapped
passphrase into the kernel keyring.  I have modified the base
library functionality to unconditionally also insert the fnek
passphrase.  THIS SHOULD BE FIXED IN A SUBSEQUENT COMMIT.

Also, the ecryptfs-setup-private utility needs to be enhanced
to write out the Private_fnek.sig file.  This may necessitate
a new binary utility to perform this operation.

Signed-off-by: Dustin Kirkland <kirkland@canonical.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
172
172
}
173
173
 
174
174
/**
 
175
 * @fnek An allocated char array into which the generated
 
176
 * passphrase is written; ECRYPTFS_MAX_PASSPHRASE_BYTES bytes should be
 
177
 * allocated
 
178
 *
 
179
 * @passphrase A NULL-terminated char array
 
180
 *
 
181
 * @salt A salt
 
182
 *
 
183
 * @passphrase_sig An allocated char array into which the generated
 
184
 * signature is written; PASSWORD_SIG_SIZE bytes should be allocated
 
185
 *
 
186
 */
 
187
int
 
188
generate_fnek(char *fnek, char *salt, char *passphrase)
 
189
{
 
190
        char salt_and_passphrase[ECRYPTFS_MAX_PASSPHRASE_BYTES
 
191
                                 + ECRYPTFS_SALT_SIZE];
 
192
        int passphrase_size;
 
193
#ifdef ENABLE_NSS
 
194
        int alg = SEC_OID_SHA512;
 
195
#else
 
196
        int alg = GCRY_MD_SHA512;
 
197
#endif /* #ifdef ENABLE_NSS */
 
198
        int dig_len = SHA512_DIGEST_LENGTH;
 
199
        char buf[SHA512_DIGEST_LENGTH];
 
200
        int hash_iterations = ECRYPTFS_DEFAULT_NUM_HASH_ITERATIONS;
 
201
        int rc = 0;
 
202
 
 
203
        passphrase_size = strlen(passphrase);
 
204
        if (passphrase_size > ECRYPTFS_MAX_PASSPHRASE_BYTES) {
 
205
                fnek = NULL;
 
206
                syslog(LOG_ERR, "Passphrase too large (%d bytes)\n",
 
207
                       passphrase_size);
 
208
                return -EINVAL;
 
209
        }
 
210
        memcpy(salt_and_passphrase, salt, ECRYPTFS_SALT_SIZE);
 
211
        memcpy((salt_and_passphrase + ECRYPTFS_SALT_SIZE), passphrase,
 
212
                passphrase_size);
 
213
        if ((rc = do_hash(salt_and_passphrase,
 
214
                          (ECRYPTFS_SALT_SIZE + passphrase_size), buf, alg))) {
 
215
                return rc;
 
216
        }
 
217
        hash_iterations--;
 
218
        while (hash_iterations--) {
 
219
                if ((rc = do_hash(buf, dig_len, buf, alg))) {
 
220
                        return rc;
 
221
                }
 
222
        }
 
223
        if ((rc = do_hash(buf, dig_len, buf, alg))) {
 
224
                return rc;
 
225
        }
 
226
        to_hex(fnek, buf, ECRYPTFS_MAX_KEY_BYTES/4);
 
227
        return 0;
 
228
}
 
229
 
 
230
/**
175
231
 * @return Zero on success
176
232
 */
177
233
int