/* * trusted_read - copy the sealed blob data to userspace in hex. * On success, return to userspace the trusted key datablob size. */ static long trusted_read(const struct key *key, char __user *buffer, size_t buflen) { const struct trusted_key_payload *p; char *ascii_buf; char *bufp; int i; p = dereference_key_locked(key); if (!p) return -EINVAL; if (buffer && buflen >= 2 * p->blob_len) { ascii_buf = kmalloc_array(2, p->blob_len, GFP_KERNEL); if (!ascii_buf) return -ENOMEM; bufp = ascii_buf; for (i = 0; i < p->blob_len; i++) bufp = hex_byte_pack(bufp, p->blob[i]); if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) { kzfree(ascii_buf); return -EFAULT; } kzfree(ascii_buf); } return 2 * p->blob_len; }
/* * encrypted_read - format and copy the encrypted data to userspace * * The resulting datablob format is: * <master-key name> <decrypted data length> <encrypted iv> <encrypted data> * * On success, return to userspace the encrypted key datablob size. */ static long encrypted_read(const struct key *key, char __user *buffer, size_t buflen) { struct encrypted_key_payload *epayload; struct key *mkey; const u8 *master_key; size_t master_keylen; char derived_key[HASH_SIZE]; char *ascii_buf; size_t asciiblob_len; int ret; epayload = dereference_key_locked(key); /* returns the hex encoded iv, encrypted-data, and hmac as ascii */ asciiblob_len = epayload->datablob_len + ivsize + 1 + roundup(epayload->decrypted_datalen, blksize) + (HASH_SIZE * 2); if (!buffer || buflen < asciiblob_len) return asciiblob_len; mkey = request_master_key(epayload, &master_key, &master_keylen); if (IS_ERR(mkey)) return PTR_ERR(mkey); ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen); if (ret < 0) goto out; ret = derived_key_encrypt(epayload, derived_key, sizeof derived_key); if (ret < 0) goto out; ret = datablob_hmac_append(epayload, master_key, master_keylen); if (ret < 0) goto out; ascii_buf = datablob_format(epayload, asciiblob_len); if (!ascii_buf) { ret = -ENOMEM; goto out; } up_read(&mkey->sem); key_put(mkey); if (copy_to_user(buffer, ascii_buf, asciiblob_len) != 0) ret = -EFAULT; kfree(ascii_buf); return asciiblob_len; out: up_read(&mkey->sem); key_put(mkey); return ret; }