Linux kernel commit 146aa8b1453b ("KEYS: Merge the type-specific data with the payload data") merges the type-specific data with the payload data. Introduce these changes to access type/payload data and scrub the key type. These changes are not compatible with previous kernel versions, so add new keyring script file for kernel version >= 4.4 and kernel version <= 4.8. Signed-off-by: Kamalesh Babulal <kamalesh at linux.vnet.ibm.com> Cc: Atsushi Kumagai <ats-kumagai at wm.jp.nec.com> --- eppic_scripts/keyring_4_4_to_4_8.c | 378 +++++++++++++++++++++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 eppic_scripts/keyring_4_4_to_4_8.c diff --git a/eppic_scripts/keyring_4_4_to_4_8.c b/eppic_scripts/keyring_4_4_to_4_8.c new file mode 100644 index 0000000..db74033 --- /dev/null +++ b/eppic_scripts/keyring_4_4_to_4_8.c @@ -0,0 +1,378 @@ +string +skey_opt() +{ + return "l"; +} + +string +skey_usage() +{ + return "\n"; +} + +static void +skey_showusage() +{ + printf("usage : skey %s", skey_usage()); +} + +string +skey_help() +{ + return "Help"; +} + +#define ASSOC_ARRAY_FAN_OUT 16 +#define ASSOC_ARRAY_FAN_MASK (ASSOC_ARRAY_FAN_OUT - 1) +#define ASSOC_ARRAY_LEVEL_STEP (ilog2(ASSOC_ARRAY_FAN_OUT)) +#define ASSOC_ARRAY_LEVEL_STEP_MASK (ASSOC_ARRAY_LEVEL_STEP - 1) +#define ASSOC_ARRAY_KEY_CHUNK_MASK (ASSOC_ARRAY_KEY_CHUNK_SIZE - 1) +#define ASSOC_ARRAY_KEY_CHUNK_SHIFT (ilog2(BITS_PER_LONG)) +#define ASSOC_ARRAY_PTR_TYPE_MASK 0x1UL +#define ASSOC_ARRAY_PTR_LEAF_TYPE 0x0UL /* Points to leaf (or nowhere) */ +#define ASSOC_ARRAY_PTR_META_TYPE 0x1UL /* Points to node or shortcut */ +#define ASSOC_ARRAY_PTR_SUBTYPE_MASK 0x2UL +#define ASSOC_ARRAY_PTR_NODE_SUBTYPE 0x0UL +#define ASSOC_ARRAY_PTR_SHORTCUT_SUBTYPE 0x2UL + +/* Keyring stuff */ +#define KEYRING_PTR_SUBTYPE 0x2UL + +static int keyring_ptr_is_keyring(const struct assoc_array_ptr *x) +{ + return (unsigned long)x & KEYRING_PTR_SUBTYPE; +} + +static int assoc_array_ptr_is_meta(const struct assoc_array_ptr *x) +{ + return (unsigned long)x & ASSOC_ARRAY_PTR_TYPE_MASK; +} + +static int assoc_array_ptr_is_leaf(const struct assoc_array_ptr *x) +{ + return !assoc_array_ptr_is_meta(x); +} +static int assoc_array_ptr_is_shortcut(const struct assoc_array_ptr *x) +{ + return (unsigned long)x & ASSOC_ARRAY_PTR_SUBTYPE_MASK; +} +static int assoc_array_ptr_is_node(const struct assoc_array_ptr *x) +{ + return !assoc_array_ptr_is_shortcut(x); +} + +static void *assoc_array_ptr_to_leaf(const struct assoc_array_ptr *x) +{ + return (void *)((unsigned long)x & ~ASSOC_ARRAY_PTR_TYPE_MASK); +} + +static +unsigned long __assoc_array_ptr_to_meta(const struct assoc_array_ptr *x) +{ + return (unsigned long)x & + ~(ASSOC_ARRAY_PTR_SUBTYPE_MASK | ASSOC_ARRAY_PTR_TYPE_MASK); +} +static +struct assoc_array_node *assoc_array_ptr_to_node(const struct assoc_array_ptr *x) +{ + return (struct assoc_array_node *)__assoc_array_ptr_to_meta(x); +} +static +struct assoc_array_shortcut *assoc_array_ptr_to_shortcut(const struct assoc_array_ptr *x) +{ + return (struct assoc_array_shortcut *)__assoc_array_ptr_to_meta(x); +} + +static +struct assoc_array_ptr *__assoc_array_x_to_ptr(const void *p, unsigned long t) +{ + return (struct assoc_array_ptr *)((unsigned long)p | t); +} +static +struct assoc_array_ptr *assoc_array_leaf_to_ptr(const void *p) +{ + return __assoc_array_x_to_ptr(p, ASSOC_ARRAY_PTR_LEAF_TYPE); +} +static +struct assoc_array_ptr *assoc_array_node_to_ptr(const struct assoc_array_node *p) +{ + return __assoc_array_x_to_ptr( + p, ASSOC_ARRAY_PTR_META_TYPE | ASSOC_ARRAY_PTR_NODE_SUBTYPE); +} + +static +struct assoc_array_ptr *assoc_array_shortcut_to_ptr(const struct assoc_array_shortcut *p) +{ + return __assoc_array_x_to_ptr( + p, ASSOC_ARRAY_PTR_META_TYPE | ASSOC_ARRAY_PTR_SHORTCUT_SUBTYPE); +} + +/* Keyring stuff */ +static inline struct key *keyring_ptr_to_key(const struct assoc_array_ptr *x) +{ + void *object = assoc_array_ptr_to_leaf(x); + return (struct key *)((unsigned long)object & ~KEYRING_PTR_SUBTYPE); +} + +/* BEGIN: struct key access */ +struct keyring_index_key *get_index_key_from_key(struct key *key) +{ + return (struct keyring_index_key *)((unsigned long)&(key->flags) + + sizeof(key->flags)); +} + +struct key_type *get_type_from_key(struct key *key) +{ + return (struct key_type *)((unsigned long)&(key->flags) + + sizeof(key->flags)); +} + +char *get_description_from_key(struct key *key) +{ + return (char *)((unsigned long)&(key->flags) + + sizeof(key->flags) + + sizeof(struct key_type *)); +} + +union key_payload *get_payload_from_key(struct key *key) +{ + return (union key_payload *)((unsigned long)&(key->flags) + + sizeof(key->flags) + + sizeof(struct keyring_index_key)); +} + +struct list_head *get_name_link_from_key(struct key *key) +{ + return (struct list_head *)((unsigned long)&(key->flags) + + sizeof(key->flags) + + sizeof(struct keyring_index_key)); +} + +struct assoc_array *get_keys_from_key(struct key *key) +{ + return (struct assoc_array *)((unsigned long)&(key->flags) + + sizeof(key->flags) + + sizeof(struct keyring_index_key) + + sizeof(struct list_head)); +} +/* END: struct key access */ + +static void delete_keyring_subtree(struct assoc_array_ptr *root) +{ + struct assoc_array_shortcut *shortcut; + struct assoc_array_node *node; + struct assoc_array_ptr *cursor, *parent; + int slot = -1; + + cursor = root; + if (!cursor) { + return; + } + + if (assoc_array_ptr_is_shortcut(cursor)) { + /* Descend through a shortcut */ + shortcut = assoc_array_ptr_to_shortcut(cursor); + parent = cursor; + cursor = shortcut->next_node; + } + + node = assoc_array_ptr_to_node(cursor); + slot = 0; + + if(node->nr_leaves_on_branch <= 0) return; + + do { + for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) { + struct assoc_array_ptr *ptr = node->slots[slot]; + + if (!ptr) + continue; + if (assoc_array_ptr_is_meta(ptr)) { + parent = cursor; + cursor = ptr; + if (assoc_array_ptr_is_shortcut(cursor)) { + /* Descend through a shortcut */ + shortcut = assoc_array_ptr_to_shortcut(cursor); + parent = cursor; + cursor = shortcut->next_node; + } + node = assoc_array_ptr_to_node(cursor); + slot = 0; + } else { + struct key *leaf; + struct keyring_index_key *index_key; + char *description; + void *payload_ptr; + int i,j; + + /* no need to delete keyrings, only data */ + if(keyring_ptr_is_keyring(ptr)) + continue; + + /* delete the leaf payload */ + leaf = (struct key *)assoc_array_ptr_to_leaf(ptr); + index_key = get_index_key_from_key(leaf); + /* + Now delete the keys of the different key types. + The following key types are handled for now: + user, ceph, pkcs7_test, asymmetric(X509), rxpc + + The following key types are NOT handled (yet): + dns_resolver (no secret keys, just used for DNS) + + Add a new else if() for new key types. + */ + if(getstr(index_key->type->name) == "user") { + struct user_key_payload **user_key_payload; + unsigned short datalen; + + payload_ptr=(void *)get_payload_from_key(leaf); + user_key_payload = (struct user_key_payload **)payload_ptr; + datalen = (*user_key_payload)->datalen; + memset((char *)&(*user_key_payload)->data, 'A', datalen); + } else if(getstr(index_key->type->name) == "ceph") { + struct ceph_crypto_key **ceph_payload; + int len; + + payload_ptr=(void *)get_payload_from_key(leaf); + ceph_payload = (struct ceph_crypto_key **)payload_ptr; + len = (*ceph_payload)->len; + memset((char *)&(*ceph_payload)->key, 'A', len); + } else if(getstr(index_key->type->name) == "pkcs7_test") { + struct user_key_payload **user_key_payload; + unsigned short datalen; + + payload_ptr=(void *)get_payload_from_key(leaf); + user_key_payload = (struct user_key_payload **)payload_ptr; + datalen = (*user_key_payload)->datalen; + memset((char *)&(*user_key_payload)->data, 'A', datalen); + } else if(getstr(index_key->type->name) == "asymmetric") { + struct public_key **public_key; + unsigned short keylen; + + /* data[0] is asym_crypto */ + payload_ptr=(void *)get_payload_from_key(leaf); + public_key = (struct public_key **)payload_ptr; + keylen = (*public_key)->keylen; + memset((char *)&(*public_key)->key, 'A', keylen); + } else if(getstr(index_key->type->name) == ".request_key_auth") { + struct request_key_auth **request_key; + unsigned short datalen; + + payload_ptr=(void *)get_payload_from_key(leaf); + request_key = (struct request_key_auth **)payload_ptr; + datalen = leaf->datalen; + memset((char *)&(*request_key)->data, 'A', datalen); + } else if(getstr(index_key->type->name) == "rxrpc") { + struct rxrpc_key_token **rxrpc_key_token, *token; + struct rxkad_key *kad; + struct rxk5_key *k5; + int token_count = 0; + + payload_ptr=(void *)get_payload_from_key(leaf); + rxrpc_key_token = (struct rxrpc_key_token **)payload_ptr; + for(; rxrpc_key_token; + rxrpc_key_token = &(*rxrpc_key_token)->next, + token_count++) { + token = *rxrpc_key_token; + switch(token->security_index) { + case 2 : /* RXRPC_SECURITY_RXKAD */ + /* anonymous union, use pointer arithmetic */ + kad = token->next + + sizeof(struct rxrpc_key_token *); + memset(&kad.session_key, 'A', 8); + memset(&kad.ticket, 'A', kad.ticket_len); + break; + case 5 : /* RXRPC_SECURITY_RXK5 */ + /* anonymous union, use pointer arithmetic */ + k5 = token->next + + sizeof(struct rxrpc_key_token *); + memset(k5.ticket, 'A', k5.ticket_len); + memset(k5.ticket2, 'A', k5.ticket2_len); + memset(k5.session.data, 'A', k5.session.data_len); + memset(k5->addresses.data, 'A', k5->addresses.data_len); + memset(k5->authdata.data, 'A', k5->authdata.data_len); + break; + default : + printf("WARNING: unknown security index: %d\n", + token->security_index); + } + /* max number of tokens = 8 */ + if(token_count > 8) { + printf("WARNING: too many rxrpc tokens!\n"); + break; + } + } + } else if(getstr(index_key->type->name) == "dns_resolver") { + /* nothing to do here, no secret data */ + } else if(getstr(index_key->type->name) == "big_key") { + printf("WARNING: key_type=big_key not handled!\n"); + } else { + printf("WARNING: unsupported key type = %s!\n", + getstr(index_key->type->name)); + } + } + } + + parent = node->back_pointer; + slot = node->parent_slot; + if (parent) { + /* Move back up to the parent */ + if (assoc_array_ptr_is_shortcut(parent)) { + shortcut = assoc_array_ptr_to_shortcut(parent); + cursor = parent; + parent = shortcut->back_pointer; + slot = shortcut->parent_slot; + } + + /* Ascend to next slot in parent node */ + cursor = parent; + node = assoc_array_ptr_to_node(cursor); + slot++; + } + } while(parent); + + return; +} + +void delete_keyring(struct assoc_array *keyring) +{ + delete_keyring_subtree(keyring->root); +} + +int +skey() +{ + int i,j,k; + struct list_head **tab; + + tab = &keyring_name_hash; + + for (i = 0; i < 32; i++) + { + struct list_head *next, *head; + + head = (struct list_head *) (tab + i); + next = (struct list_head *) head->next; + + if (!next) + continue; + + while (next != head) + { + struct key *mykey, *off = 0; + struct list_head *name_link; + struct assoc_array *keys; + + mykey = (struct key *)((unsigned long)(next) + - (unsigned long)&(off->flags) + - sizeof(off->flags) + - sizeof(struct keyring_index_key)); + name_link = get_name_link_from_key(mykey); + keys = get_keys_from_key(mykey); + delete_keyring(keys); + next = (struct list_head *) name_link->next; + } + } + return 1; +} -- 2.7.4