cifs: merge the hash calculation helpers
three practically identical copies... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									2da62906b1
								
							
						
					
					
						commit
						16c568efff
					
				| @ -66,6 +66,60 @@ cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
| 	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(shash, | ||||
| 				iov[i].iov_base + 4, iov[i].iov_len - 4); | ||||
| 		} else { | ||||
| 			rc = crypto_shash_update(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++) { | ||||
| 		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); | ||||
| 
 | ||||
| 		kunmap(rqst->rq_pages[i]); | ||||
| 	} | ||||
| 
 | ||||
| 	rc = crypto_shash_final(shash, signature); | ||||
| 	if (rc) | ||||
| 		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 | ||||
| @ -76,12 +130,9 @@ cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) | ||||
| static int cifs_calc_signature(struct smb_rqst *rqst, | ||||
| 			struct TCP_Server_Info *server, char *signature) | ||||
| { | ||||
| 	int i; | ||||
| 	int rc; | ||||
| 	struct kvec *iov = rqst->rq_iov; | ||||
| 	int n_vec = rqst->rq_nvec; | ||||
| 
 | ||||
| 	if (iov == NULL || signature == NULL || server == NULL) | ||||
| 	if (!rqst->rq_iov || !signature || !server) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	if (!server->secmech.sdescmd5) { | ||||
| @ -105,48 +156,8 @@ static int cifs_calc_signature(struct smb_rqst *rqst, | ||||
| 		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.sdescmd5->shash, | ||||
| 				iov[i].iov_base + 4, iov[i].iov_len - 4); | ||||
| 		} else { | ||||
| 			rc = | ||||
| 			crypto_shash_update(&server->secmech.sdescmd5->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.sdescmd5->shash, | ||||
| 					p_iov.iov_base, p_iov.iov_len); | ||||
| 		kunmap(rqst->rq_pages[i]); | ||||
| 	} | ||||
| 
 | ||||
| 	rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); | ||||
| 	if (rc) | ||||
| 		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__); | ||||
| 
 | ||||
| 	return rc; | ||||
| 	return __cifs_calc_signature(rqst, server, signature, | ||||
| 				     &server->secmech.sdescmd5->shash); | ||||
| } | ||||
| 
 | ||||
| /* must be called with server->srv_mutex held */ | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
| @ -171,53 +170,11 @@ 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; | ||||
| 		} | ||||
| 	} | ||||
| 	rc = __cifs_calc_signature(rqst, server, sigptr, | ||||
| 		&server->secmech.sdeschmacsha256->shash); | ||||
| 
 | ||||
| 	/* 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__); | ||||
| 
 | ||||
| 	memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); | ||||
| 	if (!rc) | ||||
| 		memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); | ||||
| 
 | ||||
| 	return rc; | ||||
| } | ||||
| @ -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; | ||||
| 
 | ||||
| @ -431,54 +386,12 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) | ||||
| 		cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__); | ||||
| 		return rc; | ||||
| 	} | ||||
| 	 | ||||
| 	rc = __cifs_calc_signature(rqst, server, sigptr, | ||||
| 				   &server->secmech.sdesccmacaes->shash); | ||||
| 
 | ||||
| 	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__); | ||||
| 
 | ||||
| 	memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); | ||||
| 	if (!rc) | ||||
| 		memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); | ||||
| 
 | ||||
| 	return rc; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user