/* * Request an asymmetric key. */ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) { struct key *key; char name[12]; sprintf(name, "id:%08x", keyid); pr_debug("key search: \"%s\"\n", name); key = get_ima_blacklist_keyring(); if (key) { key_ref_t kref; kref = keyring_search(make_key_ref(key, 1), &key_type_asymmetric, name); if (!IS_ERR(kref)) { pr_err("Key '%s' is in ima_blacklist_keyring\n", name); return ERR_PTR(-EKEYREJECTED); } } if (keyring) { /* search in specific keyring */ key_ref_t kref; kref = keyring_search(make_key_ref(keyring, 1), &key_type_asymmetric, name); if (IS_ERR(kref)) key = ERR_CAST(kref); else key = key_ref_to_ptr(kref); } else { key = request_key(&key_type_asymmetric, name, NULL); } if (IS_ERR(key)) { pr_err_ratelimited("Request for unknown key '%s' err %ld\n", name, PTR_ERR(key)); switch (PTR_ERR(key)) { /* Hide some search errors */ case -EACCES: case -ENOTDIR: case -EAGAIN: return ERR_PTR(-ENOKEY); default: return key; } } pr_debug("%s() = 0 [%x]\n", __func__, key_serial(key)); return key; }
/* * Search through all keydb resources, starting at the current position, * for a keyblock which contains one of the keys described in the DESC array. */ int keydb_search2 (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc, size_t *descindex) { int rc = -1; if (!hd) return G10ERR_INV_ARG; while (rc == -1 && hd->current >= 0 && hd->current < hd->used) { switch (hd->active[hd->current].type) { case KEYDB_RESOURCE_TYPE_NONE: BUG(); /* we should never see it here */ break; case KEYDB_RESOURCE_TYPE_KEYRING: rc = keyring_search (hd->active[hd->current].u.kr, desc, ndesc, descindex); break; } if (rc == -1) /* EOF -> switch to next resource */ hd->current++; else if (!rc) hd->found = hd->current; } return rc; }
int keydb_search2 (int *hdfound, int *hdcurrent, int *a) { int rc = -1; while (rc == -1) { if (*a == 1) rc = keyring_search (); if (rc == -1) *hdcurrent++; if (!rc) *hdfound = *hdcurrent; } return rc; }
/* * Request an asymmetric key. */ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, const u8 *key_id, size_t key_id_len) { key_ref_t key; size_t i; char *id, *q; pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len); /* Construct an identifier. */ id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL); if (!id) return ERR_PTR(-ENOKEY); memcpy(id, signer, signer_len); q = id + signer_len; *q++ = ':'; *q++ = ' '; for (i = 0; i < key_id_len; i++) { *q++ = hex_asc[*key_id >> 4]; *q++ = hex_asc[*key_id++ & 0x0f]; } *q = 0; pr_debug("Look up: \"%s\"\n", id); key = keyring_search(make_key_ref(modsign_keyring, 1), &key_type_asymmetric, id); if (IS_ERR(key)) pr_warn("Request for unknown 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); }
/** * x509_request_asymmetric_key - Request a key by X.509 certificate params. * @keyring: The keys to search. * @kid: The key ID. * @partial: Use partial match if true, exact if false. * * Find a key in the given keyring by subject name and key ID. These might, * for instance, be the issuer name and the authority key ID of an X.509 * certificate that needs to be verified. */ struct key *x509_request_asymmetric_key(struct key *keyring, const struct asymmetric_key_id *kid, bool partial) { key_ref_t key; char *id, *p; /* Construct an identifier "id:<keyid>". */ p = id = kmalloc(2 + 1 + kid->len * 2 + 1, GFP_KERNEL); if (!id) return ERR_PTR(-ENOMEM); if (partial) { *p++ = 'i'; *p++ = 'd'; } else { *p++ = 'e'; *p++ = 'x'; } *p++ = ':'; p = bin2hex(p, kid->data, kid->len); *p = 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 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); }
/* * 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); }
/** * x509_request_asymmetric_key - Request a key by X.509 certificate params. * @keyring: The keys to search. * @subject: The name of the subject to whom the key belongs. * @key_id: The subject key ID as a hex string. * * Find a key in the given keyring by subject name and key ID. These might, * for instance, be the issuer name and the authority key ID of an X.509 * certificate that needs to be verified. */ struct key *x509_request_asymmetric_key(struct key *keyring, const char *subject, const char *key_id) { key_ref_t key; size_t subject_len = strlen(subject), key_id_len = strlen(key_id); char *id; /* Construct an identifier "<subjname>:<keyid>". */ id = kmalloc(subject_len + 2 + key_id_len + 1, GFP_KERNEL); if (!id) return ERR_PTR(-ENOMEM); memcpy(id, subject, subject_len); id[subject_len + 0] = ':'; id[subject_len + 1] = ' '; memcpy(id + subject_len + 2, key_id, key_id_len); id[subject_len + 2 + key_id_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 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); }
/* * Search through all keydb resources, starting at the current * position, for a keyblock which contains one of the keys described * in the DESC array. Returns GPG_ERR_NOT_FOUND if no matching * keyring was found. */ gpg_error_t keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc, size_t *descindex) { gpg_error_t rc; if (!hd) return gpg_error (GPG_ERR_INV_ARG); if (DBG_CLOCK) log_clock ("keydb_search enter"); if (DBG_CACHE) dump_search_desc ("keydb_search", desc, ndesc); if (ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID && keyblock_cache.state == KEYBLOCK_CACHE_FILLED && keyblock_cache.kid[0] == desc[0].u.kid[0] && keyblock_cache.kid[1] == desc[0].u.kid[1]) { if (DBG_CLOCK) log_clock ("keydb_search leave (cached)"); return 0; } rc = -1; while ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) && hd->current >= 0 && hd->current < hd->used) { switch (hd->active[hd->current].type) { case KEYDB_RESOURCE_TYPE_NONE: BUG(); /* we should never see it here */ break; case KEYDB_RESOURCE_TYPE_KEYRING: rc = keyring_search (hd->active[hd->current].u.kr, desc, ndesc, descindex); break; case KEYDB_RESOURCE_TYPE_KEYBOX: rc = keybox_search (hd->active[hd->current].u.kb, desc, ndesc); break; } if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) { /* EOF -> switch to next resource */ hd->current++; } else if (!rc) hd->found = hd->current; } rc = ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) ? gpg_error (GPG_ERR_NOT_FOUND) : rc); keyblock_cache_clear (); if (!rc && ndesc == 1 && desc[0].mode == KEYDB_SEARCH_MODE_LONG_KID) { keyblock_cache.state = KEYBLOCK_CACHE_PREPARED; keyblock_cache.kid[0] = desc[0].u.kid[0]; keyblock_cache.kid[1] = desc[0].u.kid[1]; } if (DBG_CLOCK) log_clock (rc? "keydb_search leave (not found)" : "keydb_search leave (found)"); return rc; }
/** * x509_request_asymmetric_key - Request a key by X.509 certificate params. * @keyring: The keys to search. * @id: The issuer & serialNumber to look for or NULL. * @skid: The subjectKeyIdentifier to look for or NULL. * @partial: Use partial match if true, exact if false. * * Find a key in the given keyring by identifier. The preferred identifier is * the issuer + serialNumber and the fallback identifier is the * subjectKeyIdentifier. If both are given, the lookup is by the former, but * the latter must also match. */ struct key *x509_request_asymmetric_key(struct key *keyring, const struct asymmetric_key_id *id, const struct asymmetric_key_id *skid, bool partial) { struct key *key; key_ref_t ref; const char *lookup; char *req, *p; int len; if (id) { lookup = id->data; len = id->len; } else { lookup = skid->data; len = skid->len; } /* Construct an identifier "id:<keyid>". */ p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL); if (!req) return ERR_PTR(-ENOMEM); if (partial) { *p++ = 'i'; *p++ = 'd'; } else { *p++ = 'e'; *p++ = 'x'; } *p++ = ':'; p = bin2hex(p, lookup, len); *p = 0; pr_debug("Look up: \"%s\"\n", req); ref = keyring_search(make_key_ref(keyring, 1), &key_type_asymmetric, req); if (IS_ERR(ref)) pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); kfree(req); if (IS_ERR(ref)) { switch (PTR_ERR(ref)) { /* Hide some search errors */ case -EACCES: case -ENOTDIR: case -EAGAIN: return ERR_PTR(-ENOKEY); default: return ERR_CAST(ref); } } key = key_ref_to_ptr(ref); if (id && skid) { const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); if (!kids->id[1]) { pr_debug("issuer+serial match, but expected SKID missing\n"); goto reject; } if (!asymmetric_key_id_same(skid, kids->id[1])) { pr_debug("issuer+serial match, but SKID does not\n"); goto reject; } } pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key)); return key; reject: key_put(key); return ERR_PTR(-EKEYREJECTED); }
/* * search the specified keyring for a matching key * - the start keyring must be searchable * - nested keyrings may also be searched if they are searchable * - only keys with search permission may be found * - if a key is found, it will be attached to the destination keyring if * there's one specified * - implements keyctl(KEYCTL_SEARCH) */ long keyctl_keyring_search(key_serial_t ringid, const char __user *_type, const char __user *_description, key_serial_t destringid) { struct key_type *ktype; key_ref_t keyring_ref, key_ref, dest_ref; char type[32], *description; long dlen, ret; /* pull the type and description into kernel space */ ret = strncpy_from_user(type, _type, sizeof(type) - 1); if (ret < 0) goto error; type[31] = '\0'; ret = -EFAULT; dlen = strnlen_user(_description, PAGE_SIZE - 1); if (dlen <= 0) goto error; ret = -EINVAL; if (dlen > PAGE_SIZE - 1) goto error; ret = -ENOMEM; description = kmalloc(dlen + 1, GFP_KERNEL); if (!description) goto error; ret = -EFAULT; if (copy_from_user(description, _description, dlen + 1) != 0) goto error2; /* get the keyring at which to begin the search */ keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH); if (IS_ERR(keyring_ref)) { ret = PTR_ERR(keyring_ref); goto error2; } /* get the destination keyring if specified */ dest_ref = NULL; if (destringid) { dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); if (IS_ERR(dest_ref)) { ret = PTR_ERR(dest_ref); goto error3; } } /* find the key type */ ktype = key_type_lookup(type); if (IS_ERR(ktype)) { ret = PTR_ERR(ktype); goto error4; } /* do the search */ key_ref = keyring_search(keyring_ref, ktype, description); if (IS_ERR(key_ref)) { ret = PTR_ERR(key_ref); /* treat lack or presence of a negative key the same */ if (ret == -EAGAIN) ret = -ENOKEY; goto error5; } /* link the resulting key to the destination keyring if we can */ if (dest_ref) { ret = key_permission(key_ref, KEY_LINK); if (ret < 0) goto error6; ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref)); if (ret < 0) goto error6; } ret = key_ref_to_ptr(key_ref)->serial; error6: key_ref_put(key_ref); error5: key_type_put(ktype); error4: key_ref_put(dest_ref); error3: key_ref_put(keyring_ref); error2: kfree(description); error: return ret; } /* end keyctl_keyring_search() */