Loading fs/cifs/cifsencrypt.c +54 −43 Original line number Diff line number Diff line Loading @@ -66,45 +66,15 @@ cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) return 0; } /* * Calculate and return the CIFS signature based on the mac key and SMB PDU. * The 16 byte signature must be allocated by the caller. Note we only use the * 1st eight bytes and that the smb header signature field on input contains * the sequence number before this function is called. Also, this function * should be called with the server->srv_mutex held. */ static int cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, char *signature) int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, char *signature, struct shash_desc *shash) { int i; int rc; struct kvec *iov = rqst->rq_iov; int n_vec = rqst->rq_nvec; if (iov == NULL || signature == NULL || server == NULL) return -EINVAL; if (!server->secmech.sdescmd5) { rc = cifs_crypto_shash_md5_allocate(server); if (rc) { cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__); return -1; } } rc = crypto_shash_init(&server->secmech.sdescmd5->shash); if (rc) { cifs_dbg(VFS, "%s: Could not init md5\n", __func__); return rc; } rc = crypto_shash_update(&server->secmech.sdescmd5->shash, server->session_key.response, server->session_key.len); if (rc) { cifs_dbg(VFS, "%s: Could not update with response\n", __func__); return rc; } for (i = 0; i < n_vec; i++) { if (iov[i].iov_len == 0) continue; Loading @@ -117,12 +87,10 @@ static int cifs_calc_signature(struct smb_rqst *rqst, if (i == 0) { if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ break; /* nothing to sign or corrupt header */ rc = crypto_shash_update(&server->secmech.sdescmd5->shash, rc = crypto_shash_update(shash, iov[i].iov_base + 4, iov[i].iov_len - 4); } else { rc = crypto_shash_update(&server->secmech.sdescmd5->shash, rc = crypto_shash_update(shash, iov[i].iov_base, iov[i].iov_len); } if (rc) { Loading @@ -134,21 +102,64 @@ static int cifs_calc_signature(struct smb_rqst *rqst, /* now hash over the rq_pages array */ for (i = 0; i < rqst->rq_npages; i++) { struct kvec p_iov; void *kaddr = kmap(rqst->rq_pages[i]); size_t len = rqst->rq_pagesz; if (i == rqst->rq_npages - 1) len = rqst->rq_tailsz; crypto_shash_update(shash, kaddr, len); cifs_rqst_page_to_kvec(rqst, i, &p_iov); crypto_shash_update(&server->secmech.sdescmd5->shash, p_iov.iov_base, p_iov.iov_len); kunmap(rqst->rq_pages[i]); } rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); rc = crypto_shash_final(shash, signature); if (rc) cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__); cifs_dbg(VFS, "%s: Could not generate hash\n", __func__); return rc; } /* * Calculate and return the CIFS signature based on the mac key and SMB PDU. * The 16 byte signature must be allocated by the caller. Note we only use the * 1st eight bytes and that the smb header signature field on input contains * the sequence number before this function is called. Also, this function * should be called with the server->srv_mutex held. */ static int cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, char *signature) { int rc; if (!rqst->rq_iov || !signature || !server) return -EINVAL; if (!server->secmech.sdescmd5) { rc = cifs_crypto_shash_md5_allocate(server); if (rc) { cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__); return -1; } } rc = crypto_shash_init(&server->secmech.sdescmd5->shash); if (rc) { cifs_dbg(VFS, "%s: Could not init md5\n", __func__); return rc; } rc = crypto_shash_update(&server->secmech.sdescmd5->shash, server->session_key.response, server->session_key.len); if (rc) { cifs_dbg(VFS, "%s: Could not update with response\n", __func__); return rc; } return __cifs_calc_signature(rqst, server, signature, &server->secmech.sdescmd5->shash); } /* must be called with server->srv_mutex held */ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server, __u32 *pexpected_response_sequence_number) Loading fs/cifs/cifsproto.h +3 −0 Original line number Diff line number Diff line Loading @@ -512,4 +512,7 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const unsigned char *path, char *pbuf, unsigned int *pbytes_written); int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, char *signature, struct shash_desc *shash); #endif /* _CIFSPROTO_H */ fs/cifs/smb2transport.c +10 −97 Original line number Diff line number Diff line Loading @@ -135,11 +135,10 @@ smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server) int smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) { int i, rc; int rc; unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; unsigned char *sigptr = smb2_signature; struct kvec *iov = rqst->rq_iov; int n_vec = rqst->rq_nvec; struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; struct cifs_ses *ses; Loading Loading @@ -171,52 +170,10 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) return rc; } for (i = 0; i < n_vec; i++) { if (iov[i].iov_len == 0) continue; if (iov[i].iov_base == NULL) { cifs_dbg(VFS, "null iovec entry\n"); return -EIO; } /* * The first entry includes a length field (which does not get * signed that occupies the first 4 bytes before the header). */ if (i == 0) { if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ break; /* nothing to sign or corrupt header */ rc = crypto_shash_update( &server->secmech.sdeschmacsha256->shash, iov[i].iov_base + 4, iov[i].iov_len - 4); } else { rc = crypto_shash_update( &server->secmech.sdeschmacsha256->shash, iov[i].iov_base, iov[i].iov_len); } if (rc) { cifs_dbg(VFS, "%s: Could not update with payload\n", __func__); return rc; } } /* now hash over the rq_pages array */ for (i = 0; i < rqst->rq_npages; i++) { struct kvec p_iov; cifs_rqst_page_to_kvec(rqst, i, &p_iov); crypto_shash_update(&server->secmech.sdeschmacsha256->shash, p_iov.iov_base, p_iov.iov_len); kunmap(rqst->rq_pages[i]); } rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash, sigptr); if (rc) cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__); rc = __cifs_calc_signature(rqst, server, sigptr, &server->secmech.sdeschmacsha256->shash); if (!rc) memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); return rc; Loading Loading @@ -395,12 +352,10 @@ generate_smb311signingkey(struct cifs_ses *ses) int smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) { int i; int rc = 0; unsigned char smb3_signature[SMB2_CMACAES_SIZE]; unsigned char *sigptr = smb3_signature; struct kvec *iov = rqst->rq_iov; int n_vec = rqst->rq_nvec; struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; struct cifs_ses *ses; Loading Loading @@ -432,52 +387,10 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) return rc; } for (i = 0; i < n_vec; i++) { if (iov[i].iov_len == 0) continue; if (iov[i].iov_base == NULL) { cifs_dbg(VFS, "null iovec entry"); return -EIO; } /* * The first entry includes a length field (which does not get * signed that occupies the first 4 bytes before the header). */ if (i == 0) { if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ break; /* nothing to sign or corrupt header */ rc = crypto_shash_update( &server->secmech.sdesccmacaes->shash, iov[i].iov_base + 4, iov[i].iov_len - 4); } else { rc = crypto_shash_update( &server->secmech.sdesccmacaes->shash, iov[i].iov_base, iov[i].iov_len); } if (rc) { cifs_dbg(VFS, "%s: Couldn't update cmac aes with payload\n", __func__); return rc; } } /* now hash over the rq_pages array */ for (i = 0; i < rqst->rq_npages; i++) { struct kvec p_iov; cifs_rqst_page_to_kvec(rqst, i, &p_iov); crypto_shash_update(&server->secmech.sdesccmacaes->shash, p_iov.iov_base, p_iov.iov_len); kunmap(rqst->rq_pages[i]); } rc = crypto_shash_final(&server->secmech.sdesccmacaes->shash, sigptr); if (rc) cifs_dbg(VFS, "%s: Could not generate cmac aes\n", __func__); rc = __cifs_calc_signature(rqst, server, sigptr, &server->secmech.sdesccmacaes->shash); if (!rc) memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); return rc; Loading Loading
fs/cifs/cifsencrypt.c +54 −43 Original line number Diff line number Diff line Loading @@ -66,45 +66,15 @@ cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) return 0; } /* * Calculate and return the CIFS signature based on the mac key and SMB PDU. * The 16 byte signature must be allocated by the caller. Note we only use the * 1st eight bytes and that the smb header signature field on input contains * the sequence number before this function is called. Also, this function * should be called with the server->srv_mutex held. */ static int cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, char *signature) int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, char *signature, struct shash_desc *shash) { int i; int rc; struct kvec *iov = rqst->rq_iov; int n_vec = rqst->rq_nvec; if (iov == NULL || signature == NULL || server == NULL) return -EINVAL; if (!server->secmech.sdescmd5) { rc = cifs_crypto_shash_md5_allocate(server); if (rc) { cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__); return -1; } } rc = crypto_shash_init(&server->secmech.sdescmd5->shash); if (rc) { cifs_dbg(VFS, "%s: Could not init md5\n", __func__); return rc; } rc = crypto_shash_update(&server->secmech.sdescmd5->shash, server->session_key.response, server->session_key.len); if (rc) { cifs_dbg(VFS, "%s: Could not update with response\n", __func__); return rc; } for (i = 0; i < n_vec; i++) { if (iov[i].iov_len == 0) continue; Loading @@ -117,12 +87,10 @@ static int cifs_calc_signature(struct smb_rqst *rqst, if (i == 0) { if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ break; /* nothing to sign or corrupt header */ rc = crypto_shash_update(&server->secmech.sdescmd5->shash, rc = crypto_shash_update(shash, iov[i].iov_base + 4, iov[i].iov_len - 4); } else { rc = crypto_shash_update(&server->secmech.sdescmd5->shash, rc = crypto_shash_update(shash, iov[i].iov_base, iov[i].iov_len); } if (rc) { Loading @@ -134,21 +102,64 @@ static int cifs_calc_signature(struct smb_rqst *rqst, /* now hash over the rq_pages array */ for (i = 0; i < rqst->rq_npages; i++) { struct kvec p_iov; void *kaddr = kmap(rqst->rq_pages[i]); size_t len = rqst->rq_pagesz; if (i == rqst->rq_npages - 1) len = rqst->rq_tailsz; crypto_shash_update(shash, kaddr, len); cifs_rqst_page_to_kvec(rqst, i, &p_iov); crypto_shash_update(&server->secmech.sdescmd5->shash, p_iov.iov_base, p_iov.iov_len); kunmap(rqst->rq_pages[i]); } rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); rc = crypto_shash_final(shash, signature); if (rc) cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__); cifs_dbg(VFS, "%s: Could not generate hash\n", __func__); return rc; } /* * Calculate and return the CIFS signature based on the mac key and SMB PDU. * The 16 byte signature must be allocated by the caller. Note we only use the * 1st eight bytes and that the smb header signature field on input contains * the sequence number before this function is called. Also, this function * should be called with the server->srv_mutex held. */ static int cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, char *signature) { int rc; if (!rqst->rq_iov || !signature || !server) return -EINVAL; if (!server->secmech.sdescmd5) { rc = cifs_crypto_shash_md5_allocate(server); if (rc) { cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__); return -1; } } rc = crypto_shash_init(&server->secmech.sdescmd5->shash); if (rc) { cifs_dbg(VFS, "%s: Could not init md5\n", __func__); return rc; } rc = crypto_shash_update(&server->secmech.sdescmd5->shash, server->session_key.response, server->session_key.len); if (rc) { cifs_dbg(VFS, "%s: Could not update with response\n", __func__); return rc; } return __cifs_calc_signature(rqst, server, signature, &server->secmech.sdescmd5->shash); } /* must be called with server->srv_mutex held */ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server, __u32 *pexpected_response_sequence_number) Loading
fs/cifs/cifsproto.h +3 −0 Original line number Diff line number Diff line Loading @@ -512,4 +512,7 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const unsigned char *path, char *pbuf, unsigned int *pbytes_written); int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, char *signature, struct shash_desc *shash); #endif /* _CIFSPROTO_H */
fs/cifs/smb2transport.c +10 −97 Original line number Diff line number Diff line Loading @@ -135,11 +135,10 @@ smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server) int smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) { int i, rc; int rc; unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; unsigned char *sigptr = smb2_signature; struct kvec *iov = rqst->rq_iov; int n_vec = rqst->rq_nvec; struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; struct cifs_ses *ses; Loading Loading @@ -171,52 +170,10 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) return rc; } for (i = 0; i < n_vec; i++) { if (iov[i].iov_len == 0) continue; if (iov[i].iov_base == NULL) { cifs_dbg(VFS, "null iovec entry\n"); return -EIO; } /* * The first entry includes a length field (which does not get * signed that occupies the first 4 bytes before the header). */ if (i == 0) { if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ break; /* nothing to sign or corrupt header */ rc = crypto_shash_update( &server->secmech.sdeschmacsha256->shash, iov[i].iov_base + 4, iov[i].iov_len - 4); } else { rc = crypto_shash_update( &server->secmech.sdeschmacsha256->shash, iov[i].iov_base, iov[i].iov_len); } if (rc) { cifs_dbg(VFS, "%s: Could not update with payload\n", __func__); return rc; } } /* now hash over the rq_pages array */ for (i = 0; i < rqst->rq_npages; i++) { struct kvec p_iov; cifs_rqst_page_to_kvec(rqst, i, &p_iov); crypto_shash_update(&server->secmech.sdeschmacsha256->shash, p_iov.iov_base, p_iov.iov_len); kunmap(rqst->rq_pages[i]); } rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash, sigptr); if (rc) cifs_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__); rc = __cifs_calc_signature(rqst, server, sigptr, &server->secmech.sdeschmacsha256->shash); if (!rc) memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); return rc; Loading Loading @@ -395,12 +352,10 @@ generate_smb311signingkey(struct cifs_ses *ses) int smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) { int i; int rc = 0; unsigned char smb3_signature[SMB2_CMACAES_SIZE]; unsigned char *sigptr = smb3_signature; struct kvec *iov = rqst->rq_iov; int n_vec = rqst->rq_nvec; struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; struct cifs_ses *ses; Loading Loading @@ -432,52 +387,10 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) return rc; } for (i = 0; i < n_vec; i++) { if (iov[i].iov_len == 0) continue; if (iov[i].iov_base == NULL) { cifs_dbg(VFS, "null iovec entry"); return -EIO; } /* * The first entry includes a length field (which does not get * signed that occupies the first 4 bytes before the header). */ if (i == 0) { if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ break; /* nothing to sign or corrupt header */ rc = crypto_shash_update( &server->secmech.sdesccmacaes->shash, iov[i].iov_base + 4, iov[i].iov_len - 4); } else { rc = crypto_shash_update( &server->secmech.sdesccmacaes->shash, iov[i].iov_base, iov[i].iov_len); } if (rc) { cifs_dbg(VFS, "%s: Couldn't update cmac aes with payload\n", __func__); return rc; } } /* now hash over the rq_pages array */ for (i = 0; i < rqst->rq_npages; i++) { struct kvec p_iov; cifs_rqst_page_to_kvec(rqst, i, &p_iov); crypto_shash_update(&server->secmech.sdesccmacaes->shash, p_iov.iov_base, p_iov.iov_len); kunmap(rqst->rq_pages[i]); } rc = crypto_shash_final(&server->secmech.sdesccmacaes->shash, sigptr); if (rc) cifs_dbg(VFS, "%s: Could not generate cmac aes\n", __func__); rc = __cifs_calc_signature(rqst, server, sigptr, &server->secmech.sdesccmacaes->shash); if (!rc) memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); return rc; Loading