The Samba-Bugzilla – Attachment 7408 Details for
Bug 8828
possible rc4 encryption error in Samba libraries
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
cifs client sspi signature generation code (with fixed constants)
cifsencrypt.c (text/plain), 7.67 KB, created by
shirishpargaonkar@gmail.com
on 2012-03-27 19:58:27 UTC
(
hide
)
Description:
cifs client sspi signature generation code (with fixed constants)
Filename:
MIME Type:
Creator:
shirishpargaonkar@gmail.com
Created:
2012-03-27 19:58:27 UTC
Size:
7.67 KB
patch
obsolete
> >static int >cifs_calc_sealsignature(const struct kvec *iov, int n_vec, > struct cifs_tcon *tcon, char *sealsign, enum sealdir dir) >{ > int i, rc; > u32 nvernum = NTLMSSP_SIGN_VERSION; > unsigned char sealsigncph[CIFS_HMAC_MD5_HASH_SIZE]; > struct scatterlist sg; > > if (!tcon->secmech.arc4) { > cERROR(1, "%s: Error: NULL rc4 encryption function", __func__); > return -1; > } > > if (!tcon->ses->server->secmech.sdeschmacmd5) { > cERROR(1, "%s: Can't generate signature\n", __func__); > return -1; > } > > /* generate hmac-md5 hash using client side sign key */ > if (dir == send) > rc = crypto_shash_setkey( > tcon->ses->server->secmech.hmacmd5, > tcon->clsignkey, CIFS_HMAC_MD5_HASH_SIZE); > else > rc = crypto_shash_setkey( > tcon->ses->server->secmech.hmacmd5, > tcon->srvsignkey, CIFS_HMAC_MD5_HASH_SIZE); > if (rc) { > cERROR(1, "%s: Could not set client signing key\n", __func__); > return rc; > } > > rc = crypto_shash_init(&tcon->ses->server->secmech.sdeschmacmd5->shash); > if (rc) { > cERROR(1, "%s: Could not init md5\n", __func__); > return rc; > } > > rc = crypto_shash_update( > &tcon->ses->server->secmech.sdeschmacmd5->shash, > (char *)&tcon->sequence_number, sizeof(__u32)); > if (rc) { > cERROR(1, "%s: Could not update with sequence #\n", __func__); > return rc; > } > > for (i = 0; i < n_vec; i++) { > if (iov[i].iov_len == 0) > continue; > if (iov[i].iov_base == NULL) { > cERROR(1, "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( > &tcon->ses->server->secmech.sdeschmacmd5->shash, > iov[i].iov_base + 8, iov[i].iov_len - 8); > } else { > rc = > crypto_shash_update( > &tcon->ses->server->secmech.sdeschmacmd5->shash, > iov[i].iov_base, iov[i].iov_len); > } > > if (rc) { > cERROR(1, "%s: Could not update with payload\n", > __func__); > return rc; > } > } > > rc = crypto_shash_final( > &tcon->ses->server->secmech.sdeschmacmd5->shash, sealsigncph); > if (rc) { > cERROR(1, "%s: Could not generate md5 hash\n", __func__); > return rc; > } > > /* encrypt/seal the hmac-md5 hash using client side seal key */ > if (dir == send) > rc = crypto_blkcipher_setkey(tcon->secmech.arc4, > tcon->clsealkey, CIFS_HMAC_MD5_HASH_SIZE); > else > rc = crypto_blkcipher_setkey(tcon->secmech.arc4, > tcon->srvsealkey, CIFS_HMAC_MD5_HASH_SIZE); > > if (rc) { > cERROR(1, "%s: Could not set response as a key", __func__); > return rc; > } > > // memcpy(sealsigncph, "abcdefgh", 8); > sg_init_one(&sg, sealsigncph, 8); > > cifs_dump_mem("XXX unenc seal sign", sealsigncph, 8); > rc = crypto_blkcipher_encrypt(&tcon->secmech.sdescarc4, > &sg, &sg, 8); > if (rc) { > cERROR(1, "%s: Error %d during seal sign ciphertext\n", > __func__, rc); > return rc; > } > cifs_dump_mem("XXX enc seal sign", sealsigncph, 8); > > /* SSPI signature consists of > version number + encrypted signature + tcon seq number > */ > memcpy(sealsign, &nvernum, 4); > memcpy(sealsign + 4, sealsigncph, 8); > memcpy(sealsign + 12, &tcon->sequence_number, 4); > > return rc; >} > >/* must be called with server->srv_mutex held */ >int >cifs_seal_smb(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, > __u32 *pexpected_response_sequence_number, > struct cifs_tcon *tcon) >{ > int i; > int rc = 0; > unsigned int pldlen = 0; > unsigned buflen; > struct scatterlist *sgin, *sgout; > char sealsign[CIFS_HMAC_MD5_HASH_SIZE]; > struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base; > unsigned char *niov; > > buflen = be32_to_cpu(cifs_pdu->smb_buf_length); > memcpy(iov[0].iov_base + 8, "jCIFS", 5); > iov[0].iov_len = 8 + 5; > buflen = 4 + 5; > cifs_pdu->smb_buf_length = cpu_to_be32(buflen); > buflen = be32_to_cpu(cifs_pdu->smb_buf_length); > cERROR(1, "%s: XXX iov[0].iov_len: %d buflen: %d\n", > __func__, iov[0].iov_len, buflen); > cifs_dump_mem("XXX iov[0]", iov[0].iov_base, iov[0].iov_len); > > rc = cifs_calc_sealsignature(iov, n_vec, tcon, sealsign, send); > if (rc) { > cERROR(1, "%s: Error %d generating seal signature\n", > __func__, rc); > return rc; > } > > /* generate the sealed message */ > if (!server->secmech.arc4) { > cERROR(1, "%s: Error: NULL rc4 encryption function", __func__); > return -ENOKEY; > } > > sgin = kmalloc(sizeof(struct scatterlist) * n_vec, GFP_KERNEL); > if (!sgin) { > cERROR(1, "%s: Can't allocate scatterlist memory", __func__); > return -ENOMEM; > } > > sgout = kmalloc(sizeof(struct scatterlist) * n_vec, GFP_KERNEL); > if (!sgout) { > cERROR(1, "%s: Can't allocate scatterlist memory", __func__); > return -ENOMEM; > } > > niov = kmalloc(iov[0].iov_len + 16, GFP_KERNEL); > if (!niov) { > cERROR(1, "%s: Can't allocate buffer memory", __func__); > return -ENOMEM; > } > > rc = crypto_blkcipher_setkey(tcon->secmech.arc4, > tcon->clsealkey, CIFS_HMAC_MD5_HASH_SIZE); > if (rc) { > cERROR(1, "%s: Could not set response as a key", __func__); > goto cifs_seal_msg_ret; > } > > for (i = 0; i < n_vec; i++) { > if (iov[i].iov_len == 0) > continue; > if (iov[i].iov_base == NULL) { > cERROR(1, "null iovec entry"); > rc = -EIO; > goto cifs_seal_msg_ret; > } > > /* 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 */ > sg_init_one(&sgin[i], > iov[i].iov_base + 8, iov[i].iov_len - 8); > sg_init_one(&sgout[i], > niov, iov[i].iov_len - 8); > } else { > sg_init_one(&sgin[i], iov[i].iov_base, iov[i].iov_len); > sg_init_one(&sgout[i], iov[i].iov_base, iov[i].iov_len); > } > } > pldlen = iov[0].iov_len - 8; > > rc = crypto_blkcipher_encrypt_iv(&tcon->secmech.sdescarc4, > sgout, sgin, pldlen); > if (rc) { > cERROR(1, "%s: Error %d encrypting smb signature\n", > __func__, rc); > goto cifs_seal_msg_ret; > } > > *(char *)(iov[0].iov_base + 4) = 0xFF; > *(char *)(iov[0].iov_base + 5) = 'E'; > *(char *)(iov[0].iov_base + 6) = 0x0; > *(char *)(iov[0].iov_base + 7) = 0x0; > > memcpy(iov[0].iov_base + 24, niov, iov[0].iov_len - 8); > memcpy(iov[0].iov_base + 8, sealsign, CIFS_HMAC_MD5_HASH_SIZE); > iov[0].iov_len += 16; > cifs_pdu->smb_buf_length = cpu_to_be32(buflen + 16); > > *pexpected_response_sequence_number = tcon->sequence_number++; > tcon->sequence_number++; > >cifs_seal_msg_ret: > kfree(sgin); > kfree(sgout); > kfree(niov); > > return rc; >} > >int >calc_seckey(struct cifs_ses *ses) >{ > int rc = 0; > struct scatterlist sgin, sgout; > unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */ > unsigned long long fixedkey1 = 0x0807060504030201; > unsigned long long fixedkey2 = 0x000f0e0d0c0b0a09; > > mutex_lock(&ses->server->srv_mutex); > if (!ses->server->secmech.arc4) { > rc = -ENOKEY; > cERROR(1, "%s: Error: NULL rc4 encryption function", __func__); > goto calc_seckey_ret; > } > > // get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE); > memcpy(sec_key, &fixedkey1, 8); > memcpy(sec_key + 8, &fixedkey2, 8); > > rc = crypto_blkcipher_setkey(ses->server->secmech.arc4, > ses->auth_key.response, CIFS_SESS_KEY_SIZE); > if (rc) { > cERROR(1, "%s: Could not set response as a key", __func__); > goto calc_seckey_ret; > } > > sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE); > sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); > > rc = crypto_blkcipher_encrypt(&ses->server->secmech.sdescarc4, > &sgout, &sgin, CIFS_CPHTXT_SIZE); > if (rc) { > cERROR(1, "could not encrypt session key rc: %d\n", rc); > goto calc_seckey_ret; > } > > /* make secondary_key/nonce as session key */ > memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE); > /* and make len as that of session key only */ > ses->auth_key.len = CIFS_SESS_KEY_SIZE; > >calc_seckey_ret: > mutex_unlock(&ses->server->srv_mutex); > return rc; >} >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 8828
: 7408