Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jmorris/security-testing-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (54 commits)
  tpm_nsc: Fix bug when loading multiple TPM drivers
  tpm: Move tpm_tis_reenable_interrupts out of CONFIG_PNP block
  tpm: Fix compilation warning when CONFIG_PNP is not defined
  TOMOYO: Update kernel-doc.
  tpm: Fix a typo
  tpm_tis: Probing function for Intel iTPM bug
  tpm_tis: Fix the probing for interrupts
  tpm_tis: Delay ACPI S3 suspend while the TPM is busy
  tpm_tis: Re-enable interrupts upon (S3) resume
  tpm: Fix display of data in pubek sysfs entry
  tpm_tis: Add timeouts sysfs entry
  tpm: Adjust interface timeouts if they are too small
  tpm: Use interface timeouts returned from the TPM
  tpm_tis: Introduce durations sysfs entry
  tpm: Adjust the durations if they are too small
  tpm: Use durations returned from TPM
  TOMOYO: Enable conditional ACL.
  TOMOYO: Allow using argv[]/envp[] of execve() as conditions.
  TOMOYO: Allow using executable's realpath and symlink's target as conditions.
  TOMOYO: Allow using owner/group etc. of file objects as conditions.
  ...

Fix up trivial conflict in security/tomoyo/realpath.c
  • Loading branch information
Linus Torvalds committed Jul 28, 2011
2 parents 2271220 + 29412f0 commit 95b6886
Show file tree
Hide file tree
Showing 36 changed files with 6,487 additions and 2,843 deletions.
68 changes: 68 additions & 0 deletions Documentation/security/keys-ecryptfs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
Encrypted keys for the eCryptfs filesystem

ECryptfs is a stacked filesystem which transparently encrypts and decrypts each
file using a randomly generated File Encryption Key (FEK).

Each FEK is in turn encrypted with a File Encryption Key Encryption Key (FEFEK)
either in kernel space or in user space with a daemon called 'ecryptfsd'. In
the former case the operation is performed directly by the kernel CryptoAPI
using a key, the FEFEK, derived from a user prompted passphrase; in the latter
the FEK is encrypted by 'ecryptfsd' with the help of external libraries in order
to support other mechanisms like public key cryptography, PKCS#11 and TPM based
operations.

The data structure defined by eCryptfs to contain information required for the
FEK decryption is called authentication token and, currently, can be stored in a
kernel key of the 'user' type, inserted in the user's session specific keyring
by the userspace utility 'mount.ecryptfs' shipped with the package
'ecryptfs-utils'.

The 'encrypted' key type has been extended with the introduction of the new
format 'ecryptfs' in order to be used in conjunction with the eCryptfs
filesystem. Encrypted keys of the newly introduced format store an
authentication token in its payload with a FEFEK randomly generated by the
kernel and protected by the parent master key.

In order to avoid known-plaintext attacks, the datablob obtained through
commands 'keyctl print' or 'keyctl pipe' does not contain the overall
authentication token, which content is well known, but only the FEFEK in
encrypted form.

The eCryptfs filesystem may really benefit from using encrypted keys in that the
required key can be securely generated by an Administrator and provided at boot
time after the unsealing of a 'trusted' key in order to perform the mount in a
controlled environment. Another advantage is that the key is not exposed to
threats of malicious software, because it is available in clear form only at
kernel level.

Usage:
keyctl add encrypted name "new ecryptfs key-type:master-key-name keylen" ring
keyctl add encrypted name "load hex_blob" ring
keyctl update keyid "update key-type:master-key-name"

name:= '<16 hexadecimal characters>'
key-type:= 'trusted' | 'user'
keylen:= 64


Example of encrypted key usage with the eCryptfs filesystem:

Create an encrypted key "1000100010001000" of length 64 bytes with format
'ecryptfs' and save it using a previously loaded user key "test":

$ keyctl add encrypted 1000100010001000 "new ecryptfs user:test 64" @u
19184530

$ keyctl print 19184530
ecryptfs user:test 64 490045d4bfe48c99f0d465fbbbb79e7500da954178e2de0697
dd85091f5450a0511219e9f7cd70dcd498038181466f78ac8d4c19504fcc72402bfc41c2
f253a41b7507ccaa4b2b03fff19a69d1cc0b16e71746473f023a95488b6edfd86f7fdd40
9d292e4bacded1258880122dd553a661

$ keyctl pipe 19184530 > ecryptfs.blob

Mount an eCryptfs filesystem using the created encrypted key "1000100010001000"
into the '/secret' directory:

$ mount -i -t ecryptfs -oecryptfs_sig=1000100010001000,\
ecryptfs_cipher=aes,ecryptfs_key_bytes=32 /secret /secret
52 changes: 33 additions & 19 deletions Documentation/security/keys-trusted-encrypted.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,19 @@ they are only as secure as the user key encrypting them. The master user key
should therefore be loaded in as secure a way as possible, preferably early in
boot.

The decrypted portion of encrypted keys can contain either a simple symmetric
key or a more complex structure. The format of the more complex structure is
application specific, which is identified by 'format'.

Usage:
keyctl add encrypted name "new key-type:master-key-name keylen" ring
keyctl add encrypted name "load hex_blob" ring
keyctl update keyid "update key-type:master-key-name"
keyctl add encrypted name "new [format] key-type:master-key-name keylen"
ring
keyctl add encrypted name "load hex_blob" ring
keyctl update keyid "update key-type:master-key-name"

format:= 'default | ecryptfs'
key-type:= 'trusted' | 'user'

where 'key-type' is either 'trusted' or 'user'.

Examples of trusted and encrypted key usage:

Expand Down Expand Up @@ -114,15 +121,25 @@ Reseal a trusted key under new pcr values:
7ef6a24defe4846104209bf0c3eced7fa1a672ed5b125fc9d8cd88b476a658a4434644ef
df8ae9a178e9f83ba9f08d10fa47e4226b98b0702f06b3b8

Create and save an encrypted key "evm" using the above trusted key "kmk":
The initial consumer of trusted keys is EVM, which at boot time needs a high
quality symmetric key for HMAC protection of file metadata. The use of a
trusted key provides strong guarantees that the EVM key has not been
compromised by a user level problem, and when sealed to specific boot PCR
values, protects against boot and offline attacks. Create and save an
encrypted key "evm" using the above trusted key "kmk":

option 1: omitting 'format'
$ keyctl add encrypted evm "new trusted:kmk 32" @u
159771175

option 2: explicitly defining 'format' as 'default'
$ keyctl add encrypted evm "new default trusted:kmk 32" @u
159771175

$ keyctl print 159771175
trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55
be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64
5972dcb82ab2dde83376d82b2e3c09ffc
default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
24717c64 5972dcb82ab2dde83376d82b2e3c09ffc

$ keyctl pipe 159771175 > evm.blob

Expand All @@ -132,14 +149,11 @@ Load an encrypted key "evm" from saved blob:
831684262

$ keyctl print 831684262
trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b382dbbc55
be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e024717c64
5972dcb82ab2dde83376d82b2e3c09ffc


The initial consumer of trusted keys is EVM, which at boot time needs a high
quality symmetric key for HMAC protection of file metadata. The use of a
trusted key provides strong guarantees that the EVM key has not been
compromised by a user level problem, and when sealed to specific boot PCR
values, protects against boot and offline attacks. Other uses for trusted and
encrypted keys, such as for disk and file encryption are anticipated.
default trusted:kmk 32 2375725ad57798846a9bbd240de8906f006e66c03af53b1b3
82dbbc55be2a44616e4959430436dc4f2a7a9659aa60bb4652aeb2120f149ed197c564e0
24717c64 5972dcb82ab2dde83376d82b2e3c09ffc

Other uses for trusted and encrypted keys, such as for disk and file encryption
are anticipated. In particular the new format 'ecryptfs' has been defined in
in order to use encrypted keys to mount an eCryptfs filesystem. More details
about the usage can be found in the file 'Documentation/keys-ecryptfs.txt'.
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -6408,7 +6408,7 @@ L: tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for users in English)
L: tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese)
L: tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese)
W: http://tomoyo.sourceforge.jp/
T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.3.x/tomoyo-lsm/patches/
T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.4.x/tomoyo-lsm/patches/
S: Maintained
F: security/tomoyo/

Expand Down
102 changes: 76 additions & 26 deletions drivers/char/tpm/tpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ void tpm_get_timeouts(struct tpm_chip *chip)
struct duration_t *duration_cap;
ssize_t rc;
u32 timeout;
unsigned int scale = 1;

tpm_cmd.header.in = tpm_getcap_header;
tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
Expand All @@ -545,24 +546,30 @@ void tpm_get_timeouts(struct tpm_chip *chip)
if (rc)
goto duration;

if (be32_to_cpu(tpm_cmd.header.out.length)
!= 4 * sizeof(u32))
goto duration;
if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
be32_to_cpu(tpm_cmd.header.out.length)
!= sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
return;

timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
/* Don't overwrite default if value is 0 */
timeout = be32_to_cpu(timeout_cap->a);
if (timeout && timeout < 1000) {
/* timeouts in msec rather usec */
scale = 1000;
chip->vendor.timeout_adjusted = true;
}
if (timeout)
chip->vendor.timeout_a = usecs_to_jiffies(timeout);
chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale);
timeout = be32_to_cpu(timeout_cap->b);
if (timeout)
chip->vendor.timeout_b = usecs_to_jiffies(timeout);
chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale);
timeout = be32_to_cpu(timeout_cap->c);
if (timeout)
chip->vendor.timeout_c = usecs_to_jiffies(timeout);
chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale);
timeout = be32_to_cpu(timeout_cap->d);
if (timeout)
chip->vendor.timeout_d = usecs_to_jiffies(timeout);
chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale);

duration:
tpm_cmd.header.in = tpm_getcap_header;
Expand All @@ -575,23 +582,31 @@ void tpm_get_timeouts(struct tpm_chip *chip)
if (rc)
return;

if (be32_to_cpu(tpm_cmd.header.out.return_code)
!= 3 * sizeof(u32))
if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
be32_to_cpu(tpm_cmd.header.out.length)
!= sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
return;

duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
chip->vendor.duration[TPM_SHORT] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
chip->vendor.duration[TPM_MEDIUM] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
chip->vendor.duration[TPM_LONG] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));

/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
* value wrong and apparently reports msecs rather than usecs. So we
* fix up the resulting too-small TPM_SHORT value to make things work.
* We also scale the TPM_MEDIUM and -_LONG values by 1000.
*/
if (chip->vendor.duration[TPM_SHORT] < (HZ/100))
if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) {
chip->vendor.duration[TPM_SHORT] = HZ;

chip->vendor.duration[TPM_MEDIUM] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
chip->vendor.duration[TPM_LONG] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
chip->vendor.duration[TPM_MEDIUM] *= 1000;
chip->vendor.duration[TPM_LONG] *= 1000;
chip->vendor.duration_adjusted = true;
dev_info(chip->dev, "Adjusting TPM timeout parameters.");
}
}
EXPORT_SYMBOL_GPL(tpm_get_timeouts);

Expand All @@ -600,7 +615,7 @@ void tpm_continue_selftest(struct tpm_chip *chip)
u8 data[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 10, /* length */
0, 0, 0, 83, /* TPM_ORD_GetCapability */
0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */
};

tpm_transmit(chip, data, sizeof(data));
Expand Down Expand Up @@ -863,18 +878,24 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
data = tpm_cmd.params.readpubek_out_buffer;
str +=
sprintf(str,
"Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
"Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
" %02X %02X %02X %02X %02X %02X %02X %02X\n"
"Modulus length: %d\nModulus: \n",
data[10], data[11], data[12], data[13], data[14],
data[15], data[16], data[17], data[22], data[23],
data[24], data[25], data[26], data[27], data[28],
data[29], data[30], data[31], data[32], data[33],
be32_to_cpu(*((__be32 *) (data + 34))));
"Algorithm: %02X %02X %02X %02X\n"
"Encscheme: %02X %02X\n"
"Sigscheme: %02X %02X\n"
"Parameters: %02X %02X %02X %02X "
"%02X %02X %02X %02X "
"%02X %02X %02X %02X\n"
"Modulus length: %d\n"
"Modulus:\n",
data[0], data[1], data[2], data[3],
data[4], data[5],
data[6], data[7],
data[12], data[13], data[14], data[15],
data[16], data[17], data[18], data[19],
data[20], data[21], data[22], data[23],
be32_to_cpu(*((__be32 *) (data + 24))));

for (i = 0; i < 256; i++) {
str += sprintf(str, "%02X ", data[i + 38]);
str += sprintf(str, "%02X ", data[i + 28]);
if ((i + 1) % 16 == 0)
str += sprintf(str, "\n");
}
Expand Down Expand Up @@ -937,6 +958,35 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
}
EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);

ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct tpm_chip *chip = dev_get_drvdata(dev);

return sprintf(buf, "%d %d %d [%s]\n",
jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
jiffies_to_usecs(chip->vendor.duration[TPM_LONG]),
chip->vendor.duration_adjusted
? "adjusted" : "original");
}
EXPORT_SYMBOL_GPL(tpm_show_durations);

ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct tpm_chip *chip = dev_get_drvdata(dev);

return sprintf(buf, "%d %d %d %d [%s]\n",
jiffies_to_usecs(chip->vendor.timeout_a),
jiffies_to_usecs(chip->vendor.timeout_b),
jiffies_to_usecs(chip->vendor.timeout_c),
jiffies_to_usecs(chip->vendor.timeout_d),
chip->vendor.timeout_adjusted
? "adjusted" : "original");
}
EXPORT_SYMBOL_GPL(tpm_show_timeouts);

ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
Expand Down
7 changes: 7 additions & 0 deletions drivers/char/tpm/tpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_show_temp_deactivated(struct device *,
struct device_attribute *attr, char *);
extern ssize_t tpm_show_durations(struct device *,
struct device_attribute *attr, char *);
extern ssize_t tpm_show_timeouts(struct device *,
struct device_attribute *attr, char *);

struct tpm_chip;

Expand All @@ -67,6 +71,7 @@ struct tpm_vendor_specific {
unsigned long base; /* TPM base address */

int irq;
int probed_irq;

int region_size;
int have_region;
Expand All @@ -81,7 +86,9 @@ struct tpm_vendor_specific {
struct list_head list;
int locality;
unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
bool timeout_adjusted;
unsigned long duration[3]; /* jiffies */
bool duration_adjusted;

wait_queue_head_t read_queue;
wait_queue_head_t int_queue;
Expand Down
14 changes: 7 additions & 7 deletions drivers/char/tpm/tpm_nsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,12 +330,12 @@ static int __init init_nsc(void)
pdev->dev.driver = &nsc_drv.driver;
pdev->dev.release = tpm_nsc_remove;

if ((rc = platform_device_register(pdev)) < 0)
goto err_free_dev;
if ((rc = platform_device_add(pdev)) < 0)
goto err_put_dev;

if (request_region(base, 2, "tpm_nsc0") == NULL ) {
rc = -EBUSY;
goto err_unreg_dev;
goto err_del_dev;
}

if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
Expand Down Expand Up @@ -382,10 +382,10 @@ static int __init init_nsc(void)

err_rel_reg:
release_region(base, 2);
err_unreg_dev:
platform_device_unregister(pdev);
err_free_dev:
kfree(pdev);
err_del_dev:
platform_device_del(pdev);
err_put_dev:
platform_device_put(pdev);
err_unreg_drv:
platform_driver_unregister(&nsc_drv);
return rc;
Expand Down
Loading

0 comments on commit 95b6886

Please sign in to comment.