Loading crypto/asymmetric_keys/pkcs7_trust.c +1 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, pr_devel("sinfo %u: Direct signer is key %x\n", sinfo->index, key_serial(key)); x509 = NULL; sig = sinfo->sig; goto matched; } if (PTR_ERR(key) != -ENOKEY) Loading crypto/asymmetric_keys/pkcs7_verify.c +7 −5 Original line number Diff line number Diff line Loading @@ -270,7 +270,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, sinfo->index); return 0; } ret = public_key_verify_signature(p->pub, p->sig); ret = public_key_verify_signature(p->pub, x509->sig); if (ret < 0) return ret; x509->signer = p; Loading Loading @@ -366,8 +366,7 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, * * (*) -EBADMSG if some part of the message was invalid, or: * * (*) 0 if no signature chains were found to be blacklisted or to contain * unsupported crypto, or: * (*) 0 if a signature chain passed verification, or: * * (*) -EKEYREJECTED if a blacklisted key was encountered, or: * Loading Loading @@ -423,8 +422,11 @@ int pkcs7_verify(struct pkcs7_message *pkcs7, for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { ret = pkcs7_verify_one(pkcs7, sinfo); if (sinfo->blacklisted && actual_ret == -ENOPKG) if (sinfo->blacklisted) { if (actual_ret == -ENOPKG) actual_ret = -EKEYREJECTED; continue; } if (ret < 0) { if (ret == -ENOPKG) { sinfo->unsupported_crypto = true; Loading crypto/asymmetric_keys/public_key.c +3 −1 Original line number Diff line number Diff line Loading @@ -79,9 +79,11 @@ int public_key_verify_signature(const struct public_key *pkey, BUG_ON(!pkey); BUG_ON(!sig); BUG_ON(!sig->digest); BUG_ON(!sig->s); if (!sig->digest) return -ENOPKG; alg_name = sig->pkey_algo; if (strcmp(sig->pkey_algo, "rsa") == 0) { /* The data wangled by the RSA algorithm is typically padded Loading crypto/asymmetric_keys/restrict.c +13 −8 Original line number Diff line number Diff line Loading @@ -67,8 +67,9 @@ __setup("ca_keys=", ca_keys_setup); * * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a * matching parent certificate in the trusted list, -EKEYREJECTED if the * signature check fails or the key is blacklisted and some other error if * there is a matching certificate but the signature check cannot be performed. * signature check fails or the key is blacklisted, -ENOPKG if the signature * uses unsupported crypto, or some other error if there is a matching * certificate but the signature check cannot be performed. */ int restrict_link_by_signature(struct key *dest_keyring, const struct key_type *type, Loading @@ -88,6 +89,8 @@ int restrict_link_by_signature(struct key *dest_keyring, return -EOPNOTSUPP; sig = payload->data[asym_auth]; if (!sig) return -ENOPKG; if (!sig->auth_ids[0] && !sig->auth_ids[1]) return -ENOKEY; Loading Loading @@ -139,6 +142,8 @@ static int key_or_keyring_common(struct key *dest_keyring, return -EOPNOTSUPP; sig = payload->data[asym_auth]; if (!sig) return -ENOPKG; if (!sig->auth_ids[0] && !sig->auth_ids[1]) return -ENOKEY; Loading Loading @@ -222,9 +227,9 @@ static int key_or_keyring_common(struct key *dest_keyring, * * Returns 0 if the new certificate was accepted, -ENOKEY if we * couldn't find a matching parent certificate in the trusted list, * -EKEYREJECTED if the signature check fails, and some other error if * there is a matching certificate but the signature check cannot be * performed. * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses * unsupported crypto, or some other error if there is a matching certificate * but the signature check cannot be performed. */ int restrict_link_by_key_or_keyring(struct key *dest_keyring, const struct key_type *type, Loading @@ -249,9 +254,9 @@ int restrict_link_by_key_or_keyring(struct key *dest_keyring, * * Returns 0 if the new certificate was accepted, -ENOKEY if we * couldn't find a matching parent certificate in the trusted list, * -EKEYREJECTED if the signature check fails, and some other error if * there is a matching certificate but the signature check cannot be * performed. * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses * unsupported crypto, or some other error if there is a matching certificate * but the signature check cannot be performed. */ int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring, const struct key_type *type, Loading security/keys/big_key.c +87 −23 Original line number Diff line number Diff line Loading @@ -22,6 +22,13 @@ #include <keys/big_key-type.h> #include <crypto/aead.h> struct big_key_buf { unsigned int nr_pages; void *virt; struct scatterlist *sg; struct page *pages[]; }; /* * Layout of key payload words. */ Loading Loading @@ -91,10 +98,9 @@ static DEFINE_MUTEX(big_key_aead_lock); /* * Encrypt/decrypt big_key data */ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key) static int big_key_crypt(enum big_key_op op, struct big_key_buf *buf, size_t datalen, u8 *key) { int ret; struct scatterlist sgio; struct aead_request *aead_req; /* We always use a zero nonce. The reason we can get away with this is * because we're using a different randomly generated key for every Loading @@ -109,8 +115,7 @@ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key) return -ENOMEM; memset(zero_nonce, 0, sizeof(zero_nonce)); sg_init_one(&sgio, data, datalen + (op == BIG_KEY_ENC ? ENC_AUTHTAG_SIZE : 0)); aead_request_set_crypt(aead_req, &sgio, &sgio, datalen, zero_nonce); aead_request_set_crypt(aead_req, buf->sg, buf->sg, datalen, zero_nonce); aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); aead_request_set_ad(aead_req, 0); Loading @@ -129,22 +134,82 @@ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key) return ret; } /* * Free up the buffer. */ static void big_key_free_buffer(struct big_key_buf *buf) { unsigned int i; if (buf->virt) { memset(buf->virt, 0, buf->nr_pages * PAGE_SIZE); vunmap(buf->virt); } for (i = 0; i < buf->nr_pages; i++) if (buf->pages[i]) __free_page(buf->pages[i]); kfree(buf); } /* * Allocate a buffer consisting of a set of pages with a virtual mapping * applied over them. */ static void *big_key_alloc_buffer(size_t len) { struct big_key_buf *buf; unsigned int npg = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned int i, l; buf = kzalloc(sizeof(struct big_key_buf) + sizeof(struct page) * npg + sizeof(struct scatterlist) * npg, GFP_KERNEL); if (!buf) return NULL; buf->nr_pages = npg; buf->sg = (void *)(buf->pages + npg); sg_init_table(buf->sg, npg); for (i = 0; i < buf->nr_pages; i++) { buf->pages[i] = alloc_page(GFP_KERNEL); if (!buf->pages[i]) goto nomem; l = min_t(size_t, len, PAGE_SIZE); sg_set_page(&buf->sg[i], buf->pages[i], l, 0); len -= l; } buf->virt = vmap(buf->pages, buf->nr_pages, VM_MAP, PAGE_KERNEL); if (!buf->virt) goto nomem; return buf; nomem: big_key_free_buffer(buf); return NULL; } /* * Preparse a big key */ int big_key_preparse(struct key_preparsed_payload *prep) { struct big_key_buf *buf; struct path *path = (struct path *)&prep->payload.data[big_key_path]; struct file *file; u8 *enckey; u8 *data = NULL; ssize_t written; size_t datalen = prep->datalen; size_t datalen = prep->datalen, enclen = datalen + ENC_AUTHTAG_SIZE; int ret; ret = -EINVAL; if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data) goto error; return -EINVAL; /* Set an arbitrary quota */ prep->quotalen = 16; Loading @@ -157,13 +222,12 @@ int big_key_preparse(struct key_preparsed_payload *prep) * * File content is stored encrypted with randomly generated key. */ size_t enclen = datalen + ENC_AUTHTAG_SIZE; loff_t pos = 0; data = kmalloc(enclen, GFP_KERNEL); if (!data) buf = big_key_alloc_buffer(enclen); if (!buf) return -ENOMEM; memcpy(data, prep->data, datalen); memcpy(buf->virt, prep->data, datalen); /* generate random key */ enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL); Loading @@ -176,7 +240,7 @@ int big_key_preparse(struct key_preparsed_payload *prep) goto err_enckey; /* encrypt aligned data */ ret = big_key_crypt(BIG_KEY_ENC, data, datalen, enckey); ret = big_key_crypt(BIG_KEY_ENC, buf, datalen, enckey); if (ret) goto err_enckey; Loading @@ -187,7 +251,7 @@ int big_key_preparse(struct key_preparsed_payload *prep) goto err_enckey; } written = kernel_write(file, data, enclen, &pos); written = kernel_write(file, buf->virt, enclen, &pos); if (written != enclen) { ret = written; if (written >= 0) Loading @@ -202,7 +266,7 @@ int big_key_preparse(struct key_preparsed_payload *prep) *path = file->f_path; path_get(path); fput(file); kzfree(data); big_key_free_buffer(buf); } else { /* Just store the data in a buffer */ void *data = kmalloc(datalen, GFP_KERNEL); Loading @@ -220,7 +284,7 @@ int big_key_preparse(struct key_preparsed_payload *prep) err_enckey: kzfree(enckey); error: kzfree(data); big_key_free_buffer(buf); return ret; } Loading Loading @@ -298,15 +362,15 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen) return datalen; if (datalen > BIG_KEY_FILE_THRESHOLD) { struct big_key_buf *buf; struct path *path = (struct path *)&key->payload.data[big_key_path]; struct file *file; u8 *data; u8 *enckey = (u8 *)key->payload.data[big_key_data]; size_t enclen = datalen + ENC_AUTHTAG_SIZE; loff_t pos = 0; data = kmalloc(enclen, GFP_KERNEL); if (!data) buf = big_key_alloc_buffer(enclen); if (!buf) return -ENOMEM; file = dentry_open(path, O_RDONLY, current_cred()); Loading @@ -316,26 +380,26 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen) } /* read file to kernel and decrypt */ ret = kernel_read(file, data, enclen, &pos); ret = kernel_read(file, buf->virt, enclen, &pos); if (ret >= 0 && ret != enclen) { ret = -EIO; goto err_fput; } ret = big_key_crypt(BIG_KEY_DEC, data, enclen, enckey); ret = big_key_crypt(BIG_KEY_DEC, buf, enclen, enckey); if (ret) goto err_fput; ret = datalen; /* copy decrypted data to user */ if (copy_to_user(buffer, data, datalen) != 0) if (copy_to_user(buffer, buf->virt, datalen) != 0) ret = -EFAULT; err_fput: fput(file); error: kzfree(data); big_key_free_buffer(buf); } else { ret = datalen; if (copy_to_user(buffer, key->payload.data[big_key_data], Loading Loading
crypto/asymmetric_keys/pkcs7_trust.c +1 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, pr_devel("sinfo %u: Direct signer is key %x\n", sinfo->index, key_serial(key)); x509 = NULL; sig = sinfo->sig; goto matched; } if (PTR_ERR(key) != -ENOKEY) Loading
crypto/asymmetric_keys/pkcs7_verify.c +7 −5 Original line number Diff line number Diff line Loading @@ -270,7 +270,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, sinfo->index); return 0; } ret = public_key_verify_signature(p->pub, p->sig); ret = public_key_verify_signature(p->pub, x509->sig); if (ret < 0) return ret; x509->signer = p; Loading Loading @@ -366,8 +366,7 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, * * (*) -EBADMSG if some part of the message was invalid, or: * * (*) 0 if no signature chains were found to be blacklisted or to contain * unsupported crypto, or: * (*) 0 if a signature chain passed verification, or: * * (*) -EKEYREJECTED if a blacklisted key was encountered, or: * Loading Loading @@ -423,8 +422,11 @@ int pkcs7_verify(struct pkcs7_message *pkcs7, for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { ret = pkcs7_verify_one(pkcs7, sinfo); if (sinfo->blacklisted && actual_ret == -ENOPKG) if (sinfo->blacklisted) { if (actual_ret == -ENOPKG) actual_ret = -EKEYREJECTED; continue; } if (ret < 0) { if (ret == -ENOPKG) { sinfo->unsupported_crypto = true; Loading
crypto/asymmetric_keys/public_key.c +3 −1 Original line number Diff line number Diff line Loading @@ -79,9 +79,11 @@ int public_key_verify_signature(const struct public_key *pkey, BUG_ON(!pkey); BUG_ON(!sig); BUG_ON(!sig->digest); BUG_ON(!sig->s); if (!sig->digest) return -ENOPKG; alg_name = sig->pkey_algo; if (strcmp(sig->pkey_algo, "rsa") == 0) { /* The data wangled by the RSA algorithm is typically padded Loading
crypto/asymmetric_keys/restrict.c +13 −8 Original line number Diff line number Diff line Loading @@ -67,8 +67,9 @@ __setup("ca_keys=", ca_keys_setup); * * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a * matching parent certificate in the trusted list, -EKEYREJECTED if the * signature check fails or the key is blacklisted and some other error if * there is a matching certificate but the signature check cannot be performed. * signature check fails or the key is blacklisted, -ENOPKG if the signature * uses unsupported crypto, or some other error if there is a matching * certificate but the signature check cannot be performed. */ int restrict_link_by_signature(struct key *dest_keyring, const struct key_type *type, Loading @@ -88,6 +89,8 @@ int restrict_link_by_signature(struct key *dest_keyring, return -EOPNOTSUPP; sig = payload->data[asym_auth]; if (!sig) return -ENOPKG; if (!sig->auth_ids[0] && !sig->auth_ids[1]) return -ENOKEY; Loading Loading @@ -139,6 +142,8 @@ static int key_or_keyring_common(struct key *dest_keyring, return -EOPNOTSUPP; sig = payload->data[asym_auth]; if (!sig) return -ENOPKG; if (!sig->auth_ids[0] && !sig->auth_ids[1]) return -ENOKEY; Loading Loading @@ -222,9 +227,9 @@ static int key_or_keyring_common(struct key *dest_keyring, * * Returns 0 if the new certificate was accepted, -ENOKEY if we * couldn't find a matching parent certificate in the trusted list, * -EKEYREJECTED if the signature check fails, and some other error if * there is a matching certificate but the signature check cannot be * performed. * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses * unsupported crypto, or some other error if there is a matching certificate * but the signature check cannot be performed. */ int restrict_link_by_key_or_keyring(struct key *dest_keyring, const struct key_type *type, Loading @@ -249,9 +254,9 @@ int restrict_link_by_key_or_keyring(struct key *dest_keyring, * * Returns 0 if the new certificate was accepted, -ENOKEY if we * couldn't find a matching parent certificate in the trusted list, * -EKEYREJECTED if the signature check fails, and some other error if * there is a matching certificate but the signature check cannot be * performed. * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses * unsupported crypto, or some other error if there is a matching certificate * but the signature check cannot be performed. */ int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring, const struct key_type *type, Loading
security/keys/big_key.c +87 −23 Original line number Diff line number Diff line Loading @@ -22,6 +22,13 @@ #include <keys/big_key-type.h> #include <crypto/aead.h> struct big_key_buf { unsigned int nr_pages; void *virt; struct scatterlist *sg; struct page *pages[]; }; /* * Layout of key payload words. */ Loading Loading @@ -91,10 +98,9 @@ static DEFINE_MUTEX(big_key_aead_lock); /* * Encrypt/decrypt big_key data */ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key) static int big_key_crypt(enum big_key_op op, struct big_key_buf *buf, size_t datalen, u8 *key) { int ret; struct scatterlist sgio; struct aead_request *aead_req; /* We always use a zero nonce. The reason we can get away with this is * because we're using a different randomly generated key for every Loading @@ -109,8 +115,7 @@ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key) return -ENOMEM; memset(zero_nonce, 0, sizeof(zero_nonce)); sg_init_one(&sgio, data, datalen + (op == BIG_KEY_ENC ? ENC_AUTHTAG_SIZE : 0)); aead_request_set_crypt(aead_req, &sgio, &sgio, datalen, zero_nonce); aead_request_set_crypt(aead_req, buf->sg, buf->sg, datalen, zero_nonce); aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); aead_request_set_ad(aead_req, 0); Loading @@ -129,22 +134,82 @@ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key) return ret; } /* * Free up the buffer. */ static void big_key_free_buffer(struct big_key_buf *buf) { unsigned int i; if (buf->virt) { memset(buf->virt, 0, buf->nr_pages * PAGE_SIZE); vunmap(buf->virt); } for (i = 0; i < buf->nr_pages; i++) if (buf->pages[i]) __free_page(buf->pages[i]); kfree(buf); } /* * Allocate a buffer consisting of a set of pages with a virtual mapping * applied over them. */ static void *big_key_alloc_buffer(size_t len) { struct big_key_buf *buf; unsigned int npg = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned int i, l; buf = kzalloc(sizeof(struct big_key_buf) + sizeof(struct page) * npg + sizeof(struct scatterlist) * npg, GFP_KERNEL); if (!buf) return NULL; buf->nr_pages = npg; buf->sg = (void *)(buf->pages + npg); sg_init_table(buf->sg, npg); for (i = 0; i < buf->nr_pages; i++) { buf->pages[i] = alloc_page(GFP_KERNEL); if (!buf->pages[i]) goto nomem; l = min_t(size_t, len, PAGE_SIZE); sg_set_page(&buf->sg[i], buf->pages[i], l, 0); len -= l; } buf->virt = vmap(buf->pages, buf->nr_pages, VM_MAP, PAGE_KERNEL); if (!buf->virt) goto nomem; return buf; nomem: big_key_free_buffer(buf); return NULL; } /* * Preparse a big key */ int big_key_preparse(struct key_preparsed_payload *prep) { struct big_key_buf *buf; struct path *path = (struct path *)&prep->payload.data[big_key_path]; struct file *file; u8 *enckey; u8 *data = NULL; ssize_t written; size_t datalen = prep->datalen; size_t datalen = prep->datalen, enclen = datalen + ENC_AUTHTAG_SIZE; int ret; ret = -EINVAL; if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data) goto error; return -EINVAL; /* Set an arbitrary quota */ prep->quotalen = 16; Loading @@ -157,13 +222,12 @@ int big_key_preparse(struct key_preparsed_payload *prep) * * File content is stored encrypted with randomly generated key. */ size_t enclen = datalen + ENC_AUTHTAG_SIZE; loff_t pos = 0; data = kmalloc(enclen, GFP_KERNEL); if (!data) buf = big_key_alloc_buffer(enclen); if (!buf) return -ENOMEM; memcpy(data, prep->data, datalen); memcpy(buf->virt, prep->data, datalen); /* generate random key */ enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL); Loading @@ -176,7 +240,7 @@ int big_key_preparse(struct key_preparsed_payload *prep) goto err_enckey; /* encrypt aligned data */ ret = big_key_crypt(BIG_KEY_ENC, data, datalen, enckey); ret = big_key_crypt(BIG_KEY_ENC, buf, datalen, enckey); if (ret) goto err_enckey; Loading @@ -187,7 +251,7 @@ int big_key_preparse(struct key_preparsed_payload *prep) goto err_enckey; } written = kernel_write(file, data, enclen, &pos); written = kernel_write(file, buf->virt, enclen, &pos); if (written != enclen) { ret = written; if (written >= 0) Loading @@ -202,7 +266,7 @@ int big_key_preparse(struct key_preparsed_payload *prep) *path = file->f_path; path_get(path); fput(file); kzfree(data); big_key_free_buffer(buf); } else { /* Just store the data in a buffer */ void *data = kmalloc(datalen, GFP_KERNEL); Loading @@ -220,7 +284,7 @@ int big_key_preparse(struct key_preparsed_payload *prep) err_enckey: kzfree(enckey); error: kzfree(data); big_key_free_buffer(buf); return ret; } Loading Loading @@ -298,15 +362,15 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen) return datalen; if (datalen > BIG_KEY_FILE_THRESHOLD) { struct big_key_buf *buf; struct path *path = (struct path *)&key->payload.data[big_key_path]; struct file *file; u8 *data; u8 *enckey = (u8 *)key->payload.data[big_key_data]; size_t enclen = datalen + ENC_AUTHTAG_SIZE; loff_t pos = 0; data = kmalloc(enclen, GFP_KERNEL); if (!data) buf = big_key_alloc_buffer(enclen); if (!buf) return -ENOMEM; file = dentry_open(path, O_RDONLY, current_cred()); Loading @@ -316,26 +380,26 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen) } /* read file to kernel and decrypt */ ret = kernel_read(file, data, enclen, &pos); ret = kernel_read(file, buf->virt, enclen, &pos); if (ret >= 0 && ret != enclen) { ret = -EIO; goto err_fput; } ret = big_key_crypt(BIG_KEY_DEC, data, enclen, enckey); ret = big_key_crypt(BIG_KEY_DEC, buf, enclen, enckey); if (ret) goto err_fput; ret = datalen; /* copy decrypted data to user */ if (copy_to_user(buffer, data, datalen) != 0) if (copy_to_user(buffer, buf->virt, datalen) != 0) ret = -EFAULT; err_fput: fput(file); error: kzfree(data); big_key_free_buffer(buf); } else { ret = datalen; if (copy_to_user(buffer, key->payload.data[big_key_data], Loading