summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2012-07-20 09:16:08 +0200
committerStefan Metzmacher <metze@samba.org>2012-07-23 18:19:36 +0200
commitfd736f7f18294aa1589aacd495b2a48bbaf8715c (patch)
tree8954676d1247719005d421dcba2f5b8a6f780f23
parent7e0982421b1e8b6a73ef67cdb085ffc60cd3b59b (diff)
downloadsamba-fd736f7f18294aa1589aacd495b2a48bbaf8715c.tar.gz
samba-fd736f7f18294aa1589aacd495b2a48bbaf8715c.tar.bz2
samba-fd736f7f18294aa1589aacd495b2a48bbaf8715c.zip
libcli/smb: add smb2_signing_[en|e]crypt_pdu()
metze
-rw-r--r--libcli/smb/smb2_signing.c132
-rw-r--r--libcli/smb/smb2_signing.h9
2 files changed, 141 insertions, 0 deletions
diff --git a/libcli/smb/smb2_signing.c b/libcli/smb/smb2_signing.c
index 43c9ba5c1c..bb621fd27e 100644
--- a/libcli/smb/smb2_signing.c
+++ b/libcli/smb/smb2_signing.c
@@ -207,3 +207,135 @@ void smb2_key_derivation(const uint8_t *KI, size_t KI_len,
memcpy(KO, digest, 16);
}
+
+NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key,
+ enum protocol_types protocol,
+ struct iovec *vector,
+ int count)
+{
+ uint8_t *tf;
+ uint16_t alg;
+ uint8_t sig[16];
+ int i;
+ size_t a_total;
+ size_t m_total = 0;
+ struct aes_ccm_128_context ctx;
+ uint8_t key[AES_BLOCK_SIZE];
+
+ if (count < 1) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ tf = (uint8_t *)vector[0].iov_base;
+
+ if (encryption_key.length == 0) {
+ DEBUG(2,("Wrong encryption key length %u for SMB2 signing\n",
+ (unsigned)encryption_key.length));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ alg = SMB2_ENCRYPTION_AES128_CCM;
+ SSVAL(tf, SMB2_TF_ALGORITHM, alg);
+
+ a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
+ for (i=1; i < count; i++) {
+ m_total += vector[i].iov_len;
+ }
+ ZERO_STRUCT(key);
+ memcpy(key, encryption_key.data,
+ MIN(encryption_key.length, AES_BLOCK_SIZE));
+ aes_ccm_128_init(&ctx, key,
+ tf + SMB2_TF_NONCE,
+ a_total, m_total);
+ aes_ccm_128_update(&ctx, tf + SMB2_TF_NONCE, a_total);
+ for (i=1; i < count; i++) {
+ aes_ccm_128_update(&ctx,
+ (const uint8_t *)vector[i].iov_base,
+ vector[i].iov_len);
+ }
+ for (i=1; i < count; i++) {
+ aes_ccm_128_crypt(&ctx,
+ (uint8_t *)vector[i].iov_base,
+ vector[i].iov_len);
+ }
+ aes_ccm_128_digest(&ctx, sig);
+
+ memcpy(tf + SMB2_TF_SIGNATURE, sig, 16);
+
+ DEBUG(5,("encrypt SMB2 message\n"));
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS smb2_signing_decrypt_pdu(DATA_BLOB decryption_key,
+ enum protocol_types protocol,
+ struct iovec *vector,
+ int count)
+{
+ uint8_t *tf;
+ uint16_t alg;
+ uint8_t *sig_ptr = NULL;
+ uint8_t sig[16];
+ int i;
+ size_t a_total;
+ size_t m_total = 0;
+ struct aes_ccm_128_context ctx;
+ uint8_t key[AES_BLOCK_SIZE];
+
+ if (count < 1) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (vector[0].iov_len != SMB2_TF_HDR_SIZE) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ tf = (uint8_t *)vector[0].iov_base;
+
+ if (decryption_key.length == 0) {
+ DEBUG(2,("Wrong decryption key length %u for SMB2 signing\n",
+ (unsigned)decryption_key.length));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ alg = SVAL(tf, SMB2_TF_ALGORITHM);
+ if (alg != SMB2_ENCRYPTION_AES128_CCM) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ a_total = SMB2_TF_HDR_SIZE - SMB2_TF_NONCE;
+ for (i=1; i < count; i++) {
+ m_total += vector[i].iov_len;
+ }
+ ZERO_STRUCT(key);
+ memcpy(key, decryption_key.data,
+ MIN(decryption_key.length, AES_BLOCK_SIZE));
+ aes_ccm_128_init(&ctx, key,
+ tf + SMB2_TF_NONCE,
+ a_total, m_total);
+ for (i=1; i < count; i++) {
+ aes_ccm_128_crypt(&ctx,
+ (uint8_t *)vector[i].iov_base,
+ vector[i].iov_len);
+ }
+ aes_ccm_128_update(&ctx, tf + SMB2_TF_NONCE, a_total);
+ for (i=1; i < count; i++) {
+ aes_ccm_128_update(&ctx,
+ ( uint8_t *)vector[i].iov_base,
+ vector[i].iov_len);
+ }
+ aes_ccm_128_digest(&ctx, sig);
+
+ sig_ptr = tf + SMB2_TF_SIGNATURE;
+ if (memcmp(sig_ptr, sig, 16) != 0) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ DEBUG(5,("decrypt SMB2 message\n"));
+
+ return NT_STATUS_OK;
+}
diff --git a/libcli/smb/smb2_signing.h b/libcli/smb/smb2_signing.h
index 200274ba6d..e8e2e6a718 100644
--- a/libcli/smb/smb2_signing.h
+++ b/libcli/smb/smb2_signing.h
@@ -38,4 +38,13 @@ void smb2_key_derivation(const uint8_t *KI, size_t KI_len,
const uint8_t *Context, size_t Context_len,
uint8_t KO[16]);
+NTSTATUS smb2_signing_encrypt_pdu(DATA_BLOB encryption_key,
+ enum protocol_types protocol,
+ struct iovec *vector,
+ int count);
+NTSTATUS smb2_signing_decrypt_pdu(DATA_BLOB decryption_key,
+ enum protocol_types protocol,
+ struct iovec *vector,
+ int count);
+
#endif /* _LIBCLI_SMB_SMB2_SIGNING_H_ */