void kinit(void) { kenter(FOR, "for"); kenter(IN, "in"); kenter(WHILE, "while"); kenter(IF, "if"); kenter(NOT, "not"); kenter(TWIDDLE, "~"); kenter(BANG, "!"); kenter(SUBSHELL, "@"); kenter(SWITCH, "switch"); kenter(FN, "fn"); }
/* * Perform the verification step [RFC3447 sec 8.2.2]. */ static int RSA_verify_signature(const struct public_key *key, const struct public_key_signature *sig) { size_t tsize; int ret; /* Variables as per RFC3447 sec 8.2.2 */ const u8 *H = sig->digest; u8 *EM = NULL; MPI m = NULL; size_t k; kenter(""); if (!RSA_ASN1_templates[sig->pkey_hash_algo].data) return -ENOTSUPP; /* (1) Check the signature size against the public key modulus size */ k = mpi_get_nbits(key->rsa.n); tsize = mpi_get_nbits(sig->rsa.s); /* According to RFC 4880 sec 3.2, length of MPI is computed starting * from most significant bit. So the RFC 3447 sec 8.2.2 size check * must be relaxed to conform with shorter signatures - so we fail here * only if signature length is longer than modulus size. */ pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); if (k < tsize) { ret = -EBADMSG; goto error; } /* Round up and convert to octets */ k = (k + 7) / 8; /* (2b) Apply the RSAVP1 verification primitive to the public key */ ret = RSAVP1(key, sig->rsa.s, &m); if (ret < 0) goto error; /* (2c) Convert the message representative (m) to an encoded message * (EM) of length k octets. * * NOTE! The leading zero byte is suppressed by MPI, so we pass a * pointer to the _preceding_ byte to RSA_verify()! */ ret = RSA_I2OSP(m, k, &EM); if (ret < 0) goto error; ret = RSA_verify(H, EM - 1, k, sig->digest_size, RSA_ASN1_templates[sig->pkey_hash_algo].data, RSA_ASN1_templates[sig->pkey_hash_algo].size); error: kfree(EM); mpi_free(m); kleave(" = %d", ret); return ret; }
/* * Some key's cleanup time was met after it expired, so we need to get the * reaper to go through a cycle finding expired keys. */ static void key_gc_timer_func(unsigned long data) { kenter(""); key_gc_next_run = LONG_MAX; set_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags); queue_work(system_nrt_wq, &key_gc_work); }
/** * verify_pefile_signature - Verify the signature on a PE binary image * @pebuf: Buffer containing the PE binary image * @pelen: Length of the binary image * @trust_keyring: Signing certificates to use as starting points * @usage: The use to which the key is being put. * @_trusted: Set to true if trustworth, false otherwise * * Validate that the certificate chain inside the PKCS#7 message inside the PE * binary image intersects keys we already know and trust. * * Returns, in order of descending priority: * * (*) -ELIBBAD if the image cannot be parsed, or: * * (*) -EKEYREJECTED if a signature failed to match for which we have a valid * key, or: * * (*) 0 if at least one signature chain intersects with the keys in the trust * keyring, or: * * (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a * chain. * * (*) -ENOKEY if we couldn't find a match for any of the signature chains in * the message. * * May also return -ENOMEM. */ int verify_pefile_signature(const void *pebuf, unsigned pelen, struct key *trusted_keyring, enum key_being_used_for usage, bool *_trusted) { struct pkcs7_message *pkcs7; struct pefile_context ctx; const void *data; size_t datalen; int ret; kenter(""); memset(&ctx, 0, sizeof(ctx)); ret = pefile_parse_binary(pebuf, pelen, &ctx); if (ret < 0) return ret; ret = pefile_strip_sig_wrapper(pebuf, &ctx); if (ret < 0) return ret; pkcs7 = pkcs7_parse_message(pebuf + ctx.sig_offset, ctx.sig_len); if (IS_ERR(pkcs7)) return PTR_ERR(pkcs7); ctx.pkcs7 = pkcs7; ret = pkcs7_get_content_data(ctx.pkcs7, &data, &datalen, false); if (ret < 0 || datalen == 0) { pr_devel("PKCS#7 message does not contain data\n"); ret = -EBADMSG; goto error; } ret = mscode_parse(&ctx); if (ret < 0) goto error; pr_debug("Digest: %u [%*ph]\n", ctx.digest_len, ctx.digest_len, ctx.digest); /* Generate the digest and check against the PKCS7 certificate * contents. */ ret = pefile_digest_pe(pebuf, pelen, &ctx); if (ret < 0) goto error; ret = pkcs7_verify(pkcs7, usage); if (ret < 0) goto error; ret = pkcs7_validate_trust(pkcs7, trusted_keyring, _trusted); error: pkcs7_free_message(ctx.pkcs7); return ret; }
/* * allocate a new key in under-construction state and attempt to link it in to * the requested place * - may return a key that's already under construction instead */ static int construct_alloc_key(struct key_type *type, const char *description, struct key *dest_keyring, unsigned long flags, struct key_user *user, struct key **_key) { const struct cred *cred = current_cred(); struct key *key; key_ref_t key_ref; kenter("%s,%s,,,", type->name, description); mutex_lock(&user->cons_lock); key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, KEY_POS_ALL, flags); if (IS_ERR(key)) goto alloc_failed; set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); down_write(&dest_keyring->sem); /* attach the key to the destination keyring under lock, but we do need * to do another check just in case someone beat us to it whilst we * waited for locks */ mutex_lock(&key_construction_mutex); key_ref = search_process_keyrings(type, description, type->match, cred); if (!IS_ERR(key_ref)) goto key_already_present; __key_link(dest_keyring, key); mutex_unlock(&key_construction_mutex); up_write(&dest_keyring->sem); mutex_unlock(&user->cons_lock); *_key = key; kleave(" = 0 [%d]", key_serial(key)); return 0; key_already_present: mutex_unlock(&key_construction_mutex); if (dest_keyring) up_write(&dest_keyring->sem); mutex_unlock(&user->cons_lock); key_put(key); *_key = key = key_ref_to_ptr(key_ref); kleave(" = -EINPROGRESS [%d]", key_serial(key)); return -EINPROGRESS; alloc_failed: mutex_unlock(&user->cons_lock); *_key = NULL; kleave(" = %ld", PTR_ERR(key)); return PTR_ERR(key); }
/* * destroy an instantiation authorisation token key */ static void request_key_auth_destroy(struct key *key) { struct request_key_auth *rka = key->payload.data; kenter("{%d}", key->serial); key_put(rka->target_key); } /* end request_key_auth_destroy() */
/* * handle mountpoint expiry timer going off */ static void afs_mntpt_expiry_timed_out(struct afs_timer *timer) { kenter(""); mark_mounts_for_expiry(&afs_vfsmounts); afs_kafstimod_add_timer(&afs_mntpt_expiry_timer, afs_mntpt_expiry_timeout * HZ); kleave(""); } /* end afs_mntpt_expiry_timed_out() */
/* * Handle revocation of an authorisation token key. * * Called with the key sem write-locked. */ static void request_key_auth_revoke(struct key *key) { struct request_key_auth *rka = key->payload.data[0]; kenter("{%d}", key->serial); if (rka->cred) { put_cred(rka->cred); rka->cred = NULL; } }
/* * handle revocation of an authorisation token key * - called with the key sem write-locked */ static void request_key_auth_revoke(struct key *key) { struct request_key_auth *rka = key->payload.data; kenter("{%d}", key->serial); if (rka->context) { put_task_struct(rka->context); rka->context = NULL; } } /* end request_key_auth_revoke() */
/* * no valid open procedure on this sort of dir */ static int afs_mntpt_open(struct inode *inode, struct file *file) { kenter("%p,%p{%p{%s},%s}", inode, file, file->f_dentry->d_parent, file->f_dentry->d_parent ? file->f_dentry->d_parent->d_name.name : (const unsigned char *) "", file->f_dentry->d_name.name); return -EREMOTE; } /* end afs_mntpt_open() */
/** * request_key_and_link - Request a key and cache it in a keyring. * @type: The type of key we want. * @description: The searchable description of the key. * @callout_info: The data to pass to the instantiation upcall (or NULL). * @callout_len: The length of callout_info. * @aux: Auxiliary data for the upcall. * @dest_keyring: Where to cache the key. * @flags: Flags to key_alloc(). * * A key matching the specified criteria is searched for in the process's * keyrings and returned with its usage count incremented if found. Otherwise, * if callout_info is not NULL, a key will be allocated and some service * (probably in userspace) will be asked to instantiate it. * * If successfully found or created, the key will be linked to the destination * keyring if one is provided. * * Returns a pointer to the key if successful; -EACCES, -ENOKEY, -EKEYREVOKED * or -EKEYEXPIRED if an inaccessible, negative, revoked or expired key was * found; -ENOKEY if no key was found and no @callout_info was given; -EDQUOT * if insufficient key quota was available to create a new key; or -ENOMEM if * insufficient memory was available. * * If the returned key was created, then it may still be under construction, * and wait_for_key_construction() should be used to wait for that to complete. */ struct key *request_key_and_link(struct key_type *type, const char *description, const void *callout_info, size_t callout_len, void *aux, struct key *dest_keyring, unsigned long flags) { const struct cred *cred = current_cred(); struct key *key; key_ref_t key_ref; int ret; kenter("%s,%s,%p,%zu,%p,%p,%lx", type->name, description, callout_info, callout_len, aux, dest_keyring, flags); /* search all the process keyrings for a key */ key_ref = search_process_keyrings(type, description, type->match, cred); if (!IS_ERR(key_ref)) { key = key_ref_to_ptr(key_ref); if (dest_keyring) { construct_get_dest_keyring(&dest_keyring); ret = key_link(dest_keyring, key); key_put(dest_keyring); if (ret < 0) { key_put(key); key = ERR_PTR(ret); goto error; } } } else if (PTR_ERR(key_ref) != -EAGAIN) { key = ERR_CAST(key_ref); } else { /* the search failed, but the keyrings were searchable, so we * should consult userspace if we can */ key = ERR_PTR(-ENOKEY); if (!callout_info) goto error; key = construct_key_and_link(type, description, callout_info, callout_len, aux, dest_keyring, flags); } error: kleave(" = %p", key); return key; }
/* * no valid lookup procedure on this sort of dir */ static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { kenter("%p,%p{%p{%s},%s}", dir, dentry, dentry->d_parent, dentry->d_parent ? dentry->d_parent->d_name.name : (const unsigned char *) "", dentry->d_name.name); return ERR_PTR(-EREMOTE); } /* end afs_mntpt_lookup() */
/* * Commence key construction. */ static struct key *construct_key_and_link(struct keyring_search_context *ctx, const char *callout_info, size_t callout_len, void *aux, struct key *dest_keyring, unsigned long flags) { struct key_user *user; struct key *key; int ret; kenter(""); if (ctx->index_key.type == &key_type_keyring) return ERR_PTR(-EPERM); user = key_user_lookup(current_fsuid()); if (!user) return ERR_PTR(-ENOMEM); construct_get_dest_keyring(&dest_keyring); ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key); key_user_put(user); if (ret == 0) { ret = construct_key(key, callout_info, callout_len, aux, dest_keyring); if (ret < 0) { kdebug("cons failed"); goto construction_failed; } } else if (ret == -EINPROGRESS) { ret = 0; } else { goto couldnt_alloc_key; } key_put(dest_keyring); kleave(" = key %d", key_serial(key)); return key; construction_failed: key_negate_and_link(key, key_negative_timeout, NULL, NULL); key_put(key); couldnt_alloc_key: key_put(dest_keyring); kleave(" = %d", ret); return ERR_PTR(ret); }
/* * link a key to the appropriate destination keyring * - the caller must hold a write lock on the destination keyring */ static void construct_key_make_link(struct key *key, struct key *dest_keyring) { struct task_struct *tsk = current; struct key *drop = NULL; kenter("{%d},%p", key->serial, dest_keyring); /* find the appropriate keyring */ if (!dest_keyring) { switch (tsk->jit_keyring) { case KEY_REQKEY_DEFL_DEFAULT: case KEY_REQKEY_DEFL_THREAD_KEYRING: dest_keyring = tsk->thread_keyring; if (dest_keyring) break; case KEY_REQKEY_DEFL_PROCESS_KEYRING: dest_keyring = tsk->signal->process_keyring; if (dest_keyring) break; case KEY_REQKEY_DEFL_SESSION_KEYRING: rcu_read_lock(); dest_keyring = key_get( rcu_dereference(tsk->signal->session_keyring)); rcu_read_unlock(); drop = dest_keyring; if (dest_keyring) break; case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: dest_keyring = tsk->user->session_keyring; break; case KEY_REQKEY_DEFL_USER_KEYRING: dest_keyring = tsk->user->uid_keyring; break; case KEY_REQKEY_DEFL_GROUP_KEYRING: default: BUG(); } } /* and attach the key to it */ __key_link(dest_keyring, key); key_put(drop); kleave(""); }
void key_schedule_gc(time_t gc_at) { unsigned long expires; time_t now = current_kernel_time().tv_sec; kenter("%ld", gc_at - now); if (gc_at <= now) { schedule_work(&key_gc_work); } else if (gc_at < key_gc_next_run) { expires = jiffies + (gc_at - now) * HZ; mod_timer(&key_gc_timer, expires); } }
/** * complete_request_key - Complete the construction of a key. * @cons: The key construction record. * @error: The success or failute of the construction. * * Complete the attempt to construct a key. The key will be negated * if an error is indicated. The authorisation key will be revoked * unconditionally. */ void complete_request_key(struct key_construction *cons, int error) { kenter("{%d,%d},%d", cons->key->serial, cons->authkey->serial, error); if (error < 0) key_negate_and_link(cons->key, key_negative_timeout, NULL, cons->authkey); else key_revoke(cons->authkey); key_put(cons->key); key_put(cons->authkey); kfree(cons); }
/* * destroy an instantiation authorisation token key */ static void request_key_auth_destroy(struct key *key) { struct request_key_auth *rka = key->payload.data; kenter("{%d}", key->serial); if (rka->context) { put_task_struct(rka->context); rka->context = NULL; } key_put(rka->target_key); kfree(rka); } /* end request_key_auth_destroy() */
/* * Destroy an instantiation authorisation token key. */ static void request_key_auth_destroy(struct key *key) { struct request_key_auth *rka = key->payload.data[0]; kenter("{%d}", key->serial); if (rka->cred) { put_cred(rka->cred); rka->cred = NULL; } key_put(rka->target_key); key_put(rka->dest_keyring); kfree(rka->callout_info); kfree(rka); }
/* * Verify one signed information block from a PKCS#7 message. */ static int pkcs7_verify_one(struct pkcs7_message *pkcs7, struct pkcs7_signed_info *sinfo) { int ret; kenter(",%u", sinfo->index); /* First of all, digest the data in the PKCS#7 message and the * signed information block */ ret = pkcs7_digest(pkcs7, sinfo); if (ret < 0) return ret; /* Find the key for the signature if there is one */ ret = pkcs7_find_key(pkcs7, sinfo); if (ret < 0) return ret; if (!sinfo->signer) return 0; pr_devel("Using X.509[%u] for sig %u\n", sinfo->signer->index, sinfo->index); /* Check that the PKCS#7 signing time is valid according to the X.509 * certificate. We can't, however, check against the system clock * since that may not have been set yet and may be wrong. */ if (test_bit(sinfo_has_signing_time, &sinfo->aa_set)) { if (sinfo->signing_time < sinfo->signer->valid_from || sinfo->signing_time > sinfo->signer->valid_to) { pr_warn("Message signed outside of X.509 validity window\n"); return -EKEYREJECTED; } } /* Verify the PKCS#7 binary against the key */ ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig); if (ret < 0) return ret; pr_devel("Verified signature %u\n", sinfo->index); /* Verify the internal certificate chain */ return pkcs7_verify_sig_chain(pkcs7, sinfo); }
/* * Schedule a garbage collection run. * - time precision isn't particularly important */ void key_schedule_gc(time_t gc_at) { unsigned long expires; time_t now = current_kernel_time().tv_sec; kenter("%ld", gc_at - now); if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) { kdebug("IMMEDIATE"); schedule_work(&key_gc_work); } else if (gc_at < key_gc_next_run) { kdebug("DEFERRED"); key_gc_next_run = gc_at; expires = jiffies + (gc_at - now) * HZ; mod_timer(&key_gc_timer, expires); } }
/* * Request an asymmetric key. */ static struct key *pkcs7_request_asymmetric_key( struct key *keyring, const char *signer, size_t signer_len, const char *authority, size_t auth_len) { key_ref_t key; char *id; kenter(",%zu,,%zu", signer_len, auth_len); /* Construct an identifier. */ id = kmalloc(signer_len + 2 + auth_len + 1, GFP_KERNEL); if (!id) return ERR_PTR(-ENOMEM); memcpy(id, signer, signer_len); id[signer_len + 0] = ':'; id[signer_len + 1] = ' '; memcpy(id + signer_len + 2, authority, auth_len); id[signer_len + 2 + auth_len] = 0; pr_debug("Look up: \"%s\"\n", id); key = keyring_search(make_key_ref(keyring, 1), &key_type_asymmetric, id); if (IS_ERR(key)) pr_debug("Request for module key '%s' err %ld\n", id, PTR_ERR(key)); kfree(id); if (IS_ERR(key)) { switch (PTR_ERR(key)) { /* Hide some search errors */ case -EACCES: case -ENOTDIR: case -EAGAIN: return ERR_PTR(-ENOKEY); default: return ERR_CAST(key); } } pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); return key_ref_to_ptr(key); }
/* * create a session keyring to be for the invokation of /sbin/request-key and * stick an authorisation token in it */ struct key *request_key_auth_new(struct key *target, struct key **_rkakey) { struct key *keyring, *rkakey = NULL; char desc[20]; int ret; kenter("%d,", target->serial); /* allocate a new session keyring */ sprintf(desc, "_req.%u", target->serial); keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL); if (IS_ERR(keyring)) { kleave("= %ld", PTR_ERR(keyring)); return keyring; } /* allocate the auth key */ sprintf(desc, "%x", target->serial); rkakey = key_alloc(&key_type_request_key_auth, desc, current->fsuid, current->fsgid, KEY_USR_VIEW, 1); if (IS_ERR(rkakey)) { key_put(keyring); kleave("= %ld", PTR_ERR(rkakey)); return rkakey; } /* construct and attach to the keyring */ ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL); if (ret < 0) { key_revoke(rkakey); key_put(rkakey); key_put(keyring); kleave("= %d", ret); return ERR_PTR(ret); } *_rkakey = rkakey; kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial); return keyring; } /* end request_key_auth_new() */
/* * Instantiate a PKCS#7 wrapped and validated key. */ int pkcs7_instantiate(struct key *key, struct key_preparsed_payload *prep) { struct pkcs7_message *pkcs7; const void *data, *saved_prep_data; size_t datalen, saved_prep_datalen; bool trusted; int ret; kenter(""); saved_prep_data = prep->data; saved_prep_datalen = prep->datalen; pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen); if (IS_ERR(pkcs7)) { ret = PTR_ERR(pkcs7); goto error; } ret = pkcs7_verify(pkcs7); if (ret < 0) goto error_free; ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted); if (ret < 0) goto error_free; if (!trusted) pr_warn("PKCS#7 message doesn't chain back to a trusted key\n"); ret = pkcs7_get_content_data(pkcs7, &data, &datalen, false); if (ret < 0) goto error_free; prep->data = data; prep->datalen = datalen; ret = user_instantiate(key, prep); prep->data = saved_prep_data; prep->datalen = saved_prep_datalen; error_free: pkcs7_free_message(pkcs7); error: kleave(" = %d", ret); return ret; }
/* * commence key construction */ static struct key *construct_key_and_link(struct key_type *type, const char *description, const char *callout_info, size_t callout_len, void *aux, struct key *dest_keyring, unsigned long flags) { struct key_user *user; struct key *key; int ret; kenter(""); user = key_user_lookup(current_fsuid(), current_user_ns()); if (!user) return ERR_PTR(-ENOMEM); construct_get_dest_keyring(&dest_keyring); ret = construct_alloc_key(type, description, dest_keyring, flags, user, &key); key_user_put(user); if (ret == 0) { ret = construct_key(key, callout_info, callout_len, aux, dest_keyring); if (ret < 0) { kdebug("cons failed"); goto construction_failed; } } key_put(dest_keyring); kleave(" = key %d", key_serial(key)); return key; construction_failed: key_negate_and_link(key, key_negative_timeout, NULL, NULL); key_put(key); key_put(dest_keyring); kleave(" = %d", ret); return ERR_PTR(ret); }
/* * Reap keys of dead type. * * We use three flags to make sure we see three complete cycles of the garbage * collector: the first to mark keys of that type as being dead, the second to * collect dead links and the third to clean up the dead keys. We have to be * careful as there may already be a cycle in progress. * * The caller must be holding key_types_sem. */ void key_gc_keytype(struct key_type *ktype) { kenter("%s", ktype->name); key_gc_dead_keytype = ktype; set_bit(KEY_GC_REAPING_KEYTYPE, &key_gc_flags); smp_mb(); set_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags); kdebug("schedule"); schedule_work(&key_gc_work); kdebug("sleep"); wait_on_bit(&key_gc_flags, KEY_GC_REAPING_KEYTYPE, key_gc_wait_bit, TASK_UNINTERRUPTIBLE); key_gc_dead_keytype = NULL; kleave(""); }
/* * Perform the RSA signature verification. * @H: Value of hash of data and metadata * @EM: The computed signature value * @k: The size of EM (EM[0] is an invalid location but should hold 0x00) * @hash_size: The size of H * @asn1_template: The DigestInfo ASN.1 template * @asn1_size: Size of asm1_template[] */ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, const u8 *asn1_template, size_t asn1_size) { unsigned PS_end, T_offset, i; kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size); if (k < 2 + 1 + asn1_size + hash_size) return -EBADMSG; /* Decode the EMSA-PKCS1-v1_5 */ if (EM[1] != 0x01) { kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]); return -EBADMSG; } T_offset = k - (asn1_size + hash_size); PS_end = T_offset - 1; if (EM[PS_end] != 0x00) { kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]); return -EBADMSG; } for (i = 2; i < PS_end; i++) { if (EM[i] != 0xff) { kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]); return -EBADMSG; } } if (crypto_memneq(asn1_template, EM + T_offset, asn1_size) != 0) { kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]"); return -EBADMSG; } if (crypto_memneq(H, EM + T_offset + asn1_size, hash_size) != 0) { kleave(" = -EKEYREJECTED [EM[T] hash mismatch]"); return -EKEYREJECTED; } kleave(" = 0"); return 0; }
/* * Call out to userspace for key construction. * * Program failure is ignored in favour of key status. */ static int construct_key(struct key *key, const void *callout_info, size_t callout_len, void *aux, struct key *dest_keyring) { struct key_construction *cons; request_key_actor_t actor; struct key *authkey; int ret; kenter("%d,%p,%zu,%p", key->serial, callout_info, callout_len, aux); cons = kmalloc(sizeof(*cons), GFP_KERNEL); if (!cons) return -ENOMEM; /* allocate an authorisation key */ authkey = request_key_auth_new(key, callout_info, callout_len, dest_keyring); if (IS_ERR(authkey)) { kfree(cons); ret = PTR_ERR(authkey); authkey = NULL; } else { cons->authkey = key_get(authkey); cons->key = key_get(key); /* make the call */ actor = call_sbin_request_key; if (key->type->request_key) actor = key->type->request_key; ret = actor(cons, "create", aux); /* check that the actor called complete_request_key() prior to * returning an error */ WARN_ON(ret < 0 && !test_bit(KEY_FLAG_REVOKED, &authkey->flags)); key_put(authkey); } kleave(" = %d", ret); return ret; }
/* * Garbage collect pointers from a keyring. * * Not called with any locks held. The keyring's key struct will not be * deallocated under us as only our caller may deallocate it. */ static void key_gc_keyring(struct key *keyring, time_t limit) { struct keyring_list *klist; struct key *key; int loop; kenter("%x", key_serial(keyring)); if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) goto dont_gc; /* scan the keyring looking for dead keys */ rcu_read_lock(); klist = rcu_dereference(keyring->payload.subscriptions); if (!klist) goto unlock_dont_gc; loop = klist->nkeys; smp_rmb(); for (loop--; loop >= 0; loop--) { key = klist->keys[loop]; if (test_bit(KEY_FLAG_DEAD, &key->flags) || (key->expiry > 0 && key->expiry <= limit)) goto do_gc; } unlock_dont_gc: rcu_read_unlock(); dont_gc: kleave(" [no gc]"); return; do_gc: rcu_read_unlock(); keyring_gc(keyring, limit); kleave(" [gc]"); }
/* * Garbage collect pointers from a keyring. * * Not called with any locks held. The keyring's key struct will not be * deallocated under us as only our caller may deallocate it. */ static void key_gc_keyring(struct key *keyring, time_t limit) { struct keyring_list *klist; int loop; kenter("%x", key_serial(keyring)); if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) | (1 << KEY_FLAG_REVOKED))) goto dont_gc; /* scan the keyring looking for dead keys */ rcu_read_lock(); klist = rcu_dereference(keyring->payload.subscriptions); if (!klist) goto unlock_dont_gc; loop = klist->nkeys; smp_rmb(); for (loop--; loop >= 0; loop--) { struct key *key = rcu_dereference(klist->keys[loop]); if (key_is_dead(key, limit)) goto do_gc; } unlock_dont_gc: rcu_read_unlock(); dont_gc: kleave(" [no gc]"); return; do_gc: rcu_read_unlock(); keyring_gc(keyring, limit); kleave(" [gc]"); }
/* * Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7 * uses the issuer's name and the issuing certificate serial number for * matching purposes. These must match the certificate issuer's name (not * subject's name) and the certificate serial number [RFC 2315 6.7]. */ static int pkcs7_find_key(struct pkcs7_message *pkcs7, struct pkcs7_signed_info *sinfo) { struct x509_certificate *x509; unsigned certix = 1; kenter("%u", sinfo->index); for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) { /* I'm _assuming_ that the generator of the PKCS#7 message will * encode the fields from the X.509 cert in the same way in the * PKCS#7 message - but I can't be 100% sure of that. It's * possible this will need element-by-element comparison. */ if (!asymmetric_key_id_same(x509->id, sinfo->signing_cert_id)) continue; pr_devel("Sig %u: Found cert serial match X.509[%u]\n", sinfo->index, certix); if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) { pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n", sinfo->index); continue; } sinfo->signer = x509; return 0; } /* The relevant X.509 cert isn't found here, but it might be found in * the trust keyring. */ pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n", sinfo->index, sinfo->signing_cert_id->len, sinfo->signing_cert_id->data); return 0; }