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 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 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 gboolean snmp_usm_auth(const snmp_usm_auth_model_t model, snmp_usm_params_t* p, guint8**, guint*, gchar const**); static const value_string auth_types[] = { - {0,"MD5"}, - {1,"SHA1"}, + {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 snmp_usm_auth_model_t* auth_models[] = {&model_md5,&model_sha1}; + +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 const guint auth_tag_len[] = { + 12, + 12, + 16, + 24, + 32, + 48 +}; + +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 +}; #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,77 +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) { - *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_MD5_LENGTH); - - if (ws_hmac_buffer(GCRY_MD_MD5, 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; -} - - -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) { + if (auth_len != auth_tag_len[model]) { *error = "Authenticator length wrong"; return FALSE; } @@ -1631,23 +1591,23 @@ snmp_usm_auth_sha1(snmp_usm_params_t* p _U_, guint8** calc_auth_p, guint* calc_a 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_SHA1_LENGTH); + calc_auth = (guint8*)wmem_alloc(wmem_packet_scope(), auth_hash_len[model]); - if (ws_hmac_buffer(GCRY_MD_SHA1, 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; + return ( memcmp(auth,calc_auth,auth_len) != 0 ) ? FALSE : TRUE; } static tvbuff_t* @@ -2122,25 +2082,27 @@ 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)) { + gcry_md_hd_t hash_handle; + guint8 *cp, password_buf[64]; + guint32 password_index = 0; + guint32 count = 0, i; + guint hash_len; + + if (gcry_md_open(&hash_handle, auth_hash_algo[model], 0)) { return; } + hash_len = auth_hash_len[model]; + /**********************************************/ /* Use while loop until we've done 1 Megabyte */ /**********************************************/ @@ -2157,92 +2119,29 @@ snmp_usm_password_to_key_md5(const guint8 *password, guint passwordlen, } else { *cp = 0; } - gcry_md_write(md5_handle, password_buf, 64); + gcry_md_write(hash_handle, password_buf, 64); count += 64; } - memcpy(key1, gcry_md_read(md5_handle, 0), HASH_MD5_LENGTH); - gcry_md_close(md5_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 MD5 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(&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); - + 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; } - - - -/* - 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; - } - - /**********************************************/ - /* 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(sha1_handle, password_buf, 64); - count += 64; - } - memcpy(key, gcry_md_read(sha1_handle, 0), HASH_SHA1_LENGTH); - gcry_md_close(sha1_handle); - - /*****************************************************/ - /* Now localize the key with the engineID and pass */ - /* through SHA 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)) { - 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); - 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 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 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 gboolean snmp_usm_auth(const snmp_usm_auth_model_t model, snmp_usm_params_t* p, guint8**, guint*, gchar const**); static const value_string auth_types[] = { - {0,"MD5"}, - {1,"SHA1"}, + {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 snmp_usm_auth_model_t* auth_models[] = {&model_md5,&model_sha1}; + +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 const guint auth_tag_len[] = { + 12, + 12, + 16, + 24, + 32, + 48 +}; + +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 +}; #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,77 +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) { - *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_MD5_LENGTH); - - if (ws_hmac_buffer(GCRY_MD_MD5, 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; -} - - -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) { + if (auth_len != auth_tag_len[model]) { *error = "Authenticator length wrong"; return FALSE; } @@ -1733,23 +1693,23 @@ snmp_usm_auth_sha1(snmp_usm_params_t* p _U_, guint8** calc_auth_p, guint* calc_a 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_SHA1_LENGTH); + calc_auth = (guint8*)wmem_alloc(wmem_packet_scope(), auth_hash_len[model]); - if (ws_hmac_buffer(GCRY_MD_SHA1, 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; + 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,25 +3291,27 @@ 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)) { + gcry_md_hd_t hash_handle; + guint8 *cp, password_buf[64]; + guint32 password_index = 0; + guint32 count = 0, i; + guint hash_len; + + if (gcry_md_open(&hash_handle, auth_hash_algo[model], 0)) { return; } + hash_len = auth_hash_len[model]; + /**********************************************/ /* Use while loop until we've done 1 Megabyte */ /**********************************************/ @@ -3366,92 +3328,29 @@ snmp_usm_password_to_key_md5(const guint8 *password, guint passwordlen, } else { *cp = 0; } - gcry_md_write(md5_handle, password_buf, 64); + gcry_md_write(hash_handle, password_buf, 64); count += 64; } - memcpy(key1, gcry_md_read(md5_handle, 0), HASH_MD5_LENGTH); - gcry_md_close(md5_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 MD5 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(&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); - + 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; } - - - -/* - 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; - } - - /**********************************************/ - /* 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(sha1_handle, password_buf, 64); - count += 64; - } - memcpy(key, gcry_md_read(sha1_handle, 0), HASH_SHA1_LENGTH); - gcry_md_close(sha1_handle); - - /*****************************************************/ - /* Now localize the key with the engineID and pass */ - /* through SHA 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)) { - 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); - 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; diff --git a/wsutil/wsgcrypt.h b/wsutil/wsgcrypt.h index 8ad0fcfd4f..b323c35c3a 100644 --- a/wsutil/wsgcrypt.h +++ b/wsutil/wsgcrypt.h @@ -37,8 +37,12 @@ DIAG_OFF(deprecated-declarations) DIAG_ON(deprecated-declarations) -#define HASH_MD5_LENGTH 16 -#define HASH_SHA1_LENGTH 20 +#define HASH_MD5_LENGTH 16 +#define HASH_SHA1_LENGTH 20 +#define HASH_SHA2_224_LENGTH 28 +#define HASH_SHA2_256_LENGTH 32 +#define HASH_SHA2_384_LENGTH 48 +#define HASH_SHA2_512_LENGTH 64 /* Convenience function to calculate the HMAC from the data in BUFFER of size LENGTH with key KEY of size KEYLEN using the algorithm ALGO avoiding the creating of a