📄 keystore.c
字号:
ecryptfs_dump_hex(key_rec->enc_key, key_rec->enc_key_size); }encrypted_session_key_set: /* This format is inspired by OpenPGP; see RFC 2440 * packet tag 1 */ max_packet_size = (1 /* Tag 1 identifier */ + 3 /* Max Tag 1 packet size */ + 1 /* Version */ + ECRYPTFS_SIG_SIZE /* Key identifier */ + 1 /* Cipher identifier */ + key_rec->enc_key_size); /* Encrypted key size */ if (max_packet_size > (*remaining_bytes)) { printk(KERN_ERR "Packet length larger than maximum allowable; " "need up to [%td] bytes, but there are only [%td] " "available\n", max_packet_size, (*remaining_bytes)); rc = -EINVAL; goto out; } dest[(*packet_size)++] = ECRYPTFS_TAG_1_PACKET_TYPE; rc = write_packet_length(&dest[(*packet_size)], (max_packet_size - 4), &packet_size_length); if (rc) { ecryptfs_printk(KERN_ERR, "Error generating tag 1 packet " "header; cannot generate packet length\n"); goto out; } (*packet_size) += packet_size_length; dest[(*packet_size)++] = 0x03; /* version 3 */ memcpy(&dest[(*packet_size)], key_rec->sig, ECRYPTFS_SIG_SIZE); (*packet_size) += ECRYPTFS_SIG_SIZE; dest[(*packet_size)++] = RFC2440_CIPHER_RSA; memcpy(&dest[(*packet_size)], key_rec->enc_key, key_rec->enc_key_size); (*packet_size) += key_rec->enc_key_size;out: if (rc) (*packet_size) = 0; else (*remaining_bytes) -= (*packet_size); return rc;}/** * write_tag_11_packet * @dest: Target into which Tag 11 packet is to be written * @remaining_bytes: Maximum packet length * @contents: Byte array of contents to copy in * @contents_length: Number of bytes in contents * @packet_length: Length of the Tag 11 packet written; zero on error * * Returns zero on success; non-zero on error. */static intwrite_tag_11_packet(char *dest, size_t *remaining_bytes, char *contents, size_t contents_length, size_t *packet_length){ size_t packet_size_length; size_t max_packet_size; int rc = 0; (*packet_length) = 0; /* This format is inspired by OpenPGP; see RFC 2440 * packet tag 11 */ max_packet_size = (1 /* Tag 11 identifier */ + 3 /* Max Tag 11 packet size */ + 1 /* Binary format specifier */ + 1 /* Filename length */ + 8 /* Filename ("_CONSOLE") */ + 4 /* Modification date */ + contents_length); /* Literal data */ if (max_packet_size > (*remaining_bytes)) { printk(KERN_ERR "Packet length larger than maximum allowable; " "need up to [%td] bytes, but there are only [%td] " "available\n", max_packet_size, (*remaining_bytes)); rc = -EINVAL; goto out; } dest[(*packet_length)++] = ECRYPTFS_TAG_11_PACKET_TYPE; rc = write_packet_length(&dest[(*packet_length)], (max_packet_size - 4), &packet_size_length); if (rc) { printk(KERN_ERR "Error generating tag 11 packet header; cannot " "generate packet length. rc = [%d]\n", rc); goto out; } (*packet_length) += packet_size_length; dest[(*packet_length)++] = 0x62; /* binary data format specifier */ dest[(*packet_length)++] = 8; memcpy(&dest[(*packet_length)], "_CONSOLE", 8); (*packet_length) += 8; memset(&dest[(*packet_length)], 0x00, 4); (*packet_length) += 4; memcpy(&dest[(*packet_length)], contents, contents_length); (*packet_length) += contents_length; out: if (rc) (*packet_length) = 0; else (*remaining_bytes) -= (*packet_length); return rc;}/** * write_tag_3_packet * @dest: Buffer into which to write the packet * @remaining_bytes: Maximum number of bytes that can be written * @auth_tok: Authentication token * @crypt_stat: The cryptographic context * @key_rec: encrypted key * @packet_size: This function will write the number of bytes that end * up constituting the packet; set to zero on error * * Returns zero on success; non-zero on error. */static intwrite_tag_3_packet(char *dest, size_t *remaining_bytes, struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_crypt_stat *crypt_stat, struct ecryptfs_key_record *key_rec, size_t *packet_size){ size_t i; size_t encrypted_session_key_valid = 0; char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; struct scatterlist dst_sg; struct scatterlist src_sg; struct mutex *tfm_mutex = NULL; size_t cipher_code; size_t packet_size_length; size_t max_packet_size; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = crypt_stat->mount_crypt_stat; struct blkcipher_desc desc = { .tfm = NULL, .flags = CRYPTO_TFM_REQ_MAY_SLEEP }; int rc = 0; (*packet_size) = 0; ecryptfs_from_hex(key_rec->sig, auth_tok->token.password.signature, ECRYPTFS_SIG_SIZE); rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex, crypt_stat->cipher); if (unlikely(rc)) { printk(KERN_ERR "Internal error whilst attempting to get " "tfm and mutex for cipher name [%s]; rc = [%d]\n", crypt_stat->cipher, rc); goto out; } if (mount_crypt_stat->global_default_cipher_key_size == 0) { struct blkcipher_alg *alg = crypto_blkcipher_alg(desc.tfm); printk(KERN_WARNING "No key size specified at mount; " "defaulting to [%d]\n", alg->max_keysize); mount_crypt_stat->global_default_cipher_key_size = alg->max_keysize; } if (crypt_stat->key_size == 0) crypt_stat->key_size = mount_crypt_stat->global_default_cipher_key_size; if (auth_tok->session_key.encrypted_key_size == 0) auth_tok->session_key.encrypted_key_size = crypt_stat->key_size; if (crypt_stat->key_size == 24 && strcmp("aes", crypt_stat->cipher) == 0) { memset((crypt_stat->key + 24), 0, 8); auth_tok->session_key.encrypted_key_size = 32; } else auth_tok->session_key.encrypted_key_size = crypt_stat->key_size; key_rec->enc_key_size = auth_tok->session_key.encrypted_key_size; encrypted_session_key_valid = 0; for (i = 0; i < auth_tok->session_key.encrypted_key_size; i++) encrypted_session_key_valid |= auth_tok->session_key.encrypted_key[i]; if (encrypted_session_key_valid) { ecryptfs_printk(KERN_DEBUG, "encrypted_session_key_valid != 0; " "using auth_tok->session_key.encrypted_key, " "where key_rec->enc_key_size = [%d]\n", key_rec->enc_key_size); memcpy(key_rec->enc_key, auth_tok->session_key.encrypted_key, key_rec->enc_key_size); goto encrypted_session_key_set; } if (auth_tok->token.password.flags & ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET) { ecryptfs_printk(KERN_DEBUG, "Using previously generated " "session key encryption key of size [%d]\n", auth_tok->token.password. session_key_encryption_key_bytes); memcpy(session_key_encryption_key, auth_tok->token.password.session_key_encryption_key, crypt_stat->key_size); ecryptfs_printk(KERN_DEBUG, "Cached session key " "encryption key: \n"); if (ecryptfs_verbosity > 0) ecryptfs_dump_hex(session_key_encryption_key, 16); } if (unlikely(ecryptfs_verbosity > 0)) { ecryptfs_printk(KERN_DEBUG, "Session key encryption key:\n"); ecryptfs_dump_hex(session_key_encryption_key, 16); } rc = virt_to_scatterlist(crypt_stat->key, key_rec->enc_key_size, &src_sg, 1); if (rc != 1) { ecryptfs_printk(KERN_ERR, "Error generating scatterlist " "for crypt_stat session key; expected rc = 1; " "got rc = [%d]. key_rec->enc_key_size = [%d]\n", rc, key_rec->enc_key_size); rc = -ENOMEM; goto out; } rc = virt_to_scatterlist(key_rec->enc_key, key_rec->enc_key_size, &dst_sg, 1); if (rc != 1) { ecryptfs_printk(KERN_ERR, "Error generating scatterlist " "for crypt_stat encrypted session key; " "expected rc = 1; got rc = [%d]. " "key_rec->enc_key_size = [%d]\n", rc, key_rec->enc_key_size); rc = -ENOMEM; goto out; } mutex_lock(tfm_mutex); rc = crypto_blkcipher_setkey(desc.tfm, session_key_encryption_key, crypt_stat->key_size); if (rc < 0) { mutex_unlock(tfm_mutex); ecryptfs_printk(KERN_ERR, "Error setting key for crypto " "context; rc = [%d]\n", rc); goto out; } rc = 0; ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n", crypt_stat->key_size); rc = crypto_blkcipher_encrypt(&desc, &dst_sg, &src_sg, (*key_rec).enc_key_size); mutex_unlock(tfm_mutex); if (rc) { printk(KERN_ERR "Error encrypting; rc = [%d]\n", rc); goto out; } ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n"); if (ecryptfs_verbosity > 0) { ecryptfs_printk(KERN_DEBUG, "EFEK of size [%d]:\n", key_rec->enc_key_size); ecryptfs_dump_hex(key_rec->enc_key, key_rec->enc_key_size); }encrypted_session_key_set: /* This format is inspired by OpenPGP; see RFC 2440 * packet tag 3 */ max_packet_size = (1 /* Tag 3 identifier */ + 3 /* Max Tag 3 packet size */ + 1 /* Version */ + 1 /* Cipher code */ + 1 /* S2K specifier */ + 1 /* Hash identifier */ + ECRYPTFS_SALT_SIZE /* Salt */ + 1 /* Hash iterations */ + key_rec->enc_key_size); /* Encrypted key size */ if (max_packet_size > (*remaining_bytes)) { printk(KERN_ERR "Packet too large; need up to [%td] bytes, but " "there are only [%td] available\n", max_packet_size, (*remaining_bytes)); rc = -EINVAL; goto out; } dest[(*packet_size)++] = ECRYPTFS_TAG_3_PACKET_TYPE; /* Chop off the Tag 3 identifier(1) and Tag 3 packet size(3) * to get the number of octets in the actual Tag 3 packet */ rc = write_packet_length(&dest[(*packet_size)], (max_packet_size - 4), &packet_size_length); if (rc) { printk(KERN_ERR "Error generating tag 3 packet header; cannot " "generate packet length. rc = [%d]\n", rc); goto out; } (*packet_size) += packet_size_length; dest[(*packet_size)++] = 0x04; /* version 4 */ /* TODO: Break from RFC2440 so that arbitrary ciphers can be * specified with strings */ cipher_code = ecryptfs_code_for_cipher_string(crypt_stat); if (cipher_code == 0) { ecryptfs_printk(KERN_WARNING, "Unable to generate code for " "cipher [%s]\n", crypt_stat->cipher); rc = -EINVAL; goto out; } dest[(*packet_size)++] = cipher_code; dest[(*packet_size)++] = 0x03; /* S2K */ dest[(*packet_size)++] = 0x01; /* MD5 (TODO: parameterize) */ memcpy(&dest[(*packet_size)], auth_tok->token.password.salt, ECRYPTFS_SALT_SIZE); (*packet_size) += ECRYPTFS_SALT_SIZE; /* salt */ dest[(*packet_size)++] = 0x60; /* hash iterations (65536) */ memcpy(&dest[(*packet_size)], key_rec->enc_key, key_rec->enc_key_size); (*packet_size) += key_rec->enc_key_size;out: if (rc) (*packet_size) = 0; else (*remaining_bytes) -= (*packet_size); return rc;}struct kmem_cache *ecryptfs_key_record_cache;/** * ecryptfs_generate_key_packet_set * @dest_base: Virtual address from which to write the key record set * @crypt_stat: The cryptographic context from which the * authentication tokens will be retrieved * @ecryptfs_dentry: The dentry, used to retrieve the mount crypt stat * for the global parameters * @len: The amount written * @max: The maximum amount of data allowed to be written * * Generates a key packet set and writes it to the virtual address * passed in. * * Returns zero on success; non-zero on error. */intecryptfs_generate_key_packet_set(char *dest_base, struct ecryptfs_crypt_stat *crypt_stat, struct dentry *ecryptfs_dentry, size_t *len, size_t max){ struct ecryptfs_auth_tok *auth_tok; struct ecryptfs_global_auth_tok *global_auth_tok; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &ecryptfs_superblock_to_private( ecryptfs_dentry->d_sb)->mount_crypt_stat; size_t written; struct ecryptfs_key_record *key_rec; struct ecryptfs_key_sig *key_sig; int rc = 0; (*len) = 0; mutex_lock(&crypt_stat->keysig_list_mutex); key_rec = kmem_cache_alloc(ecryptfs_key_record_cache, GFP_KERNEL); if (!key_rec) { rc = -ENOMEM; goto out; } list_for_each_entry(key_sig, &crypt_stat->keysig_list, crypt_stat_list) { memset(key_rec, 0, sizeof(*key_rec)); rc = ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok, mount_crypt_stat, key_sig->keysig); if (rc) { printk(KERN_ERR "Error attempting to get the global " "auth_tok; rc = [%d]\n", rc); goto out_free; } if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID) { printk(KERN_WARNING "Skipping invalid auth tok with sig = [%s]\n", global_auth_tok->sig); continue; } auth_tok = global_auth_tok->global_auth_tok; if (auth_tok->token_type == ECRYPTFS_PASSWORD) { rc = write_tag_3_packet((dest_base + (*len)), &max, auth_tok, crypt_stat, key_rec, &written); if (rc) { ecryptfs_printk(KERN_WARNING, "Error " "writing tag 3 packet\n"); goto out_free; } (*len) += written; /* Write auth tok signature packet */ rc = write_tag_11_packet((dest_base + (*len)), &max, key_rec->sig, ECRYPTFS_SIG_SIZE, &written); if (rc) { ecryptfs_printk(KERN_ERR, "Error writing " "auth tok signature packet\n"); goto out_free; } (*len) += written; } else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { rc = write_tag_1_packet(dest_base + (*len), &max, auth_tok, crypt_stat, key_rec, &written); if (rc) { ecryptfs_printk(KERN_WARNING, "Error " "writing tag 1 packet\n"); goto out_free; } (*len) += written; } else { ecryptfs_printk(KERN_WARNING, "Unsupported " "authentication token type\n"); rc = -EINVAL; goto out_free; } } if (likely(max > 0)) { dest_base[(*len)] = 0x00; } else { ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n"); rc = -EIO; }out_free: kmem_cache_free(ecryptfs_key_record_cache, key_rec);out: if (rc) (*len) = 0; mutex_unlock(&crypt_stat->keysig_list_mutex); return rc;}struct kmem_cache *ecryptfs_key_sig_cache;int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig){ struct ecryptfs_key_sig *new_key_sig; int rc = 0; new_key_sig = kmem_cache_alloc(ecryptfs_key_sig_cache, GFP_KERNEL); if (!new_key_sig) { rc = -ENOMEM; printk(KERN_ERR "Error allocating from ecryptfs_key_sig_cache\n"); goto out; } memcpy(new_key_sig->keysig, sig, ECRYPTFS_SIG_SIZE_HEX); mutex_lock(&crypt_stat->keysig_list_mutex); list_add(&new_key_sig->crypt_stat_list, &crypt_stat->keysig_list); mutex_unlock(&crypt_stat->keysig_list_mutex);out: return rc;}struct kmem_cache *ecryptfs_global_auth_tok_cache;intecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig){ struct ecryptfs_global_auth_tok *new_auth_tok; int rc = 0; new_auth_tok = kmem_cache_zalloc(ecryptfs_global_auth_tok_cache, GFP_KERNEL); if (!new_auth_tok) { rc = -ENOMEM; printk(KERN_ERR "Error allocating from " "ecryptfs_global_auth_tok_cache\n"); goto out; } memcpy(new_auth_tok->sig, sig, ECRYPTFS_SIG_SIZE_HEX); new_auth_tok->sig[ECRYPTFS_SIG_SIZE_HEX] = '\0'; mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); list_add(&new_auth_tok->mount_crypt_stat_list, &mount_crypt_stat->global_auth_tok_list); mount_crypt_stat->num_global_auth_toks++; mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);out: return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -