📄 keystore.c
字号:
memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key, auth_tok->session_key.decrypted_key_size); crypt_stat->key_size = auth_tok->session_key.decrypted_key_size; rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher, cipher_code); if (rc) { ecryptfs_printk(KERN_ERR, "Cipher code [%d] is invalid\n", cipher_code) goto out; } crypt_stat->flags |= ECRYPTFS_KEY_VALID; if (ecryptfs_verbosity > 0) { ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n"); ecryptfs_dump_hex(crypt_stat->key, crypt_stat->key_size); }out: if (msg) kfree(msg); return rc;}static void wipe_auth_tok_list(struct list_head *auth_tok_list_head){ struct ecryptfs_auth_tok_list_item *auth_tok_list_item; struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp; list_for_each_entry_safe(auth_tok_list_item, auth_tok_list_item_tmp, auth_tok_list_head, list) { list_del(&auth_tok_list_item->list); kmem_cache_free(ecryptfs_auth_tok_list_item_cache, auth_tok_list_item); }}struct kmem_cache *ecryptfs_auth_tok_list_item_cache;/** * parse_tag_1_packet * @crypt_stat: The cryptographic context to modify based on packet contents * @data: The raw bytes of the packet. * @auth_tok_list: eCryptfs parses packets into authentication tokens; * a new authentication token will be placed at the * end of this list for this packet. * @new_auth_tok: Pointer to a pointer to memory that this function * allocates; sets the memory address of the pointer to * NULL on error. This object is added to the * auth_tok_list. * @packet_size: This function writes the size of the parsed packet * into this memory location; zero on error. * @max_packet_size: The maximum allowable packet size * * Returns zero on success; non-zero on error. */static intparse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat, unsigned char *data, struct list_head *auth_tok_list, struct ecryptfs_auth_tok **new_auth_tok, size_t *packet_size, size_t max_packet_size){ size_t body_size; struct ecryptfs_auth_tok_list_item *auth_tok_list_item; size_t length_size; int rc = 0; (*packet_size) = 0; (*new_auth_tok) = NULL; /** * This format is inspired by OpenPGP; see RFC 2440 * packet tag 1 * * Tag 1 identifier (1 byte) * Max Tag 1 packet size (max 3 bytes) * Version (1 byte) * Key identifier (8 bytes; ECRYPTFS_SIG_SIZE) * Cipher identifier (1 byte) * Encrypted key size (arbitrary) * * 12 bytes minimum packet size */ if (unlikely(max_packet_size < 12)) { printk(KERN_ERR "Invalid max packet size; must be >=12\n"); rc = -EINVAL; goto out; } if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) { printk(KERN_ERR "Enter w/ first byte != 0x%.2x\n", ECRYPTFS_TAG_1_PACKET_TYPE); rc = -EINVAL; goto out; } /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or * at end of function upon failure */ auth_tok_list_item = kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL); if (!auth_tok_list_item) { printk(KERN_ERR "Unable to allocate memory\n"); rc = -ENOMEM; goto out; } (*new_auth_tok) = &auth_tok_list_item->auth_tok; rc = parse_packet_length(&data[(*packet_size)], &body_size, &length_size); if (rc) { printk(KERN_WARNING "Error parsing packet length; " "rc = [%d]\n", rc); goto out_free; } if (unlikely(body_size < (ECRYPTFS_SIG_SIZE + 2))) { printk(KERN_WARNING "Invalid body size ([%td])\n", body_size); rc = -EINVAL; goto out_free; } (*packet_size) += length_size; if (unlikely((*packet_size) + body_size > max_packet_size)) { printk(KERN_WARNING "Packet size exceeds max\n"); rc = -EINVAL; goto out_free; } if (unlikely(data[(*packet_size)++] != 0x03)) { printk(KERN_WARNING "Unknown version number [%d]\n", data[(*packet_size) - 1]); rc = -EINVAL; goto out_free; } ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature, &data[(*packet_size)], ECRYPTFS_SIG_SIZE); *packet_size += ECRYPTFS_SIG_SIZE; /* This byte is skipped because the kernel does not need to * know which public key encryption algorithm was used */ (*packet_size)++; (*new_auth_tok)->session_key.encrypted_key_size = body_size - (ECRYPTFS_SIG_SIZE + 2); if ((*new_auth_tok)->session_key.encrypted_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { printk(KERN_WARNING "Tag 1 packet contains key larger " "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES"); rc = -EINVAL; goto out; } memcpy((*new_auth_tok)->session_key.encrypted_key, &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2))); (*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size; (*new_auth_tok)->session_key.flags &= ~ECRYPTFS_CONTAINS_DECRYPTED_KEY; (*new_auth_tok)->session_key.flags |= ECRYPTFS_CONTAINS_ENCRYPTED_KEY; (*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY; (*new_auth_tok)->flags = 0; (*new_auth_tok)->session_key.flags &= ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT); (*new_auth_tok)->session_key.flags &= ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT); list_add(&auth_tok_list_item->list, auth_tok_list); goto out;out_free: (*new_auth_tok) = NULL; memset(auth_tok_list_item, 0, sizeof(struct ecryptfs_auth_tok_list_item)); kmem_cache_free(ecryptfs_auth_tok_list_item_cache, auth_tok_list_item);out: if (rc) (*packet_size) = 0; return rc;}/** * parse_tag_3_packet * @crypt_stat: The cryptographic context to modify based on packet * contents. * @data: The raw bytes of the packet. * @auth_tok_list: eCryptfs parses packets into authentication tokens; * a new authentication token will be placed at the end * of this list for this packet. * @new_auth_tok: Pointer to a pointer to memory that this function * allocates; sets the memory address of the pointer to * NULL on error. This object is added to the * auth_tok_list. * @packet_size: This function writes the size of the parsed packet * into this memory location; zero on error. * @max_packet_size: maximum number of bytes to parse * * Returns zero on success; non-zero on error. */static intparse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat, unsigned char *data, struct list_head *auth_tok_list, struct ecryptfs_auth_tok **new_auth_tok, size_t *packet_size, size_t max_packet_size){ size_t body_size; struct ecryptfs_auth_tok_list_item *auth_tok_list_item; size_t length_size; int rc = 0; (*packet_size) = 0; (*new_auth_tok) = NULL; /** *This format is inspired by OpenPGP; see RFC 2440 * packet tag 3 * * Tag 3 identifier (1 byte) * Max Tag 3 packet size (max 3 bytes) * Version (1 byte) * Cipher code (1 byte) * S2K specifier (1 byte) * Hash identifier (1 byte) * Salt (ECRYPTFS_SALT_SIZE) * Hash iterations (1 byte) * Encrypted key (arbitrary) * * (ECRYPTFS_SALT_SIZE + 7) minimum packet size */ if (max_packet_size < (ECRYPTFS_SALT_SIZE + 7)) { printk(KERN_ERR "Max packet size too large\n"); rc = -EINVAL; goto out; } if (data[(*packet_size)++] != ECRYPTFS_TAG_3_PACKET_TYPE) { printk(KERN_ERR "First byte != 0x%.2x; invalid packet\n", ECRYPTFS_TAG_3_PACKET_TYPE); rc = -EINVAL; goto out; } /* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or * at end of function upon failure */ auth_tok_list_item = kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL); if (!auth_tok_list_item) { printk(KERN_ERR "Unable to allocate memory\n"); rc = -ENOMEM; goto out; } (*new_auth_tok) = &auth_tok_list_item->auth_tok; rc = parse_packet_length(&data[(*packet_size)], &body_size, &length_size); if (rc) { printk(KERN_WARNING "Error parsing packet length; rc = [%d]\n", rc); goto out_free; } if (unlikely(body_size < (ECRYPTFS_SALT_SIZE + 5))) { printk(KERN_WARNING "Invalid body size ([%td])\n", body_size); rc = -EINVAL; goto out_free; } (*packet_size) += length_size; if (unlikely((*packet_size) + body_size > max_packet_size)) { printk(KERN_ERR "Packet size exceeds max\n"); rc = -EINVAL; goto out_free; } (*new_auth_tok)->session_key.encrypted_key_size = (body_size - (ECRYPTFS_SALT_SIZE + 5)); if (unlikely(data[(*packet_size)++] != 0x04)) { printk(KERN_WARNING "Unknown version number [%d]\n", data[(*packet_size) - 1]); rc = -EINVAL; goto out_free; } ecryptfs_cipher_code_to_string(crypt_stat->cipher, (u16)data[(*packet_size)]); /* A little extra work to differentiate among the AES key * sizes; see RFC2440 */ switch(data[(*packet_size)++]) { case RFC2440_CIPHER_AES_192: crypt_stat->key_size = 24; break; default: crypt_stat->key_size = (*new_auth_tok)->session_key.encrypted_key_size; } ecryptfs_init_crypt_ctx(crypt_stat); if (unlikely(data[(*packet_size)++] != 0x03)) { printk(KERN_WARNING "Only S2K ID 3 is currently supported\n"); rc = -ENOSYS; goto out_free; } /* TODO: finish the hash mapping */ switch (data[(*packet_size)++]) { case 0x01: /* See RFC2440 for these numbers and their mappings */ /* Choose MD5 */ memcpy((*new_auth_tok)->token.password.salt, &data[(*packet_size)], ECRYPTFS_SALT_SIZE); (*packet_size) += ECRYPTFS_SALT_SIZE; /* This conversion was taken straight from RFC2440 */ (*new_auth_tok)->token.password.hash_iterations = ((u32) 16 + (data[(*packet_size)] & 15)) << ((data[(*packet_size)] >> 4) + 6); (*packet_size)++; /* Friendly reminder: * (*new_auth_tok)->session_key.encrypted_key_size = * (body_size - (ECRYPTFS_SALT_SIZE + 5)); */ memcpy((*new_auth_tok)->session_key.encrypted_key, &data[(*packet_size)], (*new_auth_tok)->session_key.encrypted_key_size); (*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size; (*new_auth_tok)->session_key.flags &= ~ECRYPTFS_CONTAINS_DECRYPTED_KEY; (*new_auth_tok)->session_key.flags |= ECRYPTFS_CONTAINS_ENCRYPTED_KEY; (*new_auth_tok)->token.password.hash_algo = 0x01; /* MD5 */ break; default: ecryptfs_printk(KERN_ERR, "Unsupported hash algorithm: " "[%d]\n", data[(*packet_size) - 1]); rc = -ENOSYS; goto out_free; } (*new_auth_tok)->token_type = ECRYPTFS_PASSWORD; /* TODO: Parametarize; we might actually want userspace to * decrypt the session key. */ (*new_auth_tok)->session_key.flags &= ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT); (*new_auth_tok)->session_key.flags &= ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT); list_add(&auth_tok_list_item->list, auth_tok_list); goto out;out_free: (*new_auth_tok) = NULL; memset(auth_tok_list_item, 0, sizeof(struct ecryptfs_auth_tok_list_item)); kmem_cache_free(ecryptfs_auth_tok_list_item_cache, auth_tok_list_item);out: if (rc) (*packet_size) = 0; return rc;}/** * parse_tag_11_packet * @data: The raw bytes of the packet * @contents: This function writes the data contents of the literal * packet into this memory location * @max_contents_bytes: The maximum number of bytes that this function * is allowed to write into contents * @tag_11_contents_size: This function writes the size of the parsed * contents into this memory location; zero on * error * @packet_size: This function writes the size of the parsed packet * into this memory location; zero on error * @max_packet_size: maximum number of bytes to parse * * Returns zero on success; non-zero on error. */static intparse_tag_11_packet(unsigned char *data, unsigned char *contents, size_t max_contents_bytes, size_t *tag_11_contents_size, size_t *packet_size, size_t max_packet_size){ size_t body_size; size_t length_size; int rc = 0; (*packet_size) = 0; (*tag_11_contents_size) = 0; /* This format is inspired by OpenPGP; see RFC 2440 * packet tag 11 * * Tag 11 identifier (1 byte) * Max Tag 11 packet size (max 3 bytes) * Binary format specifier (1 byte) * Filename length (1 byte) * Filename ("_CONSOLE") (8 bytes) * Modification date (4 bytes) * Literal data (arbitrary) * * We need at least 16 bytes of data for the packet to even be * valid. */ if (max_packet_size < 16) { printk(KERN_ERR "Maximum packet size too small\n"); rc = -EINVAL; goto out; } if (data[(*packet_size)++] != ECRYPTFS_TAG_11_PACKET_TYPE) { printk(KERN_WARNING "Invalid tag 11 packet format\n"); rc = -EINVAL; goto out; } rc = parse_packet_length(&data[(*packet_size)], &body_size, &length_size); if (rc) { printk(KERN_WARNING "Invalid tag 11 packet format\n"); goto out; } if (body_size < 14) { printk(KERN_WARNING "Invalid body size ([%td])\n", body_size); rc = -EINVAL; goto out; } (*packet_size) += length_size; (*tag_11_contents_size) = (body_size - 14); if (unlikely((*packet_size) + body_size + 1 > max_packet_size)) { printk(KERN_ERR "Packet size exceeds max\n"); rc = -EINVAL; goto out; } if (data[(*packet_size)++] != 0x62) { printk(KERN_WARNING "Unrecognizable packet\n"); rc = -EINVAL; goto out; } if (data[(*packet_size)++] != 0x08) { printk(KERN_WARNING "Unrecognizable packet\n"); rc = -EINVAL; goto out; } (*packet_size) += 12; /* Ignore filename and modification date */ memcpy(contents, &data[(*packet_size)], (*tag_11_contents_size)); (*packet_size) += (*tag_11_contents_size);out: if (rc) { (*packet_size) = 0; (*tag_11_contents_size) = 0; } return rc;}static intecryptfs_find_global_auth_tok_for_sig( struct ecryptfs_global_auth_tok **global_auth_tok, struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig){ struct ecryptfs_global_auth_tok *walker; int rc = 0; (*global_auth_tok) = NULL; mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); list_for_each_entry(walker, &mount_crypt_stat->global_auth_tok_list, mount_crypt_stat_list) { if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) { (*global_auth_tok) = walker; goto out; } } rc = -EINVAL;out: mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); return rc;}/** * ecryptfs_verify_version * @version: The version number to confirm * * Returns zero on good version; non-zero otherwise */static int ecryptfs_verify_version(u16 version){ int rc = 0; unsigned char major; unsigned char minor; major = ((version >> 8) & 0xFF); minor = (version & 0xFF); if (major != ECRYPTFS_VERSION_MAJOR) { ecryptfs_printk(KERN_ERR, "Major version number mismatch. " "Expected [%d]; got [%d]\n", ECRYPTFS_VERSION_MAJOR, major); rc = -EINVAL; goto out; } if (minor != ECRYPTFS_VERSION_MINOR) { ecryptfs_printk(KERN_ERR, "Minor version number mismatch. " "Expected [%d]; got [%d]\n", ECRYPTFS_VERSION_MINOR, minor);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -