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; }