[VOL-1349] EPON ONU adapter (package B)
Change-Id: I609ba349c429bc7e87c74b66bb1121841f9caef6
diff --git a/vendor/gopkg.in/jcmturner/gokrb5.v7/crypto/rfc3961/keyDerivation.go b/vendor/gopkg.in/jcmturner/gokrb5.v7/crypto/rfc3961/keyDerivation.go
new file mode 100644
index 0000000..8c637a2
--- /dev/null
+++ b/vendor/gopkg.in/jcmturner/gokrb5.v7/crypto/rfc3961/keyDerivation.go
@@ -0,0 +1,178 @@
+package rfc3961
+
+import (
+ "bytes"
+
+ "gopkg.in/jcmturner/gokrb5.v7/crypto/etype"
+)
+
+const (
+ prfconstant = "prf"
+)
+
+// DeriveRandom implements the RFC 3961 defined function: DR(Key, Constant) = k-truncate(E(Key, Constant, initial-cipher-state)).
+//
+// key: base key or protocol key. Likely to be a key from a keytab file.
+//
+// usage: a constant.
+//
+// n: block size in bits (not bytes) - note if you use something like aes.BlockSize this is in bytes.
+//
+// k: key length / key seed length in bits. Eg. for AES256 this value is 256.
+//
+// e: the encryption etype function to use.
+func DeriveRandom(key, usage []byte, e etype.EType) ([]byte, error) {
+ n := e.GetCypherBlockBitLength()
+ k := e.GetKeySeedBitLength()
+ //Ensure the usage constant is at least the size of the cypher block size. Pass it through the nfold algorithm that will "stretch" it if needs be.
+ nFoldUsage := Nfold(usage, n)
+ //k-truncate implemented by creating a byte array the size of k (k is in bits hence /8)
+ out := make([]byte, k/8)
+
+ /*If the output of E is shorter than k bits, it is fed back into the encryption as many times as necessary.
+ The construct is as follows (where | indicates concatenation):
+
+ K1 = E(Key, n-fold(Constant), initial-cipher-state)
+ K2 = E(Key, K1, initial-cipher-state)
+ K3 = E(Key, K2, initial-cipher-state)
+ K4 = ...
+
+ DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...)*/
+ _, K, err := e.EncryptData(key, nFoldUsage)
+ if err != nil {
+ return out, err
+ }
+ for i := copy(out, K); i < len(out); {
+ _, K, _ = e.EncryptData(key, K)
+ i = i + copy(out[i:], K)
+ }
+ return out, nil
+}
+
+// DeriveKey derives a key from the protocol key based on the usage and the etype's specific methods.
+func DeriveKey(protocolKey, usage []byte, e etype.EType) ([]byte, error) {
+ r, err := e.DeriveRandom(protocolKey, usage)
+ if err != nil {
+ return nil, err
+ }
+ return e.RandomToKey(r), nil
+}
+
+// RandomToKey returns a key from the bytes provided according to the definition in RFC 3961.
+func RandomToKey(b []byte) []byte {
+ return b
+}
+
+// DES3RandomToKey returns a key from the bytes provided according to the definition in RFC 3961 for DES3 etypes.
+func DES3RandomToKey(b []byte) []byte {
+ r := fixWeakKey(stretch56Bits(b[:7]))
+ r2 := fixWeakKey(stretch56Bits(b[7:14]))
+ r = append(r, r2...)
+ r3 := fixWeakKey(stretch56Bits(b[14:21]))
+ r = append(r, r3...)
+ return r
+}
+
+// DES3StringToKey returns a key derived from the string provided according to the definition in RFC 3961 for DES3 etypes.
+func DES3StringToKey(secret, salt string, e etype.EType) ([]byte, error) {
+ s := secret + salt
+ tkey := e.RandomToKey(Nfold([]byte(s), e.GetKeySeedBitLength()))
+ return e.DeriveKey(tkey, []byte("kerberos"))
+}
+
+// PseudoRandom function as defined in RFC 3961
+func PseudoRandom(key, b []byte, e etype.EType) ([]byte, error) {
+ h := e.GetHashFunc()()
+ h.Write(b)
+ tmp := h.Sum(nil)[:e.GetMessageBlockByteSize()]
+ k, err := e.DeriveKey(key, []byte(prfconstant))
+ if err != nil {
+ return []byte{}, err
+ }
+ _, prf, err := e.EncryptData(k, tmp)
+ if err != nil {
+ return []byte{}, err
+ }
+ return prf, nil
+}
+
+func stretch56Bits(b []byte) []byte {
+ d := make([]byte, len(b), len(b))
+ copy(d, b)
+ var lb byte
+ for i, v := range d {
+ bv, nb := calcEvenParity(v)
+ d[i] = nb
+ if bv != 0 {
+ lb = lb | (1 << uint(i+1))
+ } else {
+ lb = lb &^ (1 << uint(i+1))
+ }
+ }
+ _, lb = calcEvenParity(lb)
+ d = append(d, lb)
+ return d
+}
+
+func calcEvenParity(b byte) (uint8, uint8) {
+ lowestbit := b & 0x01
+ // c counter of 1s in the first 7 bits of the byte
+ var c int
+ // Iterate over the highest 7 bits (hence p starts at 1 not zero) and count the 1s.
+ for p := 1; p < 8; p++ {
+ v := b & (1 << uint(p))
+ if v != 0 {
+ c++
+ }
+ }
+ if c%2 == 0 {
+ //Even number of 1s so set parity to 1
+ b = b | 1
+ } else {
+ //Odd number of 1s so set parity to 0
+ b = b &^ 1
+ }
+ return lowestbit, b
+}
+
+func fixWeakKey(b []byte) []byte {
+ if weak(b) {
+ b[7] ^= 0xF0
+ }
+ return b
+}
+
+func weak(b []byte) bool {
+ // weak keys from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-67r1.pdf
+ weakKeys := [4][]byte{
+ {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+ {0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE},
+ {0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1},
+ {0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
+ }
+ semiWeakKeys := [12][]byte{
+ {0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E},
+ {0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01},
+ {0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1},
+ {0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01},
+ {0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE},
+ {0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01},
+ {0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1},
+ {0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E},
+ {0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE},
+ {0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E},
+ {0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
+ {0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1},
+ }
+ for _, k := range weakKeys {
+ if bytes.Equal(b, k) {
+ return true
+ }
+ }
+ for _, k := range semiWeakKeys {
+ if bytes.Equal(b, k) {
+ return true
+ }
+ }
+ return false
+}