summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@anytun.org>2017-09-17 18:03:48 +0200
committerChristian Pointner <equinox@anytun.org>2017-09-17 18:03:48 +0200
commit54368cc32e0c3eb3003133b1f6ba2fa8d4d03436 (patch)
treef9328c7c3091c6146a4a83ccaae15fd37f6e551e
parentchanged KeyDerivation Interface to use provided memory rather then allocatiin... (diff)
implemented AES-CTR key derivation (needs testing)
-rw-r--r--satp/crypto-kd-aesctr.go89
-rw-r--r--satp/crypto-kd-aesctr_test.go67
-rw-r--r--satp/crypto-kd.go2
-rw-r--r--satp/crypto-kd_test.go57
4 files changed, 214 insertions, 1 deletions
diff --git a/satp/crypto-kd-aesctr.go b/satp/crypto-kd-aesctr.go
new file mode 100644
index 0000000..7b8c97a
--- /dev/null
+++ b/satp/crypto-kd-aesctr.go
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 2017 anygone contributors (see AUTHORS file)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * Neither the name of anygone nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+package satp
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/subtle"
+ "encoding/binary"
+ "errors"
+ "strconv"
+)
+
+const (
+ AES_CTR_KD_SALT_LENGTH = aes.BlockSize - 2 // two bytes spare for counter
+)
+
+type AESCTRKeyDerivation struct {
+ cipher cipher.Block
+ salt []byte
+}
+
+func (kd *AESCTRKeyDerivation) generateCTR(dir KeyDirection, usage KeyUsage, sequenceNumber uint32, ctr []byte) {
+ ctr[aes.BlockSize-1] = 0
+ ctr[aes.BlockSize-2] = 0
+ subtle.ConstantTimeCopy(1, ctr[:len(kd.salt)], kd.salt)
+
+ keyID := [8]byte{}
+ binary.BigEndian.PutUint32(keyID[:4], getKDLabel(dir, usage))
+ binary.BigEndian.PutUint32(keyID[4:], sequenceNumber)
+ for i, b := range keyID { // unfortunately crypto.xorBytes is not exported...
+ ctr[len(kd.salt)-i] ^= b
+ }
+}
+
+func (kd *AESCTRKeyDerivation) Generate(dir KeyDirection, usage KeyUsage, sequenceNumber uint32, out []byte) error {
+ // this needs to stay in this function so that the go compiler can detect that it doesn't escape
+ // from this function and whence will get allocated on the stack
+ ctr := [aes.BlockSize]byte{}
+ kd.generateCTR(dir, usage, sequenceNumber, ctr[:])
+ for i, _ := range out { // unfortunately there is no memset-style function in go...
+ out[i] = 0
+ }
+ c := cipher.NewCTR(kd.cipher, ctr[:])
+ c.XORKeyStream(out, out)
+ return nil
+}
+
+func NewAESCTRKeyDerivation(key, salt []byte) (KeyDerivation, error) {
+ if len(salt) != AES_CTR_KD_SALT_LENGTH {
+ return nil, errors.New("invalid salt size: " + strconv.Itoa(len(salt)))
+ }
+
+ kd := &AESCTRKeyDerivation{salt: salt}
+
+ var err error
+ if kd.cipher, err = aes.NewCipher(key); err != nil {
+ return nil, err
+ }
+ return kd, nil
+}
diff --git a/satp/crypto-kd-aesctr_test.go b/satp/crypto-kd-aesctr_test.go
new file mode 100644
index 0000000..0426f3e
--- /dev/null
+++ b/satp/crypto-kd-aesctr_test.go
@@ -0,0 +1,67 @@
+//
+// Copyright (c) 2017 anygone contributors (see AUTHORS file)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * Neither the name of anygone nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+package satp
+
+import (
+ "math/rand"
+ "testing"
+)
+
+func TestAESCTRKeyDerivationNew(t *testing.T) {
+ var buffer [100]byte
+ rand.Read(buffer[:])
+
+ testvectors := []struct {
+ key []byte
+ salt []byte
+ valid bool
+ }{
+ {[]byte{}, []byte{}, false},
+ {[]byte{}, buffer[:], false},
+ {buffer[:], []byte{}, false},
+ {[]byte{}, buffer[:14], false},
+ {buffer[:16], []byte{}, false},
+ {buffer[:16], buffer[:14], true},
+ }
+
+ for _, vector := range testvectors {
+ _, err := NewAESCTRKeyDerivation(vector.key, vector.salt)
+ if vector.valid {
+ if err != nil {
+ t.Fatal("unexpected error:", err)
+ }
+ } else {
+ if err == nil {
+ t.Fatalf("creating aes-ctr key derivation with key %v and salt %v should give an error", vector.key, vector.salt)
+ }
+ }
+ }
+}
diff --git a/satp/crypto-kd.go b/satp/crypto-kd.go
index 39a3d01..784080e 100644
--- a/satp/crypto-kd.go
+++ b/satp/crypto-kd.go
@@ -54,7 +54,7 @@ type KeyDerivation interface {
Generate(dir KeyDirection, usage KeyUsage, sequenceNumber uint32, out []byte) error
}
-func getLabel(dir KeyDirection, usage KeyUsage) uint32 {
+func getKDLabel(dir KeyDirection, usage KeyUsage) uint32 {
switch usage {
case UsageEncryptKey:
if dir == DirLeft {
diff --git a/satp/crypto-kd_test.go b/satp/crypto-kd_test.go
new file mode 100644
index 0000000..0ba2bf0
--- /dev/null
+++ b/satp/crypto-kd_test.go
@@ -0,0 +1,57 @@
+//
+// Copyright (c) 2017 anygone contributors (see AUTHORS file)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * Neither the name of anygone nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+package satp
+
+import (
+ "testing"
+)
+
+func TestKDGetLabel(t *testing.T) {
+ testvectors := []struct {
+ dir KeyDirection
+ usage KeyUsage
+ label uint32
+ }{
+ {DirLeft, UsageEncryptKey, 0x356A192B},
+ {DirRight, UsageEncryptKey, 0xDA4B9237},
+ {DirLeft, UsageEncryptSalt, 0x77DE68DA},
+ {DirRight, UsageEncryptSalt, 0x1B645389},
+ {DirLeft, UsageAuthKey, 0xAC3478D6},
+ {DirRight, UsageAuthKey, 0xC1DFD96E},
+ }
+
+ for _, vector := range testvectors {
+ label := getKDLabel(vector.dir, vector.usage)
+ if label != vector.label {
+ t.Fatalf("returned label is invalid, is: 0x%08X, should be 0x%08X", label, vector.label)
+ }
+ }
+}