Skip to content

Commit

Permalink
Add: smb_cmac_aes_signature, smb_gmac_aes_signature
Browse files Browse the repository at this point in the history
For an easier handling of smb packets new functions the functions:
- smb_cmac_aes_signature,
- smb_gmac_aes_signature

got introduced for aes cmac and gmac handling.

To use the functions you need a 64 byte long buffer and a key (with
either 16 bytes for AES-129, 24 bytes for AES-192 or 32 bytes for
AES-256) both functions will return the packet including the first 16
bytes of the signature (therefore AES-128 should be prefered).

As an example you can create a `smb-packet-sign.nasl`:

```
key = "764efa883dda1e11";

neg_prot = raw_string( 0xfe, 0x53, 0x4d, 0x42 ); # Protocol Identifier
neg_prot += raw_string( 0x40, 0x00 ); # Structure Size
neg_prot += raw_string( 0x01, 0x00 ); # CreditCharge
neg_prot += raw_string( 0x00, 0x00, 0x00, 0x00 ); # Status
neg_prot += raw_string( 0x00, 0x00 ); # Negotiate Protocol Command
neg_prot += raw_string( 0x00, 0x00 ); # Credit Request
neg_prot += raw_string( 0x00, 0x00, 0x00, 0x00 ); # Flags
neg_prot += raw_string( 0x00, 0x00, 0x00, 0x00 ); # Next Command --> Compound Request
neg_prot += raw_string( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); # Message ID
neg_prot += raw_string( 0x00, 0x00, 0x00, 0x00 ); # Reserved
neg_prot += raw_string( 0x00, 0x00, 0x00, 0x00 ); # TreeID
neg_prot += raw_string( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42 ); # SessionID
neg_prot += raw_string( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); # Signature

neg_prot += raw_string( 0x42, 0x42 ); # Structure Size
neg_prot += raw_string( 0x04, 0x00 ); # Dialect Count
neg_prot += raw_string( 0x01, 0x00 ); # Security Mode
neg_prot += raw_string( 0x00, 0x00 ); # Reserved
neg_prot += raw_string( 0x00, 0x00, 0x00, 0x00 ); # Capabilities TBD add Encyrption
neg_prot += raw_string( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); # Client GUID
neg_prot += raw_string( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ); # Different depending on dialect
neg_prot += raw_string( 0x02, 0x02 ); # SMB 2.0.2
neg_prot += raw_string( 0x10, 0x02 ); # SMB 2.1
neg_prot += raw_string( 0x00, 0x03 ); # SMB 3.0
neg_prot += raw_string( 0x02, 0x03 ); # SMB 3.0.2

display("Original:");
display(hexstr(neg_prot));

display("SHA256 (cut to 16):");
sha256sig = get_smb2_signature( buf:neg_prot, key:key );
display(hexstr(sha256sig));

display("smb_cmac_aes_signature (128 => 16 keylen):");
cmac_aes = smb_cmac_aes_signature( buf:neg_prot, key:key );
display(hexstr(cmac_aes));

display("smb_gmac_aes_signature (128 => 16 keylen):");
gmac_aes = smb_cmac_aes_signature( buf:neg_prot, key:key );
display(hexstr(gmac_aes));
```

The corresponding hash will be between `4242`.
  • Loading branch information
nichtsfrei committed May 13, 2022
1 parent 375969a commit 45d777c
Show file tree
Hide file tree
Showing 8 changed files with 280 additions and 156 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ build/
nasl/nasl_grammar.output
nasl/nasl_grammar.tab.c
nasl/nasl_grammar.tab.h
.cache/
2 changes: 1 addition & 1 deletion nasl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ endif (NOT BISON_FOUND)
set (FILES arc4.c capture_packet.c charcnv.c exec.c genrand.c hmacmd5.c
iconv.c lint.c md4.c md5.c nasl.c nasl_builtin_find_service.c
nasl_builtin_openvas_tcp_scanner.c nasl_builtin_synscan.c
nasl_cmd_exec.c nasl_crypto2.c nasl_frame_forgery.c nasl_snmp.c nasl_ssh.c
nasl_cmd_exec.c nasl_crypt_helper.c nasl_crypto2.c nasl_frame_forgery.c nasl_snmp.c nasl_ssh.c
nasl_cert.c nasl_crypto.c nasl_debug.c nasl_func.c nasl_grammar.tab.c nasl_host.c
nasl_http.c nasl_init.c nasl_lex_ctxt.c nasl_misc_funcs.c nasl_scanner_glue.c
nasl_packet_forgery.c nasl_packet_forgery_v6.c nasl_signature.c nasl_smb.c
Expand Down
198 changes: 198 additions & 0 deletions nasl/nasl_crypt_helper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
#include "../misc//support.h"
#include "nasl_crypto_helper.h"
#include "nasl_debug.h"

#include <assert.h>
#include <ctype.h>
#include <gcrypt.h>
#include <glib.h>
#include <gpg-error.h>
#include <gvm/base/logging.h>
#include <stddef.h>
#include <stdlib.h>

void *
hmac_md5_for_prf (const void *key, int keylen, const void *buf, int buflen)
{
void *signature = g_malloc0 (16);
gsize signlen = 16;
GHmac *hmac;

hmac = g_hmac_new (G_CHECKSUM_MD5, key, keylen);
g_hmac_update (hmac, buf, buflen);
g_hmac_get_digest (hmac, signature, &signlen);
g_hmac_unref (hmac);
return signature;
}

void *
hmac_sha1 (const void *key, int keylen, const void *buf, int buflen)
{
void *signature = g_malloc0 (20);
gsize signlen = 20;
GHmac *hmac;

hmac = g_hmac_new (G_CHECKSUM_SHA1, key, keylen);
g_hmac_update (hmac, buf, buflen);
g_hmac_get_digest (hmac, signature, &signlen);
g_hmac_unref (hmac);
return signature;
}

void *
hmac_sha256 (const void *key, int keylen, const void *buf, int buflen)
{
void *signature = g_malloc0 (32);
gsize signlen = 32;
GHmac *hmac;

hmac = g_hmac_new (G_CHECKSUM_SHA256, key, keylen);
g_hmac_update (hmac, buf, buflen);
g_hmac_get_digest (hmac, signature, &signlen);
g_hmac_unref (hmac);
return signature;
}

void *
hmac_sha384 (const void *key, int keylen, const void *buf, int buflen)
{
gcry_md_hd_t hd;
gcry_error_t err;
void *ret;

if (!buf || buflen <= 0)
return NULL;

err = gcry_md_open (&hd, GCRY_MD_SHA384, key ? GCRY_MD_FLAG_HMAC : 0);
if (err)
{
g_message ("nasl_gcrypt_hash(): gcry_md_open failed: %s/%s",
gcry_strsource (err), gcry_strerror (err));
return NULL;
}

if (key)
{
err = gcry_md_setkey (hd, key, keylen);
if (err)
{
g_message ("nasl_gcrypt_hash(): gcry_md_setkey failed: %s/%s",
gcry_strsource (err), gcry_strerror (err));
return NULL;
}
}

gcry_md_write (hd, buf, buflen);
ret = g_memdup2 (gcry_md_read (hd, 0), 48);
gcry_md_close (hd);
return ret;
}

gpg_err_code_t
mac (const char *key, const size_t key_len, const char *data,
const size_t data_len, const char *iv, const size_t iv_len, int algo,
int flags, char **out, size_t *out_len)
{
// guardian
gpg_err_code_t result = 0;
gcry_mac_hd_t hd;
if (key == NULL || key_len < 1)
return GPG_ERR_MISSING_KEY;
if (data == NULL || data_len < 1)
return GPG_ERR_MISSING_VALUE;
if (out == NULL)
{
return GPG_ERR_GENERAL;
}
if ((result = gcry_mac_open (&hd, algo, flags, NULL)))
return result;
if ((result = gcry_mac_setkey (hd, key, key_len)))
goto cexit;
if (iv && (result = gcry_mac_setiv (hd, iv, iv_len)))
goto cexit;
if ((result = gcry_mac_write (hd, data, data_len)))
goto cexit;

*out_len = gcry_mac_get_algo_maclen (algo);
if ((*out = calloc (*out_len, sizeof (*out))) == NULL)
{
result = GPG_ERR_ENOMEM;
goto cexit;
}
if ((result = gcry_mac_read (hd, *out, out_len)))
goto cexit;

cexit:
gcry_mac_close (hd);
return result;
}

static gcry_error_t
smb_sign (const int algo, const char *key, const size_t key_len, char *buf,
const size_t buf_len, char **out)
{
gcry_error_t error = GPG_ERR_NO_ERROR;
char *signature = NULL;
size_t signature_len;
if (buf == NULL || buf_len < 64)
{
return GPG_ERR_NO_VALUE;
}
if (key == NULL || key_len < 16)
return GPG_ERR_NO_KEY;
memset ((char *) buf + 48, 0, 16);
switch (algo)
{
case GCRY_MAC_GMAC_AES:
case GCRY_MAC_CMAC_AES:
if ((error = mac (key, key_len, buf, buf_len, NULL, 0, algo,
GCRY_MAC_FLAG_SECURE, &signature, &signature_len)))
goto exit;
break;
case G_CHECKSUM_SHA256:
signature = hmac_sha256 (key, key_len, buf, buf_len);
break;
default:
// not defined;
error = GPG_ERR_UNKNOWN_ALGORITHM;
goto exit;
}
// TODO is 16 hard coded or should it be signature_len?
*out = g_malloc0 (buf_len);
memcpy (*out, buf, buf_len);
memcpy (*out + 48, signature, 16);
free (signature);
exit:
return error;
}

tree_cell *
nasl_smb_sign (const int algo, lex_ctxt *lexic)
{
char *key, *buf, *res;
int keylen, buflen;
gcry_error_t error;
tree_cell *retc = NULL;

key = get_str_var_by_name (lexic, "key");
buf = get_str_var_by_name (lexic, "buf");
keylen = get_var_size_by_name (lexic, "key");
buflen = get_var_size_by_name (lexic, "buf");

switch ((error = smb_sign (algo, key, keylen, buf, buflen, &res)))
{
case GPG_ERR_NO_ERROR:
retc = alloc_typed_cell (CONST_DATA);
retc->x.str_val = res;
retc->size = buflen;
break;
case GPG_ERR_MISSING_KEY:
case GPG_ERR_MISSING_VALUE:
nasl_perror (lexic, "Syntax: nasl_mac: Missing key, or data argument");
break;
default:
nasl_perror (lexic, "Internal: %s.", gcry_strerror (error));
}

return retc;
}
120 changes: 13 additions & 107 deletions nasl/nasl_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "../misc/support.h"
#include "exec.h"
#include "hmacmd5.h"
#include "nasl_crypto_helper.h"
#include "nasl_debug.h"
#include "nasl_func.h"
#include "nasl_global_ctxt.h"
Expand All @@ -44,6 +45,7 @@
#include <gcrypt.h>
#include <glib.h>
#include <gvm/base/logging.h>
#include <stddef.h>
#include <stdlib.h>

#ifndef uchar
Expand Down Expand Up @@ -276,83 +278,6 @@ nasl_get_sign (lex_ctxt *lexic)
return retc;
}

static void *
hmac_md5_for_prf (const void *key, int keylen, const void *buf, int buflen)
{
void *signature = g_malloc0 (16);
gsize signlen = 16;
GHmac *hmac;

hmac = g_hmac_new (G_CHECKSUM_MD5, key, keylen);
g_hmac_update (hmac, buf, buflen);
g_hmac_get_digest (hmac, signature, &signlen);
g_hmac_unref (hmac);
return signature;
}

static void *
hmac_sha1 (const void *key, int keylen, const void *buf, int buflen)
{
void *signature = g_malloc0 (20);
gsize signlen = 20;
GHmac *hmac;

hmac = g_hmac_new (G_CHECKSUM_SHA1, key, keylen);
g_hmac_update (hmac, buf, buflen);
g_hmac_get_digest (hmac, signature, &signlen);
g_hmac_unref (hmac);
return signature;
}

static void *
hmac_sha256 (const void *key, int keylen, const void *buf, int buflen)
{
void *signature = g_malloc0 (32);
gsize signlen = 32;
GHmac *hmac;

hmac = g_hmac_new (G_CHECKSUM_SHA256, key, keylen);
g_hmac_update (hmac, buf, buflen);
g_hmac_get_digest (hmac, signature, &signlen);
g_hmac_unref (hmac);
return signature;
}

static void *
hmac_sha384 (const void *key, int keylen, const void *buf, int buflen)
{
gcry_md_hd_t hd;
gcry_error_t err;
void *ret;

if (!buf || buflen <= 0)
return NULL;

err = gcry_md_open (&hd, GCRY_MD_SHA384, key ? GCRY_MD_FLAG_HMAC : 0);
if (err)
{
g_message ("nasl_gcrypt_hash(): gcry_md_open failed: %s/%s",
gcry_strsource (err), gcry_strerror (err));
return NULL;
}

if (key)
{
err = gcry_md_setkey (hd, key, keylen);
if (err)
{
g_message ("nasl_gcrypt_hash(): gcry_md_setkey failed: %s/%s",
gcry_strsource (err), gcry_strerror (err));
return NULL;
}
}

gcry_md_write (hd, buf, buflen);
ret = g_memdup2 (gcry_md_read (hd, 0), 48);
gcry_md_close (hd);
return ret;
}

tree_cell *
nasl_hmac_sha256 (lex_ctxt *lexic)
{
Expand Down Expand Up @@ -581,38 +506,19 @@ nasl_hmac_sha512 (lex_ctxt *lexic)
tree_cell *
nasl_get_smb2_sign (lex_ctxt *lexic)
{
void *key, *buf, *signature, *ret;
int keylen, buflen;
tree_cell *retc;

key = get_str_var_by_name (lexic, "key");
buf = get_str_var_by_name (lexic, "buf");
keylen = get_var_size_by_name (lexic, "key");
buflen = get_var_size_by_name (lexic, "buf");
if (!key || !buf || keylen <= 0)
{
nasl_perror (lexic, "Syntax : get_smb2_signature(buf:<b>, key:<k>)");
return NULL;
}
if (buflen < 64)
{
nasl_perror (lexic, "get_smb2_sign: Buffer length < 64");
return NULL;
}
return nasl_smb_sign (G_CHECKSUM_SHA256, lexic);
}

/* Zero the SMB2 signature field, then calculate signature */
memset ((char *) buf + 48, 0, 16);
signature = hmac_sha256 (key, keylen, buf, buflen);
tree_cell *
nasl_smb_cmac_aes_sign (lex_ctxt *lexic)
{
return nasl_smb_sign (GCRY_MAC_CMAC_AES, lexic);
}

/* Return the header with signature included. */
ret = g_malloc0 (buflen);
memcpy (ret, buf, buflen);
memcpy ((char *) ret + 48, signature, 16);
g_free (signature);
retc = alloc_typed_cell (CONST_DATA);
retc->size = buflen;
retc->x.str_val = (char *) ret;
return retc;
tree_cell *
nasl_smb_gmac_aes_sign (lex_ctxt *lexic)
{
return nasl_smb_sign (GCRY_MAC_GMAC_AES, lexic);
}

tree_cell *
Expand Down
6 changes: 6 additions & 0 deletions nasl/nasl_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ nasl_get_sign (lex_ctxt *lexic);
tree_cell *
nasl_get_smb2_sign (lex_ctxt *lexic);

tree_cell *
nasl_smb_cmac_aes_sign (lex_ctxt *lexic);

tree_cell *
nasl_smb_gmac_aes_sign (lex_ctxt *lexic);

tree_cell *
nasl_hmac_sha256 (lex_ctxt *lexic);

Expand Down
Loading

0 comments on commit 45d777c

Please sign in to comment.