mirror of https://github.com/k3s-io/k3s
Merge pull request #46916 from smarterclayton/secretbox
Automatic merge from submit-queue (batch tested with PRs 46979, 47078, 47138, 46916) Add a secretbox and AES-CBC path for encrypt at rest Add a secretbox and AES-CBC encrypt at rest provider and alter the config, based on feedback from security review. AES-CBC is more well reviewed and generally fits better with common criteria and FIPS, secretbox is newer and faster than CBC. ```release-note Add secretbox and AES-CBC encryption modes to at rest encryption. AES-CBC is considered superior to AES-GCM because it is resistant to nonce-reuse attacks, and secretbox uses Poly1305 and XSalsa20. ```pull/6/head
commit
d16d64f620
|
@ -2596,6 +2596,10 @@
|
||||||
"ImportPath": "golang.org/x/crypto/ed25519/internal/edwards25519",
|
"ImportPath": "golang.org/x/crypto/ed25519/internal/edwards25519",
|
||||||
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/nacl/secretbox",
|
||||||
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/pkcs12",
|
"ImportPath": "golang.org/x/crypto/pkcs12",
|
||||||
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
|
@ -2604,6 +2608,14 @@
|
||||||
"ImportPath": "golang.org/x/crypto/pkcs12/internal/rc2",
|
"ImportPath": "golang.org/x/crypto/pkcs12/internal/rc2",
|
||||||
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/poly1305",
|
||||||
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/salsa20/salsa",
|
||||||
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/ssh",
|
"ImportPath": "golang.org/x/crypto/ssh",
|
||||||
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
|
|
|
@ -82434,6 +82434,41 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/golang.org/x/crypto/nacl/secretbox licensed under: =
|
||||||
|
|
||||||
|
Copyright (c) 2009 The Go Authors. 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 Google Inc. 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
|
||||||
|
OWNER 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.
|
||||||
|
|
||||||
|
= vendor/golang.org/x/crypto/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707 -
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
= vendor/golang.org/x/crypto/pkcs12 licensed under: =
|
= vendor/golang.org/x/crypto/pkcs12 licensed under: =
|
||||||
|
|
||||||
|
@ -82504,6 +82539,76 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/golang.org/x/crypto/poly1305 licensed under: =
|
||||||
|
|
||||||
|
Copyright (c) 2009 The Go Authors. 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 Google Inc. 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
|
||||||
|
OWNER 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.
|
||||||
|
|
||||||
|
= vendor/golang.org/x/crypto/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707 -
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
= vendor/golang.org/x/crypto/salsa20/salsa licensed under: =
|
||||||
|
|
||||||
|
Copyright (c) 2009 The Go Authors. 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 Google Inc. 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
|
||||||
|
OWNER 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.
|
||||||
|
|
||||||
|
= vendor/golang.org/x/crypto/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707 -
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
= vendor/golang.org/x/crypto/ssh licensed under: =
|
= vendor/golang.org/x/crypto/ssh licensed under: =
|
||||||
|
|
||||||
|
|
|
@ -374,6 +374,7 @@ staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory
|
||||||
staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory
|
staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory
|
||||||
staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes
|
staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes
|
||||||
staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/identity
|
staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/identity
|
||||||
|
staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox
|
||||||
staging/src/k8s.io/apiserver/pkg/util/flushwriter
|
staging/src/k8s.io/apiserver/pkg/util/flushwriter
|
||||||
staging/src/k8s.io/apiserver/pkg/util/logs
|
staging/src/k8s.io/apiserver/pkg/util/logs
|
||||||
staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook
|
staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook
|
||||||
|
|
|
@ -574,6 +574,18 @@
|
||||||
"ImportPath": "golang.org/x/crypto/blowfish",
|
"ImportPath": "golang.org/x/crypto/blowfish",
|
||||||
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/nacl/secretbox",
|
||||||
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/poly1305",
|
||||||
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/crypto/salsa20/salsa",
|
||||||
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/crypto/ssh/terminal",
|
"ImportPath": "golang.org/x/crypto/ssh/terminal",
|
||||||
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
"Rev": "d172538b2cfce0c13cee31e647d0367aa8cd2486"
|
||||||
|
|
|
@ -21,6 +21,7 @@ go_library(
|
||||||
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/identity:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/identity:go_default_library",
|
||||||
|
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package encryptionconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -30,10 +31,13 @@ import (
|
||||||
"k8s.io/apiserver/pkg/storage/value"
|
"k8s.io/apiserver/pkg/storage/value"
|
||||||
aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes"
|
aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes"
|
||||||
"k8s.io/apiserver/pkg/storage/value/encrypt/identity"
|
"k8s.io/apiserver/pkg/storage/value/encrypt/identity"
|
||||||
|
"k8s.io/apiserver/pkg/storage/value/encrypt/secretbox"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
aesTransformerPrefixV1 = "k8s:enc:aes:v1:"
|
aesCBCTransformerPrefixV1 = "k8s:enc:aescbc:v1:"
|
||||||
|
aesGCMTransformerPrefixV1 = "k8s:enc:aesgcm:v1:"
|
||||||
|
secretboxTransformerPrefixV1 = "k8s:enc:secretbox:v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetTransformerOverrides returns the transformer overrides by reading and parsing the encryption provider configuration file
|
// GetTransformerOverrides returns the transformer overrides by reading and parsing the encryption provider configuration file
|
||||||
|
@ -102,26 +106,49 @@ func GetPrefixTransformers(config *ResourceConfig) ([]value.PrefixTransformer, e
|
||||||
for _, provider := range config.Providers {
|
for _, provider := range config.Providers {
|
||||||
found := false
|
found := false
|
||||||
|
|
||||||
if provider.AES != nil {
|
var transformer value.PrefixTransformer
|
||||||
transformer, err := GetAESPrefixTransformer(provider.AES)
|
var err error
|
||||||
found = true
|
|
||||||
|
if provider.AESGCM != nil {
|
||||||
|
transformer, err = GetAESPrefixTransformer(provider.AESGCM, aestransformer.NewGCMTransformer, aesGCMTransformerPrefixV1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
result = append(result, transformer)
|
found = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.AESCBC != nil {
|
||||||
|
if found == true {
|
||||||
|
return result, fmt.Errorf("more than one provider specified in a single element, should split into different list elements")
|
||||||
|
}
|
||||||
|
transformer, err = GetAESPrefixTransformer(provider.AESCBC, aestransformer.NewCBCTransformer, aesCBCTransformerPrefixV1)
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.Secretbox != nil {
|
||||||
|
if found == true {
|
||||||
|
return result, fmt.Errorf("more than one provider specified in a single element, should split into different list elements")
|
||||||
|
}
|
||||||
|
transformer, err = GetSecretboxPrefixTransformer(provider.Secretbox)
|
||||||
|
found = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if provider.Identity != nil {
|
if provider.Identity != nil {
|
||||||
if found == true {
|
if found == true {
|
||||||
return result, fmt.Errorf("more than one provider specified in a single element, should split into different list elements")
|
return result, fmt.Errorf("more than one provider specified in a single element, should split into different list elements")
|
||||||
}
|
}
|
||||||
found = true
|
transformer = value.PrefixTransformer{
|
||||||
result = append(result, value.PrefixTransformer{
|
|
||||||
Transformer: identity.NewEncryptCheckTransformer(),
|
Transformer: identity.NewEncryptCheckTransformer(),
|
||||||
Prefix: []byte{},
|
Prefix: []byte{},
|
||||||
})
|
}
|
||||||
|
found = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
result = append(result, transformer)
|
||||||
|
|
||||||
if found == false {
|
if found == false {
|
||||||
return result, fmt.Errorf("invalid provider configuration provided")
|
return result, fmt.Errorf("invalid provider configuration provided")
|
||||||
}
|
}
|
||||||
|
@ -129,8 +156,12 @@ func GetPrefixTransformers(config *ResourceConfig) ([]value.PrefixTransformer, e
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAESPrefixTransformer returns a prefix transformer from the provided configuration
|
// BlockTransformerFunc taske an AES cipher block and returns a value transformer.
|
||||||
func GetAESPrefixTransformer(config *AESConfig) (value.PrefixTransformer, error) {
|
type BlockTransformerFunc func(cipher.Block) value.Transformer
|
||||||
|
|
||||||
|
// GetAESPrefixTransformer returns a prefix transformer from the provided configuration.
|
||||||
|
// Returns an AES transformer based on the provided prefix and block transformer.
|
||||||
|
func GetAESPrefixTransformer(config *AESConfig, fn BlockTransformerFunc, prefix string) (value.PrefixTransformer, error) {
|
||||||
var result value.PrefixTransformer
|
var result value.PrefixTransformer
|
||||||
|
|
||||||
if len(config.Keys) == 0 {
|
if len(config.Keys) == 0 {
|
||||||
|
@ -160,7 +191,7 @@ func GetAESPrefixTransformer(config *AESConfig) (value.PrefixTransformer, error)
|
||||||
// Create a new PrefixTransformer for this key
|
// Create a new PrefixTransformer for this key
|
||||||
keyTransformers = append(keyTransformers,
|
keyTransformers = append(keyTransformers,
|
||||||
value.PrefixTransformer{
|
value.PrefixTransformer{
|
||||||
Transformer: aestransformer.NewGCMTransformer(block),
|
Transformer: fn(block),
|
||||||
Prefix: []byte(keyData.Name + ":"),
|
Prefix: []byte(keyData.Name + ":"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -172,7 +203,58 @@ func GetAESPrefixTransformer(config *AESConfig) (value.PrefixTransformer, error)
|
||||||
// Create a PrefixTransformer which shall later be put in a list with other providers
|
// Create a PrefixTransformer which shall later be put in a list with other providers
|
||||||
result = value.PrefixTransformer{
|
result = value.PrefixTransformer{
|
||||||
Transformer: keyTransformer,
|
Transformer: keyTransformer,
|
||||||
Prefix: []byte(aesTransformerPrefixV1),
|
Prefix: []byte(prefix),
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSecretboxPrefixTransformer returns a prefix transformer from the provided configuration
|
||||||
|
func GetSecretboxPrefixTransformer(config *SecretboxConfig) (value.PrefixTransformer, error) {
|
||||||
|
var result value.PrefixTransformer
|
||||||
|
|
||||||
|
if len(config.Keys) == 0 {
|
||||||
|
return result, fmt.Errorf("secretbox provider has no valid keys")
|
||||||
|
}
|
||||||
|
for _, key := range config.Keys {
|
||||||
|
if key.Name == "" {
|
||||||
|
return result, fmt.Errorf("key with invalid name provided")
|
||||||
|
}
|
||||||
|
if key.Secret == "" {
|
||||||
|
return result, fmt.Errorf("key %v has no provided secret", key.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyTransformers := []value.PrefixTransformer{}
|
||||||
|
|
||||||
|
for _, keyData := range config.Keys {
|
||||||
|
key, err := base64.StdEncoding.DecodeString(keyData.Secret)
|
||||||
|
if err != nil {
|
||||||
|
return result, fmt.Errorf("could not obtain secret for named key %s: %s", keyData.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(key) != 32 {
|
||||||
|
return result, fmt.Errorf("expected key size 32 for aes-cbc provider, got %v", len(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
keyArray := [32]byte{}
|
||||||
|
copy(keyArray[:], key)
|
||||||
|
|
||||||
|
// Create a new PrefixTransformer for this key
|
||||||
|
keyTransformers = append(keyTransformers,
|
||||||
|
value.PrefixTransformer{
|
||||||
|
Transformer: secretbox.NewSecretboxTransformer(keyArray),
|
||||||
|
Prefix: []byte(keyData.Name + ":"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a prefixTransformer which can choose between these keys
|
||||||
|
keyTransformer := value.NewPrefixTransformers(
|
||||||
|
fmt.Errorf("no matching key was found for the provided Secretbox transformer"), keyTransformers...)
|
||||||
|
|
||||||
|
// Create a PrefixTransformer which shall later be put in a list with other providers
|
||||||
|
result = value.PrefixTransformer{
|
||||||
|
Transformer: keyTransformer,
|
||||||
|
Prefix: []byte(secretboxTransformerPrefixV1),
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,69 @@ resources:
|
||||||
- namespaces
|
- namespaces
|
||||||
providers:
|
providers:
|
||||||
- identity: {}
|
- identity: {}
|
||||||
- aes:
|
- aesgcm:
|
||||||
|
keys:
|
||||||
|
- name: key1
|
||||||
|
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||||
|
- name: key2
|
||||||
|
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||||
|
- aescbc:
|
||||||
|
keys:
|
||||||
|
- name: key1
|
||||||
|
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||||
|
- name: key2
|
||||||
|
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||||
|
- secretbox:
|
||||||
|
keys:
|
||||||
|
- name: key1
|
||||||
|
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
|
||||||
|
`
|
||||||
|
|
||||||
|
correctConfigWithAesGcmFirst = `
|
||||||
|
kind: EncryptionConfig
|
||||||
|
apiVersion: v1
|
||||||
|
resources:
|
||||||
|
- resources:
|
||||||
|
- secrets
|
||||||
|
providers:
|
||||||
|
- aesgcm:
|
||||||
|
keys:
|
||||||
|
- name: key1
|
||||||
|
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||||
|
- name: key2
|
||||||
|
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||||
|
- secretbox:
|
||||||
|
keys:
|
||||||
|
- name: key1
|
||||||
|
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
|
||||||
|
- aescbc:
|
||||||
|
keys:
|
||||||
|
- name: key1
|
||||||
|
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||||
|
- name: key2
|
||||||
|
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||||
|
- identity: {}
|
||||||
|
`
|
||||||
|
|
||||||
|
correctConfigWithAesCbcFirst = `
|
||||||
|
kind: EncryptionConfig
|
||||||
|
apiVersion: v1
|
||||||
|
resources:
|
||||||
|
- resources:
|
||||||
|
- secrets
|
||||||
|
providers:
|
||||||
|
- aescbc:
|
||||||
|
keys:
|
||||||
|
- name: key1
|
||||||
|
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||||
|
- name: key2
|
||||||
|
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||||
|
- identity: {}
|
||||||
|
- secretbox:
|
||||||
|
keys:
|
||||||
|
- name: key1
|
||||||
|
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
|
||||||
|
- aesgcm:
|
||||||
keys:
|
keys:
|
||||||
- name: key1
|
- name: key1
|
||||||
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||||
|
@ -47,20 +109,30 @@ resources:
|
||||||
secret: dGhpcyBpcyBwYXNzd29yZA==
|
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||||
`
|
`
|
||||||
|
|
||||||
correctConfigWithAesFirst = `
|
correctConfigWithSecretboxFirst = `
|
||||||
kind: EncryptionConfig
|
kind: EncryptionConfig
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
resources:
|
resources:
|
||||||
- resources:
|
- resources:
|
||||||
- secrets
|
- secrets
|
||||||
providers:
|
providers:
|
||||||
- aes:
|
- secretbox:
|
||||||
|
keys:
|
||||||
|
- name: key1
|
||||||
|
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
|
||||||
|
- aescbc:
|
||||||
keys:
|
keys:
|
||||||
- name: key1
|
- name: key1
|
||||||
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||||
- name: key2
|
- name: key2
|
||||||
secret: dGhpcyBpcyBwYXNzd29yZA==
|
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||||
- identity: {}
|
- identity: {}
|
||||||
|
- aesgcm:
|
||||||
|
keys:
|
||||||
|
- name: key1
|
||||||
|
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||||
|
- name: key2
|
||||||
|
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||||
`
|
`
|
||||||
|
|
||||||
incorrectConfigNoSecretForKey = `
|
incorrectConfigNoSecretForKey = `
|
||||||
|
@ -71,7 +143,7 @@ resources:
|
||||||
- namespaces
|
- namespaces
|
||||||
- secrets
|
- secrets
|
||||||
providers:
|
providers:
|
||||||
- aes:
|
- aesgcm:
|
||||||
keys:
|
keys:
|
||||||
- name: key1
|
- name: key1
|
||||||
`
|
`
|
||||||
|
@ -84,7 +156,7 @@ resources:
|
||||||
- namespaces
|
- namespaces
|
||||||
- secrets
|
- secrets
|
||||||
providers:
|
providers:
|
||||||
- aes:
|
- aesgcm:
|
||||||
keys:
|
keys:
|
||||||
- name: key1
|
- name: key1
|
||||||
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||||
|
@ -103,58 +175,60 @@ func TestEncryptionProviderConfigCorrect(t *testing.T) {
|
||||||
t.Fatalf("error while parsing configuration file: %s.\nThe file was:\n%s", err, correctConfigWithIdentityFirst)
|
t.Fatalf("error while parsing configuration file: %s.\nThe file was:\n%s", err, correctConfigWithIdentityFirst)
|
||||||
}
|
}
|
||||||
|
|
||||||
aesFirstTransformerOverrides, err := ParseEncryptionConfiguration(strings.NewReader(correctConfigWithAesFirst))
|
aesGcmFirstTransformerOverrides, err := ParseEncryptionConfiguration(strings.NewReader(correctConfigWithAesGcmFirst))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error while parsing configuration file: %s.\nThe file was:\n%s", err, correctConfigWithAesFirst)
|
t.Fatalf("error while parsing configuration file: %s.\nThe file was:\n%s", err, correctConfigWithAesGcmFirst)
|
||||||
|
}
|
||||||
|
|
||||||
|
aesCbcFirstTransformerOverrides, err := ParseEncryptionConfiguration(strings.NewReader(correctConfigWithAesCbcFirst))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error while parsing configuration file: %s.\nThe file was:\n%s", err, correctConfigWithAesCbcFirst)
|
||||||
|
}
|
||||||
|
|
||||||
|
secretboxFirstTransformerOverrides, err := ParseEncryptionConfiguration(strings.NewReader(correctConfigWithSecretboxFirst))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error while parsing configuration file: %s.\nThe file was:\n%s", err, correctConfigWithSecretboxFirst)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick the transformer for any of the returned resources.
|
// Pick the transformer for any of the returned resources.
|
||||||
identityFirstTransformer := identityFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
|
identityFirstTransformer := identityFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
|
||||||
aesFirstTransformer := aesFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
|
aesGcmFirstTransformer := aesGcmFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
|
||||||
|
aesCbcFirstTransformer := aesCbcFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
|
||||||
|
secretboxFirstTransformer := secretboxFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
|
||||||
|
|
||||||
context := value.DefaultContext([]byte(sampleContextText))
|
context := value.DefaultContext([]byte(sampleContextText))
|
||||||
originalText := []byte(sampleText)
|
originalText := []byte(sampleText)
|
||||||
|
|
||||||
testCases := []struct {
|
transformers := []struct {
|
||||||
WritingTransformer value.Transformer
|
Transformer value.Transformer
|
||||||
Name string
|
Name string
|
||||||
AesStale bool
|
|
||||||
IdentityStale bool
|
|
||||||
}{
|
}{
|
||||||
{aesFirstTransformer, "aesFirst", false, true},
|
{aesGcmFirstTransformer, "aesGcmFirst"},
|
||||||
{identityFirstTransformer, "identityFirst", true, false},
|
{aesCbcFirstTransformer, "aesCbcFirst"},
|
||||||
|
{secretboxFirstTransformer, "secretboxFirst"},
|
||||||
|
{identityFirstTransformer, "identityFirst"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range transformers {
|
||||||
transformedData, err := testCase.WritingTransformer.TransformToStorage(originalText, context)
|
transformedData, err := testCase.Transformer.TransformToStorage(originalText, context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s: error while transforming data to storage: %s", testCase.Name, err)
|
t.Fatalf("%s: error while transforming data to storage: %s", testCase.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
aesUntransformedData, stale, err := aesFirstTransformer.TransformFromStorage(transformedData, context)
|
for _, transformer := range transformers {
|
||||||
if err != nil {
|
untransformedData, stale, err := transformer.Transformer.TransformFromStorage(transformedData, context)
|
||||||
t.Fatalf("%s: error while reading using aesFirst transformer: %s", testCase.Name, err)
|
if err != nil {
|
||||||
}
|
t.Fatalf("%s: error while reading using %s transformer: %s", testCase.Name, transformer.Name, err)
|
||||||
if stale != testCase.AesStale {
|
}
|
||||||
t.Fatalf("%s: wrong stale information on reading using aesFirst transformer, should be %v", testCase.Name, testCase.AesStale)
|
if stale != (transformer.Name != testCase.Name) {
|
||||||
}
|
t.Fatalf("%s: wrong stale information on reading using %s transformer, should be %v", testCase.Name, transformer.Name, testCase.Name == transformer.Name)
|
||||||
|
}
|
||||||
identityUntransformedData, stale, err := identityFirstTransformer.TransformFromStorage(transformedData, context)
|
if bytes.Compare(untransformedData, originalText) != 0 {
|
||||||
if err != nil {
|
t.Fatalf("%s: %s transformer transformed data incorrectly. Expected: %v, got %v", testCase.Name, transformer.Name, originalText, untransformedData)
|
||||||
t.Fatalf("%s: error while reading using identityFirst transformer: %s", testCase.Name, err)
|
}
|
||||||
}
|
|
||||||
if stale != testCase.IdentityStale {
|
|
||||||
t.Fatalf("%s: wrong stale information on reading using identityFirst transformer, should be %v", testCase.Name, testCase.IdentityStale)
|
|
||||||
}
|
|
||||||
|
|
||||||
if bytes.Compare(aesUntransformedData, originalText) != 0 {
|
|
||||||
t.Fatalf("%s: aesFirst transformer transformed data incorrectly. Expected: %v, got %v", testCase.Name, originalText, aesUntransformedData)
|
|
||||||
}
|
|
||||||
|
|
||||||
if bytes.Compare(identityUntransformedData, originalText) != 0 {
|
|
||||||
t.Fatalf("%s: identityFirst transformer transformed data incorrectly. Expected: %v, got %v", testCase.Name, originalText, aesUntransformedData)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Throw error if key has no secret
|
// Throw error if key has no secret
|
||||||
|
|
|
@ -37,8 +37,12 @@ type ResourceConfig struct {
|
||||||
|
|
||||||
// ProviderConfig stores the provided configuration for an encryption provider.
|
// ProviderConfig stores the provided configuration for an encryption provider.
|
||||||
type ProviderConfig struct {
|
type ProviderConfig struct {
|
||||||
// aes is the configuration for the AEAD-GCM transformer.
|
// aesgcm is the configuration for the AES-GCM transformer.
|
||||||
AES *AESConfig `json:"aes,omitempty"`
|
AESGCM *AESConfig `json:"aesgcm,omitempty"`
|
||||||
|
// aescbc is the configuration for the AES-CBC transformer.
|
||||||
|
AESCBC *AESConfig `json:"aescbc,omitempty"`
|
||||||
|
// secretbox is the configuration for the Secretbox based transformer.
|
||||||
|
Secretbox *SecretboxConfig `json:"secretbox,omitempty"`
|
||||||
// identity is the (empty) configuration for the identity transformer.
|
// identity is the (empty) configuration for the identity transformer.
|
||||||
Identity *IdentityConfig `json:"identity,omitempty"`
|
Identity *IdentityConfig `json:"identity,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -49,6 +53,12 @@ type AESConfig struct {
|
||||||
Keys []Key `json:"keys"`
|
Keys []Key `json:"keys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SECRETBOXConfig contains the API configuration for an Secretbox transformer.
|
||||||
|
type SecretboxConfig struct {
|
||||||
|
// keys is a list of keys to be used for creating the Secretbox transformer.
|
||||||
|
Keys []Key `json:"keys"`
|
||||||
|
}
|
||||||
|
|
||||||
// Key contains name and secret of the provided key for AES transformer.
|
// Key contains name and secret of the provided key for AES transformer.
|
||||||
type Key struct {
|
type Key struct {
|
||||||
// name is the name of the key to be used while storing data to disk.
|
// name is the name of the key to be used while storing data to disk.
|
||||||
|
|
|
@ -18,9 +18,13 @@ limitations under the License.
|
||||||
package aes
|
package aes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"k8s.io/apiserver/pkg/storage/value"
|
"k8s.io/apiserver/pkg/storage/value"
|
||||||
)
|
)
|
||||||
|
@ -78,3 +82,71 @@ func (t *gcm) TransformToStorage(data []byte, context value.Context) ([]byte, er
|
||||||
cipherText := aead.Seal(result[nonceSize:nonceSize], result[:nonceSize], data, context.AuthenticatedData())
|
cipherText := aead.Seal(result[nonceSize:nonceSize], result[:nonceSize], data, context.AuthenticatedData())
|
||||||
return result[:nonceSize+len(cipherText)], nil
|
return result[:nonceSize+len(cipherText)], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cbc implements encryption at rest of the provided values given a cipher.Block algorithm.
|
||||||
|
type cbc struct {
|
||||||
|
block cipher.Block
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCBCTransformer takes the given block cipher and performs encryption and decryption on the given
|
||||||
|
// data.
|
||||||
|
func NewCBCTransformer(block cipher.Block) value.Transformer {
|
||||||
|
return &cbc{block: block}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
errInvalidBlockSize = fmt.Errorf("the stored data is not a multiple of the block size")
|
||||||
|
errInvalidPKCS7Data = errors.New("invalid PKCS7 data (empty or not padded)")
|
||||||
|
errInvalidPKCS7Padding = errors.New("invalid padding on input")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t *cbc) TransformFromStorage(data []byte, context value.Context) ([]byte, bool, error) {
|
||||||
|
blockSize := aes.BlockSize
|
||||||
|
if len(data) < blockSize {
|
||||||
|
return nil, false, fmt.Errorf("the stored data was shorter than the required size")
|
||||||
|
}
|
||||||
|
iv := data[:blockSize]
|
||||||
|
data = data[blockSize:]
|
||||||
|
|
||||||
|
if len(data)%blockSize != 0 {
|
||||||
|
return nil, false, errInvalidBlockSize
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]byte, len(data))
|
||||||
|
copy(result, data)
|
||||||
|
mode := cipher.NewCBCDecrypter(t.block, iv)
|
||||||
|
mode.CryptBlocks(result, result)
|
||||||
|
|
||||||
|
// remove and verify PKCS#7 padding for CBC
|
||||||
|
c := result[len(result)-1]
|
||||||
|
paddingSize := int(c)
|
||||||
|
size := len(result) - paddingSize
|
||||||
|
if paddingSize == 0 || paddingSize > len(result) {
|
||||||
|
return nil, false, errInvalidPKCS7Data
|
||||||
|
}
|
||||||
|
for i := 0; i < paddingSize; i++ {
|
||||||
|
if result[size+i] != c {
|
||||||
|
return nil, false, errInvalidPKCS7Padding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result[:size], false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *cbc) TransformToStorage(data []byte, context value.Context) ([]byte, error) {
|
||||||
|
blockSize := aes.BlockSize
|
||||||
|
paddingSize := blockSize - (len(data) % blockSize)
|
||||||
|
result := make([]byte, blockSize+len(data)+paddingSize)
|
||||||
|
iv := result[:blockSize]
|
||||||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to read sufficient random bytes")
|
||||||
|
}
|
||||||
|
copy(result[blockSize:], data)
|
||||||
|
|
||||||
|
// add PKCS#7 padding for CBC
|
||||||
|
copy(result[blockSize+len(data):], bytes.Repeat([]byte{byte(paddingSize)}, paddingSize))
|
||||||
|
|
||||||
|
mode := cipher.NewCBCEncrypter(t.block, iv)
|
||||||
|
mode.CryptBlocks(result[blockSize:], result[blockSize:])
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,11 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/apiserver/pkg/storage/value"
|
"k8s.io/apiserver/pkg/storage/value"
|
||||||
|
@ -93,6 +97,58 @@ func TestGCMKeyRotation(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCBCKeyRotation(t *testing.T) {
|
||||||
|
testErr := fmt.Errorf("test error")
|
||||||
|
block1, err := aes.NewCipher([]byte("abcdefghijklmnop"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
block2, err := aes.NewCipher([]byte("0123456789abcdef"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
context := value.DefaultContext([]byte("authenticated_data"))
|
||||||
|
|
||||||
|
p := value.NewPrefixTransformers(testErr,
|
||||||
|
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewCBCTransformer(block1)},
|
||||||
|
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewCBCTransformer(block2)},
|
||||||
|
)
|
||||||
|
out, err := p.TransformToStorage([]byte("firstvalue"), context)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.HasPrefix(out, []byte("first:")) {
|
||||||
|
t.Fatalf("unexpected prefix: %q", out)
|
||||||
|
}
|
||||||
|
from, stale, err := p.TransformFromStorage(out, context)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if stale || !bytes.Equal([]byte("firstvalue"), from) {
|
||||||
|
t.Fatalf("unexpected data: %t %q", stale, from)
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify changing the context fails storage
|
||||||
|
from, stale, err = p.TransformFromStorage(out, value.DefaultContext([]byte("incorrect_context")))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CBC mode does not support authentication: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// reverse the order, use the second key
|
||||||
|
p = value.NewPrefixTransformers(testErr,
|
||||||
|
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewCBCTransformer(block2)},
|
||||||
|
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewCBCTransformer(block1)},
|
||||||
|
)
|
||||||
|
from, stale, err = p.TransformFromStorage(out, context)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !stale || !bytes.Equal([]byte("firstvalue"), from) {
|
||||||
|
t.Fatalf("unexpected data: %t %q", stale, from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkGCMRead_16_1024(b *testing.B) { benchmarkGCMRead(b, 16, 1024, false) }
|
func BenchmarkGCMRead_16_1024(b *testing.B) { benchmarkGCMRead(b, 16, 1024, false) }
|
||||||
func BenchmarkGCMRead_32_1024(b *testing.B) { benchmarkGCMRead(b, 32, 1024, false) }
|
func BenchmarkGCMRead_32_1024(b *testing.B) { benchmarkGCMRead(b, 32, 1024, false) }
|
||||||
func BenchmarkGCMRead_32_16384(b *testing.B) { benchmarkGCMRead(b, 32, 16384, false) }
|
func BenchmarkGCMRead_32_16384(b *testing.B) { benchmarkGCMRead(b, 32, 16384, false) }
|
||||||
|
@ -170,3 +226,147 @@ func benchmarkGCMWrite(b *testing.B, keyLength int, valueLength int) {
|
||||||
}
|
}
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkCBCRead_32_1024(b *testing.B) { benchmarkCBCRead(b, 32, 1024, false) }
|
||||||
|
func BenchmarkCBCRead_32_16384(b *testing.B) { benchmarkCBCRead(b, 32, 16384, false) }
|
||||||
|
func BenchmarkCBCRead_32_16384_Stale(b *testing.B) { benchmarkCBCRead(b, 32, 16384, true) }
|
||||||
|
|
||||||
|
func BenchmarkCBCWrite_32_1024(b *testing.B) { benchmarkCBCWrite(b, 32, 1024) }
|
||||||
|
func BenchmarkCBCWrite_32_16384(b *testing.B) { benchmarkCBCWrite(b, 32, 16384) }
|
||||||
|
|
||||||
|
func benchmarkCBCRead(b *testing.B, keyLength int, valueLength int, stale bool) {
|
||||||
|
block1, err := aes.NewCipher(bytes.Repeat([]byte("a"), keyLength))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
block2, err := aes.NewCipher(bytes.Repeat([]byte("b"), keyLength))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
p := value.NewPrefixTransformers(nil,
|
||||||
|
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewCBCTransformer(block1)},
|
||||||
|
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewCBCTransformer(block2)},
|
||||||
|
)
|
||||||
|
|
||||||
|
context := value.DefaultContext([]byte("authenticated_data"))
|
||||||
|
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
|
||||||
|
|
||||||
|
out, err := p.TransformToStorage(v, context)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
// reverse the key order if stale
|
||||||
|
if stale {
|
||||||
|
p = value.NewPrefixTransformers(nil,
|
||||||
|
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewCBCTransformer(block1)},
|
||||||
|
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewCBCTransformer(block2)},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
from, stale, err := p.TransformFromStorage(out, context)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
if stale {
|
||||||
|
b.Fatalf("unexpected data: %t %q", stale, from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkCBCWrite(b *testing.B, keyLength int, valueLength int) {
|
||||||
|
block1, err := aes.NewCipher(bytes.Repeat([]byte("a"), keyLength))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
block2, err := aes.NewCipher(bytes.Repeat([]byte("b"), keyLength))
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
p := value.NewPrefixTransformers(nil,
|
||||||
|
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewCBCTransformer(block1)},
|
||||||
|
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewCBCTransformer(block2)},
|
||||||
|
)
|
||||||
|
|
||||||
|
context := value.DefaultContext([]byte("authenticated_data"))
|
||||||
|
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, err := p.TransformToStorage(v, context)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRoundTrip(t *testing.T) {
|
||||||
|
lengths := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 128, 1024}
|
||||||
|
|
||||||
|
aes16block, err := aes.NewCipher([]byte(bytes.Repeat([]byte("a"), 16)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
aes24block, err := aes.NewCipher([]byte(bytes.Repeat([]byte("b"), 24)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
aes32block, err := aes.NewCipher([]byte(bytes.Repeat([]byte("c"), 32)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
context value.Context
|
||||||
|
t value.Transformer
|
||||||
|
}{
|
||||||
|
{name: "GCM 16 byte key", t: NewGCMTransformer(aes16block)},
|
||||||
|
{name: "GCM 24 byte key", t: NewGCMTransformer(aes24block)},
|
||||||
|
{name: "GCM 32 byte key", t: NewGCMTransformer(aes32block)},
|
||||||
|
{name: "CBC 32 byte key", t: NewCBCTransformer(aes32block)},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
context := tt.context
|
||||||
|
if context == nil {
|
||||||
|
context = value.DefaultContext("")
|
||||||
|
}
|
||||||
|
for _, l := range lengths {
|
||||||
|
data := make([]byte, l)
|
||||||
|
if _, err := io.ReadFull(rand.Reader, data); err != nil {
|
||||||
|
t.Fatalf("unable to read sufficient random bytes: %v", err)
|
||||||
|
}
|
||||||
|
original := append([]byte{}, data...)
|
||||||
|
|
||||||
|
ciphertext, err := tt.t.TransformToStorage(data, context)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("TransformToStorage error = %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
result, stale, err := tt.t.TransformFromStorage(ciphertext, context)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("TransformFromStorage error = %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if stale {
|
||||||
|
t.Errorf("unexpected stale output")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case l == 0:
|
||||||
|
if len(result) != 0 {
|
||||||
|
t.Errorf("Round trip failed len=%d\noriginal:\n%s\nresult:\n%s", l, hex.Dump(original), hex.Dump(result))
|
||||||
|
}
|
||||||
|
case !reflect.DeepEqual(original, result):
|
||||||
|
t.Errorf("Round trip failed len=%d\noriginal:\n%s\nresult:\n%s", l, hex.Dump(original), hex.Dump(result))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@io_bazel_rules_go//go:def.bzl",
|
||||||
|
"go_library",
|
||||||
|
"go_test",
|
||||||
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "go_default_test",
|
||||||
|
srcs = ["secretbox_test.go"],
|
||||||
|
library = ":go_default_library",
|
||||||
|
tags = ["automanaged"],
|
||||||
|
deps = ["//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library"],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["secretbox.go"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
deps = [
|
||||||
|
"//vendor/golang.org/x/crypto/nacl/secretbox:go_default_library",
|
||||||
|
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package secretbox transforms values for storage at rest using XSalsa20 and Poly1305.
|
||||||
|
package secretbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/nacl/secretbox"
|
||||||
|
|
||||||
|
"k8s.io/apiserver/pkg/storage/value"
|
||||||
|
)
|
||||||
|
|
||||||
|
// secretbox implements at rest encryption of the provided values given a 32 byte secret key.
|
||||||
|
// Uses a standard 24 byte nonce (placed at the the beginning of the cipher text) generated
|
||||||
|
// from crypto/rand. Does not perform authentication of the data at rest.
|
||||||
|
type secretboxTransformer struct {
|
||||||
|
key [32]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
const nonceSize = 24
|
||||||
|
|
||||||
|
// NewSecretboxTransformer takes the given key and performs encryption and decryption on the given
|
||||||
|
// data.
|
||||||
|
func NewSecretboxTransformer(key [32]byte) value.Transformer {
|
||||||
|
return &secretboxTransformer{key: key}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *secretboxTransformer) TransformFromStorage(data []byte, context value.Context) ([]byte, bool, error) {
|
||||||
|
if len(data) < (secretbox.Overhead + nonceSize) {
|
||||||
|
return nil, false, fmt.Errorf("the stored data was shorter than the required size")
|
||||||
|
}
|
||||||
|
var nonce [nonceSize]byte
|
||||||
|
copy(nonce[:], data[:nonceSize])
|
||||||
|
data = data[nonceSize:]
|
||||||
|
out := make([]byte, 0, len(data)-secretbox.Overhead)
|
||||||
|
result, ok := secretbox.Open(out, data, &nonce, &t.key)
|
||||||
|
if !ok {
|
||||||
|
return nil, false, fmt.Errorf("output array was not large enough for encryption")
|
||||||
|
}
|
||||||
|
return result, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *secretboxTransformer) TransformToStorage(data []byte, context value.Context) ([]byte, error) {
|
||||||
|
var nonce [nonceSize]byte
|
||||||
|
n, err := rand.Read(nonce[:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if n != nonceSize {
|
||||||
|
return nil, fmt.Errorf("unable to read sufficient random bytes")
|
||||||
|
}
|
||||||
|
return secretbox.Seal(nonce[:], data, &nonce, &t.key), nil
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package secretbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/apiserver/pkg/storage/value"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
key1 = [32]byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}
|
||||||
|
key2 = [32]byte{0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSecretboxKeyRotation(t *testing.T) {
|
||||||
|
testErr := fmt.Errorf("test error")
|
||||||
|
context := value.DefaultContext([]byte("authenticated_data"))
|
||||||
|
|
||||||
|
p := value.NewPrefixTransformers(testErr,
|
||||||
|
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)},
|
||||||
|
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)},
|
||||||
|
)
|
||||||
|
out, err := p.TransformToStorage([]byte("firstvalue"), context)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.HasPrefix(out, []byte("first:")) {
|
||||||
|
t.Fatalf("unexpected prefix: %q", out)
|
||||||
|
}
|
||||||
|
from, stale, err := p.TransformFromStorage(out, context)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if stale || !bytes.Equal([]byte("firstvalue"), from) {
|
||||||
|
t.Fatalf("unexpected data: %t %q", stale, from)
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify changing the context does not fails storage
|
||||||
|
// Secretbox is not currently an authenticating store
|
||||||
|
from, stale, err = p.TransformFromStorage(out, value.DefaultContext([]byte("incorrect_context")))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("secretbox is not authenticated")
|
||||||
|
}
|
||||||
|
|
||||||
|
// reverse the order, use the second key
|
||||||
|
p = value.NewPrefixTransformers(testErr,
|
||||||
|
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)},
|
||||||
|
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)},
|
||||||
|
)
|
||||||
|
from, stale, err = p.TransformFromStorage(out, context)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !stale || !bytes.Equal([]byte("firstvalue"), from) {
|
||||||
|
t.Fatalf("unexpected data: %t %q", stale, from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSecretboxRead_32_1024(b *testing.B) { benchmarkSecretboxRead(b, 32, 1024, false) }
|
||||||
|
func BenchmarkSecretboxRead_32_16384(b *testing.B) { benchmarkSecretboxRead(b, 32, 16384, false) }
|
||||||
|
func BenchmarkSecretboxRead_32_16384_Stale(b *testing.B) { benchmarkSecretboxRead(b, 32, 16384, true) }
|
||||||
|
|
||||||
|
func BenchmarkSecretboxWrite_32_1024(b *testing.B) { benchmarkSecretboxWrite(b, 32, 1024) }
|
||||||
|
func BenchmarkSecretboxWrite_32_16384(b *testing.B) { benchmarkSecretboxWrite(b, 32, 16384) }
|
||||||
|
|
||||||
|
func benchmarkSecretboxRead(b *testing.B, keyLength int, valueLength int, stale bool) {
|
||||||
|
p := value.NewPrefixTransformers(nil,
|
||||||
|
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)},
|
||||||
|
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)},
|
||||||
|
)
|
||||||
|
|
||||||
|
context := value.DefaultContext([]byte("authenticated_data"))
|
||||||
|
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
|
||||||
|
|
||||||
|
out, err := p.TransformToStorage(v, context)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
// reverse the key order if stale
|
||||||
|
if stale {
|
||||||
|
p = value.NewPrefixTransformers(nil,
|
||||||
|
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)},
|
||||||
|
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
from, stale, err := p.TransformFromStorage(out, context)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
if stale {
|
||||||
|
b.Fatalf("unexpected data: %t %q", stale, from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkSecretboxWrite(b *testing.B, keyLength int, valueLength int) {
|
||||||
|
p := value.NewPrefixTransformers(nil,
|
||||||
|
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)},
|
||||||
|
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)},
|
||||||
|
)
|
||||||
|
|
||||||
|
context := value.DefaultContext([]byte("authenticated_data"))
|
||||||
|
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, err := p.TransformToStorage(v, context)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRoundTrip(t *testing.T) {
|
||||||
|
lengths := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 128, 1024}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
context value.Context
|
||||||
|
t value.Transformer
|
||||||
|
}{
|
||||||
|
{name: "GCM 16 byte key", t: NewSecretboxTransformer(key1)},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
context := tt.context
|
||||||
|
if context == nil {
|
||||||
|
context = value.DefaultContext("")
|
||||||
|
}
|
||||||
|
for _, l := range lengths {
|
||||||
|
data := make([]byte, l)
|
||||||
|
if _, err := io.ReadFull(rand.Reader, data); err != nil {
|
||||||
|
t.Fatalf("unable to read sufficient random bytes: %v", err)
|
||||||
|
}
|
||||||
|
original := append([]byte{}, data...)
|
||||||
|
|
||||||
|
ciphertext, err := tt.t.TransformToStorage(data, context)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("TransformToStorage error = %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
result, stale, err := tt.t.TransformFromStorage(ciphertext, context)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("TransformFromStorage error = %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if stale {
|
||||||
|
t.Errorf("unexpected stale output")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case l == 0:
|
||||||
|
if len(result) != 0 {
|
||||||
|
t.Errorf("Round trip failed len=%d\noriginal:\n%s\nresult:\n%s", l, hex.Dump(original), hex.Dump(result))
|
||||||
|
}
|
||||||
|
case !reflect.DeepEqual(original, result):
|
||||||
|
t.Errorf("Round trip failed len=%d\noriginal:\n%s\nresult:\n%s", l, hex.Dump(original), hex.Dump(result))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -320,7 +320,10 @@ filegroup(
|
||||||
"//vendor/golang.org/x/crypto/blowfish:all-srcs",
|
"//vendor/golang.org/x/crypto/blowfish:all-srcs",
|
||||||
"//vendor/golang.org/x/crypto/curve25519:all-srcs",
|
"//vendor/golang.org/x/crypto/curve25519:all-srcs",
|
||||||
"//vendor/golang.org/x/crypto/ed25519:all-srcs",
|
"//vendor/golang.org/x/crypto/ed25519:all-srcs",
|
||||||
|
"//vendor/golang.org/x/crypto/nacl/secretbox:all-srcs",
|
||||||
"//vendor/golang.org/x/crypto/pkcs12:all-srcs",
|
"//vendor/golang.org/x/crypto/pkcs12:all-srcs",
|
||||||
|
"//vendor/golang.org/x/crypto/poly1305:all-srcs",
|
||||||
|
"//vendor/golang.org/x/crypto/salsa20/salsa:all-srcs",
|
||||||
"//vendor/golang.org/x/crypto/ssh:all-srcs",
|
"//vendor/golang.org/x/crypto/ssh:all-srcs",
|
||||||
"//vendor/golang.org/x/exp/inotify:all-srcs",
|
"//vendor/golang.org/x/exp/inotify:all-srcs",
|
||||||
"//vendor/golang.org/x/net/context:all-srcs",
|
"//vendor/golang.org/x/net/context:all-srcs",
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@io_bazel_rules_go//go:def.bzl",
|
||||||
|
"go_library",
|
||||||
|
)
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["secretbox.go"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
deps = [
|
||||||
|
"//vendor/golang.org/x/crypto/poly1305:go_default_library",
|
||||||
|
"//vendor/golang.org/x/crypto/salsa20/salsa:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
|
@ -0,0 +1,149 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package secretbox encrypts and authenticates small messages.
|
||||||
|
|
||||||
|
Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with
|
||||||
|
secret-key cryptography. The length of messages is not hidden.
|
||||||
|
|
||||||
|
It is the caller's responsibility to ensure the uniqueness of nonces—for
|
||||||
|
example, by using nonce 1 for the first message, nonce 2 for the second
|
||||||
|
message, etc. Nonces are long enough that randomly generated nonces have
|
||||||
|
negligible risk of collision.
|
||||||
|
|
||||||
|
This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html.
|
||||||
|
*/
|
||||||
|
package secretbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/crypto/poly1305"
|
||||||
|
"golang.org/x/crypto/salsa20/salsa"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Overhead is the number of bytes of overhead when boxing a message.
|
||||||
|
const Overhead = poly1305.TagSize
|
||||||
|
|
||||||
|
// setup produces a sub-key and Salsa20 counter given a nonce and key.
|
||||||
|
func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) {
|
||||||
|
// We use XSalsa20 for encryption so first we need to generate a
|
||||||
|
// key and nonce with HSalsa20.
|
||||||
|
var hNonce [16]byte
|
||||||
|
copy(hNonce[:], nonce[:])
|
||||||
|
salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma)
|
||||||
|
|
||||||
|
// The final 8 bytes of the original nonce form the new nonce.
|
||||||
|
copy(counter[:], nonce[16:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// sliceForAppend takes a slice and a requested number of bytes. It returns a
|
||||||
|
// slice with the contents of the given slice followed by that many bytes and a
|
||||||
|
// second slice that aliases into it and contains only the extra bytes. If the
|
||||||
|
// original slice has sufficient capacity then no allocation is performed.
|
||||||
|
func sliceForAppend(in []byte, n int) (head, tail []byte) {
|
||||||
|
if total := len(in) + n; cap(in) >= total {
|
||||||
|
head = in[:total]
|
||||||
|
} else {
|
||||||
|
head = make([]byte, total)
|
||||||
|
copy(head, in)
|
||||||
|
}
|
||||||
|
tail = head[len(in):]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seal appends an encrypted and authenticated copy of message to out, which
|
||||||
|
// must not overlap message. The key and nonce pair must be unique for each
|
||||||
|
// distinct message and the output will be Overhead bytes longer than message.
|
||||||
|
func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte {
|
||||||
|
var subKey [32]byte
|
||||||
|
var counter [16]byte
|
||||||
|
setup(&subKey, &counter, nonce, key)
|
||||||
|
|
||||||
|
// The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
|
||||||
|
// Salsa20 works with 64-byte blocks, we also generate 32 bytes of
|
||||||
|
// keystream as a side effect.
|
||||||
|
var firstBlock [64]byte
|
||||||
|
salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
|
||||||
|
|
||||||
|
var poly1305Key [32]byte
|
||||||
|
copy(poly1305Key[:], firstBlock[:])
|
||||||
|
|
||||||
|
ret, out := sliceForAppend(out, len(message)+poly1305.TagSize)
|
||||||
|
|
||||||
|
// We XOR up to 32 bytes of message with the keystream generated from
|
||||||
|
// the first block.
|
||||||
|
firstMessageBlock := message
|
||||||
|
if len(firstMessageBlock) > 32 {
|
||||||
|
firstMessageBlock = firstMessageBlock[:32]
|
||||||
|
}
|
||||||
|
|
||||||
|
tagOut := out
|
||||||
|
out = out[poly1305.TagSize:]
|
||||||
|
for i, x := range firstMessageBlock {
|
||||||
|
out[i] = firstBlock[32+i] ^ x
|
||||||
|
}
|
||||||
|
message = message[len(firstMessageBlock):]
|
||||||
|
ciphertext := out
|
||||||
|
out = out[len(firstMessageBlock):]
|
||||||
|
|
||||||
|
// Now encrypt the rest.
|
||||||
|
counter[8] = 1
|
||||||
|
salsa.XORKeyStream(out, message, &counter, &subKey)
|
||||||
|
|
||||||
|
var tag [poly1305.TagSize]byte
|
||||||
|
poly1305.Sum(&tag, ciphertext, &poly1305Key)
|
||||||
|
copy(tagOut, tag[:])
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open authenticates and decrypts a box produced by Seal and appends the
|
||||||
|
// message to out, which must not overlap box. The output will be Overhead
|
||||||
|
// bytes smaller than box.
|
||||||
|
func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) {
|
||||||
|
if len(box) < Overhead {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
var subKey [32]byte
|
||||||
|
var counter [16]byte
|
||||||
|
setup(&subKey, &counter, nonce, key)
|
||||||
|
|
||||||
|
// The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
|
||||||
|
// Salsa20 works with 64-byte blocks, we also generate 32 bytes of
|
||||||
|
// keystream as a side effect.
|
||||||
|
var firstBlock [64]byte
|
||||||
|
salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
|
||||||
|
|
||||||
|
var poly1305Key [32]byte
|
||||||
|
copy(poly1305Key[:], firstBlock[:])
|
||||||
|
var tag [poly1305.TagSize]byte
|
||||||
|
copy(tag[:], box)
|
||||||
|
|
||||||
|
if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, out := sliceForAppend(out, len(box)-Overhead)
|
||||||
|
|
||||||
|
// We XOR up to 32 bytes of box with the keystream generated from
|
||||||
|
// the first block.
|
||||||
|
box = box[Overhead:]
|
||||||
|
firstMessageBlock := box
|
||||||
|
if len(firstMessageBlock) > 32 {
|
||||||
|
firstMessageBlock = firstMessageBlock[:32]
|
||||||
|
}
|
||||||
|
for i, x := range firstMessageBlock {
|
||||||
|
out[i] = firstBlock[32+i] ^ x
|
||||||
|
}
|
||||||
|
|
||||||
|
box = box[len(firstMessageBlock):]
|
||||||
|
out = out[len(firstMessageBlock):]
|
||||||
|
|
||||||
|
// Now decrypt the rest.
|
||||||
|
counter[8] = 1
|
||||||
|
salsa.XORKeyStream(out, box, &counter, &subKey)
|
||||||
|
|
||||||
|
return ret, true
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@io_bazel_rules_go//go:def.bzl",
|
||||||
|
"go_library",
|
||||||
|
)
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"poly1305.go",
|
||||||
|
"poly1305_amd64.s",
|
||||||
|
"sum_amd64.go",
|
||||||
|
],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf.
|
||||||
|
|
||||||
|
Poly1305 is a fast, one-time authentication function. It is infeasible for an
|
||||||
|
attacker to generate an authenticator for a message without the key. However, a
|
||||||
|
key must only be used for a single message. Authenticating two different
|
||||||
|
messages with the same key allows an attacker to forge authenticators for other
|
||||||
|
messages with the same key.
|
||||||
|
|
||||||
|
Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
|
||||||
|
used with a fixed key in order to generate one-time keys from an nonce.
|
||||||
|
However, in this package AES isn't used and the one-time key is specified
|
||||||
|
directly.
|
||||||
|
*/
|
||||||
|
package poly1305
|
||||||
|
|
||||||
|
import "crypto/subtle"
|
||||||
|
|
||||||
|
// TagSize is the size, in bytes, of a poly1305 authenticator.
|
||||||
|
const TagSize = 16
|
||||||
|
|
||||||
|
// Verify returns true if mac is a valid authenticator for m with the given
|
||||||
|
// key.
|
||||||
|
func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
|
||||||
|
var tmp [16]byte
|
||||||
|
Sum(&tmp, m, key)
|
||||||
|
return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
|
||||||
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
#define POLY1305_ADD(msg, h0, h1, h2) \
|
||||||
|
ADDQ 0(msg), h0; \
|
||||||
|
ADCQ 8(msg), h1; \
|
||||||
|
ADCQ $1, h2; \
|
||||||
|
LEAQ 16(msg), msg
|
||||||
|
|
||||||
|
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \
|
||||||
|
MOVQ r0, AX; \
|
||||||
|
MULQ h0; \
|
||||||
|
MOVQ AX, t0; \
|
||||||
|
MOVQ DX, t1; \
|
||||||
|
MOVQ r0, AX; \
|
||||||
|
MULQ h1; \
|
||||||
|
ADDQ AX, t1; \
|
||||||
|
ADCQ $0, DX; \
|
||||||
|
MOVQ r0, t2; \
|
||||||
|
IMULQ h2, t2; \
|
||||||
|
ADDQ DX, t2; \
|
||||||
|
\
|
||||||
|
MOVQ r1, AX; \
|
||||||
|
MULQ h0; \
|
||||||
|
ADDQ AX, t1; \
|
||||||
|
ADCQ $0, DX; \
|
||||||
|
MOVQ DX, h0; \
|
||||||
|
MOVQ r1, t3; \
|
||||||
|
IMULQ h2, t3; \
|
||||||
|
MOVQ r1, AX; \
|
||||||
|
MULQ h1; \
|
||||||
|
ADDQ AX, t2; \
|
||||||
|
ADCQ DX, t3; \
|
||||||
|
ADDQ h0, t2; \
|
||||||
|
ADCQ $0, t3; \
|
||||||
|
\
|
||||||
|
MOVQ t0, h0; \
|
||||||
|
MOVQ t1, h1; \
|
||||||
|
MOVQ t2, h2; \
|
||||||
|
ANDQ $3, h2; \
|
||||||
|
MOVQ t2, t0; \
|
||||||
|
ANDQ $0xFFFFFFFFFFFFFFFC, t0; \
|
||||||
|
ADDQ t0, h0; \
|
||||||
|
ADCQ t3, h1; \
|
||||||
|
ADCQ $0, h2; \
|
||||||
|
SHRQ $2, t3, t2; \
|
||||||
|
SHRQ $2, t3; \
|
||||||
|
ADDQ t2, h0; \
|
||||||
|
ADCQ t3, h1; \
|
||||||
|
ADCQ $0, h2
|
||||||
|
|
||||||
|
DATA poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
|
||||||
|
DATA poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
|
||||||
|
GLOBL poly1305Mask<>(SB), RODATA, $16
|
||||||
|
|
||||||
|
// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
|
||||||
|
TEXT ·poly1305(SB), $0-32
|
||||||
|
MOVQ out+0(FP), DI
|
||||||
|
MOVQ m+8(FP), SI
|
||||||
|
MOVQ mlen+16(FP), R15
|
||||||
|
MOVQ key+24(FP), AX
|
||||||
|
|
||||||
|
MOVQ SP, BP
|
||||||
|
ANDQ $0xFFFFFFFFFFFFFFF0, SP
|
||||||
|
SUBQ $32, SP
|
||||||
|
|
||||||
|
MOVOU 0(AX), X0
|
||||||
|
MOVOU 16(AX), X1
|
||||||
|
MOVOU poly1305Mask<>(SB), X2
|
||||||
|
PAND X2, X0
|
||||||
|
MOVO X0, 0(SP)
|
||||||
|
MOVO X1, 16(SP)
|
||||||
|
|
||||||
|
XORQ R8, R8 // h0
|
||||||
|
XORQ R9, R9 // h1
|
||||||
|
XORQ R10, R10 // h2
|
||||||
|
MOVQ 0(SP), R11 // r0
|
||||||
|
MOVQ 8(SP), R12 // r1
|
||||||
|
|
||||||
|
CMPQ R15, $16
|
||||||
|
JB bytes_between_0_and_15
|
||||||
|
|
||||||
|
loop:
|
||||||
|
POLY1305_ADD(SI, R8, R9, R10)
|
||||||
|
multiply:
|
||||||
|
POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14)
|
||||||
|
SUBQ $16, R15
|
||||||
|
CMPQ R15, $16
|
||||||
|
JAE loop
|
||||||
|
|
||||||
|
bytes_between_0_and_15:
|
||||||
|
TESTQ R15, R15
|
||||||
|
JZ done
|
||||||
|
MOVQ $1, BX
|
||||||
|
XORQ CX, CX
|
||||||
|
XORQ R13, R13
|
||||||
|
ADDQ R15, SI
|
||||||
|
|
||||||
|
flush_buffer:
|
||||||
|
SHLQ $8, BX, CX
|
||||||
|
SHLQ $8, BX
|
||||||
|
MOVB -1(SI), R13
|
||||||
|
XORQ R13, BX
|
||||||
|
DECQ SI
|
||||||
|
DECQ R15
|
||||||
|
JNZ flush_buffer
|
||||||
|
|
||||||
|
ADDQ BX, R8
|
||||||
|
ADCQ CX, R9
|
||||||
|
ADCQ $0, R10
|
||||||
|
MOVQ $16, R15
|
||||||
|
JMP multiply
|
||||||
|
|
||||||
|
done:
|
||||||
|
MOVQ R8, AX
|
||||||
|
MOVQ R9, BX
|
||||||
|
SUBQ $0xFFFFFFFFFFFFFFFB, AX
|
||||||
|
SBBQ $0xFFFFFFFFFFFFFFFF, BX
|
||||||
|
SBBQ $3, R10
|
||||||
|
CMOVQCS R8, AX
|
||||||
|
CMOVQCS R9, BX
|
||||||
|
ADDQ 16(SP), AX
|
||||||
|
ADCQ 24(SP), BX
|
||||||
|
|
||||||
|
MOVQ BP, SP
|
||||||
|
MOVQ AX, 0(DI)
|
||||||
|
MOVQ BX, 8(DI)
|
||||||
|
RET
|
|
@ -0,0 +1,379 @@
|
||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This code was translated into a form compatible with 5a from the public
|
||||||
|
// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
|
||||||
|
|
||||||
|
// +build arm,!gccgo,!appengine
|
||||||
|
|
||||||
|
DATA poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
|
||||||
|
DATA poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
|
||||||
|
DATA poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
|
||||||
|
DATA poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
|
||||||
|
DATA poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
|
||||||
|
GLOBL poly1305_init_constants_armv6<>(SB), 8, $20
|
||||||
|
|
||||||
|
// Warning: the linker may use R11 to synthesize certain instructions. Please
|
||||||
|
// take care and verify that no synthetic instructions use it.
|
||||||
|
|
||||||
|
TEXT poly1305_init_ext_armv6<>(SB),4,$-4
|
||||||
|
MOVM.DB.W [R4-R11], (R13)
|
||||||
|
MOVM.IA.W (R1), [R2-R5]
|
||||||
|
MOVW $poly1305_init_constants_armv6<>(SB), R7
|
||||||
|
MOVW R2, R8
|
||||||
|
MOVW R2>>26, R9
|
||||||
|
MOVW R3>>20, g
|
||||||
|
MOVW R4>>14, R11
|
||||||
|
MOVW R5>>8, R12
|
||||||
|
ORR R3<<6, R9, R9
|
||||||
|
ORR R4<<12, g, g
|
||||||
|
ORR R5<<18, R11, R11
|
||||||
|
MOVM.IA (R7), [R2-R6]
|
||||||
|
AND R8, R2, R2
|
||||||
|
AND R9, R3, R3
|
||||||
|
AND g, R4, R4
|
||||||
|
AND R11, R5, R5
|
||||||
|
AND R12, R6, R6
|
||||||
|
MOVM.IA.W [R2-R6], (R0)
|
||||||
|
EOR R2, R2, R2
|
||||||
|
EOR R3, R3, R3
|
||||||
|
EOR R4, R4, R4
|
||||||
|
EOR R5, R5, R5
|
||||||
|
EOR R6, R6, R6
|
||||||
|
MOVM.IA.W [R2-R6], (R0)
|
||||||
|
MOVM.IA.W (R1), [R2-R5]
|
||||||
|
MOVM.IA [R2-R6], (R0)
|
||||||
|
MOVM.IA.W (R13), [R4-R11]
|
||||||
|
RET
|
||||||
|
|
||||||
|
#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \
|
||||||
|
MOVBU (offset+0)(Rsrc), Rtmp; \
|
||||||
|
MOVBU Rtmp, (offset+0)(Rdst); \
|
||||||
|
MOVBU (offset+1)(Rsrc), Rtmp; \
|
||||||
|
MOVBU Rtmp, (offset+1)(Rdst); \
|
||||||
|
MOVBU (offset+2)(Rsrc), Rtmp; \
|
||||||
|
MOVBU Rtmp, (offset+2)(Rdst); \
|
||||||
|
MOVBU (offset+3)(Rsrc), Rtmp; \
|
||||||
|
MOVBU Rtmp, (offset+3)(Rdst)
|
||||||
|
|
||||||
|
TEXT poly1305_blocks_armv6<>(SB),4,$-4
|
||||||
|
MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13)
|
||||||
|
SUB $128, R13
|
||||||
|
MOVW R0, 36(R13)
|
||||||
|
MOVW R1, 40(R13)
|
||||||
|
MOVW R2, 44(R13)
|
||||||
|
MOVW R1, R14
|
||||||
|
MOVW R2, R12
|
||||||
|
MOVW 56(R0), R8
|
||||||
|
WORD $0xe1180008 // TST R8, R8 not working see issue 5921
|
||||||
|
EOR R6, R6, R6
|
||||||
|
MOVW.EQ $(1<<24), R6
|
||||||
|
MOVW R6, 32(R13)
|
||||||
|
ADD $64, R13, g
|
||||||
|
MOVM.IA (R0), [R0-R9]
|
||||||
|
MOVM.IA [R0-R4], (g)
|
||||||
|
CMP $16, R12
|
||||||
|
BLO poly1305_blocks_armv6_done
|
||||||
|
poly1305_blocks_armv6_mainloop:
|
||||||
|
WORD $0xe31e0003 // TST R14, #3 not working see issue 5921
|
||||||
|
BEQ poly1305_blocks_armv6_mainloop_aligned
|
||||||
|
ADD $48, R13, g
|
||||||
|
MOVW_UNALIGNED(R14, g, R0, 0)
|
||||||
|
MOVW_UNALIGNED(R14, g, R0, 4)
|
||||||
|
MOVW_UNALIGNED(R14, g, R0, 8)
|
||||||
|
MOVW_UNALIGNED(R14, g, R0, 12)
|
||||||
|
MOVM.IA (g), [R0-R3]
|
||||||
|
ADD $16, R14
|
||||||
|
B poly1305_blocks_armv6_mainloop_loaded
|
||||||
|
poly1305_blocks_armv6_mainloop_aligned:
|
||||||
|
MOVM.IA.W (R14), [R0-R3]
|
||||||
|
poly1305_blocks_armv6_mainloop_loaded:
|
||||||
|
MOVW R0>>26, g
|
||||||
|
MOVW R1>>20, R11
|
||||||
|
MOVW R2>>14, R12
|
||||||
|
MOVW R14, 40(R13)
|
||||||
|
MOVW R3>>8, R4
|
||||||
|
ORR R1<<6, g, g
|
||||||
|
ORR R2<<12, R11, R11
|
||||||
|
ORR R3<<18, R12, R12
|
||||||
|
BIC $0xfc000000, R0, R0
|
||||||
|
BIC $0xfc000000, g, g
|
||||||
|
MOVW 32(R13), R3
|
||||||
|
BIC $0xfc000000, R11, R11
|
||||||
|
BIC $0xfc000000, R12, R12
|
||||||
|
ADD R0, R5, R5
|
||||||
|
ADD g, R6, R6
|
||||||
|
ORR R3, R4, R4
|
||||||
|
ADD R11, R7, R7
|
||||||
|
ADD $64, R13, R14
|
||||||
|
ADD R12, R8, R8
|
||||||
|
ADD R4, R9, R9
|
||||||
|
MOVM.IA (R14), [R0-R4]
|
||||||
|
MULLU R4, R5, (R11, g)
|
||||||
|
MULLU R3, R5, (R14, R12)
|
||||||
|
MULALU R3, R6, (R11, g)
|
||||||
|
MULALU R2, R6, (R14, R12)
|
||||||
|
MULALU R2, R7, (R11, g)
|
||||||
|
MULALU R1, R7, (R14, R12)
|
||||||
|
ADD R4<<2, R4, R4
|
||||||
|
ADD R3<<2, R3, R3
|
||||||
|
MULALU R1, R8, (R11, g)
|
||||||
|
MULALU R0, R8, (R14, R12)
|
||||||
|
MULALU R0, R9, (R11, g)
|
||||||
|
MULALU R4, R9, (R14, R12)
|
||||||
|
MOVW g, 24(R13)
|
||||||
|
MOVW R11, 28(R13)
|
||||||
|
MOVW R12, 16(R13)
|
||||||
|
MOVW R14, 20(R13)
|
||||||
|
MULLU R2, R5, (R11, g)
|
||||||
|
MULLU R1, R5, (R14, R12)
|
||||||
|
MULALU R1, R6, (R11, g)
|
||||||
|
MULALU R0, R6, (R14, R12)
|
||||||
|
MULALU R0, R7, (R11, g)
|
||||||
|
MULALU R4, R7, (R14, R12)
|
||||||
|
ADD R2<<2, R2, R2
|
||||||
|
ADD R1<<2, R1, R1
|
||||||
|
MULALU R4, R8, (R11, g)
|
||||||
|
MULALU R3, R8, (R14, R12)
|
||||||
|
MULALU R3, R9, (R11, g)
|
||||||
|
MULALU R2, R9, (R14, R12)
|
||||||
|
MOVW g, 8(R13)
|
||||||
|
MOVW R11, 12(R13)
|
||||||
|
MOVW R12, 0(R13)
|
||||||
|
MOVW R14, w+4(SP)
|
||||||
|
MULLU R0, R5, (R11, g)
|
||||||
|
MULALU R4, R6, (R11, g)
|
||||||
|
MULALU R3, R7, (R11, g)
|
||||||
|
MULALU R2, R8, (R11, g)
|
||||||
|
MULALU R1, R9, (R11, g)
|
||||||
|
MOVM.IA (R13), [R0-R7]
|
||||||
|
MOVW g>>26, R12
|
||||||
|
MOVW R4>>26, R14
|
||||||
|
ORR R11<<6, R12, R12
|
||||||
|
ORR R5<<6, R14, R14
|
||||||
|
BIC $0xfc000000, g, g
|
||||||
|
BIC $0xfc000000, R4, R4
|
||||||
|
ADD.S R12, R0, R0
|
||||||
|
ADC $0, R1, R1
|
||||||
|
ADD.S R14, R6, R6
|
||||||
|
ADC $0, R7, R7
|
||||||
|
MOVW R0>>26, R12
|
||||||
|
MOVW R6>>26, R14
|
||||||
|
ORR R1<<6, R12, R12
|
||||||
|
ORR R7<<6, R14, R14
|
||||||
|
BIC $0xfc000000, R0, R0
|
||||||
|
BIC $0xfc000000, R6, R6
|
||||||
|
ADD R14<<2, R14, R14
|
||||||
|
ADD.S R12, R2, R2
|
||||||
|
ADC $0, R3, R3
|
||||||
|
ADD R14, g, g
|
||||||
|
MOVW R2>>26, R12
|
||||||
|
MOVW g>>26, R14
|
||||||
|
ORR R3<<6, R12, R12
|
||||||
|
BIC $0xfc000000, g, R5
|
||||||
|
BIC $0xfc000000, R2, R7
|
||||||
|
ADD R12, R4, R4
|
||||||
|
ADD R14, R0, R0
|
||||||
|
MOVW R4>>26, R12
|
||||||
|
BIC $0xfc000000, R4, R8
|
||||||
|
ADD R12, R6, R9
|
||||||
|
MOVW w+44(SP), R12
|
||||||
|
MOVW w+40(SP), R14
|
||||||
|
MOVW R0, R6
|
||||||
|
CMP $32, R12
|
||||||
|
SUB $16, R12, R12
|
||||||
|
MOVW R12, 44(R13)
|
||||||
|
BHS poly1305_blocks_armv6_mainloop
|
||||||
|
poly1305_blocks_armv6_done:
|
||||||
|
MOVW 36(R13), R12
|
||||||
|
MOVW R5, 20(R12)
|
||||||
|
MOVW R6, 24(R12)
|
||||||
|
MOVW R7, 28(R12)
|
||||||
|
MOVW R8, 32(R12)
|
||||||
|
MOVW R9, 36(R12)
|
||||||
|
ADD $128, R13, R13
|
||||||
|
MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14]
|
||||||
|
RET
|
||||||
|
|
||||||
|
#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \
|
||||||
|
MOVBU.P 1(Rsrc), Rtmp; \
|
||||||
|
MOVBU.P Rtmp, 1(Rdst); \
|
||||||
|
MOVBU.P 1(Rsrc), Rtmp; \
|
||||||
|
MOVBU.P Rtmp, 1(Rdst)
|
||||||
|
|
||||||
|
#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \
|
||||||
|
MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \
|
||||||
|
MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp)
|
||||||
|
|
||||||
|
TEXT poly1305_finish_ext_armv6<>(SB),4,$-4
|
||||||
|
MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13)
|
||||||
|
SUB $16, R13, R13
|
||||||
|
MOVW R0, R5
|
||||||
|
MOVW R1, R6
|
||||||
|
MOVW R2, R7
|
||||||
|
MOVW R3, R8
|
||||||
|
AND.S R2, R2, R2
|
||||||
|
BEQ poly1305_finish_ext_armv6_noremaining
|
||||||
|
EOR R0, R0
|
||||||
|
MOVW R13, R9
|
||||||
|
MOVW R0, 0(R13)
|
||||||
|
MOVW R0, 4(R13)
|
||||||
|
MOVW R0, 8(R13)
|
||||||
|
MOVW R0, 12(R13)
|
||||||
|
WORD $0xe3110003 // TST R1, #3 not working see issue 5921
|
||||||
|
BEQ poly1305_finish_ext_armv6_aligned
|
||||||
|
WORD $0xe3120008 // TST R2, #8 not working see issue 5921
|
||||||
|
BEQ poly1305_finish_ext_armv6_skip8
|
||||||
|
MOVWP_UNALIGNED(R1, R9, g)
|
||||||
|
MOVWP_UNALIGNED(R1, R9, g)
|
||||||
|
poly1305_finish_ext_armv6_skip8:
|
||||||
|
WORD $0xe3120004 // TST $4, R2 not working see issue 5921
|
||||||
|
BEQ poly1305_finish_ext_armv6_skip4
|
||||||
|
MOVWP_UNALIGNED(R1, R9, g)
|
||||||
|
poly1305_finish_ext_armv6_skip4:
|
||||||
|
WORD $0xe3120002 // TST $2, R2 not working see issue 5921
|
||||||
|
BEQ poly1305_finish_ext_armv6_skip2
|
||||||
|
MOVHUP_UNALIGNED(R1, R9, g)
|
||||||
|
B poly1305_finish_ext_armv6_skip2
|
||||||
|
poly1305_finish_ext_armv6_aligned:
|
||||||
|
WORD $0xe3120008 // TST R2, #8 not working see issue 5921
|
||||||
|
BEQ poly1305_finish_ext_armv6_skip8_aligned
|
||||||
|
MOVM.IA.W (R1), [g-R11]
|
||||||
|
MOVM.IA.W [g-R11], (R9)
|
||||||
|
poly1305_finish_ext_armv6_skip8_aligned:
|
||||||
|
WORD $0xe3120004 // TST $4, R2 not working see issue 5921
|
||||||
|
BEQ poly1305_finish_ext_armv6_skip4_aligned
|
||||||
|
MOVW.P 4(R1), g
|
||||||
|
MOVW.P g, 4(R9)
|
||||||
|
poly1305_finish_ext_armv6_skip4_aligned:
|
||||||
|
WORD $0xe3120002 // TST $2, R2 not working see issue 5921
|
||||||
|
BEQ poly1305_finish_ext_armv6_skip2
|
||||||
|
MOVHU.P 2(R1), g
|
||||||
|
MOVH.P g, 2(R9)
|
||||||
|
poly1305_finish_ext_armv6_skip2:
|
||||||
|
WORD $0xe3120001 // TST $1, R2 not working see issue 5921
|
||||||
|
BEQ poly1305_finish_ext_armv6_skip1
|
||||||
|
MOVBU.P 1(R1), g
|
||||||
|
MOVBU.P g, 1(R9)
|
||||||
|
poly1305_finish_ext_armv6_skip1:
|
||||||
|
MOVW $1, R11
|
||||||
|
MOVBU R11, 0(R9)
|
||||||
|
MOVW R11, 56(R5)
|
||||||
|
MOVW R5, R0
|
||||||
|
MOVW R13, R1
|
||||||
|
MOVW $16, R2
|
||||||
|
BL poly1305_blocks_armv6<>(SB)
|
||||||
|
poly1305_finish_ext_armv6_noremaining:
|
||||||
|
MOVW 20(R5), R0
|
||||||
|
MOVW 24(R5), R1
|
||||||
|
MOVW 28(R5), R2
|
||||||
|
MOVW 32(R5), R3
|
||||||
|
MOVW 36(R5), R4
|
||||||
|
MOVW R4>>26, R12
|
||||||
|
BIC $0xfc000000, R4, R4
|
||||||
|
ADD R12<<2, R12, R12
|
||||||
|
ADD R12, R0, R0
|
||||||
|
MOVW R0>>26, R12
|
||||||
|
BIC $0xfc000000, R0, R0
|
||||||
|
ADD R12, R1, R1
|
||||||
|
MOVW R1>>26, R12
|
||||||
|
BIC $0xfc000000, R1, R1
|
||||||
|
ADD R12, R2, R2
|
||||||
|
MOVW R2>>26, R12
|
||||||
|
BIC $0xfc000000, R2, R2
|
||||||
|
ADD R12, R3, R3
|
||||||
|
MOVW R3>>26, R12
|
||||||
|
BIC $0xfc000000, R3, R3
|
||||||
|
ADD R12, R4, R4
|
||||||
|
ADD $5, R0, R6
|
||||||
|
MOVW R6>>26, R12
|
||||||
|
BIC $0xfc000000, R6, R6
|
||||||
|
ADD R12, R1, R7
|
||||||
|
MOVW R7>>26, R12
|
||||||
|
BIC $0xfc000000, R7, R7
|
||||||
|
ADD R12, R2, g
|
||||||
|
MOVW g>>26, R12
|
||||||
|
BIC $0xfc000000, g, g
|
||||||
|
ADD R12, R3, R11
|
||||||
|
MOVW $-(1<<26), R12
|
||||||
|
ADD R11>>26, R12, R12
|
||||||
|
BIC $0xfc000000, R11, R11
|
||||||
|
ADD R12, R4, R14
|
||||||
|
MOVW R14>>31, R12
|
||||||
|
SUB $1, R12
|
||||||
|
AND R12, R6, R6
|
||||||
|
AND R12, R7, R7
|
||||||
|
AND R12, g, g
|
||||||
|
AND R12, R11, R11
|
||||||
|
AND R12, R14, R14
|
||||||
|
MVN R12, R12
|
||||||
|
AND R12, R0, R0
|
||||||
|
AND R12, R1, R1
|
||||||
|
AND R12, R2, R2
|
||||||
|
AND R12, R3, R3
|
||||||
|
AND R12, R4, R4
|
||||||
|
ORR R6, R0, R0
|
||||||
|
ORR R7, R1, R1
|
||||||
|
ORR g, R2, R2
|
||||||
|
ORR R11, R3, R3
|
||||||
|
ORR R14, R4, R4
|
||||||
|
ORR R1<<26, R0, R0
|
||||||
|
MOVW R1>>6, R1
|
||||||
|
ORR R2<<20, R1, R1
|
||||||
|
MOVW R2>>12, R2
|
||||||
|
ORR R3<<14, R2, R2
|
||||||
|
MOVW R3>>18, R3
|
||||||
|
ORR R4<<8, R3, R3
|
||||||
|
MOVW 40(R5), R6
|
||||||
|
MOVW 44(R5), R7
|
||||||
|
MOVW 48(R5), g
|
||||||
|
MOVW 52(R5), R11
|
||||||
|
ADD.S R6, R0, R0
|
||||||
|
ADC.S R7, R1, R1
|
||||||
|
ADC.S g, R2, R2
|
||||||
|
ADC.S R11, R3, R3
|
||||||
|
MOVM.IA [R0-R3], (R8)
|
||||||
|
MOVW R5, R12
|
||||||
|
EOR R0, R0, R0
|
||||||
|
EOR R1, R1, R1
|
||||||
|
EOR R2, R2, R2
|
||||||
|
EOR R3, R3, R3
|
||||||
|
EOR R4, R4, R4
|
||||||
|
EOR R5, R5, R5
|
||||||
|
EOR R6, R6, R6
|
||||||
|
EOR R7, R7, R7
|
||||||
|
MOVM.IA.W [R0-R7], (R12)
|
||||||
|
MOVM.IA [R0-R7], (R12)
|
||||||
|
ADD $16, R13, R13
|
||||||
|
MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14]
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
|
||||||
|
TEXT ·poly1305_auth_armv6(SB),0,$280-16
|
||||||
|
MOVW out+0(FP), R4
|
||||||
|
MOVW m+4(FP), R5
|
||||||
|
MOVW mlen+8(FP), R6
|
||||||
|
MOVW key+12(FP), R7
|
||||||
|
|
||||||
|
MOVW R13, R8
|
||||||
|
BIC $63, R13
|
||||||
|
SUB $64, R13, R13
|
||||||
|
MOVW R13, R0
|
||||||
|
MOVW R7, R1
|
||||||
|
BL poly1305_init_ext_armv6<>(SB)
|
||||||
|
BIC.S $15, R6, R2
|
||||||
|
BEQ poly1305_auth_armv6_noblocks
|
||||||
|
MOVW R13, R0
|
||||||
|
MOVW R5, R1
|
||||||
|
ADD R2, R5, R5
|
||||||
|
SUB R2, R6, R6
|
||||||
|
BL poly1305_blocks_armv6<>(SB)
|
||||||
|
poly1305_auth_armv6_noblocks:
|
||||||
|
MOVW R13, R0
|
||||||
|
MOVW R5, R1
|
||||||
|
MOVW R6, R2
|
||||||
|
MOVW R4, R3
|
||||||
|
BL poly1305_finish_ext_armv6<>(SB)
|
||||||
|
MOVW R8, R13
|
||||||
|
RET
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64,!gccgo,!appengine
|
||||||
|
|
||||||
|
package poly1305
|
||||||
|
|
||||||
|
// This function is implemented in poly1305_amd64.s
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
|
||||||
|
|
||||||
|
// Sum generates an authenticator for m using a one-time key and puts the
|
||||||
|
// 16-byte result into out. Authenticating two different messages with the same
|
||||||
|
// key allows an attacker to forge messages at will.
|
||||||
|
func Sum(out *[16]byte, m []byte, key *[32]byte) {
|
||||||
|
var mPtr *byte
|
||||||
|
if len(m) > 0 {
|
||||||
|
mPtr = &m[0]
|
||||||
|
}
|
||||||
|
poly1305(out, mPtr, uint64(len(m)), key)
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build arm,!gccgo,!appengine
|
||||||
|
|
||||||
|
package poly1305
|
||||||
|
|
||||||
|
// This function is implemented in poly1305_arm.s
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte)
|
||||||
|
|
||||||
|
// Sum generates an authenticator for m using a one-time key and puts the
|
||||||
|
// 16-byte result into out. Authenticating two different messages with the same
|
||||||
|
// key allows an attacker to forge messages at will.
|
||||||
|
func Sum(out *[16]byte, m []byte, key *[32]byte) {
|
||||||
|
var mPtr *byte
|
||||||
|
if len(m) > 0 {
|
||||||
|
mPtr = &m[0]
|
||||||
|
}
|
||||||
|
poly1305_auth_armv6(out, mPtr, uint32(len(m)), key)
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,32 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@io_bazel_rules_go//go:def.bzl",
|
||||||
|
"go_library",
|
||||||
|
)
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"hsalsa20.go",
|
||||||
|
"salsa2020_amd64.s",
|
||||||
|
"salsa208.go",
|
||||||
|
"salsa20_amd64.go",
|
||||||
|
],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
|
@ -0,0 +1,144 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package salsa provides low-level access to functions in the Salsa family.
|
||||||
|
package salsa
|
||||||
|
|
||||||
|
// Sigma is the Salsa20 constant for 256-bit keys.
|
||||||
|
var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'}
|
||||||
|
|
||||||
|
// HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte
|
||||||
|
// key k, and 16-byte constant c, and puts the result into the 32-byte array
|
||||||
|
// out.
|
||||||
|
func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
|
||||||
|
x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24
|
||||||
|
x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24
|
||||||
|
x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24
|
||||||
|
x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24
|
||||||
|
x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24
|
||||||
|
x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24
|
||||||
|
x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
|
||||||
|
x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
|
||||||
|
x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
|
||||||
|
x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
|
||||||
|
x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24
|
||||||
|
x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24
|
||||||
|
x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24
|
||||||
|
x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24
|
||||||
|
x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24
|
||||||
|
x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24
|
||||||
|
|
||||||
|
for i := 0; i < 20; i += 2 {
|
||||||
|
u := x0 + x12
|
||||||
|
x4 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x4 + x0
|
||||||
|
x8 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x8 + x4
|
||||||
|
x12 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x12 + x8
|
||||||
|
x0 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x5 + x1
|
||||||
|
x9 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x9 + x5
|
||||||
|
x13 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x13 + x9
|
||||||
|
x1 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x1 + x13
|
||||||
|
x5 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x10 + x6
|
||||||
|
x14 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x14 + x10
|
||||||
|
x2 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x2 + x14
|
||||||
|
x6 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x6 + x2
|
||||||
|
x10 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x15 + x11
|
||||||
|
x3 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x3 + x15
|
||||||
|
x7 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x7 + x3
|
||||||
|
x11 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x11 + x7
|
||||||
|
x15 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x0 + x3
|
||||||
|
x1 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x1 + x0
|
||||||
|
x2 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x2 + x1
|
||||||
|
x3 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x3 + x2
|
||||||
|
x0 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x5 + x4
|
||||||
|
x6 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x6 + x5
|
||||||
|
x7 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x7 + x6
|
||||||
|
x4 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x4 + x7
|
||||||
|
x5 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x10 + x9
|
||||||
|
x11 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x11 + x10
|
||||||
|
x8 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x8 + x11
|
||||||
|
x9 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x9 + x8
|
||||||
|
x10 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x15 + x14
|
||||||
|
x12 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x12 + x15
|
||||||
|
x13 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x13 + x12
|
||||||
|
x14 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x14 + x13
|
||||||
|
x15 ^= u<<18 | u>>(32-18)
|
||||||
|
}
|
||||||
|
out[0] = byte(x0)
|
||||||
|
out[1] = byte(x0 >> 8)
|
||||||
|
out[2] = byte(x0 >> 16)
|
||||||
|
out[3] = byte(x0 >> 24)
|
||||||
|
|
||||||
|
out[4] = byte(x5)
|
||||||
|
out[5] = byte(x5 >> 8)
|
||||||
|
out[6] = byte(x5 >> 16)
|
||||||
|
out[7] = byte(x5 >> 24)
|
||||||
|
|
||||||
|
out[8] = byte(x10)
|
||||||
|
out[9] = byte(x10 >> 8)
|
||||||
|
out[10] = byte(x10 >> 16)
|
||||||
|
out[11] = byte(x10 >> 24)
|
||||||
|
|
||||||
|
out[12] = byte(x15)
|
||||||
|
out[13] = byte(x15 >> 8)
|
||||||
|
out[14] = byte(x15 >> 16)
|
||||||
|
out[15] = byte(x15 >> 24)
|
||||||
|
|
||||||
|
out[16] = byte(x6)
|
||||||
|
out[17] = byte(x6 >> 8)
|
||||||
|
out[18] = byte(x6 >> 16)
|
||||||
|
out[19] = byte(x6 >> 24)
|
||||||
|
|
||||||
|
out[20] = byte(x7)
|
||||||
|
out[21] = byte(x7 >> 8)
|
||||||
|
out[22] = byte(x7 >> 16)
|
||||||
|
out[23] = byte(x7 >> 24)
|
||||||
|
|
||||||
|
out[24] = byte(x8)
|
||||||
|
out[25] = byte(x8 >> 8)
|
||||||
|
out[26] = byte(x8 >> 16)
|
||||||
|
out[27] = byte(x8 >> 24)
|
||||||
|
|
||||||
|
out[28] = byte(x9)
|
||||||
|
out[29] = byte(x9 >> 8)
|
||||||
|
out[30] = byte(x9 >> 16)
|
||||||
|
out[31] = byte(x9 >> 24)
|
||||||
|
}
|
|
@ -0,0 +1,902 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64,!appengine,!gccgo
|
||||||
|
|
||||||
|
// This code was translated into a form compatible with 6a from the public
|
||||||
|
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||||
|
|
||||||
|
// func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
|
||||||
|
TEXT ·salsa2020XORKeyStream(SB),0,$512-40
|
||||||
|
MOVQ out+0(FP),DI
|
||||||
|
MOVQ in+8(FP),SI
|
||||||
|
MOVQ n+16(FP),DX
|
||||||
|
MOVQ nonce+24(FP),CX
|
||||||
|
MOVQ key+32(FP),R8
|
||||||
|
|
||||||
|
MOVQ SP,R11
|
||||||
|
MOVQ $31,R9
|
||||||
|
NOTQ R9
|
||||||
|
ANDQ R9,SP
|
||||||
|
ADDQ $32,SP
|
||||||
|
|
||||||
|
MOVQ R11,352(SP)
|
||||||
|
MOVQ R12,360(SP)
|
||||||
|
MOVQ R13,368(SP)
|
||||||
|
MOVQ R14,376(SP)
|
||||||
|
MOVQ R15,384(SP)
|
||||||
|
MOVQ BX,392(SP)
|
||||||
|
MOVQ BP,400(SP)
|
||||||
|
MOVQ DX,R9
|
||||||
|
MOVQ CX,DX
|
||||||
|
MOVQ R8,R10
|
||||||
|
CMPQ R9,$0
|
||||||
|
JBE DONE
|
||||||
|
START:
|
||||||
|
MOVL 20(R10),CX
|
||||||
|
MOVL 0(R10),R8
|
||||||
|
MOVL 0(DX),AX
|
||||||
|
MOVL 16(R10),R11
|
||||||
|
MOVL CX,0(SP)
|
||||||
|
MOVL R8, 4 (SP)
|
||||||
|
MOVL AX, 8 (SP)
|
||||||
|
MOVL R11, 12 (SP)
|
||||||
|
MOVL 8(DX),CX
|
||||||
|
MOVL 24(R10),R8
|
||||||
|
MOVL 4(R10),AX
|
||||||
|
MOVL 4(DX),R11
|
||||||
|
MOVL CX,16(SP)
|
||||||
|
MOVL R8, 20 (SP)
|
||||||
|
MOVL AX, 24 (SP)
|
||||||
|
MOVL R11, 28 (SP)
|
||||||
|
MOVL 12(DX),CX
|
||||||
|
MOVL 12(R10),DX
|
||||||
|
MOVL 28(R10),R8
|
||||||
|
MOVL 8(R10),AX
|
||||||
|
MOVL DX,32(SP)
|
||||||
|
MOVL CX, 36 (SP)
|
||||||
|
MOVL R8, 40 (SP)
|
||||||
|
MOVL AX, 44 (SP)
|
||||||
|
MOVQ $1634760805,DX
|
||||||
|
MOVQ $857760878,CX
|
||||||
|
MOVQ $2036477234,R8
|
||||||
|
MOVQ $1797285236,AX
|
||||||
|
MOVL DX,48(SP)
|
||||||
|
MOVL CX, 52 (SP)
|
||||||
|
MOVL R8, 56 (SP)
|
||||||
|
MOVL AX, 60 (SP)
|
||||||
|
CMPQ R9,$256
|
||||||
|
JB BYTESBETWEEN1AND255
|
||||||
|
MOVOA 48(SP),X0
|
||||||
|
PSHUFL $0X55,X0,X1
|
||||||
|
PSHUFL $0XAA,X0,X2
|
||||||
|
PSHUFL $0XFF,X0,X3
|
||||||
|
PSHUFL $0X00,X0,X0
|
||||||
|
MOVOA X1,64(SP)
|
||||||
|
MOVOA X2,80(SP)
|
||||||
|
MOVOA X3,96(SP)
|
||||||
|
MOVOA X0,112(SP)
|
||||||
|
MOVOA 0(SP),X0
|
||||||
|
PSHUFL $0XAA,X0,X1
|
||||||
|
PSHUFL $0XFF,X0,X2
|
||||||
|
PSHUFL $0X00,X0,X3
|
||||||
|
PSHUFL $0X55,X0,X0
|
||||||
|
MOVOA X1,128(SP)
|
||||||
|
MOVOA X2,144(SP)
|
||||||
|
MOVOA X3,160(SP)
|
||||||
|
MOVOA X0,176(SP)
|
||||||
|
MOVOA 16(SP),X0
|
||||||
|
PSHUFL $0XFF,X0,X1
|
||||||
|
PSHUFL $0X55,X0,X2
|
||||||
|
PSHUFL $0XAA,X0,X0
|
||||||
|
MOVOA X1,192(SP)
|
||||||
|
MOVOA X2,208(SP)
|
||||||
|
MOVOA X0,224(SP)
|
||||||
|
MOVOA 32(SP),X0
|
||||||
|
PSHUFL $0X00,X0,X1
|
||||||
|
PSHUFL $0XAA,X0,X2
|
||||||
|
PSHUFL $0XFF,X0,X0
|
||||||
|
MOVOA X1,240(SP)
|
||||||
|
MOVOA X2,256(SP)
|
||||||
|
MOVOA X0,272(SP)
|
||||||
|
BYTESATLEAST256:
|
||||||
|
MOVL 16(SP),DX
|
||||||
|
MOVL 36 (SP),CX
|
||||||
|
MOVL DX,288(SP)
|
||||||
|
MOVL CX,304(SP)
|
||||||
|
ADDQ $1,DX
|
||||||
|
SHLQ $32,CX
|
||||||
|
ADDQ CX,DX
|
||||||
|
MOVQ DX,CX
|
||||||
|
SHRQ $32,CX
|
||||||
|
MOVL DX, 292 (SP)
|
||||||
|
MOVL CX, 308 (SP)
|
||||||
|
ADDQ $1,DX
|
||||||
|
SHLQ $32,CX
|
||||||
|
ADDQ CX,DX
|
||||||
|
MOVQ DX,CX
|
||||||
|
SHRQ $32,CX
|
||||||
|
MOVL DX, 296 (SP)
|
||||||
|
MOVL CX, 312 (SP)
|
||||||
|
ADDQ $1,DX
|
||||||
|
SHLQ $32,CX
|
||||||
|
ADDQ CX,DX
|
||||||
|
MOVQ DX,CX
|
||||||
|
SHRQ $32,CX
|
||||||
|
MOVL DX, 300 (SP)
|
||||||
|
MOVL CX, 316 (SP)
|
||||||
|
ADDQ $1,DX
|
||||||
|
SHLQ $32,CX
|
||||||
|
ADDQ CX,DX
|
||||||
|
MOVQ DX,CX
|
||||||
|
SHRQ $32,CX
|
||||||
|
MOVL DX,16(SP)
|
||||||
|
MOVL CX, 36 (SP)
|
||||||
|
MOVQ R9,408(SP)
|
||||||
|
MOVQ $20,DX
|
||||||
|
MOVOA 64(SP),X0
|
||||||
|
MOVOA 80(SP),X1
|
||||||
|
MOVOA 96(SP),X2
|
||||||
|
MOVOA 256(SP),X3
|
||||||
|
MOVOA 272(SP),X4
|
||||||
|
MOVOA 128(SP),X5
|
||||||
|
MOVOA 144(SP),X6
|
||||||
|
MOVOA 176(SP),X7
|
||||||
|
MOVOA 192(SP),X8
|
||||||
|
MOVOA 208(SP),X9
|
||||||
|
MOVOA 224(SP),X10
|
||||||
|
MOVOA 304(SP),X11
|
||||||
|
MOVOA 112(SP),X12
|
||||||
|
MOVOA 160(SP),X13
|
||||||
|
MOVOA 240(SP),X14
|
||||||
|
MOVOA 288(SP),X15
|
||||||
|
MAINLOOP1:
|
||||||
|
MOVOA X1,320(SP)
|
||||||
|
MOVOA X2,336(SP)
|
||||||
|
MOVOA X13,X1
|
||||||
|
PADDL X12,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $7,X1
|
||||||
|
PXOR X1,X14
|
||||||
|
PSRLL $25,X2
|
||||||
|
PXOR X2,X14
|
||||||
|
MOVOA X7,X1
|
||||||
|
PADDL X0,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $7,X1
|
||||||
|
PXOR X1,X11
|
||||||
|
PSRLL $25,X2
|
||||||
|
PXOR X2,X11
|
||||||
|
MOVOA X12,X1
|
||||||
|
PADDL X14,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $9,X1
|
||||||
|
PXOR X1,X15
|
||||||
|
PSRLL $23,X2
|
||||||
|
PXOR X2,X15
|
||||||
|
MOVOA X0,X1
|
||||||
|
PADDL X11,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $9,X1
|
||||||
|
PXOR X1,X9
|
||||||
|
PSRLL $23,X2
|
||||||
|
PXOR X2,X9
|
||||||
|
MOVOA X14,X1
|
||||||
|
PADDL X15,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $13,X1
|
||||||
|
PXOR X1,X13
|
||||||
|
PSRLL $19,X2
|
||||||
|
PXOR X2,X13
|
||||||
|
MOVOA X11,X1
|
||||||
|
PADDL X9,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $13,X1
|
||||||
|
PXOR X1,X7
|
||||||
|
PSRLL $19,X2
|
||||||
|
PXOR X2,X7
|
||||||
|
MOVOA X15,X1
|
||||||
|
PADDL X13,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $18,X1
|
||||||
|
PXOR X1,X12
|
||||||
|
PSRLL $14,X2
|
||||||
|
PXOR X2,X12
|
||||||
|
MOVOA 320(SP),X1
|
||||||
|
MOVOA X12,320(SP)
|
||||||
|
MOVOA X9,X2
|
||||||
|
PADDL X7,X2
|
||||||
|
MOVOA X2,X12
|
||||||
|
PSLLL $18,X2
|
||||||
|
PXOR X2,X0
|
||||||
|
PSRLL $14,X12
|
||||||
|
PXOR X12,X0
|
||||||
|
MOVOA X5,X2
|
||||||
|
PADDL X1,X2
|
||||||
|
MOVOA X2,X12
|
||||||
|
PSLLL $7,X2
|
||||||
|
PXOR X2,X3
|
||||||
|
PSRLL $25,X12
|
||||||
|
PXOR X12,X3
|
||||||
|
MOVOA 336(SP),X2
|
||||||
|
MOVOA X0,336(SP)
|
||||||
|
MOVOA X6,X0
|
||||||
|
PADDL X2,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $7,X0
|
||||||
|
PXOR X0,X4
|
||||||
|
PSRLL $25,X12
|
||||||
|
PXOR X12,X4
|
||||||
|
MOVOA X1,X0
|
||||||
|
PADDL X3,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $9,X0
|
||||||
|
PXOR X0,X10
|
||||||
|
PSRLL $23,X12
|
||||||
|
PXOR X12,X10
|
||||||
|
MOVOA X2,X0
|
||||||
|
PADDL X4,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $9,X0
|
||||||
|
PXOR X0,X8
|
||||||
|
PSRLL $23,X12
|
||||||
|
PXOR X12,X8
|
||||||
|
MOVOA X3,X0
|
||||||
|
PADDL X10,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $13,X0
|
||||||
|
PXOR X0,X5
|
||||||
|
PSRLL $19,X12
|
||||||
|
PXOR X12,X5
|
||||||
|
MOVOA X4,X0
|
||||||
|
PADDL X8,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $13,X0
|
||||||
|
PXOR X0,X6
|
||||||
|
PSRLL $19,X12
|
||||||
|
PXOR X12,X6
|
||||||
|
MOVOA X10,X0
|
||||||
|
PADDL X5,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $18,X0
|
||||||
|
PXOR X0,X1
|
||||||
|
PSRLL $14,X12
|
||||||
|
PXOR X12,X1
|
||||||
|
MOVOA 320(SP),X0
|
||||||
|
MOVOA X1,320(SP)
|
||||||
|
MOVOA X4,X1
|
||||||
|
PADDL X0,X1
|
||||||
|
MOVOA X1,X12
|
||||||
|
PSLLL $7,X1
|
||||||
|
PXOR X1,X7
|
||||||
|
PSRLL $25,X12
|
||||||
|
PXOR X12,X7
|
||||||
|
MOVOA X8,X1
|
||||||
|
PADDL X6,X1
|
||||||
|
MOVOA X1,X12
|
||||||
|
PSLLL $18,X1
|
||||||
|
PXOR X1,X2
|
||||||
|
PSRLL $14,X12
|
||||||
|
PXOR X12,X2
|
||||||
|
MOVOA 336(SP),X12
|
||||||
|
MOVOA X2,336(SP)
|
||||||
|
MOVOA X14,X1
|
||||||
|
PADDL X12,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $7,X1
|
||||||
|
PXOR X1,X5
|
||||||
|
PSRLL $25,X2
|
||||||
|
PXOR X2,X5
|
||||||
|
MOVOA X0,X1
|
||||||
|
PADDL X7,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $9,X1
|
||||||
|
PXOR X1,X10
|
||||||
|
PSRLL $23,X2
|
||||||
|
PXOR X2,X10
|
||||||
|
MOVOA X12,X1
|
||||||
|
PADDL X5,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $9,X1
|
||||||
|
PXOR X1,X8
|
||||||
|
PSRLL $23,X2
|
||||||
|
PXOR X2,X8
|
||||||
|
MOVOA X7,X1
|
||||||
|
PADDL X10,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $13,X1
|
||||||
|
PXOR X1,X4
|
||||||
|
PSRLL $19,X2
|
||||||
|
PXOR X2,X4
|
||||||
|
MOVOA X5,X1
|
||||||
|
PADDL X8,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $13,X1
|
||||||
|
PXOR X1,X14
|
||||||
|
PSRLL $19,X2
|
||||||
|
PXOR X2,X14
|
||||||
|
MOVOA X10,X1
|
||||||
|
PADDL X4,X1
|
||||||
|
MOVOA X1,X2
|
||||||
|
PSLLL $18,X1
|
||||||
|
PXOR X1,X0
|
||||||
|
PSRLL $14,X2
|
||||||
|
PXOR X2,X0
|
||||||
|
MOVOA 320(SP),X1
|
||||||
|
MOVOA X0,320(SP)
|
||||||
|
MOVOA X8,X0
|
||||||
|
PADDL X14,X0
|
||||||
|
MOVOA X0,X2
|
||||||
|
PSLLL $18,X0
|
||||||
|
PXOR X0,X12
|
||||||
|
PSRLL $14,X2
|
||||||
|
PXOR X2,X12
|
||||||
|
MOVOA X11,X0
|
||||||
|
PADDL X1,X0
|
||||||
|
MOVOA X0,X2
|
||||||
|
PSLLL $7,X0
|
||||||
|
PXOR X0,X6
|
||||||
|
PSRLL $25,X2
|
||||||
|
PXOR X2,X6
|
||||||
|
MOVOA 336(SP),X2
|
||||||
|
MOVOA X12,336(SP)
|
||||||
|
MOVOA X3,X0
|
||||||
|
PADDL X2,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $7,X0
|
||||||
|
PXOR X0,X13
|
||||||
|
PSRLL $25,X12
|
||||||
|
PXOR X12,X13
|
||||||
|
MOVOA X1,X0
|
||||||
|
PADDL X6,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $9,X0
|
||||||
|
PXOR X0,X15
|
||||||
|
PSRLL $23,X12
|
||||||
|
PXOR X12,X15
|
||||||
|
MOVOA X2,X0
|
||||||
|
PADDL X13,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $9,X0
|
||||||
|
PXOR X0,X9
|
||||||
|
PSRLL $23,X12
|
||||||
|
PXOR X12,X9
|
||||||
|
MOVOA X6,X0
|
||||||
|
PADDL X15,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $13,X0
|
||||||
|
PXOR X0,X11
|
||||||
|
PSRLL $19,X12
|
||||||
|
PXOR X12,X11
|
||||||
|
MOVOA X13,X0
|
||||||
|
PADDL X9,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $13,X0
|
||||||
|
PXOR X0,X3
|
||||||
|
PSRLL $19,X12
|
||||||
|
PXOR X12,X3
|
||||||
|
MOVOA X15,X0
|
||||||
|
PADDL X11,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $18,X0
|
||||||
|
PXOR X0,X1
|
||||||
|
PSRLL $14,X12
|
||||||
|
PXOR X12,X1
|
||||||
|
MOVOA X9,X0
|
||||||
|
PADDL X3,X0
|
||||||
|
MOVOA X0,X12
|
||||||
|
PSLLL $18,X0
|
||||||
|
PXOR X0,X2
|
||||||
|
PSRLL $14,X12
|
||||||
|
PXOR X12,X2
|
||||||
|
MOVOA 320(SP),X12
|
||||||
|
MOVOA 336(SP),X0
|
||||||
|
SUBQ $2,DX
|
||||||
|
JA MAINLOOP1
|
||||||
|
PADDL 112(SP),X12
|
||||||
|
PADDL 176(SP),X7
|
||||||
|
PADDL 224(SP),X10
|
||||||
|
PADDL 272(SP),X4
|
||||||
|
MOVD X12,DX
|
||||||
|
MOVD X7,CX
|
||||||
|
MOVD X10,R8
|
||||||
|
MOVD X4,R9
|
||||||
|
PSHUFL $0X39,X12,X12
|
||||||
|
PSHUFL $0X39,X7,X7
|
||||||
|
PSHUFL $0X39,X10,X10
|
||||||
|
PSHUFL $0X39,X4,X4
|
||||||
|
XORL 0(SI),DX
|
||||||
|
XORL 4(SI),CX
|
||||||
|
XORL 8(SI),R8
|
||||||
|
XORL 12(SI),R9
|
||||||
|
MOVL DX,0(DI)
|
||||||
|
MOVL CX,4(DI)
|
||||||
|
MOVL R8,8(DI)
|
||||||
|
MOVL R9,12(DI)
|
||||||
|
MOVD X12,DX
|
||||||
|
MOVD X7,CX
|
||||||
|
MOVD X10,R8
|
||||||
|
MOVD X4,R9
|
||||||
|
PSHUFL $0X39,X12,X12
|
||||||
|
PSHUFL $0X39,X7,X7
|
||||||
|
PSHUFL $0X39,X10,X10
|
||||||
|
PSHUFL $0X39,X4,X4
|
||||||
|
XORL 64(SI),DX
|
||||||
|
XORL 68(SI),CX
|
||||||
|
XORL 72(SI),R8
|
||||||
|
XORL 76(SI),R9
|
||||||
|
MOVL DX,64(DI)
|
||||||
|
MOVL CX,68(DI)
|
||||||
|
MOVL R8,72(DI)
|
||||||
|
MOVL R9,76(DI)
|
||||||
|
MOVD X12,DX
|
||||||
|
MOVD X7,CX
|
||||||
|
MOVD X10,R8
|
||||||
|
MOVD X4,R9
|
||||||
|
PSHUFL $0X39,X12,X12
|
||||||
|
PSHUFL $0X39,X7,X7
|
||||||
|
PSHUFL $0X39,X10,X10
|
||||||
|
PSHUFL $0X39,X4,X4
|
||||||
|
XORL 128(SI),DX
|
||||||
|
XORL 132(SI),CX
|
||||||
|
XORL 136(SI),R8
|
||||||
|
XORL 140(SI),R9
|
||||||
|
MOVL DX,128(DI)
|
||||||
|
MOVL CX,132(DI)
|
||||||
|
MOVL R8,136(DI)
|
||||||
|
MOVL R9,140(DI)
|
||||||
|
MOVD X12,DX
|
||||||
|
MOVD X7,CX
|
||||||
|
MOVD X10,R8
|
||||||
|
MOVD X4,R9
|
||||||
|
XORL 192(SI),DX
|
||||||
|
XORL 196(SI),CX
|
||||||
|
XORL 200(SI),R8
|
||||||
|
XORL 204(SI),R9
|
||||||
|
MOVL DX,192(DI)
|
||||||
|
MOVL CX,196(DI)
|
||||||
|
MOVL R8,200(DI)
|
||||||
|
MOVL R9,204(DI)
|
||||||
|
PADDL 240(SP),X14
|
||||||
|
PADDL 64(SP),X0
|
||||||
|
PADDL 128(SP),X5
|
||||||
|
PADDL 192(SP),X8
|
||||||
|
MOVD X14,DX
|
||||||
|
MOVD X0,CX
|
||||||
|
MOVD X5,R8
|
||||||
|
MOVD X8,R9
|
||||||
|
PSHUFL $0X39,X14,X14
|
||||||
|
PSHUFL $0X39,X0,X0
|
||||||
|
PSHUFL $0X39,X5,X5
|
||||||
|
PSHUFL $0X39,X8,X8
|
||||||
|
XORL 16(SI),DX
|
||||||
|
XORL 20(SI),CX
|
||||||
|
XORL 24(SI),R8
|
||||||
|
XORL 28(SI),R9
|
||||||
|
MOVL DX,16(DI)
|
||||||
|
MOVL CX,20(DI)
|
||||||
|
MOVL R8,24(DI)
|
||||||
|
MOVL R9,28(DI)
|
||||||
|
MOVD X14,DX
|
||||||
|
MOVD X0,CX
|
||||||
|
MOVD X5,R8
|
||||||
|
MOVD X8,R9
|
||||||
|
PSHUFL $0X39,X14,X14
|
||||||
|
PSHUFL $0X39,X0,X0
|
||||||
|
PSHUFL $0X39,X5,X5
|
||||||
|
PSHUFL $0X39,X8,X8
|
||||||
|
XORL 80(SI),DX
|
||||||
|
XORL 84(SI),CX
|
||||||
|
XORL 88(SI),R8
|
||||||
|
XORL 92(SI),R9
|
||||||
|
MOVL DX,80(DI)
|
||||||
|
MOVL CX,84(DI)
|
||||||
|
MOVL R8,88(DI)
|
||||||
|
MOVL R9,92(DI)
|
||||||
|
MOVD X14,DX
|
||||||
|
MOVD X0,CX
|
||||||
|
MOVD X5,R8
|
||||||
|
MOVD X8,R9
|
||||||
|
PSHUFL $0X39,X14,X14
|
||||||
|
PSHUFL $0X39,X0,X0
|
||||||
|
PSHUFL $0X39,X5,X5
|
||||||
|
PSHUFL $0X39,X8,X8
|
||||||
|
XORL 144(SI),DX
|
||||||
|
XORL 148(SI),CX
|
||||||
|
XORL 152(SI),R8
|
||||||
|
XORL 156(SI),R9
|
||||||
|
MOVL DX,144(DI)
|
||||||
|
MOVL CX,148(DI)
|
||||||
|
MOVL R8,152(DI)
|
||||||
|
MOVL R9,156(DI)
|
||||||
|
MOVD X14,DX
|
||||||
|
MOVD X0,CX
|
||||||
|
MOVD X5,R8
|
||||||
|
MOVD X8,R9
|
||||||
|
XORL 208(SI),DX
|
||||||
|
XORL 212(SI),CX
|
||||||
|
XORL 216(SI),R8
|
||||||
|
XORL 220(SI),R9
|
||||||
|
MOVL DX,208(DI)
|
||||||
|
MOVL CX,212(DI)
|
||||||
|
MOVL R8,216(DI)
|
||||||
|
MOVL R9,220(DI)
|
||||||
|
PADDL 288(SP),X15
|
||||||
|
PADDL 304(SP),X11
|
||||||
|
PADDL 80(SP),X1
|
||||||
|
PADDL 144(SP),X6
|
||||||
|
MOVD X15,DX
|
||||||
|
MOVD X11,CX
|
||||||
|
MOVD X1,R8
|
||||||
|
MOVD X6,R9
|
||||||
|
PSHUFL $0X39,X15,X15
|
||||||
|
PSHUFL $0X39,X11,X11
|
||||||
|
PSHUFL $0X39,X1,X1
|
||||||
|
PSHUFL $0X39,X6,X6
|
||||||
|
XORL 32(SI),DX
|
||||||
|
XORL 36(SI),CX
|
||||||
|
XORL 40(SI),R8
|
||||||
|
XORL 44(SI),R9
|
||||||
|
MOVL DX,32(DI)
|
||||||
|
MOVL CX,36(DI)
|
||||||
|
MOVL R8,40(DI)
|
||||||
|
MOVL R9,44(DI)
|
||||||
|
MOVD X15,DX
|
||||||
|
MOVD X11,CX
|
||||||
|
MOVD X1,R8
|
||||||
|
MOVD X6,R9
|
||||||
|
PSHUFL $0X39,X15,X15
|
||||||
|
PSHUFL $0X39,X11,X11
|
||||||
|
PSHUFL $0X39,X1,X1
|
||||||
|
PSHUFL $0X39,X6,X6
|
||||||
|
XORL 96(SI),DX
|
||||||
|
XORL 100(SI),CX
|
||||||
|
XORL 104(SI),R8
|
||||||
|
XORL 108(SI),R9
|
||||||
|
MOVL DX,96(DI)
|
||||||
|
MOVL CX,100(DI)
|
||||||
|
MOVL R8,104(DI)
|
||||||
|
MOVL R9,108(DI)
|
||||||
|
MOVD X15,DX
|
||||||
|
MOVD X11,CX
|
||||||
|
MOVD X1,R8
|
||||||
|
MOVD X6,R9
|
||||||
|
PSHUFL $0X39,X15,X15
|
||||||
|
PSHUFL $0X39,X11,X11
|
||||||
|
PSHUFL $0X39,X1,X1
|
||||||
|
PSHUFL $0X39,X6,X6
|
||||||
|
XORL 160(SI),DX
|
||||||
|
XORL 164(SI),CX
|
||||||
|
XORL 168(SI),R8
|
||||||
|
XORL 172(SI),R9
|
||||||
|
MOVL DX,160(DI)
|
||||||
|
MOVL CX,164(DI)
|
||||||
|
MOVL R8,168(DI)
|
||||||
|
MOVL R9,172(DI)
|
||||||
|
MOVD X15,DX
|
||||||
|
MOVD X11,CX
|
||||||
|
MOVD X1,R8
|
||||||
|
MOVD X6,R9
|
||||||
|
XORL 224(SI),DX
|
||||||
|
XORL 228(SI),CX
|
||||||
|
XORL 232(SI),R8
|
||||||
|
XORL 236(SI),R9
|
||||||
|
MOVL DX,224(DI)
|
||||||
|
MOVL CX,228(DI)
|
||||||
|
MOVL R8,232(DI)
|
||||||
|
MOVL R9,236(DI)
|
||||||
|
PADDL 160(SP),X13
|
||||||
|
PADDL 208(SP),X9
|
||||||
|
PADDL 256(SP),X3
|
||||||
|
PADDL 96(SP),X2
|
||||||
|
MOVD X13,DX
|
||||||
|
MOVD X9,CX
|
||||||
|
MOVD X3,R8
|
||||||
|
MOVD X2,R9
|
||||||
|
PSHUFL $0X39,X13,X13
|
||||||
|
PSHUFL $0X39,X9,X9
|
||||||
|
PSHUFL $0X39,X3,X3
|
||||||
|
PSHUFL $0X39,X2,X2
|
||||||
|
XORL 48(SI),DX
|
||||||
|
XORL 52(SI),CX
|
||||||
|
XORL 56(SI),R8
|
||||||
|
XORL 60(SI),R9
|
||||||
|
MOVL DX,48(DI)
|
||||||
|
MOVL CX,52(DI)
|
||||||
|
MOVL R8,56(DI)
|
||||||
|
MOVL R9,60(DI)
|
||||||
|
MOVD X13,DX
|
||||||
|
MOVD X9,CX
|
||||||
|
MOVD X3,R8
|
||||||
|
MOVD X2,R9
|
||||||
|
PSHUFL $0X39,X13,X13
|
||||||
|
PSHUFL $0X39,X9,X9
|
||||||
|
PSHUFL $0X39,X3,X3
|
||||||
|
PSHUFL $0X39,X2,X2
|
||||||
|
XORL 112(SI),DX
|
||||||
|
XORL 116(SI),CX
|
||||||
|
XORL 120(SI),R8
|
||||||
|
XORL 124(SI),R9
|
||||||
|
MOVL DX,112(DI)
|
||||||
|
MOVL CX,116(DI)
|
||||||
|
MOVL R8,120(DI)
|
||||||
|
MOVL R9,124(DI)
|
||||||
|
MOVD X13,DX
|
||||||
|
MOVD X9,CX
|
||||||
|
MOVD X3,R8
|
||||||
|
MOVD X2,R9
|
||||||
|
PSHUFL $0X39,X13,X13
|
||||||
|
PSHUFL $0X39,X9,X9
|
||||||
|
PSHUFL $0X39,X3,X3
|
||||||
|
PSHUFL $0X39,X2,X2
|
||||||
|
XORL 176(SI),DX
|
||||||
|
XORL 180(SI),CX
|
||||||
|
XORL 184(SI),R8
|
||||||
|
XORL 188(SI),R9
|
||||||
|
MOVL DX,176(DI)
|
||||||
|
MOVL CX,180(DI)
|
||||||
|
MOVL R8,184(DI)
|
||||||
|
MOVL R9,188(DI)
|
||||||
|
MOVD X13,DX
|
||||||
|
MOVD X9,CX
|
||||||
|
MOVD X3,R8
|
||||||
|
MOVD X2,R9
|
||||||
|
XORL 240(SI),DX
|
||||||
|
XORL 244(SI),CX
|
||||||
|
XORL 248(SI),R8
|
||||||
|
XORL 252(SI),R9
|
||||||
|
MOVL DX,240(DI)
|
||||||
|
MOVL CX,244(DI)
|
||||||
|
MOVL R8,248(DI)
|
||||||
|
MOVL R9,252(DI)
|
||||||
|
MOVQ 408(SP),R9
|
||||||
|
SUBQ $256,R9
|
||||||
|
ADDQ $256,SI
|
||||||
|
ADDQ $256,DI
|
||||||
|
CMPQ R9,$256
|
||||||
|
JAE BYTESATLEAST256
|
||||||
|
CMPQ R9,$0
|
||||||
|
JBE DONE
|
||||||
|
BYTESBETWEEN1AND255:
|
||||||
|
CMPQ R9,$64
|
||||||
|
JAE NOCOPY
|
||||||
|
MOVQ DI,DX
|
||||||
|
LEAQ 416(SP),DI
|
||||||
|
MOVQ R9,CX
|
||||||
|
REP; MOVSB
|
||||||
|
LEAQ 416(SP),DI
|
||||||
|
LEAQ 416(SP),SI
|
||||||
|
NOCOPY:
|
||||||
|
MOVQ R9,408(SP)
|
||||||
|
MOVOA 48(SP),X0
|
||||||
|
MOVOA 0(SP),X1
|
||||||
|
MOVOA 16(SP),X2
|
||||||
|
MOVOA 32(SP),X3
|
||||||
|
MOVOA X1,X4
|
||||||
|
MOVQ $20,CX
|
||||||
|
MAINLOOP2:
|
||||||
|
PADDL X0,X4
|
||||||
|
MOVOA X0,X5
|
||||||
|
MOVOA X4,X6
|
||||||
|
PSLLL $7,X4
|
||||||
|
PSRLL $25,X6
|
||||||
|
PXOR X4,X3
|
||||||
|
PXOR X6,X3
|
||||||
|
PADDL X3,X5
|
||||||
|
MOVOA X3,X4
|
||||||
|
MOVOA X5,X6
|
||||||
|
PSLLL $9,X5
|
||||||
|
PSRLL $23,X6
|
||||||
|
PXOR X5,X2
|
||||||
|
PSHUFL $0X93,X3,X3
|
||||||
|
PXOR X6,X2
|
||||||
|
PADDL X2,X4
|
||||||
|
MOVOA X2,X5
|
||||||
|
MOVOA X4,X6
|
||||||
|
PSLLL $13,X4
|
||||||
|
PSRLL $19,X6
|
||||||
|
PXOR X4,X1
|
||||||
|
PSHUFL $0X4E,X2,X2
|
||||||
|
PXOR X6,X1
|
||||||
|
PADDL X1,X5
|
||||||
|
MOVOA X3,X4
|
||||||
|
MOVOA X5,X6
|
||||||
|
PSLLL $18,X5
|
||||||
|
PSRLL $14,X6
|
||||||
|
PXOR X5,X0
|
||||||
|
PSHUFL $0X39,X1,X1
|
||||||
|
PXOR X6,X0
|
||||||
|
PADDL X0,X4
|
||||||
|
MOVOA X0,X5
|
||||||
|
MOVOA X4,X6
|
||||||
|
PSLLL $7,X4
|
||||||
|
PSRLL $25,X6
|
||||||
|
PXOR X4,X1
|
||||||
|
PXOR X6,X1
|
||||||
|
PADDL X1,X5
|
||||||
|
MOVOA X1,X4
|
||||||
|
MOVOA X5,X6
|
||||||
|
PSLLL $9,X5
|
||||||
|
PSRLL $23,X6
|
||||||
|
PXOR X5,X2
|
||||||
|
PSHUFL $0X93,X1,X1
|
||||||
|
PXOR X6,X2
|
||||||
|
PADDL X2,X4
|
||||||
|
MOVOA X2,X5
|
||||||
|
MOVOA X4,X6
|
||||||
|
PSLLL $13,X4
|
||||||
|
PSRLL $19,X6
|
||||||
|
PXOR X4,X3
|
||||||
|
PSHUFL $0X4E,X2,X2
|
||||||
|
PXOR X6,X3
|
||||||
|
PADDL X3,X5
|
||||||
|
MOVOA X1,X4
|
||||||
|
MOVOA X5,X6
|
||||||
|
PSLLL $18,X5
|
||||||
|
PSRLL $14,X6
|
||||||
|
PXOR X5,X0
|
||||||
|
PSHUFL $0X39,X3,X3
|
||||||
|
PXOR X6,X0
|
||||||
|
PADDL X0,X4
|
||||||
|
MOVOA X0,X5
|
||||||
|
MOVOA X4,X6
|
||||||
|
PSLLL $7,X4
|
||||||
|
PSRLL $25,X6
|
||||||
|
PXOR X4,X3
|
||||||
|
PXOR X6,X3
|
||||||
|
PADDL X3,X5
|
||||||
|
MOVOA X3,X4
|
||||||
|
MOVOA X5,X6
|
||||||
|
PSLLL $9,X5
|
||||||
|
PSRLL $23,X6
|
||||||
|
PXOR X5,X2
|
||||||
|
PSHUFL $0X93,X3,X3
|
||||||
|
PXOR X6,X2
|
||||||
|
PADDL X2,X4
|
||||||
|
MOVOA X2,X5
|
||||||
|
MOVOA X4,X6
|
||||||
|
PSLLL $13,X4
|
||||||
|
PSRLL $19,X6
|
||||||
|
PXOR X4,X1
|
||||||
|
PSHUFL $0X4E,X2,X2
|
||||||
|
PXOR X6,X1
|
||||||
|
PADDL X1,X5
|
||||||
|
MOVOA X3,X4
|
||||||
|
MOVOA X5,X6
|
||||||
|
PSLLL $18,X5
|
||||||
|
PSRLL $14,X6
|
||||||
|
PXOR X5,X0
|
||||||
|
PSHUFL $0X39,X1,X1
|
||||||
|
PXOR X6,X0
|
||||||
|
PADDL X0,X4
|
||||||
|
MOVOA X0,X5
|
||||||
|
MOVOA X4,X6
|
||||||
|
PSLLL $7,X4
|
||||||
|
PSRLL $25,X6
|
||||||
|
PXOR X4,X1
|
||||||
|
PXOR X6,X1
|
||||||
|
PADDL X1,X5
|
||||||
|
MOVOA X1,X4
|
||||||
|
MOVOA X5,X6
|
||||||
|
PSLLL $9,X5
|
||||||
|
PSRLL $23,X6
|
||||||
|
PXOR X5,X2
|
||||||
|
PSHUFL $0X93,X1,X1
|
||||||
|
PXOR X6,X2
|
||||||
|
PADDL X2,X4
|
||||||
|
MOVOA X2,X5
|
||||||
|
MOVOA X4,X6
|
||||||
|
PSLLL $13,X4
|
||||||
|
PSRLL $19,X6
|
||||||
|
PXOR X4,X3
|
||||||
|
PSHUFL $0X4E,X2,X2
|
||||||
|
PXOR X6,X3
|
||||||
|
SUBQ $4,CX
|
||||||
|
PADDL X3,X5
|
||||||
|
MOVOA X1,X4
|
||||||
|
MOVOA X5,X6
|
||||||
|
PSLLL $18,X5
|
||||||
|
PXOR X7,X7
|
||||||
|
PSRLL $14,X6
|
||||||
|
PXOR X5,X0
|
||||||
|
PSHUFL $0X39,X3,X3
|
||||||
|
PXOR X6,X0
|
||||||
|
JA MAINLOOP2
|
||||||
|
PADDL 48(SP),X0
|
||||||
|
PADDL 0(SP),X1
|
||||||
|
PADDL 16(SP),X2
|
||||||
|
PADDL 32(SP),X3
|
||||||
|
MOVD X0,CX
|
||||||
|
MOVD X1,R8
|
||||||
|
MOVD X2,R9
|
||||||
|
MOVD X3,AX
|
||||||
|
PSHUFL $0X39,X0,X0
|
||||||
|
PSHUFL $0X39,X1,X1
|
||||||
|
PSHUFL $0X39,X2,X2
|
||||||
|
PSHUFL $0X39,X3,X3
|
||||||
|
XORL 0(SI),CX
|
||||||
|
XORL 48(SI),R8
|
||||||
|
XORL 32(SI),R9
|
||||||
|
XORL 16(SI),AX
|
||||||
|
MOVL CX,0(DI)
|
||||||
|
MOVL R8,48(DI)
|
||||||
|
MOVL R9,32(DI)
|
||||||
|
MOVL AX,16(DI)
|
||||||
|
MOVD X0,CX
|
||||||
|
MOVD X1,R8
|
||||||
|
MOVD X2,R9
|
||||||
|
MOVD X3,AX
|
||||||
|
PSHUFL $0X39,X0,X0
|
||||||
|
PSHUFL $0X39,X1,X1
|
||||||
|
PSHUFL $0X39,X2,X2
|
||||||
|
PSHUFL $0X39,X3,X3
|
||||||
|
XORL 20(SI),CX
|
||||||
|
XORL 4(SI),R8
|
||||||
|
XORL 52(SI),R9
|
||||||
|
XORL 36(SI),AX
|
||||||
|
MOVL CX,20(DI)
|
||||||
|
MOVL R8,4(DI)
|
||||||
|
MOVL R9,52(DI)
|
||||||
|
MOVL AX,36(DI)
|
||||||
|
MOVD X0,CX
|
||||||
|
MOVD X1,R8
|
||||||
|
MOVD X2,R9
|
||||||
|
MOVD X3,AX
|
||||||
|
PSHUFL $0X39,X0,X0
|
||||||
|
PSHUFL $0X39,X1,X1
|
||||||
|
PSHUFL $0X39,X2,X2
|
||||||
|
PSHUFL $0X39,X3,X3
|
||||||
|
XORL 40(SI),CX
|
||||||
|
XORL 24(SI),R8
|
||||||
|
XORL 8(SI),R9
|
||||||
|
XORL 56(SI),AX
|
||||||
|
MOVL CX,40(DI)
|
||||||
|
MOVL R8,24(DI)
|
||||||
|
MOVL R9,8(DI)
|
||||||
|
MOVL AX,56(DI)
|
||||||
|
MOVD X0,CX
|
||||||
|
MOVD X1,R8
|
||||||
|
MOVD X2,R9
|
||||||
|
MOVD X3,AX
|
||||||
|
XORL 60(SI),CX
|
||||||
|
XORL 44(SI),R8
|
||||||
|
XORL 28(SI),R9
|
||||||
|
XORL 12(SI),AX
|
||||||
|
MOVL CX,60(DI)
|
||||||
|
MOVL R8,44(DI)
|
||||||
|
MOVL R9,28(DI)
|
||||||
|
MOVL AX,12(DI)
|
||||||
|
MOVQ 408(SP),R9
|
||||||
|
MOVL 16(SP),CX
|
||||||
|
MOVL 36 (SP),R8
|
||||||
|
ADDQ $1,CX
|
||||||
|
SHLQ $32,R8
|
||||||
|
ADDQ R8,CX
|
||||||
|
MOVQ CX,R8
|
||||||
|
SHRQ $32,R8
|
||||||
|
MOVL CX,16(SP)
|
||||||
|
MOVL R8, 36 (SP)
|
||||||
|
CMPQ R9,$64
|
||||||
|
JA BYTESATLEAST65
|
||||||
|
JAE BYTESATLEAST64
|
||||||
|
MOVQ DI,SI
|
||||||
|
MOVQ DX,DI
|
||||||
|
MOVQ R9,CX
|
||||||
|
REP; MOVSB
|
||||||
|
BYTESATLEAST64:
|
||||||
|
DONE:
|
||||||
|
MOVQ 352(SP),R11
|
||||||
|
MOVQ 360(SP),R12
|
||||||
|
MOVQ 368(SP),R13
|
||||||
|
MOVQ 376(SP),R14
|
||||||
|
MOVQ 384(SP),R15
|
||||||
|
MOVQ 392(SP),BX
|
||||||
|
MOVQ 400(SP),BP
|
||||||
|
MOVQ R11,SP
|
||||||
|
RET
|
||||||
|
BYTESATLEAST65:
|
||||||
|
SUBQ $64,R9
|
||||||
|
ADDQ $64,DI
|
||||||
|
ADDQ $64,SI
|
||||||
|
JMP BYTESBETWEEN1AND255
|
|
@ -0,0 +1,199 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package salsa
|
||||||
|
|
||||||
|
// Core208 applies the Salsa20/8 core function to the 64-byte array in and puts
|
||||||
|
// the result into the 64-byte array out. The input and output may be the same array.
|
||||||
|
func Core208(out *[64]byte, in *[64]byte) {
|
||||||
|
j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
|
||||||
|
j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
|
||||||
|
j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
|
||||||
|
j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
|
||||||
|
j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24
|
||||||
|
j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24
|
||||||
|
j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24
|
||||||
|
j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24
|
||||||
|
j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24
|
||||||
|
j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24
|
||||||
|
j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24
|
||||||
|
j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24
|
||||||
|
j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24
|
||||||
|
j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24
|
||||||
|
j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24
|
||||||
|
j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24
|
||||||
|
|
||||||
|
x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8
|
||||||
|
x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15
|
||||||
|
|
||||||
|
for i := 0; i < 8; i += 2 {
|
||||||
|
u := x0 + x12
|
||||||
|
x4 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x4 + x0
|
||||||
|
x8 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x8 + x4
|
||||||
|
x12 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x12 + x8
|
||||||
|
x0 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x5 + x1
|
||||||
|
x9 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x9 + x5
|
||||||
|
x13 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x13 + x9
|
||||||
|
x1 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x1 + x13
|
||||||
|
x5 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x10 + x6
|
||||||
|
x14 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x14 + x10
|
||||||
|
x2 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x2 + x14
|
||||||
|
x6 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x6 + x2
|
||||||
|
x10 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x15 + x11
|
||||||
|
x3 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x3 + x15
|
||||||
|
x7 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x7 + x3
|
||||||
|
x11 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x11 + x7
|
||||||
|
x15 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x0 + x3
|
||||||
|
x1 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x1 + x0
|
||||||
|
x2 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x2 + x1
|
||||||
|
x3 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x3 + x2
|
||||||
|
x0 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x5 + x4
|
||||||
|
x6 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x6 + x5
|
||||||
|
x7 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x7 + x6
|
||||||
|
x4 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x4 + x7
|
||||||
|
x5 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x10 + x9
|
||||||
|
x11 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x11 + x10
|
||||||
|
x8 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x8 + x11
|
||||||
|
x9 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x9 + x8
|
||||||
|
x10 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x15 + x14
|
||||||
|
x12 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x12 + x15
|
||||||
|
x13 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x13 + x12
|
||||||
|
x14 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x14 + x13
|
||||||
|
x15 ^= u<<18 | u>>(32-18)
|
||||||
|
}
|
||||||
|
x0 += j0
|
||||||
|
x1 += j1
|
||||||
|
x2 += j2
|
||||||
|
x3 += j3
|
||||||
|
x4 += j4
|
||||||
|
x5 += j5
|
||||||
|
x6 += j6
|
||||||
|
x7 += j7
|
||||||
|
x8 += j8
|
||||||
|
x9 += j9
|
||||||
|
x10 += j10
|
||||||
|
x11 += j11
|
||||||
|
x12 += j12
|
||||||
|
x13 += j13
|
||||||
|
x14 += j14
|
||||||
|
x15 += j15
|
||||||
|
|
||||||
|
out[0] = byte(x0)
|
||||||
|
out[1] = byte(x0 >> 8)
|
||||||
|
out[2] = byte(x0 >> 16)
|
||||||
|
out[3] = byte(x0 >> 24)
|
||||||
|
|
||||||
|
out[4] = byte(x1)
|
||||||
|
out[5] = byte(x1 >> 8)
|
||||||
|
out[6] = byte(x1 >> 16)
|
||||||
|
out[7] = byte(x1 >> 24)
|
||||||
|
|
||||||
|
out[8] = byte(x2)
|
||||||
|
out[9] = byte(x2 >> 8)
|
||||||
|
out[10] = byte(x2 >> 16)
|
||||||
|
out[11] = byte(x2 >> 24)
|
||||||
|
|
||||||
|
out[12] = byte(x3)
|
||||||
|
out[13] = byte(x3 >> 8)
|
||||||
|
out[14] = byte(x3 >> 16)
|
||||||
|
out[15] = byte(x3 >> 24)
|
||||||
|
|
||||||
|
out[16] = byte(x4)
|
||||||
|
out[17] = byte(x4 >> 8)
|
||||||
|
out[18] = byte(x4 >> 16)
|
||||||
|
out[19] = byte(x4 >> 24)
|
||||||
|
|
||||||
|
out[20] = byte(x5)
|
||||||
|
out[21] = byte(x5 >> 8)
|
||||||
|
out[22] = byte(x5 >> 16)
|
||||||
|
out[23] = byte(x5 >> 24)
|
||||||
|
|
||||||
|
out[24] = byte(x6)
|
||||||
|
out[25] = byte(x6 >> 8)
|
||||||
|
out[26] = byte(x6 >> 16)
|
||||||
|
out[27] = byte(x6 >> 24)
|
||||||
|
|
||||||
|
out[28] = byte(x7)
|
||||||
|
out[29] = byte(x7 >> 8)
|
||||||
|
out[30] = byte(x7 >> 16)
|
||||||
|
out[31] = byte(x7 >> 24)
|
||||||
|
|
||||||
|
out[32] = byte(x8)
|
||||||
|
out[33] = byte(x8 >> 8)
|
||||||
|
out[34] = byte(x8 >> 16)
|
||||||
|
out[35] = byte(x8 >> 24)
|
||||||
|
|
||||||
|
out[36] = byte(x9)
|
||||||
|
out[37] = byte(x9 >> 8)
|
||||||
|
out[38] = byte(x9 >> 16)
|
||||||
|
out[39] = byte(x9 >> 24)
|
||||||
|
|
||||||
|
out[40] = byte(x10)
|
||||||
|
out[41] = byte(x10 >> 8)
|
||||||
|
out[42] = byte(x10 >> 16)
|
||||||
|
out[43] = byte(x10 >> 24)
|
||||||
|
|
||||||
|
out[44] = byte(x11)
|
||||||
|
out[45] = byte(x11 >> 8)
|
||||||
|
out[46] = byte(x11 >> 16)
|
||||||
|
out[47] = byte(x11 >> 24)
|
||||||
|
|
||||||
|
out[48] = byte(x12)
|
||||||
|
out[49] = byte(x12 >> 8)
|
||||||
|
out[50] = byte(x12 >> 16)
|
||||||
|
out[51] = byte(x12 >> 24)
|
||||||
|
|
||||||
|
out[52] = byte(x13)
|
||||||
|
out[53] = byte(x13 >> 8)
|
||||||
|
out[54] = byte(x13 >> 16)
|
||||||
|
out[55] = byte(x13 >> 24)
|
||||||
|
|
||||||
|
out[56] = byte(x14)
|
||||||
|
out[57] = byte(x14 >> 8)
|
||||||
|
out[58] = byte(x14 >> 16)
|
||||||
|
out[59] = byte(x14 >> 24)
|
||||||
|
|
||||||
|
out[60] = byte(x15)
|
||||||
|
out[61] = byte(x15 >> 8)
|
||||||
|
out[62] = byte(x15 >> 16)
|
||||||
|
out[63] = byte(x15 >> 24)
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build amd64,!appengine,!gccgo
|
||||||
|
|
||||||
|
package salsa
|
||||||
|
|
||||||
|
// This function is implemented in salsa2020_amd64.s.
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
|
||||||
|
func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
|
||||||
|
|
||||||
|
// XORKeyStream crypts bytes from in to out using the given key and counters.
|
||||||
|
// In and out may be the same slice but otherwise should not overlap. Counter
|
||||||
|
// contains the raw salsa20 counter bytes (both nonce and block counter).
|
||||||
|
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
|
||||||
|
if len(in) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0])
|
||||||
|
}
|
|
@ -0,0 +1,234 @@
|
||||||
|
// Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !amd64 appengine gccgo
|
||||||
|
|
||||||
|
package salsa
|
||||||
|
|
||||||
|
const rounds = 20
|
||||||
|
|
||||||
|
// core applies the Salsa20 core function to 16-byte input in, 32-byte key k,
|
||||||
|
// and 16-byte constant c, and puts the result into 64-byte array out.
|
||||||
|
func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) {
|
||||||
|
j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24
|
||||||
|
j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24
|
||||||
|
j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24
|
||||||
|
j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24
|
||||||
|
j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24
|
||||||
|
j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24
|
||||||
|
j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24
|
||||||
|
j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24
|
||||||
|
j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24
|
||||||
|
j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24
|
||||||
|
j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24
|
||||||
|
j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24
|
||||||
|
j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24
|
||||||
|
j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24
|
||||||
|
j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24
|
||||||
|
j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24
|
||||||
|
|
||||||
|
x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8
|
||||||
|
x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15
|
||||||
|
|
||||||
|
for i := 0; i < rounds; i += 2 {
|
||||||
|
u := x0 + x12
|
||||||
|
x4 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x4 + x0
|
||||||
|
x8 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x8 + x4
|
||||||
|
x12 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x12 + x8
|
||||||
|
x0 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x5 + x1
|
||||||
|
x9 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x9 + x5
|
||||||
|
x13 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x13 + x9
|
||||||
|
x1 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x1 + x13
|
||||||
|
x5 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x10 + x6
|
||||||
|
x14 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x14 + x10
|
||||||
|
x2 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x2 + x14
|
||||||
|
x6 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x6 + x2
|
||||||
|
x10 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x15 + x11
|
||||||
|
x3 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x3 + x15
|
||||||
|
x7 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x7 + x3
|
||||||
|
x11 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x11 + x7
|
||||||
|
x15 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x0 + x3
|
||||||
|
x1 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x1 + x0
|
||||||
|
x2 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x2 + x1
|
||||||
|
x3 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x3 + x2
|
||||||
|
x0 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x5 + x4
|
||||||
|
x6 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x6 + x5
|
||||||
|
x7 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x7 + x6
|
||||||
|
x4 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x4 + x7
|
||||||
|
x5 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x10 + x9
|
||||||
|
x11 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x11 + x10
|
||||||
|
x8 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x8 + x11
|
||||||
|
x9 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x9 + x8
|
||||||
|
x10 ^= u<<18 | u>>(32-18)
|
||||||
|
|
||||||
|
u = x15 + x14
|
||||||
|
x12 ^= u<<7 | u>>(32-7)
|
||||||
|
u = x12 + x15
|
||||||
|
x13 ^= u<<9 | u>>(32-9)
|
||||||
|
u = x13 + x12
|
||||||
|
x14 ^= u<<13 | u>>(32-13)
|
||||||
|
u = x14 + x13
|
||||||
|
x15 ^= u<<18 | u>>(32-18)
|
||||||
|
}
|
||||||
|
x0 += j0
|
||||||
|
x1 += j1
|
||||||
|
x2 += j2
|
||||||
|
x3 += j3
|
||||||
|
x4 += j4
|
||||||
|
x5 += j5
|
||||||
|
x6 += j6
|
||||||
|
x7 += j7
|
||||||
|
x8 += j8
|
||||||
|
x9 += j9
|
||||||
|
x10 += j10
|
||||||
|
x11 += j11
|
||||||
|
x12 += j12
|
||||||
|
x13 += j13
|
||||||
|
x14 += j14
|
||||||
|
x15 += j15
|
||||||
|
|
||||||
|
out[0] = byte(x0)
|
||||||
|
out[1] = byte(x0 >> 8)
|
||||||
|
out[2] = byte(x0 >> 16)
|
||||||
|
out[3] = byte(x0 >> 24)
|
||||||
|
|
||||||
|
out[4] = byte(x1)
|
||||||
|
out[5] = byte(x1 >> 8)
|
||||||
|
out[6] = byte(x1 >> 16)
|
||||||
|
out[7] = byte(x1 >> 24)
|
||||||
|
|
||||||
|
out[8] = byte(x2)
|
||||||
|
out[9] = byte(x2 >> 8)
|
||||||
|
out[10] = byte(x2 >> 16)
|
||||||
|
out[11] = byte(x2 >> 24)
|
||||||
|
|
||||||
|
out[12] = byte(x3)
|
||||||
|
out[13] = byte(x3 >> 8)
|
||||||
|
out[14] = byte(x3 >> 16)
|
||||||
|
out[15] = byte(x3 >> 24)
|
||||||
|
|
||||||
|
out[16] = byte(x4)
|
||||||
|
out[17] = byte(x4 >> 8)
|
||||||
|
out[18] = byte(x4 >> 16)
|
||||||
|
out[19] = byte(x4 >> 24)
|
||||||
|
|
||||||
|
out[20] = byte(x5)
|
||||||
|
out[21] = byte(x5 >> 8)
|
||||||
|
out[22] = byte(x5 >> 16)
|
||||||
|
out[23] = byte(x5 >> 24)
|
||||||
|
|
||||||
|
out[24] = byte(x6)
|
||||||
|
out[25] = byte(x6 >> 8)
|
||||||
|
out[26] = byte(x6 >> 16)
|
||||||
|
out[27] = byte(x6 >> 24)
|
||||||
|
|
||||||
|
out[28] = byte(x7)
|
||||||
|
out[29] = byte(x7 >> 8)
|
||||||
|
out[30] = byte(x7 >> 16)
|
||||||
|
out[31] = byte(x7 >> 24)
|
||||||
|
|
||||||
|
out[32] = byte(x8)
|
||||||
|
out[33] = byte(x8 >> 8)
|
||||||
|
out[34] = byte(x8 >> 16)
|
||||||
|
out[35] = byte(x8 >> 24)
|
||||||
|
|
||||||
|
out[36] = byte(x9)
|
||||||
|
out[37] = byte(x9 >> 8)
|
||||||
|
out[38] = byte(x9 >> 16)
|
||||||
|
out[39] = byte(x9 >> 24)
|
||||||
|
|
||||||
|
out[40] = byte(x10)
|
||||||
|
out[41] = byte(x10 >> 8)
|
||||||
|
out[42] = byte(x10 >> 16)
|
||||||
|
out[43] = byte(x10 >> 24)
|
||||||
|
|
||||||
|
out[44] = byte(x11)
|
||||||
|
out[45] = byte(x11 >> 8)
|
||||||
|
out[46] = byte(x11 >> 16)
|
||||||
|
out[47] = byte(x11 >> 24)
|
||||||
|
|
||||||
|
out[48] = byte(x12)
|
||||||
|
out[49] = byte(x12 >> 8)
|
||||||
|
out[50] = byte(x12 >> 16)
|
||||||
|
out[51] = byte(x12 >> 24)
|
||||||
|
|
||||||
|
out[52] = byte(x13)
|
||||||
|
out[53] = byte(x13 >> 8)
|
||||||
|
out[54] = byte(x13 >> 16)
|
||||||
|
out[55] = byte(x13 >> 24)
|
||||||
|
|
||||||
|
out[56] = byte(x14)
|
||||||
|
out[57] = byte(x14 >> 8)
|
||||||
|
out[58] = byte(x14 >> 16)
|
||||||
|
out[59] = byte(x14 >> 24)
|
||||||
|
|
||||||
|
out[60] = byte(x15)
|
||||||
|
out[61] = byte(x15 >> 8)
|
||||||
|
out[62] = byte(x15 >> 16)
|
||||||
|
out[63] = byte(x15 >> 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
// XORKeyStream crypts bytes from in to out using the given key and counters.
|
||||||
|
// In and out may be the same slice but otherwise should not overlap. Counter
|
||||||
|
// contains the raw salsa20 counter bytes (both nonce and block counter).
|
||||||
|
func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
|
||||||
|
var block [64]byte
|
||||||
|
var counterCopy [16]byte
|
||||||
|
copy(counterCopy[:], counter[:])
|
||||||
|
|
||||||
|
for len(in) >= 64 {
|
||||||
|
core(&block, &counterCopy, key, &Sigma)
|
||||||
|
for i, x := range block {
|
||||||
|
out[i] = in[i] ^ x
|
||||||
|
}
|
||||||
|
u := uint32(1)
|
||||||
|
for i := 8; i < 16; i++ {
|
||||||
|
u += uint32(counterCopy[i])
|
||||||
|
counterCopy[i] = byte(u)
|
||||||
|
u >>= 8
|
||||||
|
}
|
||||||
|
in = in[64:]
|
||||||
|
out = out[64:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(in) > 0 {
|
||||||
|
core(&block, &counterCopy, key, &Sigma)
|
||||||
|
for i, v := range in {
|
||||||
|
out[i] = v ^ block[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue