VOL-2112 move to voltha-lib-go
Change-Id: Ic1af08003c1d2c698c0cce371e64f47b47b8d875
diff --git a/vendor/gopkg.in/jcmturner/gokrb5.v7/crypto/rfc8009/encryption.go b/vendor/gopkg.in/jcmturner/gokrb5.v7/crypto/rfc8009/encryption.go
new file mode 100644
index 0000000..86aae09
--- /dev/null
+++ b/vendor/gopkg.in/jcmturner/gokrb5.v7/crypto/rfc8009/encryption.go
@@ -0,0 +1,128 @@
+// Package rfc8009 provides encryption and checksum methods as specified in RFC 8009
+package rfc8009
+
+import (
+ "crypto/aes"
+ "crypto/hmac"
+ "crypto/rand"
+ "errors"
+ "fmt"
+
+ "gopkg.in/jcmturner/aescts.v1"
+ "gopkg.in/jcmturner/gokrb5.v7/crypto/common"
+ "gopkg.in/jcmturner/gokrb5.v7/crypto/etype"
+ "gopkg.in/jcmturner/gokrb5.v7/iana/etypeID"
+)
+
+// EncryptData encrypts the data provided using methods specific to the etype provided as defined in RFC 8009.
+func EncryptData(key, data []byte, e etype.EType) ([]byte, []byte, error) {
+ kl := e.GetKeyByteSize()
+ if e.GetETypeID() == etypeID.AES256_CTS_HMAC_SHA384_192 {
+ kl = 32
+ }
+ if len(key) != kl {
+ return []byte{}, []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", e.GetKeyByteSize(), len(key))
+ }
+ ivz := make([]byte, aes.BlockSize)
+ return aescts.Encrypt(key, ivz, data)
+}
+
+// EncryptMessage encrypts the message provided using the methods specific to the etype provided as defined in RFC 8009.
+// The encrypted data is concatenated with its integrity hash to create an encrypted message.
+func EncryptMessage(key, message []byte, usage uint32, e etype.EType) ([]byte, []byte, error) {
+ kl := e.GetKeyByteSize()
+ if e.GetETypeID() == etypeID.AES256_CTS_HMAC_SHA384_192 {
+ kl = 32
+ }
+ if len(key) != kl {
+ return []byte{}, []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", kl, len(key))
+ }
+ if len(key) != e.GetKeyByteSize() {
+ }
+ //confounder
+ c := make([]byte, e.GetConfounderByteSize())
+ _, err := rand.Read(c)
+ if err != nil {
+ return []byte{}, []byte{}, fmt.Errorf("could not generate random confounder: %v", err)
+ }
+ plainBytes := append(c, message...)
+
+ // Derive key for encryption from usage
+ var k []byte
+ if usage != 0 {
+ k, err = e.DeriveKey(key, common.GetUsageKe(usage))
+ if err != nil {
+ return []byte{}, []byte{}, fmt.Errorf("error deriving key for encryption: %v", err)
+ }
+ }
+
+ // Encrypt the data
+ iv, b, err := e.EncryptData(k, plainBytes)
+ if err != nil {
+ return iv, b, fmt.Errorf("error encrypting data: %v", err)
+ }
+
+ ivz := make([]byte, e.GetConfounderByteSize())
+ ih, err := GetIntegityHash(ivz, b, key, usage, e)
+ if err != nil {
+ return iv, b, fmt.Errorf("error encrypting data: %v", err)
+ }
+ b = append(b, ih...)
+ return iv, b, nil
+}
+
+// DecryptData decrypts the data provided using the methods specific to the etype provided as defined in RFC 8009.
+func DecryptData(key, data []byte, e etype.EType) ([]byte, error) {
+ kl := e.GetKeyByteSize()
+ if e.GetETypeID() == etypeID.AES256_CTS_HMAC_SHA384_192 {
+ kl = 32
+ }
+ if len(key) != kl {
+ return []byte{}, fmt.Errorf("incorrect keysize: expected: %v actual: %v", kl, len(key))
+ }
+ ivz := make([]byte, aes.BlockSize)
+ return aescts.Decrypt(key, ivz, data)
+}
+
+// DecryptMessage decrypts the message provided using the methods specific to the etype provided as defined in RFC 8009.
+// The integrity of the message is also verified.
+func DecryptMessage(key, ciphertext []byte, usage uint32, e etype.EType) ([]byte, error) {
+ //Derive the key
+ k, err := e.DeriveKey(key, common.GetUsageKe(usage))
+ if err != nil {
+ return nil, fmt.Errorf("error deriving key: %v", err)
+ }
+ // Strip off the checksum from the end
+ b, err := e.DecryptData(k, ciphertext[:len(ciphertext)-e.GetHMACBitLength()/8])
+ if err != nil {
+ return nil, err
+ }
+ //Verify checksum
+ if !e.VerifyIntegrity(key, ciphertext, b, usage) {
+ return nil, errors.New("integrity verification failed")
+ }
+ //Remove the confounder bytes
+ return b[e.GetConfounderByteSize():], nil
+}
+
+// GetIntegityHash returns a keyed integrity hash of the bytes provided as defined in RFC 8009
+func GetIntegityHash(iv, c, key []byte, usage uint32, e etype.EType) ([]byte, error) {
+ // Generate and append integrity hash
+ // The HMAC is calculated over the cipher state concatenated with the
+ // AES output, instead of being calculated over the confounder and
+ // plaintext. This allows the message receiver to verify the
+ // integrity of the message before decrypting the message.
+ // H = HMAC(Ki, IV | C)
+ ib := append(iv, c...)
+ return common.GetIntegrityHash(ib, key, usage, e)
+}
+
+// VerifyIntegrity verifies the integrity of cipertext bytes ct.
+func VerifyIntegrity(key, ct []byte, usage uint32, etype etype.EType) bool {
+ h := make([]byte, etype.GetHMACBitLength()/8)
+ copy(h, ct[len(ct)-etype.GetHMACBitLength()/8:])
+ ivz := make([]byte, etype.GetConfounderByteSize())
+ ib := append(ivz, ct[:len(ct)-(etype.GetHMACBitLength()/8)]...)
+ expectedMAC, _ := common.GetIntegrityHash(ib, key, usage, etype)
+ return hmac.Equal(h, expectedMAC)
+}
diff --git a/vendor/gopkg.in/jcmturner/gokrb5.v7/crypto/rfc8009/keyDerivation.go b/vendor/gopkg.in/jcmturner/gokrb5.v7/crypto/rfc8009/keyDerivation.go
new file mode 100644
index 0000000..90ced3b
--- /dev/null
+++ b/vendor/gopkg.in/jcmturner/gokrb5.v7/crypto/rfc8009/keyDerivation.go
@@ -0,0 +1,144 @@
+package rfc8009
+
+import (
+ "crypto/hmac"
+ "encoding/binary"
+ "encoding/hex"
+ "errors"
+
+ "golang.org/x/crypto/pbkdf2"
+ "gopkg.in/jcmturner/gokrb5.v7/crypto/etype"
+ "gopkg.in/jcmturner/gokrb5.v7/iana/etypeID"
+)
+
+const (
+ s2kParamsZero = 32768
+)
+
+// DeriveRandom for key derivation as defined in RFC 8009
+func DeriveRandom(protocolKey, usage []byte, e etype.EType) ([]byte, error) {
+ h := e.GetHashFunc()()
+ return KDF_HMAC_SHA2(protocolKey, []byte("prf"), usage, h.Size(), e), nil
+}
+
+// DeriveKey derives a key from the protocol key based on the usage and the etype's specific methods.
+//
+// https://tools.ietf.org/html/rfc8009#section-5
+//
+// If the enctype is aes128-cts-hmac-sha256-128:
+// Kc = KDF-HMAC-SHA2(base-key, usage | 0x99, 128)
+// Ke = KDF-HMAC-SHA2(base-key, usage | 0xAA, 128)
+// Ki = KDF-HMAC-SHA2(base-key, usage | 0x55, 128)
+//
+// If the enctype is aes256-cts-hmac-sha384-192:
+// Kc = KDF-HMAC-SHA2(base-key, usage | 0x99, 192)
+// Ke = KDF-HMAC-SHA2(base-key, usage | 0xAA, 256)
+// Ki = KDF-HMAC-SHA2(base-key, usage | 0x55, 192)
+func DeriveKey(protocolKey, label []byte, e etype.EType) []byte {
+ var context []byte
+ var kl int
+ // Key length is longer for aes256-cts-hmac-sha384-192 is it is a Ke or from StringToKey (where label is "kerberos")
+ if e.GetETypeID() == etypeID.AES256_CTS_HMAC_SHA384_192 {
+ switch label[len(label)-1] {
+ case 0x73:
+ // 0x73 is "s" so label could be kerberos meaning StringToKey so now check if the label is "kerberos"
+ kerblabel := []byte("kerberos")
+ if len(label) != len(kerblabel) {
+ break
+ }
+ for i, b := range label {
+ if b != kerblabel[i] {
+ kl = e.GetKeySeedBitLength()
+ break
+ }
+ }
+ if kl == 0 {
+ // This is StringToKey
+ kl = 256
+ }
+ case 0xAA:
+ // This is a Ke
+ kl = 256
+ }
+ }
+ if kl == 0 {
+ kl = e.GetKeySeedBitLength()
+ }
+ return e.RandomToKey(KDF_HMAC_SHA2(protocolKey, label, context, kl, e))
+}
+
+// RandomToKey returns a key from the bytes provided according to the definition in RFC 8009.
+func RandomToKey(b []byte) []byte {
+ return b
+}
+
+// StringToKey returns a key derived from the string provided according to the definition in RFC 8009.
+func StringToKey(secret, salt, s2kparams string, e etype.EType) ([]byte, error) {
+ i, err := S2KparamsToItertions(s2kparams)
+ if err != nil {
+ return nil, err
+ }
+ return StringToKeyIter(secret, salt, i, e)
+}
+
+// StringToKeyIter returns a key derived from the string provided according to the definition in RFC 8009.
+func StringToKeyIter(secret, salt string, iterations int, e etype.EType) ([]byte, error) {
+ tkey := e.RandomToKey(StringToPBKDF2(secret, salt, iterations, e))
+ return e.DeriveKey(tkey, []byte("kerberos"))
+}
+
+// StringToPBKDF2 generates an encryption key from a pass phrase and salt string using the PBKDF2 function from PKCS #5 v2.0
+func StringToPBKDF2(secret, salt string, iterations int, e etype.EType) []byte {
+ kl := e.GetKeyByteSize()
+ if e.GetETypeID() == etypeID.AES256_CTS_HMAC_SHA384_192 {
+ kl = 32
+ }
+ return pbkdf2.Key([]byte(secret), []byte(salt), iterations, kl, e.GetHashFunc())
+}
+
+// KDF_HMAC_SHA2 key derivation: https://tools.ietf.org/html/rfc8009#section-3
+func KDF_HMAC_SHA2(protocolKey, label, context []byte, kl int, e etype.EType) []byte {
+ //k: Length in bits of the key to be outputted, expressed in big-endian binary representation in 4 bytes.
+ k := make([]byte, 4, 4)
+ binary.BigEndian.PutUint32(k, uint32(kl))
+
+ c := make([]byte, 4, 4)
+ binary.BigEndian.PutUint32(c, uint32(1))
+ c = append(c, label...)
+ c = append(c, byte(0))
+ if len(context) > 0 {
+ c = append(c, context...)
+ }
+ c = append(c, k...)
+
+ mac := hmac.New(e.GetHashFunc(), protocolKey)
+ mac.Write(c)
+ return mac.Sum(nil)[:(kl / 8)]
+}
+
+// GetSaltP returns the salt value based on the etype name: https://tools.ietf.org/html/rfc8009#section-4
+func GetSaltP(salt, ename string) string {
+ b := []byte(ename)
+ b = append(b, byte(0))
+ b = append(b, []byte(salt)...)
+ return string(b)
+}
+
+// S2KparamsToItertions converts the string representation of iterations to an integer for RFC 8009.
+func S2KparamsToItertions(s2kparams string) (int, error) {
+ var i uint32
+ if len(s2kparams) != 8 {
+ return s2kParamsZero, errors.New("Invalid s2kparams length")
+ }
+ b, err := hex.DecodeString(s2kparams)
+ if err != nil {
+ return s2kParamsZero, errors.New("Invalid s2kparams, cannot decode string to bytes")
+ }
+ i = binary.BigEndian.Uint32(b)
+ //buf := bytes.NewBuffer(b)
+ //err = binary.Read(buf, binary.BigEndian, &i)
+ if err != nil {
+ return s2kParamsZero, errors.New("Invalid s2kparams, cannot convert to big endian int32")
+ }
+ return int(i), nil
+}