aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorOlivier Verriest <verri@x25.pm>2017-07-30 14:07:43 +0000
committerAnders Broman <a.broman58@gmail.com>2017-08-04 05:57:20 +0000
commit97dcf87a868a51502e1ea6a90cd7a9ee3bbc59cf (patch)
tree515ca0088d46d38596809d6d4957ecff20ba7120 /epan
parentdc69a8446ee47fd6d38d4fb4416db89ef5487696 (diff)
SNMP: add support for USM SHA-2 algorithms (RFC 7860)
Generlize the USM handling and add support for HMAC-SHA-2 authentication protocols. Change-Id: I7cca2f24db61620423fded078c680322aff86400 Reviewed-on: https://code.wireshark.org/review/22846 Reviewed-by: Jaap Keuter <jaap.keuter@xs4all.nl> Petri-Dish: Jaap Keuter <jaap.keuter@xs4all.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan')
-rw-r--r--epan/dissectors/asn1/snmp/packet-snmp-template.c287
-rw-r--r--epan/dissectors/asn1/snmp/packet-snmp-template.h15
-rw-r--r--epan/dissectors/asn1/snmp/snmp.cnf6
-rw-r--r--epan/dissectors/packet-snmp.c303
-rw-r--r--epan/dissectors/packet-snmp.h15
5 files changed, 213 insertions, 413 deletions
diff --git a/epan/dissectors/asn1/snmp/packet-snmp-template.c b/epan/dissectors/asn1/snmp/packet-snmp-template.c
index 95f8e53066..79b433320d 100644
--- a/epan/dissectors/asn1/snmp/packet-snmp-template.c
+++ b/epan/dissectors/asn1/snmp/packet-snmp-template.c
@@ -89,28 +89,52 @@ void proto_reg_handoff_snmp(void);
void proto_register_smux(void);
void proto_reg_handoff_smux(void);
-static gboolean snmp_usm_auth_md5(snmp_usm_params_t* p, guint8**, guint*, gchar const**);
-static gboolean snmp_usm_auth_sha1(snmp_usm_params_t* p, guint8**, guint*, gchar const**);
+static void snmp_usm_password_to_key(const snmp_usm_auth_model_t model, const guint8 *password, guint passwordlen,
+ const guint8 *engineID, guint engineLength, guint8 *key);
static tvbuff_t* snmp_usm_priv_des(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
static tvbuff_t* snmp_usm_priv_aes128(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
static tvbuff_t* snmp_usm_priv_aes192(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
static tvbuff_t* snmp_usm_priv_aes256(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
+static gboolean snmp_usm_auth(const snmp_usm_auth_model_t model, snmp_usm_params_t* p, guint8**, guint*, gchar const**);
-static void snmp_usm_password_to_key_md5(const guint8 *password, guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key);
-static void snmp_usm_password_to_key_sha1(const guint8 *password, guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key);
+static const value_string auth_types[] = {
+ {SNMP_USM_AUTH_MD5,"MD5"},
+ {SNMP_USM_AUTH_SHA1,"SHA1"},
+ {SNMP_USM_AUTH_SHA2_224,"SHA2-224"},
+ {SNMP_USM_AUTH_SHA2_256,"SHA2-256"},
+ {SNMP_USM_AUTH_SHA2_384,"SHA2-384"},
+ {SNMP_USM_AUTH_SHA2_512,"SHA2-512"},
+ {0,NULL}
+};
+static const guint auth_hash_len[] = {
+ HASH_MD5_LENGTH,
+ HASH_SHA1_LENGTH,
+ HASH_SHA2_224_LENGTH,
+ HASH_SHA2_256_LENGTH,
+ HASH_SHA2_384_LENGTH,
+ HASH_SHA2_512_LENGTH
+};
-static snmp_usm_auth_model_t model_md5 = {snmp_usm_password_to_key_md5, snmp_usm_auth_md5, 16};
-static snmp_usm_auth_model_t model_sha1 = {snmp_usm_password_to_key_sha1, snmp_usm_auth_sha1, 20};
+static const guint auth_tag_len[] = {
+ 12,
+ 12,
+ 16,
+ 24,
+ 32,
+ 48
+};
-static const value_string auth_types[] = {
- {0,"MD5"},
- {1,"SHA1"},
- {0,NULL}
+static const enum gcry_md_algos auth_hash_algo[] = {
+ GCRY_MD_MD5,
+ GCRY_MD_SHA1,
+ GCRY_MD_SHA224,
+ GCRY_MD_SHA256,
+ GCRY_MD_SHA384,
+ GCRY_MD_SHA512
};
-static snmp_usm_auth_model_t* auth_models[] = {&model_md5,&model_sha1};
#define PRIV_DES 0
#define PRIV_AES128 1
@@ -1225,15 +1249,16 @@ dissect_snmp_engineid(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int o
static void set_ue_keys(snmp_ue_assoc_t* n ) {
- guint key_size = n->user.authModel->key_size;
+ guint key_size = auth_hash_len[n->user.authModel];
n->user.authKey.data = (guint8 *)g_malloc(key_size);
n->user.authKey.len = key_size;
- n->user.authModel->pass2key(n->user.authPassword.data,
- n->user.authPassword.len,
- n->engine.data,
- n->engine.len,
- n->user.authKey.data);
+ snmp_usm_password_to_key(n->user.authModel,
+ n->user.authPassword.data,
+ n->user.authPassword.len,
+ n->engine.data,
+ n->engine.len,
+ n->user.authKey.data);
if (n->priv_proto == PRIV_AES128 || n->priv_proto == PRIV_AES192 || n->priv_proto == PRIV_AES256) {
guint need_key_len =
@@ -1250,22 +1275,23 @@ static void set_ue_keys(snmp_ue_assoc_t* n ) {
n->user.privKey.data = (guint8 *)g_malloc(key_len);
n->user.privKey.len = need_key_len;
- n->user.authModel->pass2key(n->user.privPassword.data,
- n->user.privPassword.len,
- n->engine.data,
- n->engine.len,
- n->user.privKey.data);
+ snmp_usm_password_to_key(n->user.authModel,
+ n->user.privPassword.data,
+ n->user.privPassword.len,
+ n->engine.data,
+ n->engine.len,
+ n->user.privKey.data);
key_len = key_size;
/* extend key if needed */
while (key_len < need_key_len) {
- n->user.authModel->pass2key(
- n->user.privKey.data,
- key_len,
- n->engine.data,
- n->engine.len,
- n->user.privKey.data + key_len);
+ snmp_usm_password_to_key(n->user.authModel,
+ n->user.privKey.data,
+ key_len,
+ n->engine.data,
+ n->engine.len,
+ n->user.privKey.data + key_len);
key_len += key_size;
}
@@ -1273,11 +1299,12 @@ static void set_ue_keys(snmp_ue_assoc_t* n ) {
} else {
n->user.privKey.data = (guint8 *)g_malloc(key_size);
n->user.privKey.len = key_size;
- n->user.authModel->pass2key(n->user.privPassword.data,
- n->user.privPassword.len,
- n->engine.data,
- n->engine.len,
- n->user.privKey.data);
+ snmp_usm_password_to_key(n->user.authModel,
+ n->user.privPassword.data,
+ n->user.privPassword.len,
+ n->engine.data,
+ n->engine.len,
+ n->user.privKey.data);
}
}
@@ -1317,7 +1344,7 @@ snmp_users_copy_cb(void* dest, const void* orig, size_t len _U_)
snmp_ue_assoc_t* d = (snmp_ue_assoc_t*)dest;
d->auth_model = o->auth_model;
- d->user.authModel = auth_models[o->auth_model];
+ d->user.authModel = (snmp_usm_auth_model_t) o->auth_model;
d->priv_proto = o->priv_proto;
d->user.privProtocol = priv_protos[o->priv_proto];
@@ -1520,7 +1547,8 @@ get_user_assoc(tvbuff_t* engine_tvb, tvbuff_t* user_tvb)
}
static gboolean
-snmp_usm_auth_md5(snmp_usm_params_t* p, guint8** calc_auth_p, guint* calc_auth_len_p, gchar const** error)
+snmp_usm_auth(const snmp_usm_auth_model_t model, snmp_usm_params_t* p, guint8** calc_auth_p,
+ guint* calc_auth_len_p, gchar const** error)
{
gint msg_len;
guint8* msg;
@@ -1546,10 +1574,9 @@ snmp_usm_auth_md5(snmp_usm_params_t* p, guint8** calc_auth_p, guint* calc_auth_l
return FALSE;
}
-
auth_len = tvb_captured_length(p->auth_tvb);
- if (auth_len != 12) {
+ if (auth_len != auth_tag_len[model]) {
*error = "Authenticator length wrong";
return FALSE;
}
@@ -1561,93 +1588,26 @@ snmp_usm_auth_md5(snmp_usm_params_t* p, guint8** calc_auth_p, guint* calc_auth_l
}
msg = (guint8*)tvb_memdup(wmem_packet_scope(),p->msg_tvb,0,msg_len);
-
auth = (guint8*)tvb_memdup(wmem_packet_scope(),p->auth_tvb,0,auth_len);
start = p->auth_offset - p->start_offset;
- end = start + auth_len;
+ end = start + auth_len;
/* fill the authenticator with zeros */
for ( i = start ; i < end ; i++ ) {
msg[i] = '\0';
}
- calc_auth = (guint8*)wmem_alloc(wmem_packet_scope(), HASH_MD5_LENGTH);
+ calc_auth = (guint8*)wmem_alloc(wmem_packet_scope(), auth_hash_len[model]);
- if (ws_hmac_buffer(GCRY_MD_MD5, calc_auth, msg, msg_len, key, key_len)) {
+ if (ws_hmac_buffer(auth_hash_algo[model], calc_auth, msg, msg_len, key, key_len)) {
return FALSE;
}
if (calc_auth_p) *calc_auth_p = calc_auth;
- if (calc_auth_len_p) *calc_auth_len_p = 12;
+ if (calc_auth_len_p) *calc_auth_len_p = auth_len;
- return ( memcmp(auth,calc_auth,12) != 0 ) ? FALSE : TRUE;
-}
-
-
-static gboolean
-snmp_usm_auth_sha1(snmp_usm_params_t* p _U_, guint8** calc_auth_p, guint* calc_auth_len_p, gchar const** error _U_)
-{
- gint msg_len;
- guint8* msg;
- guint auth_len;
- guint8* auth;
- guint8* key;
- guint key_len;
- guint8 *calc_auth;
- guint start;
- guint end;
- guint i;
-
- if (!p->auth_tvb) {
- *error = "No Authenticator";
- return FALSE;
- }
-
- key = p->user_assoc->user.authKey.data;
- key_len = p->user_assoc->user.authKey.len;
-
- if (! key ) {
- *error = "User has no authKey";
- return FALSE;
- }
-
-
- auth_len = tvb_captured_length(p->auth_tvb);
-
-
- if (auth_len != 12) {
- *error = "Authenticator length wrong";
- return FALSE;
- }
-
- msg_len = tvb_captured_length(p->msg_tvb);
- if (msg_len <= 0) {
- *error = "Not enough data remaining";
- return FALSE;
- }
- msg = (guint8*)tvb_memdup(wmem_packet_scope(),p->msg_tvb,0,msg_len);
-
- auth = (guint8*)tvb_memdup(wmem_packet_scope(),p->auth_tvb,0,auth_len);
-
- start = p->auth_offset - p->start_offset;
- end = start + auth_len;
-
- /* fill the authenticator with zeros */
- for ( i = start ; i < end ; i++ ) {
- msg[i] = '\0';
- }
-
- calc_auth = (guint8*)wmem_alloc(wmem_packet_scope(), HASH_SHA1_LENGTH);
-
- if (ws_hmac_buffer(GCRY_MD_SHA1, calc_auth, msg, msg_len, key, key_len)) {
- return FALSE;
- }
-
- if (calc_auth_p) *calc_auth_p = calc_auth;
- if (calc_auth_len_p) *calc_auth_len_p = 12;
-
- return ( memcmp(auth,calc_auth,12) != 0 ) ? FALSE : TRUE;
+ return ( memcmp(auth,calc_auth,auth_len) != 0 ) ? FALSE : TRUE;
}
static tvbuff_t*
@@ -2122,86 +2082,26 @@ dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
return dissect_SMUX_PDUs_PDU(tvb, pinfo, smux_tree, data);
}
-
/*
- MD5 Password to Key Algorithm
- from RFC 3414 A.2.1
+ MD5 Password to Key Algorithm from RFC 3414 A.2.1
+ SHA1 Password to Key Algorithm from RFC 3414 A.2.2
+ SHA2 Password to Key Algorithm from RFC 7860 9.3
*/
static void
-snmp_usm_password_to_key_md5(const guint8 *password, guint passwordlen,
- const guint8 *engineID, guint engineLength,
- guint8 *key)
+snmp_usm_password_to_key(const snmp_usm_auth_model_t model, const guint8 *password,
+ guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key)
{
- guint8 *cp, password_buf[64];
- guint32 password_index = 0;
- guint32 count = 0, i;
- guint8 key1[16];
- gcry_md_hd_t md5_handle;
- if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
- return;
- }
+ gcry_md_hd_t hash_handle;
+ guint8 *cp, password_buf[64];
+ guint32 password_index = 0;
+ guint32 count = 0, i;
+ guint hash_len;
- /**********************************************/
- /* Use while loop until we've done 1 Megabyte */
- /**********************************************/
- while (count < 1048576) {
- cp = password_buf;
- if (passwordlen != 0) {
- for (i = 0; i < 64; i++) {
- /*************************************************/
- /* Take the next octet of the password, wrapping */
- /* to the beginning of the password as necessary.*/
- /*************************************************/
- *cp++ = password[password_index++ % passwordlen];
- }
- } else {
- *cp = 0;
- }
- gcry_md_write(md5_handle, password_buf, 64);
- count += 64;
- }
- memcpy(key1, gcry_md_read(md5_handle, 0), HASH_MD5_LENGTH);
- gcry_md_close(md5_handle);
-
- /*****************************************************/
- /* Now localize the key with the engineID and pass */
- /* through MD5 to produce final key */
- /* We ignore invalid engineLengths here. More strict */
- /* checking is done in snmp_users_update_cb. */
- /*****************************************************/
-
- if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
+ if (gcry_md_open(&hash_handle, auth_hash_algo[model], 0)) {
return;
}
- gcry_md_write(md5_handle, key1, HASH_MD5_LENGTH);
- gcry_md_write(md5_handle, engineID, engineLength);
- gcry_md_write(md5_handle, key1, HASH_MD5_LENGTH);
- memcpy(key, gcry_md_read(md5_handle, 0), HASH_MD5_LENGTH);
- gcry_md_close(md5_handle);
-
- return;
-}
-
-
-
-/*
- SHA1 Password to Key Algorithm COPIED from RFC 3414 A.2.2
- */
-
-static void
-snmp_usm_password_to_key_sha1(const guint8 *password, guint passwordlen,
- const guint8 *engineID, guint engineLength,
- guint8 *key)
-{
- gcry_md_hd_t sha1_handle;
- guint8 *cp, password_buf[64];
- guint32 password_index = 0;
- guint32 count = 0, i;
-
- if (gcry_md_open(&sha1_handle, GCRY_MD_SHA1, 0)) {
- return;
- }
+ hash_len = auth_hash_len[model];
/**********************************************/
/* Use while loop until we've done 1 Megabyte */
@@ -2219,29 +2119,28 @@ snmp_usm_password_to_key_sha1(const guint8 *password, guint passwordlen,
} else {
*cp = 0;
}
- gcry_md_write(sha1_handle, password_buf, 64);
+ gcry_md_write(hash_handle, password_buf, 64);
count += 64;
}
- memcpy(key, gcry_md_read(sha1_handle, 0), HASH_SHA1_LENGTH);
- gcry_md_close(sha1_handle);
+ memcpy(key, gcry_md_read(hash_handle, 0), hash_len);
+ gcry_md_close(hash_handle);
/*****************************************************/
- /* Now localize the key with the engineID and pass */
- /* through SHA to produce final key */
+ /* Now localise the key with the engineID and pass */
+ /* through hash function to produce final key */
/* We ignore invalid engineLengths here. More strict */
/* checking is done in snmp_users_update_cb. */
/*****************************************************/
- if (gcry_md_open(&sha1_handle, GCRY_MD_SHA1, 0)) {
+ if (gcry_md_open(&hash_handle, auth_hash_algo[model], 0)) {
return;
}
- gcry_md_write(sha1_handle, key, HASH_SHA1_LENGTH);
- gcry_md_write(sha1_handle, engineID, engineLength);
- gcry_md_write(sha1_handle, key, HASH_SHA1_LENGTH);
- memcpy(key, gcry_md_read(sha1_handle, 0), HASH_SHA1_LENGTH);
- gcry_md_close(sha1_handle);
+ gcry_md_write(hash_handle, key, hash_len);
+ gcry_md_write(hash_handle, engineID, engineLength);
+ gcry_md_write(hash_handle, key, hash_len);
+ memcpy(key, gcry_md_read(hash_handle, 0), hash_len);
+ gcry_md_close(hash_handle);
return;
- }
-
+}
static void
process_prefs(void)
diff --git a/epan/dissectors/asn1/snmp/packet-snmp-template.h b/epan/dissectors/asn1/snmp/packet-snmp-template.h
index 808b078406..0b516a384a 100644
--- a/epan/dissectors/asn1/snmp/packet-snmp-template.h
+++ b/epan/dissectors/asn1/snmp/packet-snmp-template.h
@@ -31,20 +31,21 @@ typedef struct _snmp_usm_key {
typedef struct _snmp_ue_assoc_t snmp_ue_assoc_t;
typedef struct _snmp_usm_params_t snmp_usm_params_t;
-typedef gboolean (*snmp_usm_authenticator_t)(snmp_usm_params_t*, guint8** calc_auth, guint* calc_auth_len, gchar const** error);
typedef tvbuff_t* (*snmp_usm_decoder_t)(snmp_usm_params_t*, tvbuff_t* encryptedData, packet_info *pinfo, gchar const** error);
-typedef void (*snmp_usm_password_to_key_t)(const guint8 *password, guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key);
-typedef struct _snmp_usm_auth_model_t {
- snmp_usm_password_to_key_t pass2key;
- snmp_usm_authenticator_t authenticate;
- guint key_size;
+typedef enum _snmp_usm_auth_model_t {
+ SNMP_USM_AUTH_MD5 = 0,
+ SNMP_USM_AUTH_SHA1,
+ SNMP_USM_AUTH_SHA2_224,
+ SNMP_USM_AUTH_SHA2_256,
+ SNMP_USM_AUTH_SHA2_384,
+ SNMP_USM_AUTH_SHA2_512
} snmp_usm_auth_model_t;
typedef struct _snmp_user_t {
snmp_usm_key_t userName;
- snmp_usm_auth_model_t* authModel;
+ snmp_usm_auth_model_t authModel;
snmp_usm_key_t authPassword;
snmp_usm_key_t authKey;
diff --git a/epan/dissectors/asn1/snmp/snmp.cnf b/epan/dissectors/asn1/snmp/snmp.cnf
index ee9dba9326..b717d06d83 100644
--- a/epan/dissectors/asn1/snmp/snmp.cnf
+++ b/epan/dissectors/asn1/snmp/snmp.cnf
@@ -186,10 +186,10 @@ gint pdu_type=-1;
const gchar* error = NULL;
proto_item* authen_item;
proto_tree* authen_tree = proto_item_add_subtree(usm_p.auth_item,ett_authParameters);
- guint8* calc_auth;
- guint calc_auth_len;
+ guint8* calc_auth = NULL;
+ guint calc_auth_len = 0;
- usm_p.authOK = usm_p.user_assoc->user.authModel->authenticate( &usm_p, &calc_auth, &calc_auth_len, &error );
+ usm_p.authOK = snmp_usm_auth(usm_p.user_assoc->user.authModel, &usm_p, &calc_auth, &calc_auth_len, &error );
if (error) {
expert_add_info_format( actx->pinfo, usm_p.auth_item, &ei_snmp_verify_authentication_error, "Error while verifying Message authenticity: %s", error );
diff --git a/epan/dissectors/packet-snmp.c b/epan/dissectors/packet-snmp.c
index 55f08ca6a4..82f91813a5 100644
--- a/epan/dissectors/packet-snmp.c
+++ b/epan/dissectors/packet-snmp.c
@@ -97,28 +97,52 @@ void proto_reg_handoff_snmp(void);
void proto_register_smux(void);
void proto_reg_handoff_smux(void);
-static gboolean snmp_usm_auth_md5(snmp_usm_params_t* p, guint8**, guint*, gchar const**);
-static gboolean snmp_usm_auth_sha1(snmp_usm_params_t* p, guint8**, guint*, gchar const**);
+static void snmp_usm_password_to_key(const snmp_usm_auth_model_t model, const guint8 *password, guint passwordlen,
+ const guint8 *engineID, guint engineLength, guint8 *key);
static tvbuff_t* snmp_usm_priv_des(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
static tvbuff_t* snmp_usm_priv_aes128(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
static tvbuff_t* snmp_usm_priv_aes192(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
static tvbuff_t* snmp_usm_priv_aes256(snmp_usm_params_t*, tvbuff_t*, packet_info *pinfo, gchar const**);
+static gboolean snmp_usm_auth(const snmp_usm_auth_model_t model, snmp_usm_params_t* p, guint8**, guint*, gchar const**);
-static void snmp_usm_password_to_key_md5(const guint8 *password, guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key);
-static void snmp_usm_password_to_key_sha1(const guint8 *password, guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key);
+static const value_string auth_types[] = {
+ {SNMP_USM_AUTH_MD5,"MD5"},
+ {SNMP_USM_AUTH_SHA1,"SHA1"},
+ {SNMP_USM_AUTH_SHA2_224,"SHA2-224"},
+ {SNMP_USM_AUTH_SHA2_256,"SHA2-256"},
+ {SNMP_USM_AUTH_SHA2_384,"SHA2-384"},
+ {SNMP_USM_AUTH_SHA2_512,"SHA2-512"},
+ {0,NULL}
+};
+static const guint auth_hash_len[] = {
+ HASH_MD5_LENGTH,
+ HASH_SHA1_LENGTH,
+ HASH_SHA2_224_LENGTH,
+ HASH_SHA2_256_LENGTH,
+ HASH_SHA2_384_LENGTH,
+ HASH_SHA2_512_LENGTH
+};
-static snmp_usm_auth_model_t model_md5 = {snmp_usm_password_to_key_md5, snmp_usm_auth_md5, 16};
-static snmp_usm_auth_model_t model_sha1 = {snmp_usm_password_to_key_sha1, snmp_usm_auth_sha1, 20};
+static const guint auth_tag_len[] = {
+ 12,
+ 12,
+ 16,
+ 24,
+ 32,
+ 48
+};
-static const value_string auth_types[] = {
- {0,"MD5"},
- {1,"SHA1"},
- {0,NULL}
+static const enum gcry_md_algos auth_hash_algo[] = {
+ GCRY_MD_MD5,
+ GCRY_MD_SHA1,
+ GCRY_MD_SHA224,
+ GCRY_MD_SHA256,
+ GCRY_MD_SHA384,
+ GCRY_MD_SHA512
};
-static snmp_usm_auth_model_t* auth_models[] = {&model_md5,&model_sha1};
#define PRIV_DES 0
#define PRIV_AES128 1
@@ -291,7 +315,7 @@ static int hf_snmp_priority = -1; /* INTEGER_M1_2147483647 */
static int hf_snmp_operation = -1; /* T_operation */
/*--- End of included file: packet-snmp-hf.c ---*/
-#line 217 "./asn1/snmp/packet-snmp-template.c"
+#line 241 "./asn1/snmp/packet-snmp-template.c"
/* Initialize the subtree pointers */
static gint ett_smux = -1;
@@ -331,7 +355,7 @@ static gint ett_snmp_SimpleOpen_U = -1;
static gint ett_snmp_RReqPDU_U = -1;
/*--- End of included file: packet-snmp-ett.c ---*/
-#line 233 "./asn1/snmp/packet-snmp-template.c"
+#line 257 "./asn1/snmp/packet-snmp-template.c"
static expert_field ei_snmp_failed_decrypted_data_pdu = EI_INIT;
static expert_field ei_snmp_decrypted_data_bad_formatted = EI_INIT;
@@ -1327,15 +1351,16 @@ dissect_snmp_engineid(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int o
static void set_ue_keys(snmp_ue_assoc_t* n ) {
- guint key_size = n->user.authModel->key_size;
+ guint key_size = auth_hash_len[n->user.authModel];
n->user.authKey.data = (guint8 *)g_malloc(key_size);
n->user.authKey.len = key_size;
- n->user.authModel->pass2key(n->user.authPassword.data,
- n->user.authPassword.len,
- n->engine.data,
- n->engine.len,
- n->user.authKey.data);
+ snmp_usm_password_to_key(n->user.authModel,
+ n->user.authPassword.data,
+ n->user.authPassword.len,
+ n->engine.data,
+ n->engine.len,
+ n->user.authKey.data);
if (n->priv_proto == PRIV_AES128 || n->priv_proto == PRIV_AES192 || n->priv_proto == PRIV_AES256) {
guint need_key_len =
@@ -1352,22 +1377,23 @@ static void set_ue_keys(snmp_ue_assoc_t* n ) {
n->user.privKey.data = (guint8 *)g_malloc(key_len);
n->user.privKey.len = need_key_len;
- n->user.authModel->pass2key(n->user.privPassword.data,
- n->user.privPassword.len,
- n->engine.data,
- n->engine.len,
- n->user.privKey.data);
+ snmp_usm_password_to_key(n->user.authModel,
+ n->user.privPassword.data,
+ n->user.privPassword.len,
+ n->engine.data,
+ n->engine.len,
+ n->user.privKey.data);
key_len = key_size;
/* extend key if needed */
while (key_len < need_key_len) {
- n->user.authModel->pass2key(
- n->user.privKey.data,
- key_len,
- n->engine.data,
- n->engine.len,
- n->user.privKey.data + key_len);
+ snmp_usm_password_to_key(n->user.authModel,
+ n->user.privKey.data,
+ key_len,
+ n->engine.data,
+ n->engine.len,
+ n->user.privKey.data + key_len);
key_len += key_size;
}
@@ -1375,11 +1401,12 @@ static void set_ue_keys(snmp_ue_assoc_t* n ) {
} else {
n->user.privKey.data = (guint8 *)g_malloc(key_size);
n->user.privKey.len = key_size;
- n->user.authModel->pass2key(n->user.privPassword.data,
- n->user.privPassword.len,
- n->engine.data,
- n->engine.len,
- n->user.privKey.data);
+ snmp_usm_password_to_key(n->user.authModel,
+ n->user.privPassword.data,
+ n->user.privPassword.len,
+ n->engine.data,
+ n->engine.len,
+ n->user.privKey.data);
}
}
@@ -1419,7 +1446,7 @@ snmp_users_copy_cb(void* dest, const void* orig, size_t len _U_)
snmp_ue_assoc_t* d = (snmp_ue_assoc_t*)dest;
d->auth_model = o->auth_model;
- d->user.authModel = auth_models[o->auth_model];
+ d->user.authModel = (snmp_usm_auth_model_t) o->auth_model;
d->priv_proto = o->priv_proto;
d->user.privProtocol = priv_protos[o->priv_proto];
@@ -1622,7 +1649,8 @@ get_user_assoc(tvbuff_t* engine_tvb, tvbuff_t* user_tvb)
}
static gboolean
-snmp_usm_auth_md5(snmp_usm_params_t* p, guint8** calc_auth_p, guint* calc_auth_len_p, gchar const** error)
+snmp_usm_auth(const snmp_usm_auth_model_t model, snmp_usm_params_t* p, guint8** calc_auth_p,
+ guint* calc_auth_len_p, gchar const** error)
{
gint msg_len;
guint8* msg;
@@ -1648,10 +1676,9 @@ snmp_usm_auth_md5(snmp_usm_params_t* p, guint8** calc_auth_p, guint* calc_auth_l
return FALSE;
}
-
auth_len = tvb_captured_length(p->auth_tvb);
- if (auth_len != 12) {
+ if (auth_len != auth_tag_len[model]) {
*error = "Authenticator length wrong";
return FALSE;
}
@@ -1663,93 +1690,26 @@ snmp_usm_auth_md5(snmp_usm_params_t* p, guint8** calc_auth_p, guint* calc_auth_l
}
msg = (guint8*)tvb_memdup(wmem_packet_scope(),p->msg_tvb,0,msg_len);
-
auth = (guint8*)tvb_memdup(wmem_packet_scope(),p->auth_tvb,0,auth_len);
start = p->auth_offset - p->start_offset;
- end = start + auth_len;
+ end = start + auth_len;
/* fill the authenticator with zeros */
for ( i = start ; i < end ; i++ ) {
msg[i] = '\0';
}
- calc_auth = (guint8*)wmem_alloc(wmem_packet_scope(), HASH_MD5_LENGTH);
+ calc_auth = (guint8*)wmem_alloc(wmem_packet_scope(), auth_hash_len[model]);
- if (ws_hmac_buffer(GCRY_MD_MD5, calc_auth, msg, msg_len, key, key_len)) {
+ if (ws_hmac_buffer(auth_hash_algo[model], calc_auth, msg, msg_len, key, key_len)) {
return FALSE;
}
if (calc_auth_p) *calc_auth_p = calc_auth;
- if (calc_auth_len_p) *calc_auth_len_p = 12;
+ if (calc_auth_len_p) *calc_auth_len_p = auth_len;
- return ( memcmp(auth,calc_auth,12) != 0 ) ? FALSE : TRUE;
-}
-
-
-static gboolean
-snmp_usm_auth_sha1(snmp_usm_params_t* p _U_, guint8** calc_auth_p, guint* calc_auth_len_p, gchar const** error _U_)
-{
- gint msg_len;
- guint8* msg;
- guint auth_len;
- guint8* auth;
- guint8* key;
- guint key_len;
- guint8 *calc_auth;
- guint start;
- guint end;
- guint i;
-
- if (!p->auth_tvb) {
- *error = "No Authenticator";
- return FALSE;
- }
-
- key = p->user_assoc->user.authKey.data;
- key_len = p->user_assoc->user.authKey.len;
-
- if (! key ) {
- *error = "User has no authKey";
- return FALSE;
- }
-
-
- auth_len = tvb_captured_length(p->auth_tvb);
-
-
- if (auth_len != 12) {
- *error = "Authenticator length wrong";
- return FALSE;
- }
-
- msg_len = tvb_captured_length(p->msg_tvb);
- if (msg_len <= 0) {
- *error = "Not enough data remaining";
- return FALSE;
- }
- msg = (guint8*)tvb_memdup(wmem_packet_scope(),p->msg_tvb,0,msg_len);
-
- auth = (guint8*)tvb_memdup(wmem_packet_scope(),p->auth_tvb,0,auth_len);
-
- start = p->auth_offset - p->start_offset;
- end = start + auth_len;
-
- /* fill the authenticator with zeros */
- for ( i = start ; i < end ; i++ ) {
- msg[i] = '\0';
- }
-
- calc_auth = (guint8*)wmem_alloc(wmem_packet_scope(), HASH_SHA1_LENGTH);
-
- if (ws_hmac_buffer(GCRY_MD_SHA1, calc_auth, msg, msg_len, key, key_len)) {
- return FALSE;
- }
-
- if (calc_auth_p) *calc_auth_p = calc_auth;
- if (calc_auth_len_p) *calc_auth_len_p = 12;
-
- return ( memcmp(auth,calc_auth,12) != 0 ) ? FALSE : TRUE;
+ return ( memcmp(auth,calc_auth,auth_len) != 0 ) ? FALSE : TRUE;
}
static tvbuff_t*
@@ -2742,10 +2702,10 @@ dissect_snmp_SNMPv3Message(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int off
const gchar* error = NULL;
proto_item* authen_item;
proto_tree* authen_tree = proto_item_add_subtree(usm_p.auth_item,ett_authParameters);
- guint8* calc_auth;
- guint calc_auth_len;
+ guint8* calc_auth = NULL;
+ guint calc_auth_len = 0;
- usm_p.authOK = usm_p.user_assoc->user.authModel->authenticate( &usm_p, &calc_auth, &calc_auth_len, &error );
+ usm_p.authOK = snmp_usm_auth(usm_p.user_assoc->user.authModel, &usm_p, &calc_auth, &calc_auth_len, &error );
if (error) {
expert_add_info_format( actx->pinfo, usm_p.auth_item, &ei_snmp_verify_authentication_error, "Error while verifying Message authenticity: %s", error );
@@ -3048,7 +3008,7 @@ static int dissect_SMUX_PDUs_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, prot
/*--- End of included file: packet-snmp-fn.c ---*/
-#line 1843 "./asn1/snmp/packet-snmp-template.c"
+#line 1803 "./asn1/snmp/packet-snmp-template.c"
guint
@@ -3331,86 +3291,26 @@ dissect_smux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
return dissect_SMUX_PDUs_PDU(tvb, pinfo, smux_tree, data);
}
-
/*
- MD5 Password to Key Algorithm
- from RFC 3414 A.2.1
+ MD5 Password to Key Algorithm from RFC 3414 A.2.1
+ SHA1 Password to Key Algorithm from RFC 3414 A.2.2
+ SHA2 Password to Key Algorithm from RFC 7860 9.3
*/
static void
-snmp_usm_password_to_key_md5(const guint8 *password, guint passwordlen,
- const guint8 *engineID, guint engineLength,
- guint8 *key)
+snmp_usm_password_to_key(const snmp_usm_auth_model_t model, const guint8 *password,
+ guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key)
{
- guint8 *cp, password_buf[64];
- guint32 password_index = 0;
- guint32 count = 0, i;
- guint8 key1[16];
- gcry_md_hd_t md5_handle;
- if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
- return;
- }
+ gcry_md_hd_t hash_handle;
+ guint8 *cp, password_buf[64];
+ guint32 password_index = 0;
+ guint32 count = 0, i;
+ guint hash_len;
- /**********************************************/
- /* Use while loop until we've done 1 Megabyte */
- /**********************************************/
- while (count < 1048576) {
- cp = password_buf;
- if (passwordlen != 0) {
- for (i = 0; i < 64; i++) {
- /*************************************************/
- /* Take the next octet of the password, wrapping */
- /* to the beginning of the password as necessary.*/
- /*************************************************/
- *cp++ = password[password_index++ % passwordlen];
- }
- } else {
- *cp = 0;
- }
- gcry_md_write(md5_handle, password_buf, 64);
- count += 64;
- }
- memcpy(key1, gcry_md_read(md5_handle, 0), HASH_MD5_LENGTH);
- gcry_md_close(md5_handle);
-
- /*****************************************************/
- /* Now localize the key with the engineID and pass */
- /* through MD5 to produce final key */
- /* We ignore invalid engineLengths here. More strict */
- /* checking is done in snmp_users_update_cb. */
- /*****************************************************/
-
- if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
+ if (gcry_md_open(&hash_handle, auth_hash_algo[model], 0)) {
return;
}
- gcry_md_write(md5_handle, key1, HASH_MD5_LENGTH);
- gcry_md_write(md5_handle, engineID, engineLength);
- gcry_md_write(md5_handle, key1, HASH_MD5_LENGTH);
- memcpy(key, gcry_md_read(md5_handle, 0), HASH_MD5_LENGTH);
- gcry_md_close(md5_handle);
-
- return;
-}
-
-
-
-/*
- SHA1 Password to Key Algorithm COPIED from RFC 3414 A.2.2
- */
-
-static void
-snmp_usm_password_to_key_sha1(const guint8 *password, guint passwordlen,
- const guint8 *engineID, guint engineLength,
- guint8 *key)
-{
- gcry_md_hd_t sha1_handle;
- guint8 *cp, password_buf[64];
- guint32 password_index = 0;
- guint32 count = 0, i;
-
- if (gcry_md_open(&sha1_handle, GCRY_MD_SHA1, 0)) {
- return;
- }
+ hash_len = auth_hash_len[model];
/**********************************************/
/* Use while loop until we've done 1 Megabyte */
@@ -3428,29 +3328,28 @@ snmp_usm_password_to_key_sha1(const guint8 *password, guint passwordlen,
} else {
*cp = 0;
}
- gcry_md_write(sha1_handle, password_buf, 64);
+ gcry_md_write(hash_handle, password_buf, 64);
count += 64;
}
- memcpy(key, gcry_md_read(sha1_handle, 0), HASH_SHA1_LENGTH);
- gcry_md_close(sha1_handle);
+ memcpy(key, gcry_md_read(hash_handle, 0), hash_len);
+ gcry_md_close(hash_handle);
/*****************************************************/
- /* Now localize the key with the engineID and pass */
- /* through SHA to produce final key */
+ /* Now localise the key with the engineID and pass */
+ /* through hash function to produce final key */
/* We ignore invalid engineLengths here. More strict */
/* checking is done in snmp_users_update_cb. */
/*****************************************************/
- if (gcry_md_open(&sha1_handle, GCRY_MD_SHA1, 0)) {
+ if (gcry_md_open(&hash_handle, auth_hash_algo[model], 0)) {
return;
}
- gcry_md_write(sha1_handle, key, HASH_SHA1_LENGTH);
- gcry_md_write(sha1_handle, engineID, engineLength);
- gcry_md_write(sha1_handle, key, HASH_SHA1_LENGTH);
- memcpy(key, gcry_md_read(sha1_handle, 0), HASH_SHA1_LENGTH);
- gcry_md_close(sha1_handle);
+ gcry_md_write(hash_handle, key, hash_len);
+ gcry_md_write(hash_handle, engineID, engineLength);
+ gcry_md_write(hash_handle, key, hash_len);
+ memcpy(key, gcry_md_read(hash_handle, 0), hash_len);
+ gcry_md_close(hash_handle);
return;
- }
-
+}
static void
process_prefs(void)
@@ -3876,7 +3775,7 @@ void proto_register_snmp(void) {
NULL, HFILL }},
/*--- End of included file: packet-snmp-hfarr.c ---*/
-#line 2406 "./asn1/snmp/packet-snmp-template.c"
+#line 2305 "./asn1/snmp/packet-snmp-template.c"
};
/* List of subtrees */
@@ -3916,7 +3815,7 @@ void proto_register_snmp(void) {
&ett_snmp_RReqPDU_U,
/*--- End of included file: packet-snmp-ettarr.c ---*/
-#line 2422 "./asn1/snmp/packet-snmp-template.c"
+#line 2321 "./asn1/snmp/packet-snmp-template.c"
};
static ei_register_info ei[] = {
{ &ei_snmp_failed_decrypted_data_pdu, { "snmp.failed_decrypted_data_pdu", PI_MALFORMED, PI_WARN, "Failed to decrypt encryptedPDU", EXPFILL }},
diff --git a/epan/dissectors/packet-snmp.h b/epan/dissectors/packet-snmp.h
index aaa09a85a5..11e2f2bd48 100644
--- a/epan/dissectors/packet-snmp.h
+++ b/epan/dissectors/packet-snmp.h
@@ -39,20 +39,21 @@ typedef struct _snmp_usm_key {
typedef struct _snmp_ue_assoc_t snmp_ue_assoc_t;
typedef struct _snmp_usm_params_t snmp_usm_params_t;
-typedef gboolean (*snmp_usm_authenticator_t)(snmp_usm_params_t*, guint8** calc_auth, guint* calc_auth_len, gchar const** error);
typedef tvbuff_t* (*snmp_usm_decoder_t)(snmp_usm_params_t*, tvbuff_t* encryptedData, packet_info *pinfo, gchar const** error);
-typedef void (*snmp_usm_password_to_key_t)(const guint8 *password, guint passwordlen, const guint8 *engineID, guint engineLength, guint8 *key);
-typedef struct _snmp_usm_auth_model_t {
- snmp_usm_password_to_key_t pass2key;
- snmp_usm_authenticator_t authenticate;
- guint key_size;
+typedef enum _snmp_usm_auth_model_t {
+ SNMP_USM_AUTH_MD5 = 0,
+ SNMP_USM_AUTH_SHA1,
+ SNMP_USM_AUTH_SHA2_224,
+ SNMP_USM_AUTH_SHA2_256,
+ SNMP_USM_AUTH_SHA2_384,
+ SNMP_USM_AUTH_SHA2_512
} snmp_usm_auth_model_t;
typedef struct _snmp_user_t {
snmp_usm_key_t userName;
- snmp_usm_auth_model_t* authModel;
+ snmp_usm_auth_model_t authModel;
snmp_usm_key_t authPassword;
snmp_usm_key_t authKey;