/* * 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) { struct trusted_key_payload *p; char *ascii_buf; char *bufp; int i; p = rcu_dereference_key(key); if (!p) return -EINVAL; if (!buffer || buflen <= 0) return 2 * p->blob_len; ascii_buf = kmalloc(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) { kfree(ascii_buf); return -EFAULT; } kfree(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 = rcu_dereference_key(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; }
/* * read the key data * - the key's semaphore is read-locked */ long user_read(const struct key *key, char __user *buffer, size_t buflen) { struct user_key_payload *upayload; long ret; upayload = rcu_dereference_key(key); ret = upayload->datalen; /* we can return the data as is */ if (buffer && buflen > 0) { if (buflen > upayload->datalen) buflen = upayload->datalen; if (copy_to_user(buffer, upayload->data, buflen) != 0) ret = -EFAULT; } return ret; }
/* * update a user defined key * - the key's semaphore is write-locked */ int user_update(struct key *key, struct key_preparsed_payload *prep) { struct user_key_payload *zap = NULL; int ret; /* check the quota and attach the new data */ ret = key_payload_reserve(key, prep->datalen); if (ret < 0) return ret; /* attach the new data, displacing the old */ key->expiry = prep->expiry; if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags)) zap = rcu_dereference_key(key); rcu_assign_keypointer(key, prep->payload.data[0]); prep->payload.data[0] = NULL; if (zap) kfree_rcu(zap, rcu); return ret; }