/* Executes keys from the start of key sequence or at some offset in it. * Returns error code. */ static int dispatch_keys(const wchar_t keys[], keys_info_t *keys_info, int no_remap, int prev_count) { key_info_t key_info; int result; if(fill_key_info(&keys, &key_info, prev_count, &result) != 0) { return result; } result = KEYS_UNKNOWN; if(!no_remap) { result = dispatch_keys_at_root(keys, keys_info, &user_cmds_root[vle_mode_get()], key_info, no_remap); } if(result == KEYS_UNKNOWN) { result = dispatch_keys_at_root(keys, keys_info, &builtin_cmds_root[vle_mode_get()], key_info, no_remap); } return result; }
TSS_RESULT TCS_EnumRegisteredKeys_Internal(TCS_CONTEXT_HANDLE hContext, /* in */ TSS_UUID * pKeyUUID, /* in */ UINT32 * pcKeyHierarchySize, /* out */ TSS_KM_KEYINFO ** ppKeyHierarchy) /* out */ { TSS_RESULT result = TSS_SUCCESS; UINT32 count = 0, i; TSS_KM_KEYINFO *ret = NULL; TSS_UUID tmp_uuid; struct key_disk_cache *disk_ptr, *tmp_ptrs[MAX_KEY_CHILDREN]; struct key_mem_cache *mem_ptr; TSS_BOOL is_reg = FALSE; LogDebug("Enum Reg Keys"); if (pcKeyHierarchySize == NULL || ppKeyHierarchy == NULL) return TCSERR(TSS_E_BAD_PARAMETER); if ((result = ctx_verify_context(hContext))) return result; if (pKeyUUID != NULL) { /* First have to verify the key is registered */ if ((result = isUUIDRegistered(pKeyUUID, &is_reg))) return result; if (is_reg == FALSE) { /* This return code is not listed as possible in the TSS 1.1 spec, * but it makes more sense than just TCS_SUCCESS or TSS_E_FAIL */ return TCSERR(TSS_E_PS_KEY_NOTFOUND); } } /* this entire operation needs to be atomic wrt registered keys. We must * lock the mem cache as well to test if a given key is loaded. */ MUTEX_LOCK(disk_cache_lock); MUTEX_LOCK(mem_cache_lock); /* return an array of all registered keys if pKeyUUID == NULL */ if (pKeyUUID == NULL) { /* determine the number of registered keys */ for (disk_ptr = key_disk_cache_head; disk_ptr; disk_ptr = disk_ptr->next) { if (disk_ptr->flags & CACHE_FLAG_VALID) count++; } /* malloc a structure for each of them */ if (count != 0) { ret = calloc(count, sizeof(TSS_KM_KEYINFO)); if (ret == NULL) { LogError("malloc of %zd bytes failed.", (count * sizeof(TSS_KM_KEYINFO))); count = 0; result = TCSERR(TSS_E_OUTOFMEMORY); goto done; } } else { goto done; } /* fill out the structure for each key */ i = 0; for (disk_ptr = key_disk_cache_head; disk_ptr; disk_ptr = disk_ptr->next) { if (disk_ptr->flags & CACHE_FLAG_VALID) { /* look for a mem cache entry to check if its loaded */ for (mem_ptr = key_mem_cache_head; mem_ptr; mem_ptr = mem_ptr->next) { if (!memcmp(&mem_ptr->uuid, &disk_ptr->uuid, sizeof(TSS_UUID))) { if ((result = fill_key_info(disk_ptr, mem_ptr, &ret[i]))) { free(ret); ret = NULL; count = 0; goto done; } break; } } /* if there is no mem cache entry for this key, go ahead and call * fill_key_info(), it will pull everything from disk */ if (mem_ptr == NULL) { if ((result = fill_key_info(disk_ptr, NULL, &ret[i]))) { free(ret); ret = NULL; count = 0; goto done; } } i++; } } } else { /* return a chain of a key and its parents up to the SRK */ /* determine the number of keys in the chain */ memcpy(&tmp_uuid, pKeyUUID, sizeof(TSS_UUID)); disk_ptr = key_disk_cache_head; while (disk_ptr != NULL && count < MAX_KEY_CHILDREN) { if (disk_ptr->flags & CACHE_FLAG_VALID && !memcmp(&disk_ptr->uuid, &tmp_uuid, sizeof(TSS_UUID))) { /* increment count, then search for the parent */ count++; /* save a pointer to this cache entry */ tmp_ptrs[count - 1] = disk_ptr; /* if the parent of this key is NULL, we're at the root of the tree */ if (!memcmp(&disk_ptr->parent_uuid, &NULL_UUID, sizeof(TSS_UUID))) break; /* overwrite tmp_uuid with the parent, which we will now search for */ memcpy(&tmp_uuid, &disk_ptr->parent_uuid, sizeof(TSS_UUID)); disk_ptr = key_disk_cache_head; continue; } disk_ptr = disk_ptr->next; } /* when we reach this point, we have an array of TSS_UUID's that leads from the * requested key up to the SRK*/ /* malloc a structure for each of them */ if (count != 0) { ret = calloc(count, sizeof(TSS_KM_KEYINFO)); if (ret == NULL) { LogError("malloc of %zd bytes failed.", (count * sizeof(TSS_KM_KEYINFO))); count = 0; result = TCSERR(TSS_E_OUTOFMEMORY); goto done; } } else { goto done; } for (i = 0; i < count; i++) { /* look for a mem cache entry to check if its loaded */ for (mem_ptr = key_mem_cache_head; mem_ptr; mem_ptr = mem_ptr->next) { if (!memcmp(&mem_ptr->uuid, &tmp_ptrs[i]->uuid, sizeof(TSS_UUID))) { if ((result = fill_key_info(tmp_ptrs[i], mem_ptr, &ret[i]))) { free(ret); ret = NULL; count = 0; goto done; } break; } } /* if there is no mem cache entry for this key, go ahead and call * fill_key_info(), it will pull everything from disk */ if (mem_ptr == NULL) { if ((result = fill_key_info(tmp_ptrs[i], NULL, &ret[i]))) { free(ret); ret = NULL; count = 0; goto done; } } } } done: MUTEX_UNLOCK(disk_cache_lock); MUTEX_UNLOCK(mem_cache_lock); *ppKeyHierarchy = ret; *pcKeyHierarchySize = count; return result; }
/* Dispatches keys passed in as a selector followed by arbitrary other keys. * Returns error code. */ static int dispatch_selector(const wchar_t keys[], keys_info_t *keys_info, key_info_t master_key_info, key_chunk_t *master_curr, int no_remap) { const wchar_t *keys_start = keys; key_chunk_t *curr = &selectors_root[vle_mode_get()]; key_info_t key_info; int result; if(fill_key_info(&keys, &key_info, master_key_info.count, &result) != 0) { return result; } /* The loop finds longest match of the input (keys) among registered * shortcuts. */ while(*keys != L'\0') { key_chunk_t *p; for(p = curr->child; p != NULL && p->key < *keys; p = p->next) { /* Advance. */ } if(p == NULL || p->key != *keys) { break; } ++keys; curr = p; } /* Handle ambiguous selector. */ if(*keys == '\0' && curr->type != BUILTIN_WAIT_POINT && curr->children_count > 0 && curr->conf.data.handler != NULL && !keys_info->after_wait) { return KEYS_WAIT_SHORT; } /* Execute the selector. */ if(curr->conf.followed == FOLLOWED_BY_MULTIKEY && keys[0] != L'\0') { const wchar_t mk[] = { keys[0], L'\0' }; result = execute_next_keys(curr, mk, &key_info, keys_info, 0, no_remap); ++keys; } else { result = keys[0] == L'\0' ? execute_next_keys(curr, L"", &key_info, keys_info, 0, no_remap) : dispatch_key(key_info, keys_info, curr, L""); } if(IS_KEYS_RET_CODE(result)) { return result; } /* We used this count in selector, so don't pass it to command. */ master_key_info.count = NO_COUNT_GIVEN; /* Execute command that requested the selector. */ result = execute_mapping_handler(&master_curr->conf, master_key_info, keys_info); if(IS_KEYS_RET_CODE(result)) { return result; } inc_counter(keys_info, keys - keys_start); /* execute_keys_general() treats empty input as an error. */ if(keys[0] == L'\0') { return 0; } /* Process the rest of the line. */ return execute_keys_general(keys, keys_info->after_wait, 0, no_remap); }