/*
 * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
 * Copyright 2020-present Open Networking Foundation

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * NOTE: This file was generated, manual edits will be overwritten!
 *
 * Generated by 'goCodeGenerator.py':
 *              https://github.com/cboling/OMCI-parser/README.md
 */

package generated

import "github.com/deckarep/golang-set"

// EnhancedSecurityControlClassID is the 16-bit ID for the OMCI
// Managed entity Enhanced security control
const EnhancedSecurityControlClassID = ClassID(332) // 0x014c

var enhancedsecuritycontrolBME *ManagedEntityDefinition

// EnhancedSecurityControl (Class ID: #332 / 0x014c)
//	This ME contains the capabilities, parameters and controls of enhanced GPON security features
//	when they are negotiated via the OMCI (Note). The attributes in this ME are intended to be used
//	to implement a symmetric-key-based three step authentication process as described in the
//	supplemental information section in the following.
//
//	NOTE - If an ITU-T G.987 system uses 802.1X authentication as defined in [ITU-T G.987.3], the
//	only applicable attribute of this ME is the broadcast key table.
//
//	Relationships
//		One instance of this ME is associated with the ONU ME.
//
//	Attributes
//		Managed Entity Id
//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
//			0. (R) (mandatory) (2 bytes)
//
//		Olt Crypto Capabilities
//			This attribute specifies the cryptographic mechanisms available at the OLT. It is written by the
//			OLT during authentication step 1. It is formatted as a bit map, where a 1 bit indicates that the
//			particular algorithm is supported, and a 0 bit indicates it is not supported.
//
//			Bit position	Algorithm
//
//			1 (LSB)	AES-CMAC-128 (support is mandatory)
//
//			2 	HMAC-SHA-256
//
//			3 	HMAC-SHA-512
//
//			4-128 	Reserved
//
//			(W) (mandatory) (16 bytes)
//
//		Olt Random Challenge Table
//			This attribute specifies the random challenge OLT_challenge issued by the OLT during
//			authentication step 1. It is structured as a table, with each entry being 17 bytes. The first
//			byte is the table row number, starting at 1, and the remaining 16 bytes are the contents of the
//			entry. OLT_challenge is the concatenation of all 16-byte content fields. In normal use, the OLT
//			will write all the entries in the table, and then trigger the ONU's processing of the entire
//			table using the OLT challenge status attribute. The table size is known by the maximum index set
//			by the OLT. The OLT can clear the table with a set operation to row 0. (R, W) (mandatory) (17 *
//			N-bytes)
//
//			NOTE - It is assumed that the length of OLT_challenge is always an integer multiple of 16-bytes.
//
//		Olt Challenge Status
//			This Boolean attribute controls the completion of authentication step 1. This attribute behaves
//			as follows.
//
//			When the OLT performs the first of possibly several set operations to the OLT crypto
//			capabilities or the OLT random challenge table attributes, a side effect of the set operation is
//			that the ONU sets the OLT challenge status attribute to false.
//
//			When the OLT completes the set operation(s) to the OLT crypto capabilities and the OLT random
//			challenge table attributes, then it sets the OLT challenge status attribute to true. This
//			triggers the ONU to process the OLT random challenge table, using its choice of the OLT's
//			candidate cryptographic hash algorithms.
//
//			The ONU initializes this attribute to the value false. (R, W) (mandatory) (1-byte)
//
//		Onu Selected Crypto Capabilities
//			This attribute specifies the cryptographic capability selected by the ONU in authentication step
//			2. Its value specifies one of the bit positions that has the value 1 in the OLT crypto
//			capabilities attribute. (R) (mandatory) (1 byte)
//
//		Onu Random Challenge Table
//			This attribute specifies the random challenge ONU_challenge issued by the ONU during
//			authentication step 2. It is structured as a table, with each entry being 16-bytes of content.
//			ONU_challenge is the concatenation of all 16-byte content fields in the table. Once the OLT
//			triggers a response to be generated using the OLT challenge status attribute, the ONU generates
//			the response and writes the table (in a single operation). The AVC generated by this attribute
//			signals to the OLT that the challenge is ready, so that the OLT can commence a get/get-next
//			sequence to obtain the table's contents. (R) (mandatory) (16 * P-bytes)
//
//		Onu Authentication Result Table
//			(authentication step 2). This attribute contains the result of the authentication computation
//			from the ONU (ONU_result), according to the ONU's selected crypto capabilities attribute.
//
//			ONU_result-= SelectedHashFunction (PSK, (ONU_selected_crypto capabilities | OLT_challenge |
//			ONU_challenge | 0x0000 0000 0000 0000)),
//
//			where "|" denotes concatenation.
//
//			This attribute is structured as a table, with each entry being 16 bytes of content. The number
//			of rows Q is implicit in the choice of hash algorithm.
//
//			Once the OLT triggers a response to be generated using the OLT challenge status attribute, the
//			ONU generates ONU_result and writes the table (in a single operation). The AVC generated by this
//			attribute signals to the OLT that the response is ready, so that the OLT can commence a get/get-
//			next sequence to obtain the table's contents. (R) (mandatory) (16 * Q-bytes)
//
//		Olt Authentication Result Table
//			This attribute is structured as a table, with each entry being 17 bytes. The first byte is the
//			table row number, starting at 1; the remaining 16 bytes are content. OLT_result is the
//			concatenation of all 16-byte content fields. The OLT writes all entries into the table, and then
//			triggers the ONU's processing of the table using the OLT result status attribute. The number of
//			rows R is implicit in the choice of hash algorithm. The OLT can clear the table with a set
//			operation to row 0. (W) (mandatory) (17 * R-bytes)
//
//			This attribute is used in authentication step 3. It contains OLT_result, the result of the
//			authentication computation from the OLT.
//
//			OLT_result-= SelectedHashFunction (PSK, (ONU_selected_crypto capabilities | ONU_challenge |
//			OLT_challenge | ONU_serial_number)).
//
//			The ONU_serial_number is the serial number attribute of the ONU-G ME, 8 bytes.
//
//		Olt Result Status
//			(authentication step 3). This Boolean attribute controls and reports the status of the OLT
//			authentication result table attribute. This attribute behaves as follows.
//
//			When the OLT performs the first of possibly several set operations to the OLT authentication
//			result table attribute, a side effect of the set operation is that the ONU sets the OLT result
//			status attribute to false.
//
//			When the OLT completes the set operation(s) to the OLT authentication result table, then it sets
//			the OLT result status attribute to true. This triggers the ONU to process the OLT authentication
//			result table.
//
//			(R, W) (mandatory) (1 byte)
//
//		Onu Authentication Status
//			This attribute indicates the status of the authentication relationship from the perspective of
//			the ONU. It has the following values.
//
//			0	Indeterminate. This initial value indicates that the OMCI authentication process has not yet
//			completed, and may not even have been started.
//
//			1	Reserved.
//
//			2	Reserved.
//
//			3	Authentication success: the procedure has completed at least once since the latest ONU
//			activation and in its most recent execution, the ONU has authenticated the OLT.
//
//			4	Authentication failure: the procedure has completed at least once since the latest ONU
//			activation, and either its most recent execution resulted in an error or the ONU has failed to
//			authenticate the OLT.
//
//			5	Reserved.
//
//			Upon ONU activation, the ONU sets the attribute to the initial value. When the ONU
//			authentication status has the value 3, encryption keys exchanged in the TC layer will be
//			encrypted using the master session key (ITUT G.984 systems) or the key encryption key (KEK,
//			ITU-T G.987 systems). The OLT should check the value of this attribute before initiating a key
//			switch.
//
//			(R) (mandatory) (1 byte)
//
//		Master Session Key Name
//			Following successful authentication, this register contains the "name," or the hash signature,
//			of the current master session key. The master session key is defined as:
//
//			MSK-= SelectedHashFunction (PSK, (OLT_challenge | ONU_challenge)).
//
//			The master session key name is defined as:
//
//			MSKname-= SelectedHashFunction (PSK, (ONU_challenge | OLT_challenge | 0x 3141 5926 5358 9793
//			3141 5926 5358 9793)).
//
//			If the selected hash function generates more than 128 bits, the result is truncated to the
//			leftmost (most significant) 128 bits.
//
//			Upon the invalidation of a master session key (e.g., due to an ONU reset or deactivation, or due
//			to an ONU-local decision that the master session key has expired), the ONU sets the master
//			session key name to all zeros. (R) (mandatory) (16 bytes)
//
//		Broadcast Key Table
//			10	Clear the entire table.
//
//			11	Reserved.
//
//			The four MSBs specify the length of the fragment, which is left-justified in the key fragment
//			field. The value 0 indicates 16-bytes of key fragment.
//
//			The other two bits are reserved.
//
//			Row identifier (1 byte): The two MSBs of this field are the key index, which appears in the
//			header of encrypted multicast GEM frames. Key index 0 always indicates cleartext, and should
//			therefore not appear in the identifier. The four LSBs identify the key fragment number, starting
//			with 0. The other two bits are reserved.
//
//			Key fragment (16 bytes): This field contains the specified fragment of the key (encrypted with
//			AES-ECB using the KEK).
//
//			(R, W) (optional) (18N bytes)
//
//			This attribute is defined only in ITU-T G.987 systems. It contains the broadcast key generated
//			by the OLT. It is a table, each of whose rows is structured as follows.
//
//			Row control (1 byte): The two LSBs of this byte determine the attribute's behaviour under the
//			set action. They always read back as 0 under the get next action.
//
//			00	Set the specified row.
//
//			01	Clear the specified row.
//
//		Effective Key Length
//			This attribute specifies the maximum effective length, in bits, of keys generated by the ONU.
//			(R) (optional) (2 bytes)
//
type EnhancedSecurityControl struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

func init() {
	enhancedsecuritycontrolBME = &ManagedEntityDefinition{
		Name:    "EnhancedSecurityControl",
		ClassID: 332,
		MessageTypes: mapset.NewSetWith(
			Get,
			GetNext,
			Set,
		),
		AllowedAttributeMask: 0xfff0,
		AttributeDefinitions: AttributeDefinitionMap{
			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
			1:  MultiByteField("OltCryptoCapabilities", OctetsAttributeType, 0x8000, 16, toOctets("AAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Write), false, false, false, 1),
			2:  TableField("OltRandomChallengeTable", TableAttributeType, 0x4000, TableInfo{nil, 17}, mapset.NewSetWith(Read, Write), false, false, false, 2),
			3:  ByteField("OltChallengeStatus", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, Write), false, false, false, 3),
			4:  ByteField("OnuSelectedCryptoCapabilities", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read), false, false, false, 4),
			5:  TableField("OnuRandomChallengeTable", TableAttributeType, 0x0800, TableInfo{nil, 16}, mapset.NewSetWith(Read), true, false, false, 5),
			6:  TableField("OnuAuthenticationResultTable", TableAttributeType, 0x0400, TableInfo{nil, 16}, mapset.NewSetWith(Read), true, false, false, 6),
			7:  TableField("OltAuthenticationResultTable", TableAttributeType, 0x0200, TableInfo{nil, 17}, mapset.NewSetWith(Read, Write), false, false, false, 7),
			8:  ByteField("OltResultStatus", UnsignedIntegerAttributeType, 0x0100, 0, mapset.NewSetWith(Read, Write), false, false, false, 8),
			9:  ByteField("OnuAuthenticationStatus", UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Read), true, false, false, 9),
			10: MultiByteField("MasterSessionKeyName", OctetsAttributeType, 0x0040, 16, toOctets("AAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read), false, false, false, 10),
			11: TableField("BroadcastKeyTable", TableAttributeType, 0x0020, TableInfo{nil, 18}, mapset.NewSetWith(Read, Write), false, true, false, 11),
			12: Uint16Field("EffectiveKeyLength", UnsignedIntegerAttributeType, 0x0010, 0, mapset.NewSetWith(Read), false, true, false, 12),
		},
		Access:  CreatedByOnu,
		Support: UnknownSupport,
	}
}

// NewEnhancedSecurityControl (class ID 332) creates the basic
// Managed Entity definition that is used to validate an ME of this type that
// is received from or transmitted to the OMCC.
func NewEnhancedSecurityControl(params ...ParamData) (*ManagedEntity, OmciErrors) {
	return NewManagedEntity(*enhancedsecuritycontrolBME, params...)
}
