diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index d2d04a5c01..71474d207c 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -94,10 +94,6 @@ "ImportPath": "github.com/dvsekhvalnov/jose2go", "Rev": "5307afb3bb6169b0f68cdf519a5964c843344441" }, - { - "ImportPath": "github.com/endophage/gotuf", - "Rev": "e1345f72687ad0443c25b3c58d4502c717c4936a" - }, { "ImportPath": "github.com/go-sql-driver/mysql", "Comment": "v1.2-97-g0cc29e9", @@ -200,6 +196,26 @@ "ImportPath": "golang.org/x/crypto/blowfish", "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" }, + { + "ImportPath": "golang.org/x/crypto/nacl/secretbox", + "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" + }, + { + "ImportPath": "golang.org/x/crypto/pbkdf2", + "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" + }, + { + "ImportPath": "golang.org/x/crypto/poly1305", + "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" + }, + { + "ImportPath": "golang.org/x/crypto/salsa20/salsa", + "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" + }, + { + "ImportPath": "golang.org/x/crypto/scrypt", + "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" + }, { "ImportPath": "golang.org/x/net/context", "Rev": "47990a1ba55743e6ef1affd3a14e5bac8553615d" diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/.gitignore b/Godeps/_workspace/src/github.com/endophage/gotuf/.gitignore deleted file mode 100644 index 2928b6ae98..0000000000 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/db/ -*.bkp -*.swp diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/.travis.yml b/Godeps/_workspace/src/github.com/endophage/gotuf/.travis.yml deleted file mode 100644 index b0822a6c99..0000000000 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -language: go -go: - - 1.4 - - tip - -sudo: false - -before_install: - - go get golang.org/x/tools/cmd/cover - -script: - - go test -race -cover ./... - -notifications: - irc: - channels: - - "chat.freenode.net#flynn" - use_notice: true - skip_join: true - on_success: change - on_failure: always - template: - - "%{repository}/%{branch} - %{commit}: %{message} %{build_url}" - email: - on_success: never - on_failure: always - -matrix: - allow_failures: - - go: tip diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Godeps.json b/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Godeps.json deleted file mode 100644 index 71f5992dc3..0000000000 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Godeps.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "ImportPath": "github.com/endophage/gotuf", - "GoVersion": "go1.5.1", - "Packages": [ - "./..." - ], - "Deps": [ - { - "ImportPath": "github.com/Sirupsen/logrus", - "Comment": "v0.7.3", - "Rev": "55eb11d21d2a31a3cc93838241d04800f52e823d" - }, - { - "ImportPath": "github.com/agl/ed25519", - "Rev": "d2b94fd789ea21d12fac1a4443dd3a3f79cda72c" - }, - { - "ImportPath": "github.com/docker/docker/pkg/term", - "Comment": "v1.7.1", - "Rev": "786b29d4db80a6175e72b47a794ee044918ba734" - }, - { - "ImportPath": "github.com/docker/notary/pkg/passphrase", - "Comment": "docker-v1.8.0-rc1-229-ge646033", - "Rev": "e6460330bdbef7d9a7a9a3dc51df2be83861c1b0" - }, - { - "ImportPath": "github.com/docker/notary/trustmanager", - "Comment": "docker-v1.8.0-rc1-229-ge646033", - "Rev": "e6460330bdbef7d9a7a9a3dc51df2be83861c1b0" - }, - { - "ImportPath": "github.com/google/gofuzz", - "Rev": "bbcb9da2d746f8bdbd6a936686a0a6067ada0ec5" - }, - { - "ImportPath": "github.com/jfrazelle/go/canonical/json", - "Rev": "6e461eb70cb4187b41a84e9a567d7137bdbe0f16" - }, - { - "ImportPath": "github.com/mattn/go-sqlite3", - "Comment": "v1.0.0", - "Rev": "b4142c444a8941d0d92b0b7103a24df9cd815e42" - }, - { - "ImportPath": "github.com/stretchr/testify/assert", - "Comment": "v1.0-40-g7c2b1e5", - "Rev": "7c2b1e5640dcf2631213ca962d892bffa1e08860" - }, - { - "ImportPath": "golang.org/x/crypto/nacl/secretbox", - "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" - }, - { - "ImportPath": "golang.org/x/crypto/pbkdf2", - "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" - }, - { - "ImportPath": "golang.org/x/crypto/poly1305", - "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" - }, - { - "ImportPath": "golang.org/x/crypto/salsa20/salsa", - "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" - }, - { - "ImportPath": "golang.org/x/crypto/scrypt", - "Rev": "bfc286917c5fcb7420d7e3092b50bbfd31b38a98" - } - ] -} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Readme b/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Readme deleted file mode 100644 index 4cdaa53d56..0000000000 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/Godeps/Readme +++ /dev/null @@ -1,5 +0,0 @@ -This directory tree is generated automatically by godep. - -Please do not edit. - -See https://github.com/tools/godep for more information. diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/Makefile b/Godeps/_workspace/src/github.com/endophage/gotuf/Makefile deleted file mode 100644 index 02c6d4d1b3..0000000000 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# Set an output prefix, which is the local directory if not specified -PREFIX?=$(shell pwd) - -vet: - @echo "+ $@" - @go vet ./... - -fmt: - @echo "+ $@" - @test -z "$$(gofmt -s -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)" || \ - echo "+ please format Go code with 'gofmt -s'" - -lint: - @echo "+ $@" - @test -z "$$(golint ./... | grep -v Godeps/_workspace/src/ | tee /dev/stderr)" - -build: - @echo "+ $@" - @go build -v ${GO_LDFLAGS} ./... - -test: - @echo "+ $@" - @go test -test.short ./... - -test-full: - @echo "+ $@" - @go test ./... - -binaries: ${PREFIX}/bin/registry ${PREFIX}/bin/registry-api-descriptor-template ${PREFIX}/bin/dist - @echo "+ $@" - -clean: - @echo "+ $@" - @rm -rf "${PREFIX}/bin/registry" "${PREFIX}/bin/registry-api-descriptor-template" diff --git a/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go b/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go new file mode 100644 index 0000000000..ed46ba2f2e --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go @@ -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: http://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 +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox_test.go b/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox_test.go new file mode 100644 index 0000000000..664dc1521d --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox_test.go @@ -0,0 +1,91 @@ +// 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 + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "testing" +) + +func TestSealOpen(t *testing.T) { + var key [32]byte + var nonce [24]byte + + rand.Reader.Read(key[:]) + rand.Reader.Read(nonce[:]) + + var box, opened []byte + + for msgLen := 0; msgLen < 128; msgLen += 17 { + message := make([]byte, msgLen) + rand.Reader.Read(message) + + box = Seal(box[:0], message, &nonce, &key) + var ok bool + opened, ok = Open(opened[:0], box, &nonce, &key) + if !ok { + t.Errorf("%d: failed to open box", msgLen) + continue + } + + if !bytes.Equal(opened, message) { + t.Errorf("%d: got %x, expected %x", msgLen, opened, message) + continue + } + } + + for i := range box { + box[i] ^= 0x20 + _, ok := Open(opened[:0], box, &nonce, &key) + if ok { + t.Errorf("box was opened after corrupting byte %d", i) + } + box[i] ^= 0x20 + } +} + +func TestSecretBox(t *testing.T) { + var key [32]byte + var nonce [24]byte + var message [64]byte + + for i := range key[:] { + key[i] = 1 + } + for i := range nonce[:] { + nonce[i] = 2 + } + for i := range message[:] { + message[i] = 3 + } + + box := Seal(nil, message[:], &nonce, &key) + // expected was generated using the C implementation of NaCl. + expected, _ := hex.DecodeString("8442bc313f4626f1359e3b50122b6ce6fe66ddfe7d39d14e637eb4fd5b45beadab55198df6ab5368439792a23c87db70acb6156dc5ef957ac04f6276cf6093b84be77ff0849cc33e34b7254d5a8f65ad") + + if !bytes.Equal(box, expected) { + t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) + } +} + +func TestAppend(t *testing.T) { + var key [32]byte + var nonce [24]byte + var message [8]byte + + out := make([]byte, 4) + box := Seal(out, message[:], &nonce, &key) + if !bytes.Equal(box[:4], out[:4]) { + t.Fatalf("Seal didn't correctly append") + } + + out = make([]byte, 4, 100) + box = Seal(out, message[:], &nonce, &key) + if !bytes.Equal(box[:4], out[:4]) { + t.Fatalf("Seal didn't correctly append with sufficient capacity.") + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/pbkdf2/pbkdf2.go b/Godeps/_workspace/src/golang.org/x/crypto/pbkdf2/pbkdf2.go new file mode 100644 index 0000000000..c02b4d5a70 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/pbkdf2/pbkdf2.go @@ -0,0 +1,77 @@ +// 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 pbkdf2 implements the key derivation function PBKDF2 as defined in RFC +2898 / PKCS #5 v2.0. + +A key derivation function is useful when encrypting data based on a password +or any other not-fully-random data. It uses a pseudorandom function to derive +a secure encryption key based on the password. + +While v2.0 of the standard defines only one pseudorandom function to use, +HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved +Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To +choose, you can pass the `New` functions from the different SHA packages to +pbkdf2.Key. +*/ +package pbkdf2 + +import ( + "crypto/hmac" + "hash" +) + +// Key derives a key from the password, salt and iteration count, returning a +// []byte of length keylen that can be used as cryptographic key. The key is +// derived based on the method described as PBKDF2 with the HMAC variant using +// the supplied hash function. +// +// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you +// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by +// doing: +// +// dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New) +// +// Remember to get a good random salt. At least 8 bytes is recommended by the +// RFC. +// +// Using a higher iteration count will increase the cost of an exhaustive +// search but will also make derivation proportionally slower. +func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { + prf := hmac.New(h, password) + hashLen := prf.Size() + numBlocks := (keyLen + hashLen - 1) / hashLen + + var buf [4]byte + dk := make([]byte, 0, numBlocks*hashLen) + U := make([]byte, hashLen) + for block := 1; block <= numBlocks; block++ { + // N.B.: || means concatenation, ^ means XOR + // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter + // U_1 = PRF(password, salt || uint(i)) + prf.Reset() + prf.Write(salt) + buf[0] = byte(block >> 24) + buf[1] = byte(block >> 16) + buf[2] = byte(block >> 8) + buf[3] = byte(block) + prf.Write(buf[:4]) + dk = prf.Sum(dk) + T := dk[len(dk)-hashLen:] + copy(U, T) + + // U_n = PRF(password, U_(n-1)) + for n := 2; n <= iter; n++ { + prf.Reset() + prf.Write(U) + U = U[:0] + U = prf.Sum(U) + for x := range U { + T[x] ^= U[x] + } + } + } + return dk[:keyLen] +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/pbkdf2/pbkdf2_test.go b/Godeps/_workspace/src/golang.org/x/crypto/pbkdf2/pbkdf2_test.go new file mode 100644 index 0000000000..1379240610 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/pbkdf2/pbkdf2_test.go @@ -0,0 +1,157 @@ +// 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 pbkdf2 + +import ( + "bytes" + "crypto/sha1" + "crypto/sha256" + "hash" + "testing" +) + +type testVector struct { + password string + salt string + iter int + output []byte +} + +// Test vectors from RFC 6070, http://tools.ietf.org/html/rfc6070 +var sha1TestVectors = []testVector{ + { + "password", + "salt", + 1, + []byte{ + 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6, + }, + }, + { + "password", + "salt", + 2, + []byte{ + 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57, + }, + }, + { + "password", + "salt", + 4096, + []byte{ + 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1, + }, + }, + // // This one takes too long + // { + // "password", + // "salt", + // 16777216, + // []byte{ + // 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, + // 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, + // 0x26, 0x34, 0xe9, 0x84, + // }, + // }, + { + "passwordPASSWORDpassword", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + 4096, + []byte{ + 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38, + }, + }, + { + "pass\000word", + "sa\000lt", + 4096, + []byte{ + 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3, + }, + }, +} + +// Test vectors from +// http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors +var sha256TestVectors = []testVector{ + { + "password", + "salt", + 1, + []byte{ + 0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c, + 0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37, + 0xa8, 0x65, 0x48, 0xc9, + }, + }, + { + "password", + "salt", + 2, + []byte{ + 0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3, + 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0, + 0x2a, 0x30, 0x3f, 0x8e, + }, + }, + { + "password", + "salt", + 4096, + []byte{ + 0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41, + 0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d, + 0x96, 0x28, 0x93, 0xa0, + }, + }, + { + "passwordPASSWORDpassword", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + 4096, + []byte{ + 0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f, + 0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf, + 0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18, + 0x1c, + }, + }, + { + "pass\000word", + "sa\000lt", + 4096, + []byte{ + 0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89, + 0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87, + }, + }, +} + +func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) { + for i, v := range vectors { + o := Key([]byte(v.password), []byte(v.salt), v.iter, len(v.output), h) + if !bytes.Equal(o, v.output) { + t.Errorf("%s %d: expected %x, got %x", hashName, i, v.output, o) + } + } +} + +func TestWithHMACSHA1(t *testing.T) { + testHash(t, sha1.New, "SHA1", sha1TestVectors) +} + +func TestWithHMACSHA256(t *testing.T) { + testHash(t, sha256.New, "SHA256", sha256TestVectors) +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/poly1305/const_amd64.s b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/const_amd64.s new file mode 100644 index 0000000000..33fcd6ee1a --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/const_amd64.s @@ -0,0 +1,45 @@ +// 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. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo + +DATA ·SCALE(SB)/8, $0x37F4000000000000 +GLOBL ·SCALE(SB), 8, $8 +DATA ·TWO32(SB)/8, $0x41F0000000000000 +GLOBL ·TWO32(SB), 8, $8 +DATA ·TWO64(SB)/8, $0x43F0000000000000 +GLOBL ·TWO64(SB), 8, $8 +DATA ·TWO96(SB)/8, $0x45F0000000000000 +GLOBL ·TWO96(SB), 8, $8 +DATA ·ALPHA32(SB)/8, $0x45E8000000000000 +GLOBL ·ALPHA32(SB), 8, $8 +DATA ·ALPHA64(SB)/8, $0x47E8000000000000 +GLOBL ·ALPHA64(SB), 8, $8 +DATA ·ALPHA96(SB)/8, $0x49E8000000000000 +GLOBL ·ALPHA96(SB), 8, $8 +DATA ·ALPHA130(SB)/8, $0x4C08000000000000 +GLOBL ·ALPHA130(SB), 8, $8 +DATA ·DOFFSET0(SB)/8, $0x4330000000000000 +GLOBL ·DOFFSET0(SB), 8, $8 +DATA ·DOFFSET1(SB)/8, $0x4530000000000000 +GLOBL ·DOFFSET1(SB), 8, $8 +DATA ·DOFFSET2(SB)/8, $0x4730000000000000 +GLOBL ·DOFFSET2(SB), 8, $8 +DATA ·DOFFSET3(SB)/8, $0x4930000000000000 +GLOBL ·DOFFSET3(SB), 8, $8 +DATA ·DOFFSET3MINUSTWO128(SB)/8, $0x492FFFFE00000000 +GLOBL ·DOFFSET3MINUSTWO128(SB), 8, $8 +DATA ·HOFFSET0(SB)/8, $0x43300001FFFFFFFB +GLOBL ·HOFFSET0(SB), 8, $8 +DATA ·HOFFSET1(SB)/8, $0x45300001FFFFFFFE +GLOBL ·HOFFSET1(SB), 8, $8 +DATA ·HOFFSET2(SB)/8, $0x47300001FFFFFFFE +GLOBL ·HOFFSET2(SB), 8, $8 +DATA ·HOFFSET3(SB)/8, $0x49300003FFFFFFFE +GLOBL ·HOFFSET3(SB), 8, $8 +DATA ·ROUNDING(SB)/2, $0x137f +GLOBL ·ROUNDING(SB), 8, $2 diff --git a/Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305.go b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305.go new file mode 100644 index 0000000000..2270d2b38a --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305.go @@ -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 +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305_amd64.s b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305_amd64.s new file mode 100644 index 0000000000..b9ad0ba436 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305_amd64.s @@ -0,0 +1,497 @@ +// 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. + +// This code was translated into a form compatible with 6a from the public +// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html + +// +build amd64,!gccgo + +// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key) +TEXT ·poly1305(SB),0,$224-32 + MOVQ out+0(FP),DI + MOVQ m+8(FP),SI + MOVQ mlen+16(FP),DX + MOVQ key+24(FP),CX + + MOVQ SP,R11 + MOVQ $31,R9 + NOTQ R9 + ANDQ R9,SP + ADDQ $32,SP + + MOVQ R11,32(SP) + MOVQ R12,40(SP) + MOVQ R13,48(SP) + MOVQ R14,56(SP) + MOVQ R15,64(SP) + MOVQ BX,72(SP) + MOVQ BP,80(SP) + FLDCW ·ROUNDING(SB) + MOVL 0(CX),R8 + MOVL 4(CX),R9 + MOVL 8(CX),AX + MOVL 12(CX),R10 + MOVQ DI,88(SP) + MOVQ CX,96(SP) + MOVL $0X43300000,108(SP) + MOVL $0X45300000,116(SP) + MOVL $0X47300000,124(SP) + MOVL $0X49300000,132(SP) + ANDL $0X0FFFFFFF,R8 + ANDL $0X0FFFFFFC,R9 + ANDL $0X0FFFFFFC,AX + ANDL $0X0FFFFFFC,R10 + MOVL R8,104(SP) + MOVL R9,112(SP) + MOVL AX,120(SP) + MOVL R10,128(SP) + FMOVD 104(SP), F0 + FSUBD ·DOFFSET0(SB), F0 + FMOVD 112(SP), F0 + FSUBD ·DOFFSET1(SB), F0 + FMOVD 120(SP), F0 + FSUBD ·DOFFSET2(SB), F0 + FMOVD 128(SP), F0 + FSUBD ·DOFFSET3(SB), F0 + FXCHD F0, F3 + FMOVDP F0, 136(SP) + FXCHD F0, F1 + FMOVD F0, 144(SP) + FMULD ·SCALE(SB), F0 + FMOVDP F0, 152(SP) + FMOVD F0, 160(SP) + FMULD ·SCALE(SB), F0 + FMOVDP F0, 168(SP) + FMOVD F0, 176(SP) + FMULD ·SCALE(SB), F0 + FMOVDP F0, 184(SP) + FLDZ + FLDZ + FLDZ + FLDZ + CMPQ DX,$16 + JB ADDATMOST15BYTES + INITIALATLEAST16BYTES: + MOVL 12(SI),DI + MOVL 8(SI),CX + MOVL 4(SI),R8 + MOVL 0(SI),R9 + MOVL DI,128(SP) + MOVL CX,120(SP) + MOVL R8,112(SP) + MOVL R9,104(SP) + ADDQ $16,SI + SUBQ $16,DX + FXCHD F0, F3 + FADDD 128(SP), F0 + FSUBD ·DOFFSET3MINUSTWO128(SB), F0 + FXCHD F0, F1 + FADDD 112(SP), F0 + FSUBD ·DOFFSET1(SB), F0 + FXCHD F0, F2 + FADDD 120(SP), F0 + FSUBD ·DOFFSET2(SB), F0 + FXCHD F0, F3 + FADDD 104(SP), F0 + FSUBD ·DOFFSET0(SB), F0 + CMPQ DX,$16 + JB MULTIPLYADDATMOST15BYTES + MULTIPLYADDATLEAST16BYTES: + MOVL 12(SI),DI + MOVL 8(SI),CX + MOVL 4(SI),R8 + MOVL 0(SI),R9 + MOVL DI,128(SP) + MOVL CX,120(SP) + MOVL R8,112(SP) + MOVL R9,104(SP) + ADDQ $16,SI + SUBQ $16,DX + FMOVD ·ALPHA130(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA130(SB), F0 + FSUBD F0,F2 + FMULD ·SCALE(SB), F0 + FMOVD ·ALPHA32(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA32(SB), F0 + FSUBD F0,F2 + FXCHD F0, F2 + FADDDP F0,F1 + FMOVD ·ALPHA64(SB), F0 + FADDD F4,F0 + FSUBD ·ALPHA64(SB), F0 + FSUBD F0,F4 + FMOVD ·ALPHA96(SB), F0 + FADDD F6,F0 + FSUBD ·ALPHA96(SB), F0 + FSUBD F0,F6 + FXCHD F0, F6 + FADDDP F0,F1 + FXCHD F0, F3 + FADDDP F0,F5 + FXCHD F0, F3 + FADDDP F0,F1 + FMOVD 176(SP), F0 + FMULD F3,F0 + FMOVD 160(SP), F0 + FMULD F4,F0 + FMOVD 144(SP), F0 + FMULD F5,F0 + FMOVD 136(SP), F0 + FMULDP F0,F6 + FMOVD 160(SP), F0 + FMULD F4,F0 + FADDDP F0,F3 + FMOVD 144(SP), F0 + FMULD F4,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F4,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULDP F0,F4 + FXCHD F0, F3 + FADDDP F0,F5 + FMOVD 144(SP), F0 + FMULD F4,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F4,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULD F4,F0 + FADDDP F0,F3 + FMOVD 168(SP), F0 + FMULDP F0,F4 + FXCHD F0, F3 + FADDDP F0,F4 + FMOVD 136(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FXCHD F0, F3 + FMOVD 184(SP), F0 + FMULD F5,F0 + FADDDP F0,F3 + FXCHD F0, F1 + FMOVD 168(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FMOVD 152(SP), F0 + FMULDP F0,F5 + FXCHD F0, F4 + FADDDP F0,F1 + CMPQ DX,$16 + FXCHD F0, F2 + FMOVD 128(SP), F0 + FSUBD ·DOFFSET3MINUSTWO128(SB), F0 + FADDDP F0,F1 + FXCHD F0, F1 + FMOVD 120(SP), F0 + FSUBD ·DOFFSET2(SB), F0 + FADDDP F0,F1 + FXCHD F0, F3 + FMOVD 112(SP), F0 + FSUBD ·DOFFSET1(SB), F0 + FADDDP F0,F1 + FXCHD F0, F2 + FMOVD 104(SP), F0 + FSUBD ·DOFFSET0(SB), F0 + FADDDP F0,F1 + JAE MULTIPLYADDATLEAST16BYTES + MULTIPLYADDATMOST15BYTES: + FMOVD ·ALPHA130(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA130(SB), F0 + FSUBD F0,F2 + FMULD ·SCALE(SB), F0 + FMOVD ·ALPHA32(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA32(SB), F0 + FSUBD F0,F2 + FMOVD ·ALPHA64(SB), F0 + FADDD F5,F0 + FSUBD ·ALPHA64(SB), F0 + FSUBD F0,F5 + FMOVD ·ALPHA96(SB), F0 + FADDD F7,F0 + FSUBD ·ALPHA96(SB), F0 + FSUBD F0,F7 + FXCHD F0, F7 + FADDDP F0,F1 + FXCHD F0, F5 + FADDDP F0,F1 + FXCHD F0, F3 + FADDDP F0,F5 + FADDDP F0,F1 + FMOVD 176(SP), F0 + FMULD F1,F0 + FMOVD 160(SP), F0 + FMULD F2,F0 + FMOVD 144(SP), F0 + FMULD F3,F0 + FMOVD 136(SP), F0 + FMULDP F0,F4 + FMOVD 160(SP), F0 + FMULD F5,F0 + FADDDP F0,F3 + FMOVD 144(SP), F0 + FMULD F5,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULDP F0,F5 + FXCHD F0, F4 + FADDDP F0,F3 + FMOVD 144(SP), F0 + FMULD F5,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULD F5,F0 + FADDDP F0,F4 + FMOVD 168(SP), F0 + FMULDP F0,F5 + FXCHD F0, F4 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULD F5,F0 + FADDDP F0,F4 + FMOVD 168(SP), F0 + FMULD F5,F0 + FADDDP F0,F3 + FMOVD 152(SP), F0 + FMULDP F0,F5 + FXCHD F0, F4 + FADDDP F0,F1 + ADDATMOST15BYTES: + CMPQ DX,$0 + JE NOMOREBYTES + MOVL $0,0(SP) + MOVL $0, 4 (SP) + MOVL $0, 8 (SP) + MOVL $0, 12 (SP) + LEAQ 0(SP),DI + MOVQ DX,CX + REP; MOVSB + MOVB $1,0(DI) + MOVL 12 (SP),DI + MOVL 8 (SP),SI + MOVL 4 (SP),DX + MOVL 0(SP),CX + MOVL DI,128(SP) + MOVL SI,120(SP) + MOVL DX,112(SP) + MOVL CX,104(SP) + FXCHD F0, F3 + FADDD 128(SP), F0 + FSUBD ·DOFFSET3(SB), F0 + FXCHD F0, F2 + FADDD 120(SP), F0 + FSUBD ·DOFFSET2(SB), F0 + FXCHD F0, F1 + FADDD 112(SP), F0 + FSUBD ·DOFFSET1(SB), F0 + FXCHD F0, F3 + FADDD 104(SP), F0 + FSUBD ·DOFFSET0(SB), F0 + FMOVD ·ALPHA130(SB), F0 + FADDD F3,F0 + FSUBD ·ALPHA130(SB), F0 + FSUBD F0,F3 + FMULD ·SCALE(SB), F0 + FMOVD ·ALPHA32(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA32(SB), F0 + FSUBD F0,F2 + FMOVD ·ALPHA64(SB), F0 + FADDD F6,F0 + FSUBD ·ALPHA64(SB), F0 + FSUBD F0,F6 + FMOVD ·ALPHA96(SB), F0 + FADDD F5,F0 + FSUBD ·ALPHA96(SB), F0 + FSUBD F0,F5 + FXCHD F0, F4 + FADDDP F0,F3 + FXCHD F0, F6 + FADDDP F0,F1 + FXCHD F0, F3 + FADDDP F0,F5 + FXCHD F0, F3 + FADDDP F0,F1 + FMOVD 176(SP), F0 + FMULD F3,F0 + FMOVD 160(SP), F0 + FMULD F4,F0 + FMOVD 144(SP), F0 + FMULD F5,F0 + FMOVD 136(SP), F0 + FMULDP F0,F6 + FMOVD 160(SP), F0 + FMULD F5,F0 + FADDDP F0,F3 + FMOVD 144(SP), F0 + FMULD F5,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F5,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULDP F0,F5 + FXCHD F0, F4 + FADDDP F0,F5 + FMOVD 144(SP), F0 + FMULD F6,F0 + FADDDP F0,F2 + FMOVD 136(SP), F0 + FMULD F6,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULD F6,F0 + FADDDP F0,F4 + FMOVD 168(SP), F0 + FMULDP F0,F6 + FXCHD F0, F5 + FADDDP F0,F4 + FMOVD 136(SP), F0 + FMULD F2,F0 + FADDDP F0,F1 + FMOVD 184(SP), F0 + FMULD F2,F0 + FADDDP F0,F5 + FMOVD 168(SP), F0 + FMULD F2,F0 + FADDDP F0,F3 + FMOVD 152(SP), F0 + FMULDP F0,F2 + FXCHD F0, F1 + FADDDP F0,F3 + FXCHD F0, F3 + FXCHD F0, F2 + NOMOREBYTES: + MOVL $0,R10 + FMOVD ·ALPHA130(SB), F0 + FADDD F4,F0 + FSUBD ·ALPHA130(SB), F0 + FSUBD F0,F4 + FMULD ·SCALE(SB), F0 + FMOVD ·ALPHA32(SB), F0 + FADDD F2,F0 + FSUBD ·ALPHA32(SB), F0 + FSUBD F0,F2 + FMOVD ·ALPHA64(SB), F0 + FADDD F4,F0 + FSUBD ·ALPHA64(SB), F0 + FSUBD F0,F4 + FMOVD ·ALPHA96(SB), F0 + FADDD F6,F0 + FSUBD ·ALPHA96(SB), F0 + FXCHD F0, F6 + FSUBD F6,F0 + FXCHD F0, F4 + FADDDP F0,F3 + FXCHD F0, F4 + FADDDP F0,F1 + FXCHD F0, F2 + FADDDP F0,F3 + FXCHD F0, F4 + FADDDP F0,F3 + FXCHD F0, F3 + FADDD ·HOFFSET0(SB), F0 + FXCHD F0, F3 + FADDD ·HOFFSET1(SB), F0 + FXCHD F0, F1 + FADDD ·HOFFSET2(SB), F0 + FXCHD F0, F2 + FADDD ·HOFFSET3(SB), F0 + FXCHD F0, F3 + FMOVDP F0, 104(SP) + FMOVDP F0, 112(SP) + FMOVDP F0, 120(SP) + FMOVDP F0, 128(SP) + MOVL 108(SP),DI + ANDL $63,DI + MOVL 116(SP),SI + ANDL $63,SI + MOVL 124(SP),DX + ANDL $63,DX + MOVL 132(SP),CX + ANDL $63,CX + MOVL 112(SP),R8 + ADDL DI,R8 + MOVQ R8,112(SP) + MOVL 120(SP),DI + ADCL SI,DI + MOVQ DI,120(SP) + MOVL 128(SP),DI + ADCL DX,DI + MOVQ DI,128(SP) + MOVL R10,DI + ADCL CX,DI + MOVQ DI,136(SP) + MOVQ $5,DI + MOVL 104(SP),SI + ADDL SI,DI + MOVQ DI,104(SP) + MOVL R10,DI + MOVQ 112(SP),DX + ADCL DX,DI + MOVQ DI,112(SP) + MOVL R10,DI + MOVQ 120(SP),CX + ADCL CX,DI + MOVQ DI,120(SP) + MOVL R10,DI + MOVQ 128(SP),R8 + ADCL R8,DI + MOVQ DI,128(SP) + MOVQ $0XFFFFFFFC,DI + MOVQ 136(SP),R9 + ADCL R9,DI + SARL $16,DI + MOVQ DI,R9 + XORL $0XFFFFFFFF,R9 + ANDQ DI,SI + MOVQ 104(SP),AX + ANDQ R9,AX + ORQ AX,SI + ANDQ DI,DX + MOVQ 112(SP),AX + ANDQ R9,AX + ORQ AX,DX + ANDQ DI,CX + MOVQ 120(SP),AX + ANDQ R9,AX + ORQ AX,CX + ANDQ DI,R8 + MOVQ 128(SP),DI + ANDQ R9,DI + ORQ DI,R8 + MOVQ 88(SP),DI + MOVQ 96(SP),R9 + ADDL 16(R9),SI + ADCL 20(R9),DX + ADCL 24(R9),CX + ADCL 28(R9),R8 + MOVL SI,0(DI) + MOVL DX,4(DI) + MOVL CX,8(DI) + MOVL R8,12(DI) + MOVQ 32(SP),R11 + MOVQ 40(SP),R12 + MOVQ 48(SP),R13 + MOVQ 56(SP),R14 + MOVQ 64(SP),R15 + MOVQ 72(SP),BX + MOVQ 80(SP),BP + MOVQ R11,SP + RET diff --git a/Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305_test.go b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305_test.go new file mode 100644 index 0000000000..2c6d1bc986 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305_test.go @@ -0,0 +1,74 @@ +// 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 + +import ( + "bytes" + "testing" +) + +var testData = []struct { + in, k, correct []byte +}{ + { + []byte("Hello world!"), + []byte("this is 32-byte key for Poly1305"), + []byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0}, + }, + { + make([]byte, 32), + []byte("this is 32-byte key for Poly1305"), + []byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07}, + }, + { + make([]byte, 2007), + []byte("this is 32-byte key for Poly1305"), + []byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa}, + }, + { + make([]byte, 2007), + make([]byte, 32), + make([]byte, 16), + }, +} + +func TestSum(t *testing.T) { + var out [16]byte + var key [32]byte + + for i, v := range testData { + copy(key[:], v.k) + Sum(&out, v.in, &key) + if !bytes.Equal(out[:], v.correct) { + t.Errorf("%d: expected %x, got %x", i, v.correct, out[:]) + } + } +} + +func Benchmark1K(b *testing.B) { + b.StopTimer() + var out [16]byte + var key [32]byte + in := make([]byte, 1024) + b.SetBytes(int64(len(in))) + b.StartTimer() + + for i := 0; i < b.N; i++ { + Sum(&out, in, &key) + } +} + +func Benchmark64(b *testing.B) { + b.StopTimer() + var out [16]byte + var key [32]byte + in := make([]byte, 64) + b.SetBytes(int64(len(in))) + b.StartTimer() + + for i := 0; i < b.N; i++ { + Sum(&out, in, &key) + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/poly1305/sum_amd64.go b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/sum_amd64.go new file mode 100644 index 0000000000..eb22ca1548 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/sum_amd64.go @@ -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 + +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) +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/poly1305/sum_ref.go b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/sum_ref.go new file mode 100644 index 0000000000..12568a2f64 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/poly1305/sum_ref.go @@ -0,0 +1,1531 @@ +// 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 + +package poly1305 + +// Based on original, public domain implementation from NaCl by D. J. +// Bernstein. + +import "math" + +const ( + alpham80 = 0.00000000558793544769287109375 + alpham48 = 24.0 + alpham16 = 103079215104.0 + alpha0 = 6755399441055744.0 + alpha18 = 1770887431076116955136.0 + alpha32 = 29014219670751100192948224.0 + alpha50 = 7605903601369376408980219232256.0 + alpha64 = 124615124604835863084731911901282304.0 + alpha82 = 32667107224410092492483962313449748299776.0 + alpha96 = 535217884764734955396857238543560676143529984.0 + alpha112 = 35076039295941670036888435985190792471742381031424.0 + alpha130 = 9194973245195333150150082162901855101712434733101613056.0 + scale = 0.0000000000000000000000000000000000000036734198463196484624023016788195177431833298649127735047148490821200539357960224151611328125 + offset0 = 6755408030990331.0 + offset1 = 29014256564239239022116864.0 + offset2 = 124615283061160854719918951570079744.0 + offset3 = 535219245894202480694386063513315216128475136.0 +) + +// 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) { + r := key + s := key[16:] + var ( + y7 float64 + y6 float64 + y1 float64 + y0 float64 + y5 float64 + y4 float64 + x7 float64 + x6 float64 + x1 float64 + x0 float64 + y3 float64 + y2 float64 + x5 float64 + r3lowx0 float64 + x4 float64 + r0lowx6 float64 + x3 float64 + r3highx0 float64 + x2 float64 + r0highx6 float64 + r0lowx0 float64 + sr1lowx6 float64 + r0highx0 float64 + sr1highx6 float64 + sr3low float64 + r1lowx0 float64 + sr2lowx6 float64 + r1highx0 float64 + sr2highx6 float64 + r2lowx0 float64 + sr3lowx6 float64 + r2highx0 float64 + sr3highx6 float64 + r1highx4 float64 + r1lowx4 float64 + r0highx4 float64 + r0lowx4 float64 + sr3highx4 float64 + sr3lowx4 float64 + sr2highx4 float64 + sr2lowx4 float64 + r0lowx2 float64 + r0highx2 float64 + r1lowx2 float64 + r1highx2 float64 + r2lowx2 float64 + r2highx2 float64 + sr3lowx2 float64 + sr3highx2 float64 + z0 float64 + z1 float64 + z2 float64 + z3 float64 + m0 int64 + m1 int64 + m2 int64 + m3 int64 + m00 uint32 + m01 uint32 + m02 uint32 + m03 uint32 + m10 uint32 + m11 uint32 + m12 uint32 + m13 uint32 + m20 uint32 + m21 uint32 + m22 uint32 + m23 uint32 + m30 uint32 + m31 uint32 + m32 uint32 + m33 uint64 + lbelow2 int32 + lbelow3 int32 + lbelow4 int32 + lbelow5 int32 + lbelow6 int32 + lbelow7 int32 + lbelow8 int32 + lbelow9 int32 + lbelow10 int32 + lbelow11 int32 + lbelow12 int32 + lbelow13 int32 + lbelow14 int32 + lbelow15 int32 + s00 uint32 + s01 uint32 + s02 uint32 + s03 uint32 + s10 uint32 + s11 uint32 + s12 uint32 + s13 uint32 + s20 uint32 + s21 uint32 + s22 uint32 + s23 uint32 + s30 uint32 + s31 uint32 + s32 uint32 + s33 uint32 + bits32 uint64 + f uint64 + f0 uint64 + f1 uint64 + f2 uint64 + f3 uint64 + f4 uint64 + g uint64 + g0 uint64 + g1 uint64 + g2 uint64 + g3 uint64 + g4 uint64 + ) + + var p int32 + + l := int32(len(m)) + + r00 := uint32(r[0]) + + r01 := uint32(r[1]) + + r02 := uint32(r[2]) + r0 := int64(2151) + + r03 := uint32(r[3]) + r03 &= 15 + r0 <<= 51 + + r10 := uint32(r[4]) + r10 &= 252 + r01 <<= 8 + r0 += int64(r00) + + r11 := uint32(r[5]) + r02 <<= 16 + r0 += int64(r01) + + r12 := uint32(r[6]) + r03 <<= 24 + r0 += int64(r02) + + r13 := uint32(r[7]) + r13 &= 15 + r1 := int64(2215) + r0 += int64(r03) + + d0 := r0 + r1 <<= 51 + r2 := int64(2279) + + r20 := uint32(r[8]) + r20 &= 252 + r11 <<= 8 + r1 += int64(r10) + + r21 := uint32(r[9]) + r12 <<= 16 + r1 += int64(r11) + + r22 := uint32(r[10]) + r13 <<= 24 + r1 += int64(r12) + + r23 := uint32(r[11]) + r23 &= 15 + r2 <<= 51 + r1 += int64(r13) + + d1 := r1 + r21 <<= 8 + r2 += int64(r20) + + r30 := uint32(r[12]) + r30 &= 252 + r22 <<= 16 + r2 += int64(r21) + + r31 := uint32(r[13]) + r23 <<= 24 + r2 += int64(r22) + + r32 := uint32(r[14]) + r2 += int64(r23) + r3 := int64(2343) + + d2 := r2 + r3 <<= 51 + + r33 := uint32(r[15]) + r33 &= 15 + r31 <<= 8 + r3 += int64(r30) + + r32 <<= 16 + r3 += int64(r31) + + r33 <<= 24 + r3 += int64(r32) + + r3 += int64(r33) + h0 := alpha32 - alpha32 + + d3 := r3 + h1 := alpha32 - alpha32 + + h2 := alpha32 - alpha32 + + h3 := alpha32 - alpha32 + + h4 := alpha32 - alpha32 + + r0low := math.Float64frombits(uint64(d0)) + h5 := alpha32 - alpha32 + + r1low := math.Float64frombits(uint64(d1)) + h6 := alpha32 - alpha32 + + r2low := math.Float64frombits(uint64(d2)) + h7 := alpha32 - alpha32 + + r0low -= alpha0 + + r1low -= alpha32 + + r2low -= alpha64 + + r0high := r0low + alpha18 + + r3low := math.Float64frombits(uint64(d3)) + + r1high := r1low + alpha50 + sr1low := scale * r1low + + r2high := r2low + alpha82 + sr2low := scale * r2low + + r0high -= alpha18 + r0high_stack := r0high + + r3low -= alpha96 + + r1high -= alpha50 + r1high_stack := r1high + + sr1high := sr1low + alpham80 + + r0low -= r0high + + r2high -= alpha82 + sr3low = scale * r3low + + sr2high := sr2low + alpham48 + + r1low -= r1high + r1low_stack := r1low + + sr1high -= alpham80 + sr1high_stack := sr1high + + r2low -= r2high + r2low_stack := r2low + + sr2high -= alpham48 + sr2high_stack := sr2high + + r3high := r3low + alpha112 + r0low_stack := r0low + + sr1low -= sr1high + sr1low_stack := sr1low + + sr3high := sr3low + alpham16 + r2high_stack := r2high + + sr2low -= sr2high + sr2low_stack := sr2low + + r3high -= alpha112 + r3high_stack := r3high + + sr3high -= alpham16 + sr3high_stack := sr3high + + r3low -= r3high + r3low_stack := r3low + + sr3low -= sr3high + sr3low_stack := sr3low + + if l < 16 { + goto addatmost15bytes + } + + m00 = uint32(m[p+0]) + m0 = 2151 + + m0 <<= 51 + m1 = 2215 + m01 = uint32(m[p+1]) + + m1 <<= 51 + m2 = 2279 + m02 = uint32(m[p+2]) + + m2 <<= 51 + m3 = 2343 + m03 = uint32(m[p+3]) + + m10 = uint32(m[p+4]) + m01 <<= 8 + m0 += int64(m00) + + m11 = uint32(m[p+5]) + m02 <<= 16 + m0 += int64(m01) + + m12 = uint32(m[p+6]) + m03 <<= 24 + m0 += int64(m02) + + m13 = uint32(m[p+7]) + m3 <<= 51 + m0 += int64(m03) + + m20 = uint32(m[p+8]) + m11 <<= 8 + m1 += int64(m10) + + m21 = uint32(m[p+9]) + m12 <<= 16 + m1 += int64(m11) + + m22 = uint32(m[p+10]) + m13 <<= 24 + m1 += int64(m12) + + m23 = uint32(m[p+11]) + m1 += int64(m13) + + m30 = uint32(m[p+12]) + m21 <<= 8 + m2 += int64(m20) + + m31 = uint32(m[p+13]) + m22 <<= 16 + m2 += int64(m21) + + m32 = uint32(m[p+14]) + m23 <<= 24 + m2 += int64(m22) + + m33 = uint64(m[p+15]) + m2 += int64(m23) + + d0 = m0 + m31 <<= 8 + m3 += int64(m30) + + d1 = m1 + m32 <<= 16 + m3 += int64(m31) + + d2 = m2 + m33 += 256 + + m33 <<= 24 + m3 += int64(m32) + + m3 += int64(m33) + d3 = m3 + + p += 16 + l -= 16 + + z0 = math.Float64frombits(uint64(d0)) + + z1 = math.Float64frombits(uint64(d1)) + + z2 = math.Float64frombits(uint64(d2)) + + z3 = math.Float64frombits(uint64(d3)) + + z0 -= alpha0 + + z1 -= alpha32 + + z2 -= alpha64 + + z3 -= alpha96 + + h0 += z0 + + h1 += z1 + + h3 += z2 + + h5 += z3 + + if l < 16 { + goto multiplyaddatmost15bytes + } + +multiplyaddatleast16bytes: + + m2 = 2279 + m20 = uint32(m[p+8]) + y7 = h7 + alpha130 + + m2 <<= 51 + m3 = 2343 + m21 = uint32(m[p+9]) + y6 = h6 + alpha130 + + m3 <<= 51 + m0 = 2151 + m22 = uint32(m[p+10]) + y1 = h1 + alpha32 + + m0 <<= 51 + m1 = 2215 + m23 = uint32(m[p+11]) + y0 = h0 + alpha32 + + m1 <<= 51 + m30 = uint32(m[p+12]) + y7 -= alpha130 + + m21 <<= 8 + m2 += int64(m20) + m31 = uint32(m[p+13]) + y6 -= alpha130 + + m22 <<= 16 + m2 += int64(m21) + m32 = uint32(m[p+14]) + y1 -= alpha32 + + m23 <<= 24 + m2 += int64(m22) + m33 = uint64(m[p+15]) + y0 -= alpha32 + + m2 += int64(m23) + m00 = uint32(m[p+0]) + y5 = h5 + alpha96 + + m31 <<= 8 + m3 += int64(m30) + m01 = uint32(m[p+1]) + y4 = h4 + alpha96 + + m32 <<= 16 + m02 = uint32(m[p+2]) + x7 = h7 - y7 + y7 *= scale + + m33 += 256 + m03 = uint32(m[p+3]) + x6 = h6 - y6 + y6 *= scale + + m33 <<= 24 + m3 += int64(m31) + m10 = uint32(m[p+4]) + x1 = h1 - y1 + + m01 <<= 8 + m3 += int64(m32) + m11 = uint32(m[p+5]) + x0 = h0 - y0 + + m3 += int64(m33) + m0 += int64(m00) + m12 = uint32(m[p+6]) + y5 -= alpha96 + + m02 <<= 16 + m0 += int64(m01) + m13 = uint32(m[p+7]) + y4 -= alpha96 + + m03 <<= 24 + m0 += int64(m02) + d2 = m2 + x1 += y7 + + m0 += int64(m03) + d3 = m3 + x0 += y6 + + m11 <<= 8 + m1 += int64(m10) + d0 = m0 + x7 += y5 + + m12 <<= 16 + m1 += int64(m11) + x6 += y4 + + m13 <<= 24 + m1 += int64(m12) + y3 = h3 + alpha64 + + m1 += int64(m13) + d1 = m1 + y2 = h2 + alpha64 + + x0 += x1 + + x6 += x7 + + y3 -= alpha64 + r3low = r3low_stack + + y2 -= alpha64 + r0low = r0low_stack + + x5 = h5 - y5 + r3lowx0 = r3low * x0 + r3high = r3high_stack + + x4 = h4 - y4 + r0lowx6 = r0low * x6 + r0high = r0high_stack + + x3 = h3 - y3 + r3highx0 = r3high * x0 + sr1low = sr1low_stack + + x2 = h2 - y2 + r0highx6 = r0high * x6 + sr1high = sr1high_stack + + x5 += y3 + r0lowx0 = r0low * x0 + r1low = r1low_stack + + h6 = r3lowx0 + r0lowx6 + sr1lowx6 = sr1low * x6 + r1high = r1high_stack + + x4 += y2 + r0highx0 = r0high * x0 + sr2low = sr2low_stack + + h7 = r3highx0 + r0highx6 + sr1highx6 = sr1high * x6 + sr2high = sr2high_stack + + x3 += y1 + r1lowx0 = r1low * x0 + r2low = r2low_stack + + h0 = r0lowx0 + sr1lowx6 + sr2lowx6 = sr2low * x6 + r2high = r2high_stack + + x2 += y0 + r1highx0 = r1high * x0 + sr3low = sr3low_stack + + h1 = r0highx0 + sr1highx6 + sr2highx6 = sr2high * x6 + sr3high = sr3high_stack + + x4 += x5 + r2lowx0 = r2low * x0 + z2 = math.Float64frombits(uint64(d2)) + + h2 = r1lowx0 + sr2lowx6 + sr3lowx6 = sr3low * x6 + + x2 += x3 + r2highx0 = r2high * x0 + z3 = math.Float64frombits(uint64(d3)) + + h3 = r1highx0 + sr2highx6 + sr3highx6 = sr3high * x6 + + r1highx4 = r1high * x4 + z2 -= alpha64 + + h4 = r2lowx0 + sr3lowx6 + r1lowx4 = r1low * x4 + + r0highx4 = r0high * x4 + z3 -= alpha96 + + h5 = r2highx0 + sr3highx6 + r0lowx4 = r0low * x4 + + h7 += r1highx4 + sr3highx4 = sr3high * x4 + + h6 += r1lowx4 + sr3lowx4 = sr3low * x4 + + h5 += r0highx4 + sr2highx4 = sr2high * x4 + + h4 += r0lowx4 + sr2lowx4 = sr2low * x4 + + h3 += sr3highx4 + r0lowx2 = r0low * x2 + + h2 += sr3lowx4 + r0highx2 = r0high * x2 + + h1 += sr2highx4 + r1lowx2 = r1low * x2 + + h0 += sr2lowx4 + r1highx2 = r1high * x2 + + h2 += r0lowx2 + r2lowx2 = r2low * x2 + + h3 += r0highx2 + r2highx2 = r2high * x2 + + h4 += r1lowx2 + sr3lowx2 = sr3low * x2 + + h5 += r1highx2 + sr3highx2 = sr3high * x2 + + p += 16 + l -= 16 + h6 += r2lowx2 + + h7 += r2highx2 + + z1 = math.Float64frombits(uint64(d1)) + h0 += sr3lowx2 + + z0 = math.Float64frombits(uint64(d0)) + h1 += sr3highx2 + + z1 -= alpha32 + + z0 -= alpha0 + + h5 += z3 + + h3 += z2 + + h1 += z1 + + h0 += z0 + + if l >= 16 { + goto multiplyaddatleast16bytes + } + +multiplyaddatmost15bytes: + + y7 = h7 + alpha130 + + y6 = h6 + alpha130 + + y1 = h1 + alpha32 + + y0 = h0 + alpha32 + + y7 -= alpha130 + + y6 -= alpha130 + + y1 -= alpha32 + + y0 -= alpha32 + + y5 = h5 + alpha96 + + y4 = h4 + alpha96 + + x7 = h7 - y7 + y7 *= scale + + x6 = h6 - y6 + y6 *= scale + + x1 = h1 - y1 + + x0 = h0 - y0 + + y5 -= alpha96 + + y4 -= alpha96 + + x1 += y7 + + x0 += y6 + + x7 += y5 + + x6 += y4 + + y3 = h3 + alpha64 + + y2 = h2 + alpha64 + + x0 += x1 + + x6 += x7 + + y3 -= alpha64 + r3low = r3low_stack + + y2 -= alpha64 + r0low = r0low_stack + + x5 = h5 - y5 + r3lowx0 = r3low * x0 + r3high = r3high_stack + + x4 = h4 - y4 + r0lowx6 = r0low * x6 + r0high = r0high_stack + + x3 = h3 - y3 + r3highx0 = r3high * x0 + sr1low = sr1low_stack + + x2 = h2 - y2 + r0highx6 = r0high * x6 + sr1high = sr1high_stack + + x5 += y3 + r0lowx0 = r0low * x0 + r1low = r1low_stack + + h6 = r3lowx0 + r0lowx6 + sr1lowx6 = sr1low * x6 + r1high = r1high_stack + + x4 += y2 + r0highx0 = r0high * x0 + sr2low = sr2low_stack + + h7 = r3highx0 + r0highx6 + sr1highx6 = sr1high * x6 + sr2high = sr2high_stack + + x3 += y1 + r1lowx0 = r1low * x0 + r2low = r2low_stack + + h0 = r0lowx0 + sr1lowx6 + sr2lowx6 = sr2low * x6 + r2high = r2high_stack + + x2 += y0 + r1highx0 = r1high * x0 + sr3low = sr3low_stack + + h1 = r0highx0 + sr1highx6 + sr2highx6 = sr2high * x6 + sr3high = sr3high_stack + + x4 += x5 + r2lowx0 = r2low * x0 + + h2 = r1lowx0 + sr2lowx6 + sr3lowx6 = sr3low * x6 + + x2 += x3 + r2highx0 = r2high * x0 + + h3 = r1highx0 + sr2highx6 + sr3highx6 = sr3high * x6 + + r1highx4 = r1high * x4 + + h4 = r2lowx0 + sr3lowx6 + r1lowx4 = r1low * x4 + + r0highx4 = r0high * x4 + + h5 = r2highx0 + sr3highx6 + r0lowx4 = r0low * x4 + + h7 += r1highx4 + sr3highx4 = sr3high * x4 + + h6 += r1lowx4 + sr3lowx4 = sr3low * x4 + + h5 += r0highx4 + sr2highx4 = sr2high * x4 + + h4 += r0lowx4 + sr2lowx4 = sr2low * x4 + + h3 += sr3highx4 + r0lowx2 = r0low * x2 + + h2 += sr3lowx4 + r0highx2 = r0high * x2 + + h1 += sr2highx4 + r1lowx2 = r1low * x2 + + h0 += sr2lowx4 + r1highx2 = r1high * x2 + + h2 += r0lowx2 + r2lowx2 = r2low * x2 + + h3 += r0highx2 + r2highx2 = r2high * x2 + + h4 += r1lowx2 + sr3lowx2 = sr3low * x2 + + h5 += r1highx2 + sr3highx2 = sr3high * x2 + + h6 += r2lowx2 + + h7 += r2highx2 + + h0 += sr3lowx2 + + h1 += sr3highx2 + +addatmost15bytes: + + if l == 0 { + goto nomorebytes + } + + lbelow2 = l - 2 + + lbelow3 = l - 3 + + lbelow2 >>= 31 + lbelow4 = l - 4 + + m00 = uint32(m[p+0]) + lbelow3 >>= 31 + p += lbelow2 + + m01 = uint32(m[p+1]) + lbelow4 >>= 31 + p += lbelow3 + + m02 = uint32(m[p+2]) + p += lbelow4 + m0 = 2151 + + m03 = uint32(m[p+3]) + m0 <<= 51 + m1 = 2215 + + m0 += int64(m00) + m01 &^= uint32(lbelow2) + + m02 &^= uint32(lbelow3) + m01 -= uint32(lbelow2) + + m01 <<= 8 + m03 &^= uint32(lbelow4) + + m0 += int64(m01) + lbelow2 -= lbelow3 + + m02 += uint32(lbelow2) + lbelow3 -= lbelow4 + + m02 <<= 16 + m03 += uint32(lbelow3) + + m03 <<= 24 + m0 += int64(m02) + + m0 += int64(m03) + lbelow5 = l - 5 + + lbelow6 = l - 6 + lbelow7 = l - 7 + + lbelow5 >>= 31 + lbelow8 = l - 8 + + lbelow6 >>= 31 + p += lbelow5 + + m10 = uint32(m[p+4]) + lbelow7 >>= 31 + p += lbelow6 + + m11 = uint32(m[p+5]) + lbelow8 >>= 31 + p += lbelow7 + + m12 = uint32(m[p+6]) + m1 <<= 51 + p += lbelow8 + + m13 = uint32(m[p+7]) + m10 &^= uint32(lbelow5) + lbelow4 -= lbelow5 + + m10 += uint32(lbelow4) + lbelow5 -= lbelow6 + + m11 &^= uint32(lbelow6) + m11 += uint32(lbelow5) + + m11 <<= 8 + m1 += int64(m10) + + m1 += int64(m11) + m12 &^= uint32(lbelow7) + + lbelow6 -= lbelow7 + m13 &^= uint32(lbelow8) + + m12 += uint32(lbelow6) + lbelow7 -= lbelow8 + + m12 <<= 16 + m13 += uint32(lbelow7) + + m13 <<= 24 + m1 += int64(m12) + + m1 += int64(m13) + m2 = 2279 + + lbelow9 = l - 9 + m3 = 2343 + + lbelow10 = l - 10 + lbelow11 = l - 11 + + lbelow9 >>= 31 + lbelow12 = l - 12 + + lbelow10 >>= 31 + p += lbelow9 + + m20 = uint32(m[p+8]) + lbelow11 >>= 31 + p += lbelow10 + + m21 = uint32(m[p+9]) + lbelow12 >>= 31 + p += lbelow11 + + m22 = uint32(m[p+10]) + m2 <<= 51 + p += lbelow12 + + m23 = uint32(m[p+11]) + m20 &^= uint32(lbelow9) + lbelow8 -= lbelow9 + + m20 += uint32(lbelow8) + lbelow9 -= lbelow10 + + m21 &^= uint32(lbelow10) + m21 += uint32(lbelow9) + + m21 <<= 8 + m2 += int64(m20) + + m2 += int64(m21) + m22 &^= uint32(lbelow11) + + lbelow10 -= lbelow11 + m23 &^= uint32(lbelow12) + + m22 += uint32(lbelow10) + lbelow11 -= lbelow12 + + m22 <<= 16 + m23 += uint32(lbelow11) + + m23 <<= 24 + m2 += int64(m22) + + m3 <<= 51 + lbelow13 = l - 13 + + lbelow13 >>= 31 + lbelow14 = l - 14 + + lbelow14 >>= 31 + p += lbelow13 + lbelow15 = l - 15 + + m30 = uint32(m[p+12]) + lbelow15 >>= 31 + p += lbelow14 + + m31 = uint32(m[p+13]) + p += lbelow15 + m2 += int64(m23) + + m32 = uint32(m[p+14]) + m30 &^= uint32(lbelow13) + lbelow12 -= lbelow13 + + m30 += uint32(lbelow12) + lbelow13 -= lbelow14 + + m3 += int64(m30) + m31 &^= uint32(lbelow14) + + m31 += uint32(lbelow13) + m32 &^= uint32(lbelow15) + + m31 <<= 8 + lbelow14 -= lbelow15 + + m3 += int64(m31) + m32 += uint32(lbelow14) + d0 = m0 + + m32 <<= 16 + m33 = uint64(lbelow15 + 1) + d1 = m1 + + m33 <<= 24 + m3 += int64(m32) + d2 = m2 + + m3 += int64(m33) + d3 = m3 + + z3 = math.Float64frombits(uint64(d3)) + + z2 = math.Float64frombits(uint64(d2)) + + z1 = math.Float64frombits(uint64(d1)) + + z0 = math.Float64frombits(uint64(d0)) + + z3 -= alpha96 + + z2 -= alpha64 + + z1 -= alpha32 + + z0 -= alpha0 + + h5 += z3 + + h3 += z2 + + h1 += z1 + + h0 += z0 + + y7 = h7 + alpha130 + + y6 = h6 + alpha130 + + y1 = h1 + alpha32 + + y0 = h0 + alpha32 + + y7 -= alpha130 + + y6 -= alpha130 + + y1 -= alpha32 + + y0 -= alpha32 + + y5 = h5 + alpha96 + + y4 = h4 + alpha96 + + x7 = h7 - y7 + y7 *= scale + + x6 = h6 - y6 + y6 *= scale + + x1 = h1 - y1 + + x0 = h0 - y0 + + y5 -= alpha96 + + y4 -= alpha96 + + x1 += y7 + + x0 += y6 + + x7 += y5 + + x6 += y4 + + y3 = h3 + alpha64 + + y2 = h2 + alpha64 + + x0 += x1 + + x6 += x7 + + y3 -= alpha64 + r3low = r3low_stack + + y2 -= alpha64 + r0low = r0low_stack + + x5 = h5 - y5 + r3lowx0 = r3low * x0 + r3high = r3high_stack + + x4 = h4 - y4 + r0lowx6 = r0low * x6 + r0high = r0high_stack + + x3 = h3 - y3 + r3highx0 = r3high * x0 + sr1low = sr1low_stack + + x2 = h2 - y2 + r0highx6 = r0high * x6 + sr1high = sr1high_stack + + x5 += y3 + r0lowx0 = r0low * x0 + r1low = r1low_stack + + h6 = r3lowx0 + r0lowx6 + sr1lowx6 = sr1low * x6 + r1high = r1high_stack + + x4 += y2 + r0highx0 = r0high * x0 + sr2low = sr2low_stack + + h7 = r3highx0 + r0highx6 + sr1highx6 = sr1high * x6 + sr2high = sr2high_stack + + x3 += y1 + r1lowx0 = r1low * x0 + r2low = r2low_stack + + h0 = r0lowx0 + sr1lowx6 + sr2lowx6 = sr2low * x6 + r2high = r2high_stack + + x2 += y0 + r1highx0 = r1high * x0 + sr3low = sr3low_stack + + h1 = r0highx0 + sr1highx6 + sr2highx6 = sr2high * x6 + sr3high = sr3high_stack + + x4 += x5 + r2lowx0 = r2low * x0 + + h2 = r1lowx0 + sr2lowx6 + sr3lowx6 = sr3low * x6 + + x2 += x3 + r2highx0 = r2high * x0 + + h3 = r1highx0 + sr2highx6 + sr3highx6 = sr3high * x6 + + r1highx4 = r1high * x4 + + h4 = r2lowx0 + sr3lowx6 + r1lowx4 = r1low * x4 + + r0highx4 = r0high * x4 + + h5 = r2highx0 + sr3highx6 + r0lowx4 = r0low * x4 + + h7 += r1highx4 + sr3highx4 = sr3high * x4 + + h6 += r1lowx4 + sr3lowx4 = sr3low * x4 + + h5 += r0highx4 + sr2highx4 = sr2high * x4 + + h4 += r0lowx4 + sr2lowx4 = sr2low * x4 + + h3 += sr3highx4 + r0lowx2 = r0low * x2 + + h2 += sr3lowx4 + r0highx2 = r0high * x2 + + h1 += sr2highx4 + r1lowx2 = r1low * x2 + + h0 += sr2lowx4 + r1highx2 = r1high * x2 + + h2 += r0lowx2 + r2lowx2 = r2low * x2 + + h3 += r0highx2 + r2highx2 = r2high * x2 + + h4 += r1lowx2 + sr3lowx2 = sr3low * x2 + + h5 += r1highx2 + sr3highx2 = sr3high * x2 + + h6 += r2lowx2 + + h7 += r2highx2 + + h0 += sr3lowx2 + + h1 += sr3highx2 + +nomorebytes: + + y7 = h7 + alpha130 + + y0 = h0 + alpha32 + + y1 = h1 + alpha32 + + y2 = h2 + alpha64 + + y7 -= alpha130 + + y3 = h3 + alpha64 + + y4 = h4 + alpha96 + + y5 = h5 + alpha96 + + x7 = h7 - y7 + y7 *= scale + + y0 -= alpha32 + + y1 -= alpha32 + + y2 -= alpha64 + + h6 += x7 + + y3 -= alpha64 + + y4 -= alpha96 + + y5 -= alpha96 + + y6 = h6 + alpha130 + + x0 = h0 - y0 + + x1 = h1 - y1 + + x2 = h2 - y2 + + y6 -= alpha130 + + x0 += y7 + + x3 = h3 - y3 + + x4 = h4 - y4 + + x5 = h5 - y5 + + x6 = h6 - y6 + + y6 *= scale + + x2 += y0 + + x3 += y1 + + x4 += y2 + + x0 += y6 + + x5 += y3 + + x6 += y4 + + x2 += x3 + + x0 += x1 + + x4 += x5 + + x6 += y5 + + x2 += offset1 + d1 = int64(math.Float64bits(x2)) + + x0 += offset0 + d0 = int64(math.Float64bits(x0)) + + x4 += offset2 + d2 = int64(math.Float64bits(x4)) + + x6 += offset3 + d3 = int64(math.Float64bits(x6)) + + f0 = uint64(d0) + + f1 = uint64(d1) + bits32 = math.MaxUint64 + + f2 = uint64(d2) + bits32 >>= 32 + + f3 = uint64(d3) + f = f0 >> 32 + + f0 &= bits32 + f &= 255 + + f1 += f + g0 = f0 + 5 + + g = g0 >> 32 + g0 &= bits32 + + f = f1 >> 32 + f1 &= bits32 + + f &= 255 + g1 = f1 + g + + g = g1 >> 32 + f2 += f + + f = f2 >> 32 + g1 &= bits32 + + f2 &= bits32 + f &= 255 + + f3 += f + g2 = f2 + g + + g = g2 >> 32 + g2 &= bits32 + + f4 = f3 >> 32 + f3 &= bits32 + + f4 &= 255 + g3 = f3 + g + + g = g3 >> 32 + g3 &= bits32 + + g4 = f4 + g + + g4 = g4 - 4 + s00 = uint32(s[0]) + + f = uint64(int64(g4) >> 63) + s01 = uint32(s[1]) + + f0 &= f + g0 &^= f + s02 = uint32(s[2]) + + f1 &= f + f0 |= g0 + s03 = uint32(s[3]) + + g1 &^= f + f2 &= f + s10 = uint32(s[4]) + + f3 &= f + g2 &^= f + s11 = uint32(s[5]) + + g3 &^= f + f1 |= g1 + s12 = uint32(s[6]) + + f2 |= g2 + f3 |= g3 + s13 = uint32(s[7]) + + s01 <<= 8 + f0 += uint64(s00) + s20 = uint32(s[8]) + + s02 <<= 16 + f0 += uint64(s01) + s21 = uint32(s[9]) + + s03 <<= 24 + f0 += uint64(s02) + s22 = uint32(s[10]) + + s11 <<= 8 + f1 += uint64(s10) + s23 = uint32(s[11]) + + s12 <<= 16 + f1 += uint64(s11) + s30 = uint32(s[12]) + + s13 <<= 24 + f1 += uint64(s12) + s31 = uint32(s[13]) + + f0 += uint64(s03) + f1 += uint64(s13) + s32 = uint32(s[14]) + + s21 <<= 8 + f2 += uint64(s20) + s33 = uint32(s[15]) + + s22 <<= 16 + f2 += uint64(s21) + + s23 <<= 24 + f2 += uint64(s22) + + s31 <<= 8 + f3 += uint64(s30) + + s32 <<= 16 + f3 += uint64(s31) + + s33 <<= 24 + f3 += uint64(s32) + + f2 += uint64(s23) + f3 += uint64(s33) + + out[0] = byte(f0) + f0 >>= 8 + out[1] = byte(f0) + f0 >>= 8 + out[2] = byte(f0) + f0 >>= 8 + out[3] = byte(f0) + f0 >>= 8 + f1 += f0 + + out[4] = byte(f1) + f1 >>= 8 + out[5] = byte(f1) + f1 >>= 8 + out[6] = byte(f1) + f1 >>= 8 + out[7] = byte(f1) + f1 >>= 8 + f2 += f1 + + out[8] = byte(f2) + f2 >>= 8 + out[9] = byte(f2) + f2 >>= 8 + out[10] = byte(f2) + f2 >>= 8 + out[11] = byte(f2) + f2 >>= 8 + f3 += f2 + + out[12] = byte(f3) + f3 >>= 8 + out[13] = byte(f3) + f3 >>= 8 + out[14] = byte(f3) + f3 >>= 8 + out[15] = byte(f3) +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/hsalsa20.go b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/hsalsa20.go new file mode 100644 index 0000000000..4ba47d5913 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/hsalsa20.go @@ -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) +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s new file mode 100644 index 0000000000..6e1df96391 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s @@ -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 diff --git a/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa208.go b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa208.go new file mode 100644 index 0000000000..9bfc0927ce --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa208.go @@ -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) +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go new file mode 100644 index 0000000000..903c7858e4 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go @@ -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]) +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go new file mode 100644 index 0000000000..95f8ca5bb9 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go @@ -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] + } + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa_test.go b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa_test.go new file mode 100644 index 0000000000..f8cecd9e6e --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa_test.go @@ -0,0 +1,35 @@ +// 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 + +import "testing" + +func TestCore208(t *testing.T) { + in := [64]byte{ + 0x7e, 0x87, 0x9a, 0x21, 0x4f, 0x3e, 0xc9, 0x86, + 0x7c, 0xa9, 0x40, 0xe6, 0x41, 0x71, 0x8f, 0x26, + 0xba, 0xee, 0x55, 0x5b, 0x8c, 0x61, 0xc1, 0xb5, + 0x0d, 0xf8, 0x46, 0x11, 0x6d, 0xcd, 0x3b, 0x1d, + 0xee, 0x24, 0xf3, 0x19, 0xdf, 0x9b, 0x3d, 0x85, + 0x14, 0x12, 0x1e, 0x4b, 0x5a, 0xc5, 0xaa, 0x32, + 0x76, 0x02, 0x1d, 0x29, 0x09, 0xc7, 0x48, 0x29, + 0xed, 0xeb, 0xc6, 0x8d, 0xb8, 0xb8, 0xc2, 0x5e} + + out := [64]byte{ + 0xa4, 0x1f, 0x85, 0x9c, 0x66, 0x08, 0xcc, 0x99, + 0x3b, 0x81, 0xca, 0xcb, 0x02, 0x0c, 0xef, 0x05, + 0x04, 0x4b, 0x21, 0x81, 0xa2, 0xfd, 0x33, 0x7d, + 0xfd, 0x7b, 0x1c, 0x63, 0x96, 0x68, 0x2f, 0x29, + 0xb4, 0x39, 0x31, 0x68, 0xe3, 0xc9, 0xe6, 0xbc, + 0xfe, 0x6b, 0xc5, 0xb7, 0xa0, 0x6d, 0x96, 0xba, + 0xe4, 0x24, 0xcc, 0x10, 0x2c, 0x91, 0x74, 0x5c, + 0x24, 0xad, 0x67, 0x3d, 0xc7, 0x61, 0x8f, 0x81, + } + + Core208(&in, &in) + if in != out { + t.Errorf("expected %x, got %x", out, in) + } +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt.go b/Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt.go new file mode 100644 index 0000000000..30737b0a62 --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt.go @@ -0,0 +1,243 @@ +// 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 scrypt implements the scrypt key derivation function as defined in +// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard +// Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf). +package scrypt + +import ( + "crypto/sha256" + "errors" + + "golang.org/x/crypto/pbkdf2" +) + +const maxInt = int(^uint(0) >> 1) + +// blockCopy copies n numbers from src into dst. +func blockCopy(dst, src []uint32, n int) { + copy(dst, src[:n]) +} + +// blockXOR XORs numbers from dst with n numbers from src. +func blockXOR(dst, src []uint32, n int) { + for i, v := range src[:n] { + dst[i] ^= v + } +} + +// salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in, +// and puts the result into both both tmp and out. +func salsaXOR(tmp *[16]uint32, in, out []uint32) { + w0 := tmp[0] ^ in[0] + w1 := tmp[1] ^ in[1] + w2 := tmp[2] ^ in[2] + w3 := tmp[3] ^ in[3] + w4 := tmp[4] ^ in[4] + w5 := tmp[5] ^ in[5] + w6 := tmp[6] ^ in[6] + w7 := tmp[7] ^ in[7] + w8 := tmp[8] ^ in[8] + w9 := tmp[9] ^ in[9] + w10 := tmp[10] ^ in[10] + w11 := tmp[11] ^ in[11] + w12 := tmp[12] ^ in[12] + w13 := tmp[13] ^ in[13] + w14 := tmp[14] ^ in[14] + w15 := tmp[15] ^ in[15] + + x0, x1, x2, x3, x4, x5, x6, x7, x8 := w0, w1, w2, w3, w4, w5, w6, w7, w8 + x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15 + + 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 += w0 + x1 += w1 + x2 += w2 + x3 += w3 + x4 += w4 + x5 += w5 + x6 += w6 + x7 += w7 + x8 += w8 + x9 += w9 + x10 += w10 + x11 += w11 + x12 += w12 + x13 += w13 + x14 += w14 + x15 += w15 + + out[0], tmp[0] = x0, x0 + out[1], tmp[1] = x1, x1 + out[2], tmp[2] = x2, x2 + out[3], tmp[3] = x3, x3 + out[4], tmp[4] = x4, x4 + out[5], tmp[5] = x5, x5 + out[6], tmp[6] = x6, x6 + out[7], tmp[7] = x7, x7 + out[8], tmp[8] = x8, x8 + out[9], tmp[9] = x9, x9 + out[10], tmp[10] = x10, x10 + out[11], tmp[11] = x11, x11 + out[12], tmp[12] = x12, x12 + out[13], tmp[13] = x13, x13 + out[14], tmp[14] = x14, x14 + out[15], tmp[15] = x15, x15 +} + +func blockMix(tmp *[16]uint32, in, out []uint32, r int) { + blockCopy(tmp[:], in[(2*r-1)*16:], 16) + for i := 0; i < 2*r; i += 2 { + salsaXOR(tmp, in[i*16:], out[i*8:]) + salsaXOR(tmp, in[i*16+16:], out[i*8+r*16:]) + } +} + +func integer(b []uint32, r int) uint64 { + j := (2*r - 1) * 16 + return uint64(b[j]) | uint64(b[j+1])<<32 +} + +func smix(b []byte, r, N int, v, xy []uint32) { + var tmp [16]uint32 + x := xy + y := xy[32*r:] + + j := 0 + for i := 0; i < 32*r; i++ { + x[i] = uint32(b[j]) | uint32(b[j+1])<<8 | uint32(b[j+2])<<16 | uint32(b[j+3])<<24 + j += 4 + } + for i := 0; i < N; i += 2 { + blockCopy(v[i*(32*r):], x, 32*r) + blockMix(&tmp, x, y, r) + + blockCopy(v[(i+1)*(32*r):], y, 32*r) + blockMix(&tmp, y, x, r) + } + for i := 0; i < N; i += 2 { + j := int(integer(x, r) & uint64(N-1)) + blockXOR(x, v[j*(32*r):], 32*r) + blockMix(&tmp, x, y, r) + + j = int(integer(y, r) & uint64(N-1)) + blockXOR(y, v[j*(32*r):], 32*r) + blockMix(&tmp, y, x, r) + } + j = 0 + for _, v := range x[:32*r] { + b[j+0] = byte(v >> 0) + b[j+1] = byte(v >> 8) + b[j+2] = byte(v >> 16) + b[j+3] = byte(v >> 24) + j += 4 + } +} + +// Key derives a key from the password, salt, and cost parameters, returning +// a byte slice of length keyLen that can be used as cryptographic key. +// +// N is a CPU/memory cost parameter, which must be a power of two greater than 1. +// r and p must satisfy r * p < 2³⁰. If the parameters do not satisfy the +// limits, the function returns a nil byte slice and an error. +// +// For example, you can get a derived key for e.g. AES-256 (which needs a +// 32-byte key) by doing: +// +// dk := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32) +// +// The recommended parameters for interactive logins as of 2009 are N=16384, +// r=8, p=1. They should be increased as memory latency and CPU parallelism +// increases. Remember to get a good random salt. +func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) { + if N <= 1 || N&(N-1) != 0 { + return nil, errors.New("scrypt: N must be > 1 and a power of 2") + } + if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r { + return nil, errors.New("scrypt: parameters are too large") + } + + xy := make([]uint32, 64*r) + v := make([]uint32, 32*N*r) + b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New) + + for i := 0; i < p; i++ { + smix(b[i*128*r:], r, N, v, xy) + } + + return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil +} diff --git a/Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt_test.go b/Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt_test.go new file mode 100644 index 0000000000..e096c3a31a --- /dev/null +++ b/Godeps/_workspace/src/golang.org/x/crypto/scrypt/scrypt_test.go @@ -0,0 +1,160 @@ +// 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 scrypt + +import ( + "bytes" + "testing" +) + +type testVector struct { + password string + salt string + N, r, p int + output []byte +} + +var good = []testVector{ + { + "password", + "salt", + 2, 10, 10, + []byte{ + 0x48, 0x2c, 0x85, 0x8e, 0x22, 0x90, 0x55, 0xe6, 0x2f, + 0x41, 0xe0, 0xec, 0x81, 0x9a, 0x5e, 0xe1, 0x8b, 0xdb, + 0x87, 0x25, 0x1a, 0x53, 0x4f, 0x75, 0xac, 0xd9, 0x5a, + 0xc5, 0xe5, 0xa, 0xa1, 0x5f, + }, + }, + { + "password", + "salt", + 16, 100, 100, + []byte{ + 0x88, 0xbd, 0x5e, 0xdb, 0x52, 0xd1, 0xdd, 0x0, 0x18, + 0x87, 0x72, 0xad, 0x36, 0x17, 0x12, 0x90, 0x22, 0x4e, + 0x74, 0x82, 0x95, 0x25, 0xb1, 0x8d, 0x73, 0x23, 0xa5, + 0x7f, 0x91, 0x96, 0x3c, 0x37, + }, + }, + { + "this is a long \000 password", + "and this is a long \000 salt", + 16384, 8, 1, + []byte{ + 0xc3, 0xf1, 0x82, 0xee, 0x2d, 0xec, 0x84, 0x6e, 0x70, + 0xa6, 0x94, 0x2f, 0xb5, 0x29, 0x98, 0x5a, 0x3a, 0x09, + 0x76, 0x5e, 0xf0, 0x4c, 0x61, 0x29, 0x23, 0xb1, 0x7f, + 0x18, 0x55, 0x5a, 0x37, 0x07, 0x6d, 0xeb, 0x2b, 0x98, + 0x30, 0xd6, 0x9d, 0xe5, 0x49, 0x26, 0x51, 0xe4, 0x50, + 0x6a, 0xe5, 0x77, 0x6d, 0x96, 0xd4, 0x0f, 0x67, 0xaa, + 0xee, 0x37, 0xe1, 0x77, 0x7b, 0x8a, 0xd5, 0xc3, 0x11, + 0x14, 0x32, 0xbb, 0x3b, 0x6f, 0x7e, 0x12, 0x64, 0x40, + 0x18, 0x79, 0xe6, 0x41, 0xae, + }, + }, + { + "p", + "s", + 2, 1, 1, + []byte{ + 0x48, 0xb0, 0xd2, 0xa8, 0xa3, 0x27, 0x26, 0x11, 0x98, + 0x4c, 0x50, 0xeb, 0xd6, 0x30, 0xaf, 0x52, + }, + }, + + { + "", + "", + 16, 1, 1, + []byte{ + 0x77, 0xd6, 0x57, 0x62, 0x38, 0x65, 0x7b, 0x20, 0x3b, + 0x19, 0xca, 0x42, 0xc1, 0x8a, 0x04, 0x97, 0xf1, 0x6b, + 0x48, 0x44, 0xe3, 0x07, 0x4a, 0xe8, 0xdf, 0xdf, 0xfa, + 0x3f, 0xed, 0xe2, 0x14, 0x42, 0xfc, 0xd0, 0x06, 0x9d, + 0xed, 0x09, 0x48, 0xf8, 0x32, 0x6a, 0x75, 0x3a, 0x0f, + 0xc8, 0x1f, 0x17, 0xe8, 0xd3, 0xe0, 0xfb, 0x2e, 0x0d, + 0x36, 0x28, 0xcf, 0x35, 0xe2, 0x0c, 0x38, 0xd1, 0x89, + 0x06, + }, + }, + { + "password", + "NaCl", + 1024, 8, 16, + []byte{ + 0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00, 0x78, + 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe, 0x7c, 0x6a, + 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30, 0xe7, 0x73, 0x76, + 0x63, 0x4b, 0x37, 0x31, 0x62, 0x2e, 0xaf, 0x30, 0xd9, + 0x2e, 0x22, 0xa3, 0x88, 0x6f, 0xf1, 0x09, 0x27, 0x9d, + 0x98, 0x30, 0xda, 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, + 0xee, 0x6d, 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, + 0x40, + }, + }, + { + "pleaseletmein", "SodiumChloride", + 16384, 8, 1, + []byte{ + 0x70, 0x23, 0xbd, 0xcb, 0x3a, 0xfd, 0x73, 0x48, 0x46, + 0x1c, 0x06, 0xcd, 0x81, 0xfd, 0x38, 0xeb, 0xfd, 0xa8, + 0xfb, 0xba, 0x90, 0x4f, 0x8e, 0x3e, 0xa9, 0xb5, 0x43, + 0xf6, 0x54, 0x5d, 0xa1, 0xf2, 0xd5, 0x43, 0x29, 0x55, + 0x61, 0x3f, 0x0f, 0xcf, 0x62, 0xd4, 0x97, 0x05, 0x24, + 0x2a, 0x9a, 0xf9, 0xe6, 0x1e, 0x85, 0xdc, 0x0d, 0x65, + 0x1e, 0x40, 0xdf, 0xcf, 0x01, 0x7b, 0x45, 0x57, 0x58, + 0x87, + }, + }, + /* + // Disabled: needs 1 GiB RAM and takes too long for a simple test. + { + "pleaseletmein", "SodiumChloride", + 1048576, 8, 1, + []byte{ + 0x21, 0x01, 0xcb, 0x9b, 0x6a, 0x51, 0x1a, 0xae, 0xad, + 0xdb, 0xbe, 0x09, 0xcf, 0x70, 0xf8, 0x81, 0xec, 0x56, + 0x8d, 0x57, 0x4a, 0x2f, 0xfd, 0x4d, 0xab, 0xe5, 0xee, + 0x98, 0x20, 0xad, 0xaa, 0x47, 0x8e, 0x56, 0xfd, 0x8f, + 0x4b, 0xa5, 0xd0, 0x9f, 0xfa, 0x1c, 0x6d, 0x92, 0x7c, + 0x40, 0xf4, 0xc3, 0x37, 0x30, 0x40, 0x49, 0xe8, 0xa9, + 0x52, 0xfb, 0xcb, 0xf4, 0x5c, 0x6f, 0xa7, 0x7a, 0x41, + 0xa4, + }, + }, + */ +} + +var bad = []testVector{ + {"p", "s", 0, 1, 1, nil}, // N == 0 + {"p", "s", 1, 1, 1, nil}, // N == 1 + {"p", "s", 7, 8, 1, nil}, // N is not power of 2 + {"p", "s", 16, maxInt / 2, maxInt / 2, nil}, // p * r too large +} + +func TestKey(t *testing.T) { + for i, v := range good { + k, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, len(v.output)) + if err != nil { + t.Errorf("%d: got unexpected error: %s", i, err) + } + if !bytes.Equal(k, v.output) { + t.Errorf("%d: expected %x, got %x", i, v.output, k) + } + } + for i, v := range bad { + _, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, 32) + if err == nil { + t.Errorf("%d: expected error, got nil", i) + } + } +} + +func BenchmarkKey(b *testing.B) { + for i := 0; i < b.N; i++ { + Key([]byte("password"), []byte("salt"), 16384, 8, 1, 64) + } +} diff --git a/client/changelist/change.go b/client/changelist/change.go index dfdaed5c36..bb5587bd40 100644 --- a/client/changelist/change.go +++ b/client/changelist/change.go @@ -1,7 +1,7 @@ package changelist import ( - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) // Scopes for TufChanges are simply the TUF roles. diff --git a/client/client.go b/client/client.go index 2d8643d073..68315c5990 100644 --- a/client/client.go +++ b/client/client.go @@ -16,14 +16,14 @@ import ( "github.com/docker/notary/keystoremanager" "github.com/docker/notary/pkg/passphrase" "github.com/docker/notary/trustmanager" - "github.com/endophage/gotuf" - tufclient "github.com/endophage/gotuf/client" - "github.com/endophage/gotuf/data" - tuferrors "github.com/endophage/gotuf/errors" - "github.com/endophage/gotuf/keys" - "github.com/endophage/gotuf/signed" - "github.com/endophage/gotuf/store" - tufutils "github.com/endophage/gotuf/utils" + "github.com/docker/notary/tuf" + tufclient "github.com/docker/notary/tuf/client" + "github.com/docker/notary/tuf/data" + tuferrors "github.com/docker/notary/tuf/errors" + "github.com/docker/notary/tuf/keys" + "github.com/docker/notary/tuf/signed" + "github.com/docker/notary/tuf/store" + tufutils "github.com/docker/notary/tuf/utils" ) const maxSize = 5 << 20 diff --git a/client/client_root_validation_test.go b/client/client_root_validation_test.go index 08184f7b6a..0af23da7f4 100644 --- a/client/client_root_validation_test.go +++ b/client/client_root_validation_test.go @@ -11,7 +11,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/notary/keystoremanager" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/stretchr/testify/assert" ) diff --git a/client/client_test.go b/client/client_test.go index b226475550..d0dae90434 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -18,7 +18,7 @@ import ( "github.com/docker/notary/server/storage" "github.com/docker/notary/trustmanager" "github.com/docker/notary/utils" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/gorilla/mux" "github.com/stretchr/testify/assert" "golang.org/x/net/context" diff --git a/client/helpers.go b/client/helpers.go index 8bfd8c6334..9525b58135 100644 --- a/client/helpers.go +++ b/client/helpers.go @@ -7,10 +7,10 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/notary/client/changelist" - tuf "github.com/endophage/gotuf" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/keys" - "github.com/endophage/gotuf/store" + tuf "github.com/docker/notary/tuf" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/keys" + "github.com/docker/notary/tuf/store" ) // Use this to initialize remote HTTPStores from the config settings diff --git a/client/helpers_test.go b/client/helpers_test.go index 6f50d28310..f4ade37580 100644 --- a/client/helpers_test.go +++ b/client/helpers_test.go @@ -6,9 +6,9 @@ import ( "testing" "github.com/docker/notary/client/changelist" - tuf "github.com/endophage/gotuf" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/keys" + tuf "github.com/docker/notary/tuf" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/keys" "github.com/stretchr/testify/assert" ) diff --git a/cmd/notary-server/main.go b/cmd/notary-server/main.go index 8d028e7481..c206607b8d 100644 --- a/cmd/notary-server/main.go +++ b/cmd/notary-server/main.go @@ -16,7 +16,7 @@ import ( "github.com/docker/distribution/health" _ "github.com/docker/distribution/registry/auth/htpasswd" _ "github.com/docker/distribution/registry/auth/token" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/signed" _ "github.com/go-sql-driver/mysql" "golang.org/x/net/context" diff --git a/cmd/notary-signer/main.go b/cmd/notary-signer/main.go index 4a86dde90b..d0289baa14 100644 --- a/cmd/notary-signer/main.go +++ b/cmd/notary-signer/main.go @@ -22,7 +22,7 @@ import ( "github.com/docker/notary/signer/api" "github.com/docker/notary/utils" "github.com/docker/notary/version" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" _ "github.com/go-sql-driver/mysql" "github.com/miekg/pkcs11" "github.com/spf13/viper" diff --git a/cryptoservice/crypto_service.go b/cryptoservice/crypto_service.go index a30a3fcc05..9dd9714343 100644 --- a/cryptoservice/crypto_service.go +++ b/cryptoservice/crypto_service.go @@ -13,7 +13,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/agl/ed25519" "github.com/docker/notary/trustmanager" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) const ( diff --git a/cryptoservice/crypto_service_test.go b/cryptoservice/crypto_service_test.go index be763b4f99..da4b19f5b5 100644 --- a/cryptoservice/crypto_service_test.go +++ b/cryptoservice/crypto_service_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/docker/notary/trustmanager" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" ) func TestCryptoService(t *testing.T) { diff --git a/cryptoservice/unlocked_crypto_service.go b/cryptoservice/unlocked_crypto_service.go index 8da5d444f0..bcc1d991f7 100644 --- a/cryptoservice/unlocked_crypto_service.go +++ b/cryptoservice/unlocked_crypto_service.go @@ -9,8 +9,8 @@ import ( "fmt" "github.com/docker/notary/trustmanager" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" ) // UnlockedCryptoService encapsulates a private key and a cryptoservice that diff --git a/keystoremanager/import_export_test.go b/keystoremanager/import_export_test.go index 71a85cce1e..716fade1d8 100644 --- a/keystoremanager/import_export_test.go +++ b/keystoremanager/import_export_test.go @@ -15,7 +15,7 @@ import ( "github.com/docker/notary/client" "github.com/docker/notary/keystoremanager" "github.com/docker/notary/trustmanager" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/stretchr/testify/assert" ) diff --git a/keystoremanager/keystoremanager.go b/keystoremanager/keystoremanager.go index bf39d7faa5..0e18d6b35d 100644 --- a/keystoremanager/keystoremanager.go +++ b/keystoremanager/keystoremanager.go @@ -13,8 +13,8 @@ import ( "github.com/docker/notary/cryptoservice" "github.com/docker/notary/pkg/passphrase" "github.com/docker/notary/trustmanager" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" ) // KeyStoreManager is an abstraction around the root and non-root key stores, diff --git a/keystoremanager/keystoremanager_test.go b/keystoremanager/keystoremanager_test.go index ce4f111110..9d40b977a4 100644 --- a/keystoremanager/keystoremanager_test.go +++ b/keystoremanager/keystoremanager_test.go @@ -10,8 +10,8 @@ import ( "text/template" "github.com/docker/notary/trustmanager" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" "github.com/stretchr/testify/assert" ) diff --git a/server/handlers/default.go b/server/handlers/default.go index 2c1f5f327b..c939c6a72b 100644 --- a/server/handlers/default.go +++ b/server/handlers/default.go @@ -7,8 +7,8 @@ import ( "net/http" "strings" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" "github.com/gorilla/mux" "golang.org/x/net/context" diff --git a/server/handlers/default_test.go b/server/handlers/default_test.go index a8173f9bef..91c104af74 100644 --- a/server/handlers/default_test.go +++ b/server/handlers/default_test.go @@ -7,7 +7,7 @@ import ( "golang.org/x/net/context" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/signed" "github.com/docker/notary/utils" ) diff --git a/server/handlers/validation.go b/server/handlers/validation.go index 13d355c51f..86d0524895 100644 --- a/server/handlers/validation.go +++ b/server/handlers/validation.go @@ -6,14 +6,14 @@ import ( "errors" "fmt" - "github.com/endophage/gotuf" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf" + "github.com/docker/notary/tuf/data" "github.com/Sirupsen/logrus" "github.com/docker/notary/server/storage" - "github.com/endophage/gotuf/keys" - "github.com/endophage/gotuf/signed" - "github.com/endophage/gotuf/utils" + "github.com/docker/notary/tuf/keys" + "github.com/docker/notary/tuf/signed" + "github.com/docker/notary/tuf/utils" ) // ErrValidation represents a general validation error diff --git a/server/handlers/validation_test.go b/server/handlers/validation_test.go index 677cd40dc7..b8c1aead96 100644 --- a/server/handlers/validation_test.go +++ b/server/handlers/validation_test.go @@ -3,9 +3,9 @@ package handlers import ( "testing" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" - "github.com/endophage/gotuf/testutils" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" + "github.com/docker/notary/tuf/testutils" "github.com/stretchr/testify/assert" "github.com/docker/notary/server/storage" diff --git a/server/server.go b/server/server.go index ead036958a..670b2d153a 100644 --- a/server/server.go +++ b/server/server.go @@ -9,8 +9,8 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/distribution/health" "github.com/docker/distribution/registry/auth" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" "github.com/gorilla/mux" "golang.org/x/net/context" diff --git a/server/server_test.go b/server/server_test.go index 8d3127e621..759b5ad49e 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -6,7 +6,7 @@ import ( "testing" _ "github.com/docker/distribution/registry/auth/silly" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/signed" "golang.org/x/net/context" ) diff --git a/server/storage/database.go b/server/storage/database.go index 1862ab36be..76e17da5ab 100644 --- a/server/storage/database.go +++ b/server/storage/database.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/Sirupsen/logrus" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/go-sql-driver/mysql" "github.com/jinzhu/gorm" "github.com/mattn/go-sqlite3" diff --git a/server/storage/database_test.go b/server/storage/database_test.go index 5b6cf50424..422e622302 100644 --- a/server/storage/database_test.go +++ b/server/storage/database_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/jinzhu/gorm" _ "github.com/mattn/go-sqlite3" "github.com/stretchr/testify/assert" diff --git a/server/storage/interface.go b/server/storage/interface.go index fadcefda15..906f4f44cf 100644 --- a/server/storage/interface.go +++ b/server/storage/interface.go @@ -1,6 +1,6 @@ package storage -import "github.com/endophage/gotuf/data" +import "github.com/docker/notary/tuf/data" // MetaStore holds the methods that are used for a Metadata Store type MetaStore interface { diff --git a/server/storage/memory.go b/server/storage/memory.go index 6d436697f0..64f5b1ea03 100644 --- a/server/storage/memory.go +++ b/server/storage/memory.go @@ -5,7 +5,7 @@ import ( "strings" "sync" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) type key struct { diff --git a/server/storage/memory_test.go b/server/storage/memory_test.go index e4ba6e2d76..6a25780c93 100644 --- a/server/storage/memory_test.go +++ b/server/storage/memory_test.go @@ -3,7 +3,7 @@ package storage import ( "testing" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/stretchr/testify/assert" ) diff --git a/server/timestamp/timestamp.go b/server/timestamp/timestamp.go index ae7943f148..0d31b2d56a 100644 --- a/server/timestamp/timestamp.go +++ b/server/timestamp/timestamp.go @@ -3,8 +3,8 @@ package timestamp import ( "bytes" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" "github.com/jfrazelle/go/canonical/json" "github.com/Sirupsen/logrus" diff --git a/server/timestamp/timestamp_test.go b/server/timestamp/timestamp_test.go index f8bab50d15..06f791d6c7 100644 --- a/server/timestamp/timestamp_test.go +++ b/server/timestamp/timestamp_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" "github.com/stretchr/testify/assert" "github.com/docker/notary/server/storage" diff --git a/signer/api/api.go b/signer/api/api.go index f6f39c0915..dd4b9a2e65 100644 --- a/signer/api/api.go +++ b/signer/api/api.go @@ -6,8 +6,8 @@ import ( "github.com/docker/notary/signer" "github.com/docker/notary/signer/keys" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" "github.com/gorilla/mux" pb "github.com/docker/notary/proto" diff --git a/signer/api/api_test.go b/signer/api/api_test.go index fb70be6800..4fcf24ea23 100644 --- a/signer/api/api_test.go +++ b/signer/api/api_test.go @@ -15,7 +15,7 @@ import ( "github.com/docker/notary/signer" "github.com/docker/notary/signer/api" "github.com/docker/notary/trustmanager" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/miekg/pkcs11" "github.com/stretchr/testify/assert" diff --git a/signer/api/find_key.go b/signer/api/find_key.go index 7376a26150..d494db57f6 100644 --- a/signer/api/find_key.go +++ b/signer/api/find_key.go @@ -3,8 +3,8 @@ package api import ( "github.com/docker/notary/signer" "github.com/docker/notary/signer/keys" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" pb "github.com/docker/notary/proto" ) diff --git a/signer/api/rpc_api.go b/signer/api/rpc_api.go index c3f16e6e54..c02b8f4002 100644 --- a/signer/api/rpc_api.go +++ b/signer/api/rpc_api.go @@ -6,7 +6,7 @@ import ( ctxu "github.com/docker/distribution/context" "github.com/docker/notary/signer" "github.com/docker/notary/signer/keys" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "golang.org/x/net/context" "google.golang.org/grpc" diff --git a/signer/api/rpc_api_test.go b/signer/api/rpc_api_test.go index 9734af35ed..0b7b685a84 100644 --- a/signer/api/rpc_api_test.go +++ b/signer/api/rpc_api_test.go @@ -11,7 +11,7 @@ import ( "github.com/docker/notary/signer" "github.com/docker/notary/signer/api" "github.com/docker/notary/trustmanager" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/stretchr/testify/assert" "golang.org/x/net/context" "google.golang.org/grpc" diff --git a/signer/api/rsa_hardware_crypto_service.go b/signer/api/rsa_hardware_crypto_service.go index 177695b63e..a45147faa9 100644 --- a/signer/api/rsa_hardware_crypto_service.go +++ b/signer/api/rsa_hardware_crypto_service.go @@ -11,7 +11,7 @@ import ( "math/big" "github.com/docker/notary/signer/keys" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/miekg/pkcs11" ) diff --git a/signer/keydbstore.go b/signer/keydbstore.go index a7fa5aa1ca..6617940f3d 100644 --- a/signer/keydbstore.go +++ b/signer/keydbstore.go @@ -8,7 +8,7 @@ import ( "github.com/docker/notary/pkg/passphrase" "github.com/docker/notary/trustmanager" jose "github.com/dvsekhvalnov/jose2go" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/jinzhu/gorm" ) diff --git a/signer/keys/keys.go b/signer/keys/keys.go index 6d2a1decf4..166bae38c0 100644 --- a/signer/keys/keys.go +++ b/signer/keys/keys.go @@ -3,7 +3,7 @@ package keys import ( "errors" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/miekg/pkcs11" ) diff --git a/signer/signer.go b/signer/signer.go index 2b5eb1fa3d..5a2fd4e7d2 100644 --- a/signer/signer.go +++ b/signer/signer.go @@ -2,8 +2,8 @@ package signer import ( pb "github.com/docker/notary/proto" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" ) // SigningService is the interface to implement a key management and signing service diff --git a/signer/signer_trust.go b/signer/signer_trust.go index 448a1767da..58d6571115 100644 --- a/signer/signer_trust.go +++ b/signer/signer_trust.go @@ -8,7 +8,7 @@ import ( "github.com/Sirupsen/logrus" pb "github.com/docker/notary/proto" "github.com/docker/notary/utils" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" diff --git a/trustmanager/keyfilestore.go b/trustmanager/keyfilestore.go index 51f0c4f2d5..06ffeafc4e 100644 --- a/trustmanager/keyfilestore.go +++ b/trustmanager/keyfilestore.go @@ -6,7 +6,7 @@ import ( "sync" "github.com/docker/notary/pkg/passphrase" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) // KeyFileStore persists and manages private keys on disk diff --git a/trustmanager/keystore.go b/trustmanager/keystore.go index ba5fb1a1a4..e1a4fad70d 100644 --- a/trustmanager/keystore.go +++ b/trustmanager/keystore.go @@ -3,7 +3,7 @@ package trustmanager import ( "fmt" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) // ErrAttemptsExceeded is returned when too many attempts have been made to decrypt a key diff --git a/trustmanager/x509utils.go b/trustmanager/x509utils.go index 97e75a7364..552530d425 100644 --- a/trustmanager/x509utils.go +++ b/trustmanager/x509utils.go @@ -20,7 +20,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/agl/ed25519" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) // GetCertFromURL tries to get a X509 certificate given a HTTPS URL diff --git a/trustmanager/x509utils_test.go b/trustmanager/x509utils_test.go index db7ef3ac08..cda0b1bf27 100644 --- a/trustmanager/x509utils_test.go +++ b/trustmanager/x509utils_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" "github.com/stretchr/testify/assert" ) diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/CONTRIBUTORS b/tuf/CONTRIBUTORS similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/CONTRIBUTORS rename to tuf/CONTRIBUTORS diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/LICENSE b/tuf/LICENSE similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/LICENSE rename to tuf/LICENSE diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/MAINTAINERS b/tuf/MAINTAINERS similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/MAINTAINERS rename to tuf/MAINTAINERS diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/README.md b/tuf/README.md similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/README.md rename to tuf/README.md diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/client/client.go b/tuf/client/client.go similarity index 98% rename from Godeps/_workspace/src/github.com/endophage/gotuf/client/client.go rename to tuf/client/client.go index 5ed1b6530d..4d6ad0e6c3 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/client/client.go +++ b/tuf/client/client.go @@ -12,12 +12,12 @@ import ( "strings" "github.com/Sirupsen/logrus" - tuf "github.com/endophage/gotuf" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/keys" - "github.com/endophage/gotuf/signed" - "github.com/endophage/gotuf/store" - "github.com/endophage/gotuf/utils" + tuf "github.com/docker/notary/tuf" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/keys" + "github.com/docker/notary/tuf/signed" + "github.com/docker/notary/tuf/store" + "github.com/docker/notary/tuf/utils" ) const maxSize int64 = 5 << 20 diff --git a/tuf/client/client_test.go b/tuf/client/client_test.go new file mode 100644 index 0000000000..f783eca0a4 --- /dev/null +++ b/tuf/client/client_test.go @@ -0,0 +1,588 @@ +package client + +import ( + "crypto/sha256" + "encoding/json" + "testing" + "time" + + "github.com/Sirupsen/logrus" + tuf "github.com/docker/notary/tuf" + "github.com/docker/notary/tuf/testutils" + "github.com/stretchr/testify/assert" + + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/keys" + "github.com/docker/notary/tuf/signed" + "github.com/docker/notary/tuf/store" +) + +func TestRotation(t *testing.T) { + kdb := keys.NewDB() + signer := signed.NewEd25519() + repo := tuf.NewRepo(kdb, signer) + remote := store.NewMemoryStore(nil, nil) + cache := store.NewMemoryStore(nil, nil) + + // Generate initial root key and role and add to key DB + rootKey, err := signer.Create("root", data.ED25519Key) + assert.NoError(t, err, "Error creating root key") + rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil, nil) + assert.NoError(t, err, "Error creating root role") + + kdb.AddKey(rootKey) + err = kdb.AddRole(rootRole) + assert.NoError(t, err, "Error adding root role to db") + + // Generate new key and role. These will appear in the root.json + // but will not be added to the keyDB. + replacementKey, err := signer.Create("root", data.ED25519Key) + assert.NoError(t, err, "Error creating replacement root key") + replacementRole, err := data.NewRole("root", 1, []string{replacementKey.ID()}, nil, nil) + assert.NoError(t, err, "Error creating replacement root role") + + // Generate a new root with the replacement key and role + testRoot, err := data.NewRoot( + map[string]data.PublicKey{replacementKey.ID(): replacementKey}, + map[string]*data.RootRole{"root": &replacementRole.RootRole}, + false, + ) + assert.NoError(t, err, "Failed to create new root") + + // Sign testRoot with both old and new keys + signedRoot, err := testRoot.ToSigned() + err = signed.Sign(signer, signedRoot, rootKey, replacementKey) + assert.NoError(t, err, "Failed to sign root") + var origKeySig bool + var replKeySig bool + for _, sig := range signedRoot.Signatures { + if sig.KeyID == rootKey.ID() { + origKeySig = true + } else if sig.KeyID == replacementKey.ID() { + replKeySig = true + } + } + assert.True(t, origKeySig, "Original root key signature not present") + assert.True(t, replKeySig, "Replacement root key signature not present") + + client := NewClient(repo, remote, kdb, cache) + + err = client.verifyRoot("root", signedRoot, 0) + assert.NoError(t, err, "Failed to verify key rotated root") +} + +func TestRotationNewSigMissing(t *testing.T) { + logrus.SetLevel(logrus.DebugLevel) + kdb := keys.NewDB() + signer := signed.NewEd25519() + repo := tuf.NewRepo(kdb, signer) + remote := store.NewMemoryStore(nil, nil) + cache := store.NewMemoryStore(nil, nil) + + // Generate initial root key and role and add to key DB + rootKey, err := signer.Create("root", data.ED25519Key) + assert.NoError(t, err, "Error creating root key") + rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil, nil) + assert.NoError(t, err, "Error creating root role") + + kdb.AddKey(rootKey) + err = kdb.AddRole(rootRole) + assert.NoError(t, err, "Error adding root role to db") + + // Generate new key and role. These will appear in the root.json + // but will not be added to the keyDB. + replacementKey, err := signer.Create("root", data.ED25519Key) + assert.NoError(t, err, "Error creating replacement root key") + replacementRole, err := data.NewRole("root", 1, []string{replacementKey.ID()}, nil, nil) + assert.NoError(t, err, "Error creating replacement root role") + + assert.NotEqual(t, rootKey.ID(), replacementKey.ID(), "Key IDs are the same") + + // Generate a new root with the replacement key and role + testRoot, err := data.NewRoot( + map[string]data.PublicKey{replacementKey.ID(): replacementKey}, + map[string]*data.RootRole{"root": &replacementRole.RootRole}, + false, + ) + assert.NoError(t, err, "Failed to create new root") + + _, ok := testRoot.Signed.Keys[rootKey.ID()] + assert.False(t, ok, "Old root key appeared in test root") + + // Sign testRoot with both old and new keys + signedRoot, err := testRoot.ToSigned() + err = signed.Sign(signer, signedRoot, rootKey) + assert.NoError(t, err, "Failed to sign root") + var origKeySig bool + var replKeySig bool + for _, sig := range signedRoot.Signatures { + if sig.KeyID == rootKey.ID() { + origKeySig = true + } else if sig.KeyID == replacementKey.ID() { + replKeySig = true + } + } + assert.True(t, origKeySig, "Original root key signature not present") + assert.False(t, replKeySig, "Replacement root key signature was present and shouldn't be") + + client := NewClient(repo, remote, kdb, cache) + + err = client.verifyRoot("root", signedRoot, 0) + assert.Error(t, err, "Should have errored on verify as replacement signature was missing.") + +} + +func TestRotationOldSigMissing(t *testing.T) { + logrus.SetLevel(logrus.DebugLevel) + kdb := keys.NewDB() + signer := signed.NewEd25519() + repo := tuf.NewRepo(kdb, signer) + remote := store.NewMemoryStore(nil, nil) + cache := store.NewMemoryStore(nil, nil) + + // Generate initial root key and role and add to key DB + rootKey, err := signer.Create("root", data.ED25519Key) + assert.NoError(t, err, "Error creating root key") + rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil, nil) + assert.NoError(t, err, "Error creating root role") + + kdb.AddKey(rootKey) + err = kdb.AddRole(rootRole) + assert.NoError(t, err, "Error adding root role to db") + + // Generate new key and role. These will appear in the root.json + // but will not be added to the keyDB. + replacementKey, err := signer.Create("root", data.ED25519Key) + assert.NoError(t, err, "Error creating replacement root key") + replacementRole, err := data.NewRole("root", 1, []string{replacementKey.ID()}, nil, nil) + assert.NoError(t, err, "Error creating replacement root role") + + assert.NotEqual(t, rootKey.ID(), replacementKey.ID(), "Key IDs are the same") + + // Generate a new root with the replacement key and role + testRoot, err := data.NewRoot( + map[string]data.PublicKey{replacementKey.ID(): replacementKey}, + map[string]*data.RootRole{"root": &replacementRole.RootRole}, + false, + ) + assert.NoError(t, err, "Failed to create new root") + + _, ok := testRoot.Signed.Keys[rootKey.ID()] + assert.False(t, ok, "Old root key appeared in test root") + + // Sign testRoot with both old and new keys + signedRoot, err := testRoot.ToSigned() + err = signed.Sign(signer, signedRoot, replacementKey) + assert.NoError(t, err, "Failed to sign root") + var origKeySig bool + var replKeySig bool + for _, sig := range signedRoot.Signatures { + if sig.KeyID == rootKey.ID() { + origKeySig = true + } else if sig.KeyID == replacementKey.ID() { + replKeySig = true + } + } + assert.False(t, origKeySig, "Original root key signature was present and shouldn't be") + assert.True(t, replKeySig, "Replacement root key signature was not present") + + client := NewClient(repo, remote, kdb, cache) + + err = client.verifyRoot("root", signedRoot, 0) + assert.Error(t, err, "Should have errored on verify as replacement signature was missing.") + +} + +func TestCheckRootExpired(t *testing.T) { + repo := tuf.NewRepo(nil, nil) + storage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, storage, nil, storage) + + root := &data.SignedRoot{} + root.Signed.Expires = time.Now().AddDate(-1, 0, 0) + + signedRoot, err := root.ToSigned() + assert.NoError(t, err) + rootJSON, err := json.Marshal(signedRoot) + assert.NoError(t, err) + + rootHash := sha256.Sum256(rootJSON) + + testSnap := &data.SignedSnapshot{ + Signed: data.Snapshot{ + Meta: map[string]data.FileMeta{ + "root": { + Length: int64(len(rootJSON)), + Hashes: map[string][]byte{ + "sha256": rootHash[:], + }, + }, + }, + }, + } + repo.SetRoot(root) + repo.SetSnapshot(testSnap) + + storage.SetMeta("root", rootJSON) + + err = client.checkRoot() + assert.Error(t, err) + assert.IsType(t, tuf.ErrLocalRootExpired{}, err) +} + +func TestChecksumMismatch(t *testing.T) { + repo := tuf.NewRepo(nil, nil) + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, nil, localStorage) + + sampleTargets := data.NewTargets() + orig, err := json.Marshal(sampleTargets) + origSha256 := sha256.Sum256(orig) + orig[0] = '}' // corrupt data, should be a { + assert.NoError(t, err) + + remoteStorage.SetMeta("targets", orig) + + _, _, err = client.downloadSigned("targets", int64(len(orig)), origSha256[:]) + assert.IsType(t, ErrChecksumMismatch{}, err) +} + +func TestChecksumMatch(t *testing.T) { + repo := tuf.NewRepo(nil, nil) + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, nil, localStorage) + + sampleTargets := data.NewTargets() + orig, err := json.Marshal(sampleTargets) + origSha256 := sha256.Sum256(orig) + assert.NoError(t, err) + + remoteStorage.SetMeta("targets", orig) + + _, _, err = client.downloadSigned("targets", int64(len(orig)), origSha256[:]) + assert.NoError(t, err) +} + +func TestSizeMismatchLong(t *testing.T) { + repo := tuf.NewRepo(nil, nil) + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, nil, localStorage) + + sampleTargets := data.NewTargets() + orig, err := json.Marshal(sampleTargets) + origSha256 := sha256.Sum256(orig) + assert.NoError(t, err) + l := int64(len(orig)) + + orig = append([]byte(" "), orig...) + assert.Equal(t, l+1, int64(len(orig))) + + remoteStorage.SetMeta("targets", orig) + + _, _, err = client.downloadSigned("targets", l, origSha256[:]) + // size just limits the data received, the error is caught + // either during checksum verification or during json deserialization + assert.IsType(t, ErrChecksumMismatch{}, err) +} + +func TestSizeMismatchShort(t *testing.T) { + repo := tuf.NewRepo(nil, nil) + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, nil, localStorage) + + sampleTargets := data.NewTargets() + orig, err := json.Marshal(sampleTargets) + origSha256 := sha256.Sum256(orig) + assert.NoError(t, err) + l := int64(len(orig)) + + orig = orig[1:] + + remoteStorage.SetMeta("targets", orig) + + _, _, err = client.downloadSigned("targets", l, origSha256[:]) + // size just limits the data received, the error is caught + // either during checksum verification or during json deserialization + assert.IsType(t, ErrChecksumMismatch{}, err) +} + +func TestDownloadTargetsHappy(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("targets", orig) + assert.NoError(t, err) + + // call repo.SignSnapshot to update the targets role in the snapshot + repo.SignSnapshot(data.DefaultExpires("snapshot"), nil) + + err = client.downloadTargets("targets") + assert.NoError(t, err) +} + +func TestDownloadTargetChecksumMismatch(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + // create and "upload" sample targets + signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + origSha256 := sha256.Sum256(orig) + orig[0] = '}' // corrupt data, should be a { + err = remoteStorage.SetMeta("targets", orig) + assert.NoError(t, err) + + // create local snapshot with targets file + // It's necessary to do it this way rather than calling repo.SignSnapshot + // so that we have the wrong sha256 in the snapshot. + snap := data.SignedSnapshot{ + Signed: data.Snapshot{ + Meta: data.Files{ + "targets": data.FileMeta{ + Length: int64(len(orig)), + Hashes: data.Hashes{ + "sha256": origSha256[:], + }, + }, + }, + }, + } + + repo.Snapshot = &snap + + err = client.downloadTargets("targets") + assert.IsType(t, ErrChecksumMismatch{}, err) +} + +// TestDownloadTargetsNoChecksum: it's never valid to download any targets +// role (incl. delegations) when a checksum is not available. +func TestDownloadTargetsNoChecksum(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + // create and "upload" sample targets + signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("targets", orig) + assert.NoError(t, err) + + delete(repo.Snapshot.Signed.Meta["targets"].Hashes, "sha256") + + err = client.downloadTargets("targets") + assert.IsType(t, ErrMissingMeta{}, err) +} + +// TestDownloadTargetsNoSnapshot: it's never valid to download any targets +// role (incl. delegations) when a checksum is not available. +func TestDownloadTargetsNoSnapshot(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + // create and "upload" sample targets + signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("targets", orig) + assert.NoError(t, err) + + repo.Snapshot = nil + + err = client.downloadTargets("targets") + assert.IsType(t, ErrMissingMeta{}, err) +} + +func TestBootstrapDownloadRootHappy(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + // create and "upload" sample root + signedOrig, err := repo.SignRoot(data.DefaultExpires("root"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("root", orig) + assert.NoError(t, err) + + // unset snapshot as if we're bootstrapping from nothing + repo.Snapshot = nil + + err = client.downloadRoot() + assert.NoError(t, err) +} + +func TestUpdateDownloadRootHappy(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + // create and "upload" sample root, snapshot, and timestamp + signedOrig, err := repo.SignRoot(data.DefaultExpires("root"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("root", orig) + assert.NoError(t, err) + + // sign snapshot to make root meta in snapshot get updated + signedOrig, err = repo.SignSnapshot(data.DefaultExpires("snapshot"), nil) + + err = client.downloadRoot() + assert.NoError(t, err) +} + +func TestUpdateDownloadRootBadChecksum(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + // sign snapshot to make sure we have a checksum for root + _, err := repo.SignSnapshot(data.DefaultExpires("snapshot"), nil) + assert.NoError(t, err) + + // create and "upload" sample root, snapshot, and timestamp + signedOrig, err := repo.SignRoot(data.DefaultExpires("root"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("root", orig) + assert.NoError(t, err) + + // don't sign snapshot again to ensure checksum is out of date (bad) + + err = client.downloadRoot() + assert.IsType(t, ErrChecksumMismatch{}, err) +} + +func TestDownloadTimestampHappy(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + // create and "upload" sample timestamp + signedOrig, err := repo.SignTimestamp(data.DefaultExpires("timestamp"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("timestamp", orig) + assert.NoError(t, err) + + err = client.downloadTimestamp() + assert.NoError(t, err) +} + +func TestDownloadSnapshotHappy(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + // create and "upload" sample snapshot and timestamp + signedOrig, err := repo.SignSnapshot(data.DefaultExpires("snapshot"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("snapshot", orig) + assert.NoError(t, err) + + signedOrig, err = repo.SignTimestamp(data.DefaultExpires("timestamp"), nil) + assert.NoError(t, err) + orig, err = json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("timestamp", orig) + assert.NoError(t, err) + + err = client.downloadSnapshot() + assert.NoError(t, err) +} + +// TestDownloadSnapshotNoChecksum: It should never be valid to download a +// snapshot if we don't have a checksum +func TestDownloadSnapshotNoTimestamp(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + // create and "upload" sample snapshot and timestamp + signedOrig, err := repo.SignSnapshot(data.DefaultExpires("snapshot"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("snapshot", orig) + assert.NoError(t, err) + + repo.Timestamp = nil + + err = client.downloadSnapshot() + assert.IsType(t, ErrMissingMeta{}, err) +} + +func TestDownloadSnapshotNoChecksum(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + // create and "upload" sample snapshot and timestamp + signedOrig, err := repo.SignSnapshot(data.DefaultExpires("snapshot"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("snapshot", orig) + assert.NoError(t, err) + + delete(repo.Timestamp.Signed.Meta["snapshot"].Hashes, "sha256") + + err = client.downloadSnapshot() + assert.IsType(t, ErrMissingMeta{}, err) +} + +func TestDownloadSnapshotBadChecksum(t *testing.T) { + kdb, repo, _ := testutils.EmptyRepo() + localStorage := store.NewMemoryStore(nil, nil) + remoteStorage := store.NewMemoryStore(nil, nil) + client := NewClient(repo, remoteStorage, kdb, localStorage) + + // sign timestamp to ensure it has a checksum for snapshot + _, err := repo.SignTimestamp(data.DefaultExpires("timestamp"), nil) + assert.NoError(t, err) + + // create and "upload" sample snapshot and timestamp + signedOrig, err := repo.SignSnapshot(data.DefaultExpires("snapshot"), nil) + assert.NoError(t, err) + orig, err := json.Marshal(signedOrig) + assert.NoError(t, err) + err = remoteStorage.SetMeta("snapshot", orig) + assert.NoError(t, err) + + // by not signing timestamp again we ensure it has the wrong checksum + + err = client.downloadSnapshot() + assert.IsType(t, ErrChecksumMismatch{}, err) +} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/client/errors.go b/tuf/client/errors.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/client/errors.go rename to tuf/client/errors.go diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/keys.go b/tuf/data/keys.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/data/keys.go rename to tuf/data/keys.go diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/roles.go b/tuf/data/roles.go similarity index 99% rename from Godeps/_workspace/src/github.com/endophage/gotuf/data/roles.go rename to tuf/data/roles.go index 12b76b23c4..d2d0063814 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/data/roles.go +++ b/tuf/data/roles.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/endophage/gotuf/errors" + "github.com/docker/notary/tuf/errors" ) // Canonical base role names diff --git a/tuf/data/roles_test.go b/tuf/data/roles_test.go new file mode 100644 index 0000000000..243a2df5e6 --- /dev/null +++ b/tuf/data/roles_test.go @@ -0,0 +1,52 @@ +package data + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCanonicalRole(t *testing.T) { + + testRoles := map[string]string{ + CanonicalRootRole: "testRoot", + CanonicalTargetsRole: "testTargets", + CanonicalSnapshotRole: "testSnapshot", + CanonicalTimestampRole: "testTimestamp", + "garbageRole": "testGarbageRole", + } + + SetValidRoles(testRoles) + + // make sure roles were set correctly + assert.Equal(t, "testRoot", ValidRoles[CanonicalRootRole]) + assert.Equal(t, "testTargets", ValidRoles[CanonicalTargetsRole]) + assert.Equal(t, "testSnapshot", ValidRoles[CanonicalSnapshotRole]) + assert.Equal(t, "testTimestamp", ValidRoles[CanonicalTimestampRole]) + // check SetValidRoles doesn't allow non-valid roles in + assert.Equal(t, "", ValidRoles["garbageRole"]) + + // check when looking up CanonicalRole from configured role + assert.Equal(t, CanonicalRootRole, CanonicalRole("testRoot")) + assert.Equal(t, CanonicalTargetsRole, CanonicalRole("testTargets")) + assert.Equal(t, CanonicalSnapshotRole, CanonicalRole("testSnapshot")) + assert.Equal(t, CanonicalTimestampRole, CanonicalRole("testTimestamp")) + assert.Equal(t, "", CanonicalRole("testGarbageRole")) + + // check when looking up CanonicalRole with canonical role + assert.Equal(t, CanonicalRootRole, CanonicalRole(CanonicalRootRole)) + assert.Equal(t, CanonicalTargetsRole, CanonicalRole(CanonicalTargetsRole)) + assert.Equal(t, CanonicalSnapshotRole, CanonicalRole(CanonicalSnapshotRole)) + assert.Equal(t, CanonicalTimestampRole, CanonicalRole(CanonicalTimestampRole)) + assert.Equal(t, "", CanonicalRole("garbageRole")) + + assert.Equal(t, "", CanonicalRole("not found")) + + // reset ValidRoles so other tests aren't messed up + ValidRoles = map[string]string{ + CanonicalRootRole: CanonicalRootRole, + CanonicalTargetsRole: CanonicalTargetsRole, + CanonicalSnapshotRole: CanonicalSnapshotRole, + CanonicalTimestampRole: CanonicalTimestampRole, + } +} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/root.go b/tuf/data/root.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/data/root.go rename to tuf/data/root.go diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/snapshot.go b/tuf/data/snapshot.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/data/snapshot.go rename to tuf/data/snapshot.go diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/targets.go b/tuf/data/targets.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/data/targets.go rename to tuf/data/targets.go diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/timestamp.go b/tuf/data/timestamp.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/data/timestamp.go rename to tuf/data/timestamp.go diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/data/types.go b/tuf/data/types.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/data/types.go rename to tuf/data/types.go diff --git a/tuf/data/types_test.go b/tuf/data/types_test.go new file mode 100644 index 0000000000..119348f3c1 --- /dev/null +++ b/tuf/data/types_test.go @@ -0,0 +1,55 @@ +package data + +import ( + "bytes" + "encoding/hex" + "testing" + + "github.com/jfrazelle/go/canonical/json" + "github.com/stretchr/testify/assert" +) + +func TestGenerateFileMetaDefault(t *testing.T) { + // default is sha512 + r := bytes.NewReader([]byte("foo")) + meta, err := NewFileMeta(r, "sha512") + assert.NoError(t, err, "Unexpected error.") + assert.Equal(t, meta.Length, int64(3), "Meta did not have expected Length field value") + hashes := meta.Hashes + assert.Len(t, hashes, 1, "Only expected one hash to be present") + hash, ok := hashes["sha512"] + if !ok { + t.Fatal("missing sha512 hash") + } + assert.Equal(t, "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7", hex.EncodeToString(hash), "Hashes not equal") +} + +func TestGenerateFileMetaExplicit(t *testing.T) { + r := bytes.NewReader([]byte("foo")) + meta, err := NewFileMeta(r, "sha256", "sha512") + assert.NoError(t, err) + assert.Equal(t, meta.Length, int64(3)) + hashes := meta.Hashes + assert.Len(t, hashes, 2) + for name, val := range map[string]string{ + "sha256": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", + "sha512": "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7", + } { + hash, ok := hashes[name] + if !ok { + t.Fatalf("missing %s hash", name) + } + assert.Equal(t, hex.EncodeToString(hash), val) + } +} + +func TestSignatureUnmarshalJSON(t *testing.T) { + signatureJSON := `{"keyid":"97e8e1b51b6e7cf8720a56b5334bd8692ac5b28233c590b89fab0b0cd93eeedc","method":"RSA","sig":"2230cba525e4f5f8fc744f234221ca9a92924da4cc5faf69a778848882fcf7a20dbb57296add87f600891f2569a9c36706314c240f9361c60fd36f5a915a0e9712fc437b761e8f480868d7a4444724daa0d29a2669c0edbd4046046649a506b3d711d0aa5e70cb9d09dec7381e7de27a3168e77731e08f6ed56fcce2478855e837816fb69aff53412477748cd198dce783850080d37aeb929ad0f81460ebd31e61b772b6c7aa56977c787d4281fa45dbdefbb38d449eb5bccb2702964a52c78811545939712c8280dee0b23b2fa9fbbdd6a0c42476689ace655eba0745b4a21ba108bcd03ad00fdefff416dc74e08486a0538f8fd24989e1b9fc89e675141b7c"}` + + var sig Signature + err := json.Unmarshal([]byte(signatureJSON), &sig) + assert.NoError(t, err) + + // Check that the method string is lowercased + assert.Equal(t, sig.Method.String(), "rsa") +} diff --git a/tuf/db/files.db b/tuf/db/files.db new file mode 100644 index 0000000000..e30c3ee59f Binary files /dev/null and b/tuf/db/files.db differ diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/encrypted/encrypted.go b/tuf/encrypted/encrypted.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/encrypted/encrypted.go rename to tuf/encrypted/encrypted.go diff --git a/tuf/encrypted/encrypted_test.go b/tuf/encrypted/encrypted_test.go new file mode 100644 index 0000000000..a2ab37f5c1 --- /dev/null +++ b/tuf/encrypted/encrypted_test.go @@ -0,0 +1,57 @@ +package encrypted + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +var plaintext = []byte("reallyimportant") + +func TestRoundtrip(t *testing.T) { + passphrase := []byte("supersecret") + + enc, err := Encrypt(plaintext, passphrase) + assert.NoError(t, err) + + // successful decrypt + dec, err := Decrypt(enc, passphrase) + assert.NoError(t, err) + assert.Equal(t, dec, plaintext) + + // wrong passphrase + passphrase[0] = 0 + dec, err = Decrypt(enc, passphrase) + assert.Error(t, err) + assert.Nil(t, dec) +} + +func TestTamperedRoundtrip(t *testing.T) { + passphrase := []byte("supersecret") + + enc, err := Encrypt(plaintext, passphrase) + assert.NoError(t, err) + + data := &data{} + err = json.Unmarshal(enc, data) + assert.NoError(t, err) + + data.Ciphertext[0] = 0 + data.Ciphertext[1] = 0 + + enc, _ = json.Marshal(data) + + dec, err := Decrypt(enc, passphrase) + assert.Error(t, err) + assert.Nil(t, dec) +} + +func TestDecrypt(t *testing.T) { + enc := []byte(`{"kdf":{"name":"scrypt","params":{"N":32768,"r":8,"p":1},"salt":"N9a7x5JFGbrtB2uBR81jPwp0eiLR4A7FV3mjVAQrg1g="},"cipher":{"name":"nacl/secretbox","nonce":"2h8HxMmgRfuYdpswZBQaU3xJ1nkA/5Ik"},"ciphertext":"SEW6sUh0jf2wfdjJGPNS9+bkk2uB+Cxamf32zR8XkQ=="}`) + passphrase := []byte("supersecret") + + dec, err := Decrypt(enc, passphrase) + assert.NoError(t, err) + assert.Equal(t, dec, plaintext) +} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/errors/errors.go b/tuf/errors/errors.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/errors/errors.go rename to tuf/errors/errors.go diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/keys/db.go b/tuf/keys/db.go similarity index 97% rename from Godeps/_workspace/src/github.com/endophage/gotuf/keys/db.go rename to tuf/keys/db.go index f4837afdc0..30afc8d1dc 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/keys/db.go +++ b/tuf/keys/db.go @@ -3,7 +3,7 @@ package keys import ( "errors" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) // Various basic key database errors diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/resources/tuf_update_flow.jpg b/tuf/resources/tuf_update_flow.jpg similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/resources/tuf_update_flow.jpg rename to tuf/resources/tuf_update_flow.jpg diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/ed25519.go b/tuf/signed/ed25519.go similarity index 98% rename from Godeps/_workspace/src/github.com/endophage/gotuf/signed/ed25519.go rename to tuf/signed/ed25519.go index 4cfbdc44a9..67eb12be00 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/ed25519.go +++ b/tuf/signed/ed25519.go @@ -5,7 +5,7 @@ import ( "errors" "github.com/agl/ed25519" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) // Ed25519 implements a simple in memory cryptosystem for ED25519 keys diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/errors.go b/tuf/signed/errors.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/signed/errors.go rename to tuf/signed/errors.go diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/interface.go b/tuf/signed/interface.go similarity index 97% rename from Godeps/_workspace/src/github.com/endophage/gotuf/signed/interface.go rename to tuf/signed/interface.go index 7a46bdee26..a8e686ccc7 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/interface.go +++ b/tuf/signed/interface.go @@ -1,7 +1,7 @@ package signed import ( - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) // SigningService defines the necessary functions to determine diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go b/tuf/signed/sign.go similarity index 95% rename from Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go rename to tuf/signed/sign.go index e0a9b3b83d..c33aa075d4 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/sign.go +++ b/tuf/signed/sign.go @@ -15,9 +15,9 @@ import ( "fmt" "github.com/Sirupsen/logrus" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/errors" - "github.com/endophage/gotuf/utils" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/errors" + "github.com/docker/notary/tuf/utils" ) type idPair struct { diff --git a/tuf/signed/sign_test.go b/tuf/signed/sign_test.go new file mode 100644 index 0000000000..73acfd8137 --- /dev/null +++ b/tuf/signed/sign_test.go @@ -0,0 +1,230 @@ +package signed + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "testing" + + "github.com/docker/notary/trustmanager" + "github.com/docker/notary/tuf/data" + "github.com/stretchr/testify/assert" +) + +const ( + testKeyPEM1 = "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAnKuXZeefa2LmgxaL5NsM\nzKOHNe+x/nL6ik+lDBCTV6OdcwAhHQS+PONGhrChIUVR6Vth3hUCrreLzPO73Oo5\nVSCuRJ53UronENl6lsa5mFKP8StYLvIDITNvkoT3j52BJIjyNUK9UKY9As2TNqDf\nBEPIRp28ev/NViwGOEkBu2UAbwCIdnDXm8JQErCZA0Ydm7PKGgjLbFsFGrVzqXHK\n6pdzJXlhr9yap3UpgQ/iO9JtoEYB2EXsnSrPc9JRjR30bNHHtnVql3fvinXrAEwq\n3xmN4p+R4VGzfdQN+8Kl/IPjqWB535twhFYEG/B7Ze8IwbygBjK3co/KnOPqMUrM\nBI8ztvPiogz+MvXb8WvarZ6TMTh8ifZI96r7zzqyzjR1hJulEy3IsMGvz8XS2J0X\n7sXoaqszEtXdq5ef5zKVxkiyIQZcbPgmpHLq4MgfdryuVVc/RPASoRIXG4lKaTJj\n1ANMFPxDQpHudCLxwCzjCb+sVa20HBRPTnzo8LSZkI6jAgMBAAE=\n-----END PUBLIC KEY-----" + testKeyID1 = "51324b59d4888faa91219ebbe5a3876bb4efb21f0602ddf363cd4c3996ded3d4" + + testKeyPEM2 = "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEArvqUPYb6JJROPJQglPTj\n5uDrsxQKl34Mo+3pSlBVuD6puE4lDnG649a2YksJy+C8ZIPJgokn5w+C3alh+dMe\nzbdWHHxrY1h9CLpYz5cbMlE16303ubkt1rvwDqEezG0HDBzPaKj4oP9YJ9x7wbsq\ndvFcy+Qc3wWd7UWcieo6E0ihbJkYcY8chRXVLg1rL7EfZ+e3bq5+ojA2ECM5JqzZ\nzgDpqCv5hTCYYZp72MZcG7dfSPAHrcSGIrwg7whzz2UsEtCOpsJTuCl96FPN7kAu\n4w/WyM3+SPzzr4/RQXuY1SrLCFD8ebM2zHt/3ATLhPnGmyG5I0RGYoegFaZ2AViw\nlqZDOYnBtgDvKP0zakMtFMbkh2XuNBUBO7Sjs0YcZMjLkh9gYUHL1yWS3Aqus1Lw\nlI0gHS22oyGObVBWkZEgk/Foy08sECLGao+5VvhmGpfVuiz9OKFUmtPVjWzRE4ng\niekEu4drSxpH41inLGSvdByDWLpcTvWQI9nkgclh3AT/AgMBAAE=\n-----END PUBLIC KEY-----" + testKeyID2 = "26f2f5c0fbfa98823bf1ad39d5f3b32575895793baf80f1df675597d5b95dba8" +) + +type FailingCryptoService struct { + testKey data.PublicKey +} + +func (mts *FailingCryptoService) Sign(keyIDs []string, _ []byte) ([]data.Signature, error) { + sigs := make([]data.Signature, 0, len(keyIDs)) + return sigs, nil +} + +func (mts *FailingCryptoService) Create(_ string, _ data.KeyAlgorithm) (data.PublicKey, error) { + return mts.testKey, nil +} + +func (mts *FailingCryptoService) GetKey(keyID string) data.PublicKey { + if keyID == "testID" { + return mts.testKey + } + return nil +} + +func (mts *FailingCryptoService) RemoveKey(keyID string) error { + return nil +} + +type MockCryptoService struct { + testKey data.PublicKey +} + +func (mts *MockCryptoService) Sign(keyIDs []string, _ []byte) ([]data.Signature, error) { + sigs := make([]data.Signature, 0, len(keyIDs)) + for _, keyID := range keyIDs { + sigs = append(sigs, data.Signature{KeyID: keyID}) + } + return sigs, nil +} + +func (mts *MockCryptoService) Create(_ string, _ data.KeyAlgorithm) (data.PublicKey, error) { + return mts.testKey, nil +} + +func (mts *MockCryptoService) GetKey(keyID string) data.PublicKey { + if keyID == "testID" { + return mts.testKey + } + return nil +} + +func (mts *MockCryptoService) RemoveKey(keyID string) error { + return nil +} + +var _ CryptoService = &MockCryptoService{} + +type StrictMockCryptoService struct { + MockCryptoService +} + +func (mts *StrictMockCryptoService) Sign(keyIDs []string, _ []byte) ([]data.Signature, error) { + sigs := make([]data.Signature, 0, len(keyIDs)) + for _, keyID := range keyIDs { + if keyID == mts.testKey.ID() { + sigs = append(sigs, data.Signature{KeyID: keyID}) + } + } + return sigs, nil +} + +func (mts *StrictMockCryptoService) GetKey(keyID string) data.PublicKey { + if keyID == mts.testKey.ID() { + return mts.testKey + } + return nil +} + +// Test signing and ensure the expected signature is added +func TestBasicSign(t *testing.T) { + testKey, _ := pem.Decode([]byte(testKeyPEM1)) + k := data.NewPublicKey(data.RSAKey, testKey.Bytes) + mockCryptoService := &MockCryptoService{testKey: k} + key, err := mockCryptoService.Create("root", data.ED25519Key) + if err != nil { + t.Fatal(err) + } + testData := data.Signed{} + + Sign(mockCryptoService, &testData, key) + + if len(testData.Signatures) != 1 { + t.Fatalf("Incorrect number of signatures: %d", len(testData.Signatures)) + } + + if testData.Signatures[0].KeyID != testKeyID1 { + t.Fatalf("Wrong signature ID returned: %s", testData.Signatures[0].KeyID) + } +} + +// Test signing with the same key multiple times only registers a single signature +// for the key (N.B. MockCryptoService.Sign will still be called again, but Signer.Sign +// should be cleaning previous signatures by the KeyID when asked to sign again) +func TestReSign(t *testing.T) { + testKey, _ := pem.Decode([]byte(testKeyPEM1)) + k := data.NewPublicKey(data.RSAKey, testKey.Bytes) + mockCryptoService := &MockCryptoService{testKey: k} + testData := data.Signed{} + + Sign(mockCryptoService, &testData, k) + Sign(mockCryptoService, &testData, k) + + if len(testData.Signatures) != 1 { + t.Fatalf("Incorrect number of signatures: %d", len(testData.Signatures)) + } + + if testData.Signatures[0].KeyID != testKeyID1 { + t.Fatalf("Wrong signature ID returned: %s", testData.Signatures[0].KeyID) + } + +} + +func TestMultiSign(t *testing.T) { + mockCryptoService := &MockCryptoService{} + testData := data.Signed{} + + testKey, _ := pem.Decode([]byte(testKeyPEM1)) + key := data.NewPublicKey(data.RSAKey, testKey.Bytes) + Sign(mockCryptoService, &testData, key) + + testKey, _ = pem.Decode([]byte(testKeyPEM2)) + key = data.NewPublicKey(data.RSAKey, testKey.Bytes) + Sign(mockCryptoService, &testData, key) + + if len(testData.Signatures) != 2 { + t.Fatalf("Incorrect number of signatures: %d", len(testData.Signatures)) + } + + keyIDs := map[string]struct{}{testKeyID1: struct{}{}, testKeyID2: struct{}{}} + for _, sig := range testData.Signatures { + if _, ok := keyIDs[sig.KeyID]; !ok { + t.Fatalf("Got a signature we didn't expect: %s", sig.KeyID) + } + } + +} + +func TestSignReturnsNoSigs(t *testing.T) { + failingCryptoService := &FailingCryptoService{} + testData := data.Signed{} + + testKey, _ := pem.Decode([]byte(testKeyPEM1)) + key := data.NewPublicKey(data.RSAKey, testKey.Bytes) + err := Sign(failingCryptoService, &testData, key) + + if err == nil { + t.Fatalf("Expected failure due to no signature being returned by the crypto service") + } + if len(testData.Signatures) != 0 { + t.Fatalf("Incorrect number of signatures, expected 0: %d", len(testData.Signatures)) + } +} + +func TestCreate(t *testing.T) { + testKey, _ := pem.Decode([]byte(testKeyPEM1)) + k := data.NewPublicKey(data.RSAKey, testKey.Bytes) + mockCryptoService := &MockCryptoService{testKey: k} + + key, err := mockCryptoService.Create("root", data.ED25519Key) + + if err != nil { + t.Fatal(err) + } + if key.ID() != testKeyID1 { + t.Fatalf("Expected key ID not found: %s", key.ID()) + } +} + +func TestSignWithX509(t *testing.T) { + // generate a key becase we need a cert + privKey, err := rsa.GenerateKey(rand.Reader, 1024) + assert.NoError(t, err) + + // make a RSA x509 key + template, err := trustmanager.NewCertificate("test") + assert.NoError(t, err) + + derBytes, err := x509.CreateCertificate( + rand.Reader, template, template, &privKey.PublicKey, privKey) + assert.NoError(t, err) + + cert, err := x509.ParseCertificate(derBytes) + assert.NoError(t, err) + + tufRSAx509Key := trustmanager.CertToKey(cert) + assert.NoError(t, err) + + // make a data.PublicKey from the generated private key + pubBytes, err := x509.MarshalPKIXPublicKey(&privKey.PublicKey) + assert.NoError(t, err) + tufRSAKey := data.NewPublicKey(data.RSAKey, pubBytes) + + // test signing against a service that only recognizes a RSAKey (not + // RSAx509 key) + mockCryptoService := &StrictMockCryptoService{MockCryptoService{tufRSAKey}} + testData := data.Signed{} + err = Sign(mockCryptoService, &testData, tufRSAx509Key) + assert.NoError(t, err) + + assert.Len(t, testData.Signatures, 1) + assert.Equal(t, tufRSAx509Key.ID(), testData.Signatures[0].KeyID) +} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers.go b/tuf/signed/verifiers.go similarity index 99% rename from Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers.go rename to tuf/signed/verifiers.go index ef518f0b27..4570bce3df 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verifiers.go +++ b/tuf/signed/verifiers.go @@ -13,7 +13,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/agl/ed25519" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) const ( diff --git a/tuf/signed/verifiers_test.go b/tuf/signed/verifiers_test.go new file mode 100644 index 0000000000..06801190bd --- /dev/null +++ b/tuf/signed/verifiers_test.go @@ -0,0 +1,515 @@ +package signed + +import ( + "bytes" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "crypto/x509" + "encoding/hex" + "encoding/json" + "fmt" + "testing" + "text/template" + + "github.com/docker/notary/tuf/data" + "github.com/stretchr/testify/assert" +) + +type KeyTemplate struct { + KeyType data.KeyAlgorithm +} + +const baseRSAKey = `{"keytype":"{{.KeyType}}","keyval":{"public":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyyvBtTg2xzYS+MTTIBqSpI4V78tt8Yzqi7Jki/Z6NqjiDvcnbgcTqNR2t6B2W5NjGdp/hSaT2jyHM+kdmEGaPxg/zIuHbL3NIp4e0qwovWiEgACPIaELdn8O/kt5swsSKl1KMvLCH1sM86qMibNMAZ/hXOwd90TcHXCgZ91wHEAmsdjDC3dB0TT+FBgOac8RM01Y196QrZoOaDMTWh0EQfw7YbXAElhFVDFxBzDdYWbcIHSIogXQmq0CP+zaL/1WgcZZIClt2M6WCaxxF1S34wNn45gCvVZiZQ/iKWHerSr/2dGQeGo+7ezMSutRzvJ+01fInD86RS/CEtBCFZ1VyQIDAQAB","private":"MIIEpAIBAAKCAQEAyyvBtTg2xzYS+MTTIBqSpI4V78tt8Yzqi7Jki/Z6NqjiDvcnbgcTqNR2t6B2W5NjGdp/hSaT2jyHM+kdmEGaPxg/zIuHbL3NIp4e0qwovWiEgACPIaELdn8O/kt5swsSKl1KMvLCH1sM86qMibNMAZ/hXOwd90TcHXCgZ91wHEAmsdjDC3dB0TT+FBgOac8RM01Y196QrZoOaDMTWh0EQfw7YbXAElhFVDFxBzDdYWbcIHSIogXQmq0CP+zaL/1WgcZZIClt2M6WCaxxF1S34wNn45gCvVZiZQ/iKWHerSr/2dGQeGo+7ezMSutRzvJ+01fInD86RS/CEtBCFZ1VyQIDAQABAoIBAHar8FFxrE1gAGTeUpOF8fG8LIQMRwO4U6eVY7V9GpWiv6gOJTHXYFxU/aL0Ty3eQRxwy9tyVRo8EJz5pRex+e6ws1M+jLOviYqW4VocxQ8dZYd+zBvQfWmRfah7XXJ/HPUx2I05zrmR7VbGX6Bu4g5w3KnyIO61gfyQNKF2bm2Q3yblfupx3URvX0bl180R/+QN2Aslr4zxULFE6b+qJqBydrztq+AAP3WmskRxGa6irFnKxkspJqUpQN1mFselj6iQrzAcwkRPoCw0RwCCMq1/OOYvQtgxTJcO4zDVlbw54PvnxPZtcCWw7fO8oZ2Fvo2SDo75CDOATOGaT4Y9iqECgYEAzWZSpFbN9ZHmvq1lJQg//jFAyjsXRNn/nSvyLQILXltz6EHatImnXo3v+SivG91tfzBI1GfDvGUGaJpvKHoomB+qmhd8KIQhO5MBdAKZMf9fZqZofOPTD9xRXECCwdi+XqHBmL+l1OWz+O9Bh+Qobs2as/hQVgHaoXhQpE0NkTcCgYEA/Tjf6JBGl1+WxQDoGZDJrXoejzG9OFW19RjMdmPrg3t4fnbDtqTpZtCzXxPTCSeMrvplKbqAqZglWyq227ksKw4p7O6YfyhdtvC58oJmivlLr6sFaTsER7mDcYce8sQpqm+XQ8IPbnOk0Z1l6g56euTwTnew49uy25M6U1xL0P8CgYEAxEXv2Kw+OVhHV5PX4BBHHj6we88FiDyMfwM8cvfOJ0datekf9X7ImZkmZEAVPJpWBMD+B0J0jzU2b4SLjfFVkzBHVOH2Ob0xCH2MWPAWtekin7OKizUlPbW5ZV8b0+Kq30DQ/4a7D3rEhK8UPqeuX1tHZox1MAqrgbq3zJj4yvcCgYEAktYPKPm4pYCdmgFrlZ+bA0iEPf7Wvbsd91F5BtHsOOM5PQQ7e0bnvWIaEXEad/2CG9lBHlBy2WVLjDEZthILpa/h6e11ao8KwNGY0iKBuebT17rxOVMqqTjPGt8CuD2994IcEgOPFTpkAdUmyvG4XlkxbB8F6St17NPUB5DGuhsCgYA//Lfytk0FflXEeRQ16LT1YXgV7pcR2jsha4+4O5pxSFw/kTsOfJaYHg8StmROoyFnyE3sg76dCgLn0LENRCe5BvDhJnp5bMpQldG3XwcAxH8FGFNY4LtV/2ZKnJhxcONkfmzQPOmTyedOzrKQ+bNURsqLukCypP7/by6afBY4dA=="}}` +const baseRSAx509Key = `{"keytype":"{{.KeyType}}","keyval":{"public":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZLekNDQXhXZ0F3SUJBZ0lRVERENFNHZS8yaUVJQjAxZFhzTHE5akFMQmdrcWhraUc5dzBCQVFzd09ERWEKTUJnR0ExVUVDaE1SWkc5amEyVnlMbU52YlM5dWIzUmhjbmt4R2pBWUJnTlZCQU1URVdSdlkydGxjaTVqYjIwdgpibTkwWVhKNU1CNFhEVEUxTURjeE56QXdNemt6TVZvWERURTNNRGN4TmpBd016a3pNVm93T0RFYU1CZ0dBMVVFCkNoTVJaRzlqYTJWeUxtTnZiUzl1YjNSaGNua3hHakFZQmdOVkJBTVRFV1J2WTJ0bGNpNWpiMjB2Ym05MFlYSjUKTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDQ2dLQ0FnRUFzYnY1R01oS21DK0J6V3hhZTZSTQpyaHVxU082VkNpb1dhMkZmdmtzYlhtaDhNaktTeUFHQUJLSnVoVksyTHI3NWsrZktTeVVOSFpEWUYxVXFhMnljCnlDQndVVVFXYTNqVDdPaFI3T2FzRDBXYVJEL2MvODhkVlNRejVsdEV0Y3IvVGpRSHpqcjVXL2dWWXJIVkV2UXkKWUJGS3BkSHdRRGpLNnZ6Njc1WnRxMjBKUStzcXRNNFlUeis5dXg5Y25LQTFuc0JDM1YvVk1ybTRWZ3pqL0lOawppL0ZNMVh0Yjd1UFFTK0hRSElYc2R5SktsTHdsTXg2RjhTeFpYZHROUjh4bE8wdkI3Qm5KK0hKZlBWTEpYZDVmCjRld1lUZkE3WmtRNWJESzAzeDRkSzloR2VFUjlEVURja2tNM3RVZHhleTFQZXBkK1BSWWRsL0k5MG5UYXN0L2EKdmpQdUxkYjR2KzFuVnZQVzhjMHNvaGhQK1VkUUU1UHA0dlhDUmMvbVZ1S1NNbEU5bFRDYzY2TFoxcm5tQzJ4agpzKzNpcWZWeWFIcjFmbnUrZjdhTk9jSmFSTlpRN1ErWEdBbXljMXJ6MmJzTmc0S1pIVGdHQnBzNHMwQWV6MUhSCll6NW94QmVUVEZUaUNtZFBJS2lhbGhrTmJQWS9FUXQzNzBXYjIzMTVUQm12QkI0NitXbWoycG9ka2FJeGhJLzMKblRwT25mZlFub25rTmRwdTlKeFJWNFlWQTh1b0hvNWc1WjMreEF1S1A1TnlRSHdvQkwwbElKbTdBK2lHUDF5cwpuNnFVVk5ab0dENFR4ZHduYllmMFBKa3ZhL0FjLzkvaktyajVyQ2NrL1NDOVllbGNxaCt1dklENDA5YU9veVAzCk83SDF0bmQ4M1hXZm5nczRuaFNmQmdzQ0F3RUFBYU0xTURNd0RnWURWUjBQQVFIL0JBUURBZ0NnTUJNR0ExVWQKSlFRTU1Bb0dDQ3NHQVFVRkJ3TURNQXdHQTFVZEV3RUIvd1FDTUFBd0N3WUpLb1pJaHZjTkFRRUxBNElDQVFCawpnRGExQ0F2NWY4QWFaN1YvN2JoMzBtUnZEajVwNGtPWkpSclc3UDdsTTJZU2tNVWFnQzB1QTQySUU1TjI4R2VWCkp4VEh6V0FCQThwNE1ZREllTVZJdGJndHBUWVorZTByL3RPL3pnRHVxNEZ5UFZmZllRYlh1L2k5N29TbVNQYy8KRXpZQktrNHl1RHZ3ZjZtNjJPSGxNalZNcitzM3pQUHB4dFFTaFRndkJ4QWp2ekdmVFBRSEZSdm5jWFZPd2dyRAp0ampsS3RzMGx0azI4eWJ3dyt3SVVCdWg0dzNrZFVBR2RYME9sY3NIdnM3TFhoc01XcmdxMUs4ZVNJZlR6YUdGClMwcE5MNEZObUV4VDVKaFk1SnZ4cWRxclB2RFJEU2FOUXV0OHc2K2FpeXVPVFpiZDRQeTlLZHd2bUNrNk5GdHoKd3lpWUwzT2hZa201Ui9iUm93YVY1dWwrY1BETmV0cGV3WnZJQTUzUkJYZlZCejl0TXI0M2ZaaW9YRFltNTkyVQpKTE1GaGRWMm1zYk9McWFIcGRoN0JhWFFITGxEdHZpaUVLdVRqalJKWEZWTk9seTA1UHBxeFhjWnRSbHhpRjhhCkoveWJ5a1Y0aWc0K3U1aVNGK2dFZjkyaWpaRTNjNnlsYkZjSDhoRVV0bTRqSElHZ1JsWGJ3NmZvV3llb2Z5VUIKTk5COTZyVG5UdkxmdDlReGprUjdlNGgycU41MnFIOVY5L3NLSjlSVFFqU1RERXM3MDF2Z1ZVd0tpVC9VZ3hLTAp3UzJ5dnZJeTN5TFpFUGltQnF6emFSeStCZ3Q4anNrNnQvNEdIT2Y0Rzk0a3paMkIyNUJnYjV5MTl2WVdDQSswCitXdlRCeGdxb0o1Y2lCdXMxYWJiUjZORU1RbXQyeUtneTZEejNJVXgxZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K","private":"MIIJKAIBAAKCAgEAsbv5GMhKmC+BzWxae6RMrhuqSO6VCioWa2FfvksbXmh8MjKSyAGABKJuhVK2Lr75k+fKSyUNHZDYF1Uqa2ycyCBwUUQWa3jT7OhR7OasD0WaRD/c/88dVSQz5ltEtcr/TjQHzjr5W/gVYrHVEvQyYBFKpdHwQDjK6vz675Ztq20JQ+sqtM4YTz+9ux9cnKA1nsBC3V/VMrm4Vgzj/INki/FM1Xtb7uPQS+HQHIXsdyJKlLwlMx6F8SxZXdtNR8xlO0vB7BnJ+HJfPVLJXd5f4ewYTfA7ZkQ5bDK03x4dK9hGeER9DUDckkM3tUdxey1Pepd+PRYdl/I90nTast/avjPuLdb4v+1nVvPW8c0sohhP+UdQE5Pp4vXCRc/mVuKSMlE9lTCc66LZ1rnmC2xjs+3iqfVyaHr1fnu+f7aNOcJaRNZQ7Q+XGAmyc1rz2bsNg4KZHTgGBps4s0Aez1HRYz5oxBeTTFTiCmdPIKialhkNbPY/EQt370Wb2315TBmvBB46+Wmj2podkaIxhI/3nTpOnffQnonkNdpu9JxRV4YVA8uoHo5g5Z3+xAuKP5NyQHwoBL0lIJm7A+iGP1ysn6qUVNZoGD4TxdwnbYf0PJkva/Ac/9/jKrj5rCck/SC9Yelcqh+uvID409aOoyP3O7H1tnd83XWfngs4nhSfBgsCAwEAAQKCAgEAjVZB3GdKioMc4dLMkY4yPDJb0+uGMbMOaQ3iKV1owkasnO6CsvIeb5EL+pGvtrS/m9Kzl9Y6+8v3S3a6aPrSIoNJTharDYPkY3zLyWwWX36mEqgGgpadaNuFOiZSGY74P6Q4oNNdALnjp7xrCMuQU7zsc7jjKO8AzqWml2g0hiILQCt+ppFN25eAtZFXAGaWvUt+4LQYwmHWKPfPRTrndjHJO+sBTJN1TSKhcE0/oe1vCaAkpOYc9ZCi8HQ4nGP6DJFOAQbxCdVJz2ZKI493CB3Lpg7n7YdLcrNQCi3UXM18HJ+6IhP2U4mIf2v03lNF5OMbzFAN8Ir+hqHOWHiTZWESvILzzcc4UPKNaxkO+YSLbKOoQNQR/1OblBwsqM3sHwmUalxjyn0U2yCOiw51Q/jIls7kGUdW48YLXdiQ0o+HlB98Ly78Mr3JNx3dky0sBBZG+U9MqroKb6+tbGCz0Y11prEzLIHWlDGHkixWfNYEqvpetKxQ8fYo06HHsoq7PeYa7bbxQZL+HDEml0528SfcNYmdzv/+NhgQxHmsJ4kX4Umeo28ENAURMIPSrsOSxbOOYhFGBptRzR9UZmkt1CzTs0aoHkwjo61FZadYxUbqZnfoAvkaqs5crLmQz0MTEglZK7wohfym91xiTkcx/7WnOZlbfMsLWxM7HDEU2WECggEBAMKww5agT3Yl1cxQHg1pGnMDX9SFm4Q0U4keSEY6SjkLBfTuOusZ5+OivIofrRYudCz6x6Epm6ID26s2exfILoQ/aOGNxsGuZQc4pXYCTZ9rZUG/9PIpAS9JUwZ3MHfFVomzST3EcVzq6qYkb9l6X+QD5sOlHnrTlga2tvTgA7HVKoeVmtnMeKuFNNRUKf7PF3xdrEtusU0xsAndnDKcSY8TU793h8O51aLJpvdf+etRnRRMWI2i0YsBdFjFNi96HMDjeP6TqA+Ev6KzmwbcLHoHcKp2bt2lz7J5CcArXR05PTGnaiwK7KWpCZTz1GcqHMg7EpiPorh03ZgZh7+lqm8CggEBAOm0Qsn2O46qpIb3o/25kziUXpYJLz4V3EL9vvpuTyPV0kia8Mtn05+fq6MphEDeQNgCeHI24UPUrbH7bwljjW6CHRhsOzbiThXZctkIfdlsAAXPKIRlDqmqNGsawqQNVdnUK4kaQgAQoy7EYevAGvPG+E0USJxJHAuKOGy4ir8j8Pap/Nc/u6pWgTxuwBDcwoA8/xWVbB48e+ucEh5LFZociRPLS8P+WH9geFJCHNX1uELM97JE6G1KfFwDGulPhojnL7Dyz2CiFZC+zl/bRHyG/qjxHkabukayVHIbtgpNmANHqjlK31V7MYgnekLmly7bjhPpzNAbfn8nvEMq3CUCggEAaRjm3H75pjvSaBKvxmmAX6nop17gjsN4fMKeHVsGCjkLJCceIx++8EE/KgjjdN/q0wUlkrhVTWZrxMcKN9JWWgmo4mmYa6Fq5DUODOA9atucs5ud7MN54j7g1NKulVkv1/GyjednktM1jC6LOok3Dm2UuvR9uaxShplHtnTfSbZa2QpHp18bnOuxkxVD/kto0Df49Fdy2ssBzrGUyjVX+CZkxS0PWvcMfm4A9fUXgpJyCy0TeJH2L+W/GtSK5aIzt2SUQkkPJiFxGbF+9HsSf2VYyoxYWMpTjnKMcvJ1t3rYr99CDzhuexb/Fytw86fmFajd5wFSw+RCYwMVJr2VfQKCAQAU+aLM8Zai1Vny6yMC0LcP6vEaUjS1Q80DDjcnzuK3eqdm8NEP0H/D4dbLzBwcnlX/jSk2RwqsxdfZE5IBq7ez5WWrHXurD2CmwV93bzWsX+8YlmEykMdiHu6Zdktl4fSEmnBV2890pgmfVuza9eD1ZDRA5sMlk8I6nus1htKdGSK1YMhaoVO8lAsBW4dNfCLQ06ipTUHo7NDKcrWFloOX01vSNPrV2mwi8ouaBmkEIwuoozDQBTM/K+JBd93gdszCWM2E+iX2rFV3KkjnfYyGCK+uhgWLnMp5MeQ2YZpTDmfIU5RJlBi7WVU2vSRSANQs1nPIAcHqI62UyAIznRMpAoIBABka5m4uC6HOeDNuZNYKF8HnTTGxyKUqiDLe6mCWTw4+aQjT3YyZeKDldBl9ICfw/5Igljc5+uFG8I1etEGYJzuvLbd7tj/pJLveUB6UonkrIo1yBWWINdOgU/Iwxn2K662wiUzODy/RLXUzZ7ZppsGf32YgPGLUEpLvd6gsa2ZIcRIebzX8FK2h/gwVq11IijVFlodWqn5ttrmmYI4YVotQf8I15Xi8NvziLVvKWWWaf15GjO/ZW0OzjucQhg/2Jk8brXayuzYxTBT8LN6lxb4CdHcxFPDF6s7ongzOz6TbKYW4XzcQAKHWQSeErKjwXLooWUoqS3o2Y4Rp/lV4Alo="}}` +const baseECDSAKey = ` +{"keytype":"{{.KeyType}}","keyval":{"public":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgl3rzMPMEKhS1k/AX16MM4PdidpjJr+z4pj0Td+30QnpbOIARgpyR1PiFztU8BZlqG3cUazvFclr2q/xHvfrqw==","private":"MHcCAQEEIDqtcdzU7H3AbIPSQaxHl9+xYECt7NpK7B1+6ep5cv9CoAoGCCqGSM49AwEHoUQDQgAEgl3rzMPMEKhS1k/AX16MM4PdidpjJr+z4pj0Td+30QnpbOIARgpyR1PiFztU8BZlqG3cUazvFclr2q/xHvfrqw=="}}` +const baseECDSAx509Key = `{"keytype":"ecdsa-x509","keyval":{"public":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJwRENDQVVtZ0F3SUJBZ0lRQlBWc1NoUmRMdG45WEtRZ29JaDIvREFLQmdncWhrak9QUVFEQWpBNE1Sb3cKR0FZRFZRUUtFeEZrYjJOclpYSXVZMjl0TDI1dmRHRnllVEVhTUJnR0ExVUVBeE1SWkc5amEyVnlMbU52YlM5dQpiM1JoY25rd0hoY05NVFV3TnpFek1EVXdORFF4V2hjTk1UY3dOekV5TURVd05EUXhXakE0TVJvd0dBWURWUVFLCkV4RmtiMk5yWlhJdVkyOXRMMjV2ZEdGeWVURWFNQmdHQTFVRUF4TVJaRzlqYTJWeUxtTnZiUzl1YjNSaGNua3cKV1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVI3SjNSOGpWODV5Rnp0dGFTV3FMRDFHa042UHlhWAowUUdmOHh2Rzd6MUYwUG5DQUdSWk9QQ01aWWpZSGVkdzNXY0FmQWVVcDY5OVExSjNEYW9kbzNBcm96VXdNekFPCkJnTlZIUThCQWY4RUJBTUNBS0F3RXdZRFZSMGxCQXd3Q2dZSUt3WUJCUVVIQXdNd0RBWURWUjBUQVFIL0JBSXcKQURBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQWppVkJjaTBDRTBaazgwZ2ZqbytYdE9xM3NURGJkSWJRRTZBTQpoL29mN1RFQ0lRRGxlbXB5MDRhY0RKODNnVHBvaFNtcFJYdjdJbnRLc0lRTU1oLy9VZzliU2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==","private":null}}` + +func TestRSAPSSVerifier(t *testing.T) { + // Unmarshal our private RSA Key + var testRSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseRSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Sign some data using RSAPSS + message := []byte("test data for signing") + hash := crypto.SHA256 + hashed := sha256.Sum256(message) + signedData, err := rsaPSSSign(&testRSAKey, hash, hashed[:]) + assert.NoError(t, err) + + // Create and call Verify on the verifier + rsaVerifier := RSAPSSVerifier{} + err = rsaVerifier.Verify(&testRSAKey, signedData, message) + assert.NoError(t, err, "expecting success but got error while verifying data using RSA PSS") +} + +func TestRSAPSSx509Verifier(t *testing.T) { + // Unmarshal our public RSA Key + var testRSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseRSAx509Key) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAx509Key}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Valid signed message + signedData, _ := hex.DecodeString("3de02fa54cdba45c67860f058b7cff1ba264610dc3c5b466b7df027bc52068bdf2956fe438dba08b0b71daa0780a3037bf8f50a09d91ca81fa872bbdbbbff6ef17e04df8741ad5c2f2c3ea5de97d6ffaf4999c83fdfba4b6cb2443da11c7b7eea84123c2fdaf3319fa6342cbbdbd1aa25d1ac20aeee687e48cbf191cc8f68049230261469eeada33dec0af74287766bd984dd01820a7edfb8b0d030e2fcf00886c578b07eb905a2eebc81fd982a578e717c7ac773cab345950c71e1eaf81b70401e5bf3c67cdcb9068bf4b50ff0456b530b3cec5586827eb39b123f9d666a65f4b418a355438ed1753da8a27577ab9cd791d7b840c7e34ecc1290c46d98aa0dd73c0427f6ef8f63e36af42e9657520b8f56c9231ba7e0172dfc3456c63c54e9eae95d06bafe571e91afa1e42d4010e60dd5c441df112cc8474253eee7f1d6c5350039ffcd1f8b0bb013e4403c16fc5b40d6bd56b742ea1ed82c87880147db194b33b022077cc2e8d31ef3eada3e46683ad437ad8ef7ecbe03c29d7a53a9771e42cc4f9d782813c491186fde2cd1dfa408c4e21dd4c3ca1664e901772ffe1713e37b07c9287572114865a05e17cbe29d8622c6b033dcb43c9721d0943c58098607cc28bd58b3caf3dfc1f66d01ebfaf1aa5c2c5945c23af83fe114e587fa7bcbaea6bdccff3c0ad03ce3328f67af30168e225e5827ad9e94b4702de984e6dd775") + message := []byte("test data for signing") + + // Create and call Verify on the verifier + rsaVerifier := RSAPSSVerifier{} + err := rsaVerifier.Verify(&testRSAKey, signedData, message) + assert.NoError(t, err, "expecting success but got error while verifying data using RSAPSS and an X509 encoded Key") +} + +func TestRSAPSSVerifierWithInvalidKeyType(t *testing.T) { + var testRSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseRSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: "rsa-invalid"}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Valid signed data with invalidRsaKeyJSON + signedData, _ := hex.DecodeString("2741a57a5ef89f841b4e0a6afbcd7940bc982cd919fbd11dfc21b5ccfe13855b9c401e3df22da5480cef2fa585d0f6dfc6c35592ed92a2a18001362c3a17f74da3906684f9d81c5846bf6a09e2ede6c009ae164f504e6184e666adb14eadf5f6e12e07ff9af9ad49bf1ea9bcfa3bebb2e33be7d4c0fabfe39534f98f1e3c4bff44f637cff3dae8288aea54d86476a3f1320adc39008eae24b991c1de20744a7967d2e685ac0bcc0bc725947f01c9192ffd3e9300eba4b7faa826e84478493fdf97c705dd331dd46072050d6c5e317c2d63df21694dbaf909ebf46ce0ff04f3979fe13723ae1a823c65f27e56efa19e88f9e7b8ee56eac34353b944067deded3a") + message := []byte("test data for signing") + + // Create and call Verify on the verifier + rsaVerifier := RSAPSSVerifier{} + err := rsaVerifier.Verify(&testRSAKey, signedData, message) + assert.Error(t, err, "invalid key type for RSAPSS verifier: rsa-invalid") +} + +func TestRSAPSSVerifierWithInvalidKeyLength(t *testing.T) { + key, err := rsa.GenerateKey(rand.Reader, 512) + assert.NoError(t, err) + + err = verifyPSS(key.Public(), nil, nil) + assert.Error(t, err) + assert.IsType(t, ErrInvalidKeyLength{}, err) +} + +func TestRSAPSSVerifierWithInvalidKey(t *testing.T) { + var testRSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: "ecdsa"}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Valid signed data with invalidRsaKeyJSON + signedData, _ := hex.DecodeString("2741a57a5ef89f841b4e0a6afbcd7940bc982cd919fbd11dfc21b5ccfe13855b9c401e3df22da5480cef2fa585d0f6dfc6c35592ed92a2a18001362c3a17f74da3906684f9d81c5846bf6a09e2ede6c009ae164f504e6184e666adb14eadf5f6e12e07ff9af9ad49bf1ea9bcfa3bebb2e33be7d4c0fabfe39534f98f1e3c4bff44f637cff3dae8288aea54d86476a3f1320adc39008eae24b991c1de20744a7967d2e685ac0bcc0bc725947f01c9192ffd3e9300eba4b7faa826e84478493fdf97c705dd331dd46072050d6c5e317c2d63df21694dbaf909ebf46ce0ff04f3979fe13723ae1a823c65f27e56efa19e88f9e7b8ee56eac34353b944067deded3a") + message := []byte("test data for signing") + + // Create and call Verify on the verifier + rsaVerifier := RSAPSSVerifier{} + err := rsaVerifier.Verify(&testRSAKey, signedData, message) + assert.Error(t, err, "invalid key type for RSAPSS verifier: ecdsa") +} + +func TestRSAPSSVerifierWithInvalidSignature(t *testing.T) { + var testRSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseRSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Sign some data using RSAPSS + message := []byte("test data for signing") + hash := crypto.SHA256 + hashed := sha256.Sum256(message) + signedData, err := rsaPSSSign(&testRSAKey, hash, hashed[:]) + assert.NoError(t, err) + + // Modify the signature + signedData[0]++ + + // Create and call Verify on the verifier + rsaVerifier := RSAPSSVerifier{} + err = rsaVerifier.Verify(&testRSAKey, signedData, message) + assert.Error(t, err, "signature verification failed") +} + +func TestRSAPKCS1v15Verifier(t *testing.T) { + // Unmarshal our private RSA Key + var testRSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseRSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Sign some data using RSAPKCS1v15 + message := []byte("test data for signing") + hash := crypto.SHA256 + hashed := sha256.Sum256(message) + signedData, err := rsaPKCS1v15Sign(&testRSAKey, hash, hashed[:]) + assert.NoError(t, err) + + // Create and call Verify on the verifier + rsaVerifier := RSAPKCS1v15Verifier{} + err = rsaVerifier.Verify(&testRSAKey, signedData, message) + assert.NoError(t, err, "expecting success but got error while verifying data using RSAPKCS1v15") +} + +func TestRSAPKCS1v15x509Verifier(t *testing.T) { + // Unmarshal our public RSA Key + var testRSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseRSAx509Key) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAx509Key}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Valid signed message + signedData, _ := hex.DecodeString("a19602f609646d57f3d0db930bbe491a997baf33f13191916713734ae778ddb4898ece2078741bb0c24d726514c6b4538c3665c374b0b8ec9ff234b45459633268224c9962756ad3684aca5f13a286657375e798ddcb857ed2707c900f097666b958df56b43b790357430c2e7a5c379ba9972c8b008363c144aac5c7e0fbfad83cf6855cf73baf8e3ad774e910ba6ac8dc4cce58fe19cffb7b0a1feaa73d23ebd2d59de2d7d9e98a809d73a310c5396df64ff7a22d735e661e39d37a6c4a013caa6005e91f597ea35db24e6c750d704d292a180128dcf72a818c53a96b0a83ba0414a3611097905262eb79a6ced1484af27c7da6809aa21ae7c6f05ae6568d5e5d9c170470213a30caf2340c3d52e7bd4056d22074daffee6e29d0a6fd3ca6dbd001831fb1e48573f3663b63e110cde19efaf56e49a835aeda82e4d7286de591376ecd03de36d402ec703f39f79b2f764f991d8950a119f2618f6d4e4618114900597a1e89ced609949410623a17b97095afe08babc4c295ade954f055ca01b7909f5585e98eb99bd916583476aa877d20da8f4fe35c0867e934f41c935d469664b80904a93f9f4d9432cabd9383e08559d6452f8e12b2d861412c450709ff874ad63c25a640605a41c4073f0eb4e16e1965abf8e088e210cbf9d3ca884ec2c13fc8a288cfcef2425d9607fcab01dab45c5c346671a9ae1d0e52c81379fa212c") + message := []byte("test data for signing") + + // Create and call Verify on the verifier + rsaVerifier := RSAPKCS1v15Verifier{} + err := rsaVerifier.Verify(&testRSAKey, signedData, message) + assert.NoError(t, err, "expecting success but got error while verifying data using RSAPKCS1v15 and an X509 encoded Key") +} + +func TestRSAPKCS1v15VerifierWithInvalidKeyType(t *testing.T) { + var testRSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseRSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: "rsa-invalid"}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Valid signed data with invalidRsaKeyJSON + signedData, _ := hex.DecodeString("2741a57a5ef89f841b4e0a6afbcd7940bc982cd919fbd11dfc21b5ccfe13855b9c401e3df22da5480cef2fa585d0f6dfc6c35592ed92a2a18001362c3a17f74da3906684f9d81c5846bf6a09e2ede6c009ae164f504e6184e666adb14eadf5f6e12e07ff9af9ad49bf1ea9bcfa3bebb2e33be7d4c0fabfe39534f98f1e3c4bff44f637cff3dae8288aea54d86476a3f1320adc39008eae24b991c1de20744a7967d2e685ac0bcc0bc725947f01c9192ffd3e9300eba4b7faa826e84478493fdf97c705dd331dd46072050d6c5e317c2d63df21694dbaf909ebf46ce0ff04f3979fe13723ae1a823c65f27e56efa19e88f9e7b8ee56eac34353b944067deded3a") + message := []byte("test data for signing") + + // Create and call Verify on the verifier + rsaVerifier := RSAPKCS1v15Verifier{} + err := rsaVerifier.Verify(&testRSAKey, signedData, message) + assert.Error(t, err, "invalid key type for RSAPKCS1v15 verifier: rsa-invalid") +} + +func TestRSAPKCS1v15VerifierWithInvalidKey(t *testing.T) { + var testRSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: "ecdsa"}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Valid signed data with invalidRsaKeyJSON + signedData, _ := hex.DecodeString("2741a57a5ef89f841b4e0a6afbcd7940bc982cd919fbd11dfc21b5ccfe13855b9c401e3df22da5480cef2fa585d0f6dfc6c35592ed92a2a18001362c3a17f74da3906684f9d81c5846bf6a09e2ede6c009ae164f504e6184e666adb14eadf5f6e12e07ff9af9ad49bf1ea9bcfa3bebb2e33be7d4c0fabfe39534f98f1e3c4bff44f637cff3dae8288aea54d86476a3f1320adc39008eae24b991c1de20744a7967d2e685ac0bcc0bc725947f01c9192ffd3e9300eba4b7faa826e84478493fdf97c705dd331dd46072050d6c5e317c2d63df21694dbaf909ebf46ce0ff04f3979fe13723ae1a823c65f27e56efa19e88f9e7b8ee56eac34353b944067deded3a") + message := []byte("test data for signing") + + // Create and call Verify on the verifier + rsaVerifier := RSAPKCS1v15Verifier{} + err := rsaVerifier.Verify(&testRSAKey, signedData, message) + assert.Error(t, err, "invalid key type for RSAPKCS1v15 verifier: ecdsa") +} + +func TestRSAPKCS1v15VerifierWithInvalidSignature(t *testing.T) { + var testRSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseRSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + // Sign some data using RSAPKCS1v15 + message := []byte("test data for signing") + hash := crypto.SHA256 + hashed := sha256.Sum256(message) + signedData, err := rsaPKCS1v15Sign(&testRSAKey, hash, hashed[:]) + assert.NoError(t, err) + + // Modify the signature + signedData[0]++ + + // Create and call Verify on the verifier + rsaVerifier := RSAPKCS1v15Verifier{} + err = rsaVerifier.Verify(&testRSAKey, signedData, message) + assert.Error(t, err, "signature verification failed") +} + +func TestECDSAVerifier(t *testing.T) { + var testECDSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.ECDSAKey}) + + json.Unmarshal(jsonKey.Bytes(), &testECDSAKey) + + // Sign some data using ECDSA + message := []byte("test data for signing") + hashed := sha256.Sum256(message) + signedData, err := ecdsaSign(&testECDSAKey, hashed[:]) + assert.NoError(t, err) + + // Create and call Verify on the verifier + ecdsaVerifier := ECDSAVerifier{} + err = ecdsaVerifier.Verify(&testECDSAKey, signedData, message) + assert.NoError(t, err, "expecting success but got error while verifying data using ECDSA") +} + +func TestECDSAVerifierOtherCurves(t *testing.T) { + curves := []elliptic.Curve{elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521()} + + for _, curve := range curves { + ecdsaPrivKey, err := ecdsa.GenerateKey(curve, rand.Reader) + + // Get a DER-encoded representation of the PublicKey + ecdsaPubBytes, err := x509.MarshalPKIXPublicKey(&ecdsaPrivKey.PublicKey) + assert.NoError(t, err, "failed to marshal public key") + + // Get a DER-encoded representation of the PrivateKey + ecdsaPrivKeyBytes, err := x509.MarshalECPrivateKey(ecdsaPrivKey) + assert.NoError(t, err, "failed to marshal private key") + + testECDSAKey := data.NewPrivateKey(data.ECDSAKey, ecdsaPubBytes, ecdsaPrivKeyBytes) + + // Sign some data using ECDSA + message := []byte("test data for signing") + hashed := sha256.Sum256(message) + signedData, err := ecdsaSign(testECDSAKey, hashed[:]) + assert.NoError(t, err) + + // Create and call Verify on the verifier + ecdsaVerifier := ECDSAVerifier{} + err = ecdsaVerifier.Verify(testECDSAKey, signedData, message) + assert.NoError(t, err, "expecting success but got error while verifying data using ECDSA") + + // Make sure an invalid signature fails verification + signedData[0]++ + err = ecdsaVerifier.Verify(testECDSAKey, signedData, message) + assert.Error(t, err, "expecting error but got success while verifying data using ECDSA") + } +} + +func TestECDSAx509Verifier(t *testing.T) { + var testECDSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseECDSAx509Key) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.ECDSAx509Key}) + + json.Unmarshal(jsonKey.Bytes(), &testECDSAKey) + + // Valid signature for message + signedData, _ := hex.DecodeString("b82e0ed5c5dddd74c8d3602bfd900c423511697c3cfe54e1d56b9c1df599695c53aa0caafcdc40df3ef496d78ccf67750ba9413f1ccbd8b0ef137f0da1ee9889") + message := []byte("test data for signing") + + // Create and call Verify on the verifier + ecdsaVerifier := ECDSAVerifier{} + err := ecdsaVerifier.Verify(&testECDSAKey, signedData, message) + assert.NoError(t, err, "expecting success but got error while verifying data using ECDSA and an x509 encoded key") +} + +func TestECDSAVerifierWithInvalidKeyType(t *testing.T) { + var testECDSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: "ecdsa-invalid"}) + + json.Unmarshal(jsonKey.Bytes(), &testECDSAKey) + + // Valid signature using invalidECDSAx509Key + signedData, _ := hex.DecodeString("7b1c45a4dd488a087db46ee459192d890d4f52352620cb84c2c10e0ce8a67fd6826936463a91ffdffab8e6f962da6fc3d3e5735412f7cd161a9fcf97ba1a7033") + message := []byte("test data for signing") + + // Create and call Verify on the verifier + ecdsaVerifier := ECDSAVerifier{} + err := ecdsaVerifier.Verify(&testECDSAKey, signedData, message) + assert.Error(t, err, "invalid key type for ECDSA verifier: ecdsa-invalid") +} + +func TestECDSAVerifierWithInvalidKey(t *testing.T) { + var testECDSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseRSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: "rsa"}) + + json.Unmarshal(jsonKey.Bytes(), &testECDSAKey) + + // Valid signature using invalidECDSAx509Key + signedData, _ := hex.DecodeString("7b1c45a4dd488a087db46ee459192d890d4f52352620cb84c2c10e0ce8a67fd6826936463a91ffdffab8e6f962da6fc3d3e5735412f7cd161a9fcf97ba1a7033") + message := []byte("test data for signing") + + // Create and call Verify on the verifier + ecdsaVerifier := ECDSAVerifier{} + err := ecdsaVerifier.Verify(&testECDSAKey, signedData, message) + assert.Error(t, err, "invalid key type for ECDSA verifier: rsa") +} + +func TestECDSAVerifierWithInvalidSignature(t *testing.T) { + var testECDSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseECDSAKey) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.ECDSAKey}) + + json.Unmarshal(jsonKey.Bytes(), &testECDSAKey) + + // Sign some data using ECDSA + message := []byte("test data for signing") + hashed := sha256.Sum256(message) + signedData, err := ecdsaSign(&testECDSAKey, hashed[:]) + assert.NoError(t, err) + + // Modify the signature + signedData[0]++ + + // Create and call Verify on the verifier + ecdsaVerifier := ECDSAVerifier{} + err = ecdsaVerifier.Verify(&testECDSAKey, signedData, message) + assert.Error(t, err, "signature verification failed") + +} + +func TestED25519VerifierInvalidKeyType(t *testing.T) { + key := data.NewPublicKey("bad_type", nil) + v := Ed25519Verifier{} + err := v.Verify(key, nil, nil) + assert.Error(t, err) + assert.IsType(t, ErrInvalidKeyType{}, err) +} + +func TestRSAPyCryptoVerifierInvalidKeyType(t *testing.T) { + key := data.NewPublicKey("bad_type", nil) + v := RSAPyCryptoVerifier{} + err := v.Verify(key, nil, nil) + assert.Error(t, err) + assert.IsType(t, ErrInvalidKeyType{}, err) +} + +func rsaPSSSign(privKey data.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) { + if privKey.Algorithm() != data.RSAKey { + return nil, fmt.Errorf("private key type not supported: %s", privKey.Algorithm()) + } + + // Create an rsa.PrivateKey out of the private key bytes + rsaPrivKey, err := x509.ParsePKCS1PrivateKey(privKey.Private()) + if err != nil { + return nil, err + } + + // Use the RSA key to RSASSA-PSS sign the data + sig, err := rsa.SignPSS(rand.Reader, rsaPrivKey, hash, hashed[:], &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}) + if err != nil { + return nil, err + } + + return sig, nil +} + +func rsaPKCS1v15Sign(privKey data.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) { + if privKey.Algorithm() != data.RSAKey { + return nil, fmt.Errorf("private key type not supported: %s", privKey.Algorithm()) + } + + // Create an rsa.PrivateKey out of the private key bytes + rsaPrivKey, err := x509.ParsePKCS1PrivateKey(privKey.Private()) + if err != nil { + return nil, err + } + + // Use the RSA key to RSAPKCS1v15 sign the data + sig, err := rsa.SignPKCS1v15(rand.Reader, rsaPrivKey, hash, hashed[:]) + if err != nil { + return nil, err + } + + return sig, nil +} + +func ecdsaSign(privKey data.PrivateKey, hashed []byte) ([]byte, error) { + if privKey.Algorithm() != data.ECDSAKey { + return nil, fmt.Errorf("private key type not supported: %s", privKey.Algorithm()) + } + + // Create an ecdsa.PrivateKey out of the private key bytes + ecdsaPrivKey, err := x509.ParseECPrivateKey(privKey.Private()) + if err != nil { + return nil, err + } + + // Use the ECDSA key to sign the data + r, s, err := ecdsa.Sign(rand.Reader, ecdsaPrivKey, hashed[:]) + if err != nil { + return nil, err + } + + rBytes, sBytes := r.Bytes(), s.Bytes() + octetLength := (ecdsaPrivKey.Params().BitSize + 7) >> 3 + + // MUST include leading zeros in the output + rBuf := make([]byte, octetLength-len(rBytes), octetLength) + sBuf := make([]byte, octetLength-len(sBytes), octetLength) + + rBuf = append(rBuf, rBytes...) + sBuf = append(sBuf, sBytes...) + + return append(rBuf, sBuf...), nil +} + +// Use this function to generate the X509 signatures that are hardcoded into +// the test +func signX509() { + // Unmarshal our private RSA Key + var testRSAKey data.TUFKey + var jsonKey bytes.Buffer + + // Execute our template + templ, _ := template.New("KeyTemplate").Parse(baseRSAx509Key) + templ.Execute(&jsonKey, KeyTemplate{KeyType: data.RSAKey}) + + json.Unmarshal(jsonKey.Bytes(), &testRSAKey) + + message := []byte("test data for signing") + hash := crypto.SHA256 + hashed := sha256.Sum256(message) + + // Use the RSA key to RSAPKCS1v15 sign the data + signedData, _ := rsaPKCS1v15Sign(&testRSAKey, hash, hashed[:]) + fmt.Println("signed with pkcs1v15:", hex.EncodeToString(signedData)) + + // Use the RSA key to RSAPSS sign the data + signedData, _ = rsaPSSSign(&testRSAKey, hash, hashed[:]) + fmt.Println("signed with pss:", hex.EncodeToString(signedData)) +} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify.go b/tuf/signed/verify.go similarity index 98% rename from Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify.go rename to tuf/signed/verify.go index b0acf816ad..1b74f83f93 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/signed/verify.go +++ b/tuf/signed/verify.go @@ -6,8 +6,8 @@ import ( "time" "github.com/Sirupsen/logrus" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/keys" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/keys" "github.com/jfrazelle/go/canonical/json" ) diff --git a/tuf/signed/verify_test.go b/tuf/signed/verify_test.go new file mode 100644 index 0000000000..4c0ee9d519 --- /dev/null +++ b/tuf/signed/verify_test.go @@ -0,0 +1,202 @@ +package signed + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/keys" + "github.com/jfrazelle/go/canonical/json" +) + +func Test(t *testing.T) { + cryptoService := NewEd25519() + type test struct { + name string + keys []data.PublicKey + roles map[string]*data.Role + s *data.Signed + ver int + exp *time.Time + typ string + role string + err error + mut func(*test) + } + + expiredTime := time.Now().Add(-time.Hour) + minVer := 10 + tests := []test{ + { + name: "no signatures", + mut: func(t *test) { t.s.Signatures = []data.Signature{} }, + err: ErrNoSignatures, + }, + { + name: "unknown role", + role: "foo", + err: ErrUnknownRole, + }, + //{ + // name: "wrong signature method", + // mut: func(t *test) { t.s.Signatures[0].Method = "foo" }, + // err: ErrWrongMethod, + //}, + // { + // name: "signature wrong length", + // mut: func(t *test) { t.s.Signatures[0].Signature = []byte{0} }, + // err: ErrInvalid, + // }, + { + name: "key missing from role", + mut: func(t *test) { t.roles["root"].KeyIDs = nil }, + err: ErrRoleThreshold{}, + }, + // { + // name: "invalid signature", + // mut: func(t *test) { t.s.Signatures[0].Signature = make([]byte, ed25519.SignatureSize) }, + // err: ErrInvalid, + // }, + { + name: "not enough signatures", + mut: func(t *test) { t.roles["root"].Threshold = 2 }, + err: ErrRoleThreshold{}, + }, + { + name: "exactly enough signatures", + }, + { + name: "more than enough signatures", + mut: func(t *test) { + k, _ := cryptoService.Create("root", data.ED25519Key) + Sign(cryptoService, t.s, k) + t.keys = append(t.keys, k) + t.roles["root"].KeyIDs = append(t.roles["root"].KeyIDs, k.ID()) + }, + }, + { + name: "duplicate key id", + mut: func(t *test) { + t.roles["root"].Threshold = 2 + t.s.Signatures = append(t.s.Signatures, t.s.Signatures[0]) + }, + err: ErrRoleThreshold{}, + }, + { + name: "unknown key", + mut: func(t *test) { + k, _ := cryptoService.Create("root", data.ED25519Key) + Sign(cryptoService, t.s, k) + }, + }, + { + name: "unknown key below threshold", + mut: func(t *test) { + k, _ := cryptoService.Create("root", data.ED25519Key) + Sign(cryptoService, t.s, k) + t.roles["root"].Threshold = 2 + }, + err: ErrRoleThreshold{}, + }, + { + name: "unknown keys in db", + mut: func(t *test) { + k, _ := cryptoService.Create("root", data.ED25519Key) + Sign(cryptoService, t.s, k) + t.keys = append(t.keys, k) + }, + }, + { + name: "unknown keys in db below threshold", + mut: func(t *test) { + k, _ := cryptoService.Create("root", data.ED25519Key) + Sign(cryptoService, t.s, k) + t.keys = append(t.keys, k) + t.roles["root"].Threshold = 2 + }, + err: ErrRoleThreshold{}, + }, + { + name: "wrong type", + typ: "bar", + err: ErrWrongType, + }, + { + name: "low version", + ver: minVer - 1, + err: ErrLowVersion{minVer - 1, minVer}, + }, + { + role: "root", + name: "expired", + exp: &expiredTime, + err: ErrExpired{"root", expiredTime.Format("Mon Jan 2 15:04:05 MST 2006")}, + }, + } + for _, run := range tests { + if run.role == "" { + run.role = "root" + } + if run.ver == 0 { + run.ver = minVer + } + if run.exp == nil { + expires := time.Now().Add(time.Hour) + run.exp = &expires + } + if run.typ == "" { + run.typ = data.TUFTypes[run.role] + } + if run.keys == nil && run.s == nil { + k, _ := cryptoService.Create("root", data.ED25519Key) + meta := &data.SignedCommon{Type: run.typ, Version: run.ver, Expires: *run.exp} + + b, err := json.MarshalCanonical(meta) + assert.NoError(t, err) + s := &data.Signed{Signed: b} + Sign(cryptoService, s, k) + run.s = s + run.keys = []data.PublicKey{k} + } + if run.roles == nil { + run.roles = map[string]*data.Role{ + "root": &data.Role{ + RootRole: data.RootRole{ + KeyIDs: []string{run.keys[0].ID()}, + Threshold: 1, + }, + Name: "root", + }, + } + } + if run.mut != nil { + run.mut(&run) + } + + db := keys.NewDB() + for _, k := range run.keys { + db.AddKey(k) + } + for _, r := range run.roles { + err := db.AddRole(r) + assert.NoError(t, err) + } + + err := Verify(run.s, run.role, minVer, db) + if e, ok := run.err.(ErrExpired); ok { + assertErrExpired(t, err, e) + } else { + assert.Equal(t, run.err, err) + } + } +} + +func assertErrExpired(t *testing.T, err error, expected ErrExpired) { + actual, ok := err.(ErrExpired) + if !ok { + t.Fatalf("expected err to have type ErrExpired, got %T", err) + } + assert.Equal(t, actual.Expired, expected.Expired) +} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/errors.go b/tuf/store/errors.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/store/errors.go rename to tuf/store/errors.go diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/filestore.go b/tuf/store/filestore.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/store/filestore.go rename to tuf/store/filestore.go diff --git a/tuf/store/filestore_test.go b/tuf/store/filestore_test.go new file mode 100644 index 0000000000..9f41597b41 --- /dev/null +++ b/tuf/store/filestore_test.go @@ -0,0 +1,58 @@ +package store + +import ( + "io/ioutil" + "os" + "path" + "testing" + + "github.com/stretchr/testify/assert" +) + +const testDir = "/tmp/testFilesystemStore/" + +func TestNewFilesystemStore(t *testing.T) { + _, err := NewFilesystemStore(testDir, "metadata", "json", "targets") + assert.Nil(t, err, "Initializing FilesystemStore returned unexpected error: %v", err) + defer os.RemoveAll(testDir) + + info, err := os.Stat(path.Join(testDir, "metadata")) + assert.Nil(t, err, "Error attempting to stat metadata dir: %v", err) + assert.NotNil(t, info, "Nil FileInfo from stat on metadata dir") + assert.True(t, 0700&info.Mode() != 0, "Metadata directory is not writable") + + info, err = os.Stat(path.Join(testDir, "targets")) + assert.Nil(t, err, "Error attempting to stat targets dir: %v", err) + assert.NotNil(t, info, "Nil FileInfo from stat on targets dir") + assert.True(t, 0700&info.Mode() != 0, "Targets directory is not writable") +} + +func TestSetMeta(t *testing.T) { + s, err := NewFilesystemStore(testDir, "metadata", "json", "targets") + assert.Nil(t, err, "Initializing FilesystemStore returned unexpected error: %v", err) + defer os.RemoveAll(testDir) + + testContent := []byte("test data") + + err = s.SetMeta("testMeta", testContent) + assert.Nil(t, err, "SetMeta returned unexpected error: %v", err) + + content, err := ioutil.ReadFile(path.Join(testDir, "metadata", "testMeta.json")) + assert.Nil(t, err, "Error reading file: %v", err) + assert.Equal(t, testContent, content, "Content written to file was corrupted.") +} + +func TestGetMeta(t *testing.T) { + s, err := NewFilesystemStore(testDir, "metadata", "json", "targets") + assert.Nil(t, err, "Initializing FilesystemStore returned unexpected error: %v", err) + defer os.RemoveAll(testDir) + + testContent := []byte("test data") + + ioutil.WriteFile(path.Join(testDir, "metadata", "testMeta.json"), testContent, 0600) + + content, err := s.GetMeta("testMeta", int64(len(testContent))) + assert.Nil(t, err, "GetMeta returned unexpected error: %v", err) + + assert.Equal(t, testContent, content, "Content read from file was corrupted.") +} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/httpstore.go b/tuf/store/httpstore.go similarity index 100% rename from Godeps/_workspace/src/github.com/endophage/gotuf/store/httpstore.go rename to tuf/store/httpstore.go diff --git a/tuf/store/httpstore_test.go b/tuf/store/httpstore_test.go new file mode 100644 index 0000000000..512c6b3612 --- /dev/null +++ b/tuf/store/httpstore_test.go @@ -0,0 +1,154 @@ +package store + +import ( + "encoding/base64" + "encoding/hex" + "io" + "io/ioutil" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/signed" + "github.com/jfrazelle/go/canonical/json" +) + +const testRoot = `{"signed":{"_type":"Root","consistent_snapshot":false,"expires":"2025-07-17T16:19:21.101698314-07:00","keys":{"1ca15c7f4b2b0c6efce202a545e7267152da28ab7c91590b3b60bdb4da723aad":{"keytype":"ecdsa","keyval":{"private":null,"public":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEb0720c99Cj6ZmuDlznEZ52NA6YpeY9Sj45z51XvPnG63Bi2RSBezMJlPzbSfP39mXKXqOJyT+z9BZhi3FVWczg=="}},"b1d6813b55442ecbfb1f4b40eb1fcdb4290e53434cfc9ba2da24c26c9143873b":{"keytype":"ecdsa-x509","keyval":{"private":null,"public":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJVekNCKzZBREFnRUNBaEFCWDNKLzkzaW8zbHcrZUsvNFhvSHhNQW9HQ0NxR1NNNDlCQU1DTUJFeER6QU4KQmdOVkJBTVRCbVY0Y0dseVpUQWVGdzB4TlRBM01qQXlNekU1TVRkYUZ3MHlOVEEzTVRjeU16RTVNVGRhTUJFeApEekFOQmdOVkJBTVRCbVY0Y0dseVpUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJFTDhOTFhQCitreUJZYzhYY0FTMXB2S2l5MXRQUDlCZHJ1dEdrWlR3Z0dEYTM1THMzSUFXaWlrUmlPbGRuWmxVVEE5cG5JekoKOFlRQThhTjQ1TDQvUlplak5UQXpNQTRHQTFVZER3RUIvd1FFQXdJQW9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRgpCUWNEQXpBTUJnTlZIUk1CQWY4RUFqQUFNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRVJ1ZUVURG5xMlRqRFBmClhGRStqUFJqMEtqdXdEOG9HSmtoVGpMUDAycjhBaUI5cUNyL2ZqSXpJZ1NQcTJVSXZqR0hlYmZOYXh1QlpZZUUKYW8xNjd6dHNYZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"}},"fbddae7f25a6c23ca735b017206a849d4c89304a4d8de4dcc4b3d6f3eb22ce3b":{"keytype":"ecdsa","keyval":{"private":null,"public":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/xS5fBHK2HKmlGcvAr06vwPITvmxWP4P3CMDCgY25iSaIiM21OiXA1/Uvo3Pa3xh5G3cwCtDvi+4FpflW2iB/w=="}},"fd75751f010c3442e23b3e3e99a1442a112f2f21038603cb8609d8b17c9e912a":{"keytype":"ed25519","keyval":{"private":null,"public":"rc+glN01m+q8jmX8SolGsjTfk6NMhUQTWyj10hjmne0="}}},"roles":{"root":{"keyids":["b1d6813b55442ecbfb1f4b40eb1fcdb4290e53434cfc9ba2da24c26c9143873b"],"threshold":1},"snapshot":{"keyids":["1ca15c7f4b2b0c6efce202a545e7267152da28ab7c91590b3b60bdb4da723aad"],"threshold":1},"targets":{"keyids":["fbddae7f25a6c23ca735b017206a849d4c89304a4d8de4dcc4b3d6f3eb22ce3b"],"threshold":1},"timestamp":{"keyids":["fd75751f010c3442e23b3e3e99a1442a112f2f21038603cb8609d8b17c9e912a"],"threshold":1}},"version":2},"signatures":[{"keyid":"b1d6813b55442ecbfb1f4b40eb1fcdb4290e53434cfc9ba2da24c26c9143873b","method":"ecdsa","sig":"A2lNVwxHBnD9ViFtRre8r5oG6VvcvJnC6gdvvxv/Jyag40q/fNMjllCqyHrb+6z8XDZcrTTDsFU1R3/e+92d1A=="}]}` + +const testRootKey = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJVekNCKzZBREFnRUNBaEFCWDNKLzkzaW8zbHcrZUsvNFhvSHhNQW9HQ0NxR1NNNDlCQU1DTUJFeER6QU4KQmdOVkJBTVRCbVY0Y0dseVpUQWVGdzB4TlRBM01qQXlNekU1TVRkYUZ3MHlOVEEzTVRjeU16RTVNVGRhTUJFeApEekFOQmdOVkJBTVRCbVY0Y0dseVpUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJFTDhOTFhQCitreUJZYzhYY0FTMXB2S2l5MXRQUDlCZHJ1dEdrWlR3Z0dEYTM1THMzSUFXaWlrUmlPbGRuWmxVVEE5cG5JekoKOFlRQThhTjQ1TDQvUlplak5UQXpNQTRHQTFVZER3RUIvd1FFQXdJQW9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRgpCUWNEQXpBTUJnTlZIUk1CQWY4RUFqQUFNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJRVJ1ZUVURG5xMlRqRFBmClhGRStqUFJqMEtqdXdEOG9HSmtoVGpMUDAycjhBaUI5cUNyL2ZqSXpJZ1NQcTJVSXZqR0hlYmZOYXh1QlpZZUUKYW8xNjd6dHNYZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" + +type TestRoundTripper struct{} + +func (rt *TestRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + return http.DefaultClient.Do(req) +} + +func TestHTTPStoreGetMeta(t *testing.T) { + handler := func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(testRoot)) + } + server := httptest.NewServer(http.HandlerFunc(handler)) + store, err := NewHTTPStore( + server.URL, + "metadata", + "txt", + "targets", + "key", + &http.Transport{}, + ) + if err != nil { + t.Fatal(err) + } + j, err := store.GetMeta("root", 4801) + if err != nil { + t.Fatal(err) + } + p := &data.Signed{} + err = json.Unmarshal(j, p) + if err != nil { + t.Fatal(err) + } + rootKey, err := base64.StdEncoding.DecodeString(testRootKey) + assert.NoError(t, err) + k := data.NewPublicKey("ecdsa-x509", rootKey) + + sigBytes := p.Signatures[0].Signature + if err != nil { + t.Fatal(err) + } + var decoded map[string]interface{} + if err := json.Unmarshal(p.Signed, &decoded); err != nil { + t.Fatal(err) + } + msg, err := json.MarshalCanonical(decoded) + if err != nil { + t.Fatal(err) + } + method := p.Signatures[0].Method + err = signed.Verifiers[method].Verify(k, sigBytes, msg) + if err != nil { + t.Fatal(err) + } + +} + +func TestSetMultiMeta(t *testing.T) { + metas := map[string][]byte{ + "root": []byte("root data"), + "targets": []byte("targets data"), + } + + handler := func(w http.ResponseWriter, r *http.Request) { + reader, err := r.MultipartReader() + if err != nil { + t.Fatal(err) + } + updates := make(map[string][]byte) + for { + part, err := reader.NextPart() + if err == io.EOF { + break + } + role := strings.TrimSuffix(part.FileName(), ".json") + updates[role], err = ioutil.ReadAll(part) + if err != nil { + t.Fatal(err) + } + } + rd, rok := updates["root"] + assert.True(t, rok) + assert.Equal(t, rd, metas["root"]) + + td, tok := updates["targets"] + assert.True(t, tok) + assert.Equal(t, td, metas["targets"]) + + } + server := httptest.NewServer(http.HandlerFunc(handler)) + defer server.Close() + store, err := NewHTTPStore(server.URL, "metadata", "json", "targets", "key", http.DefaultTransport) + if err != nil { + t.Fatal(err) + } + + store.SetMultiMeta(metas) +} + +func TestPyCryptoRSAPSSCompat(t *testing.T) { + pubPem := "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAnKuXZeefa2LmgxaL5NsM\nzKOHNe+x/nL6ik+lDBCTV6OdcwAhHQS+PONGhrChIUVR6Vth3hUCrreLzPO73Oo5\nVSCuRJ53UronENl6lsa5mFKP8StYLvIDITNvkoT3j52BJIjyNUK9UKY9As2TNqDf\nBEPIRp28ev/NViwGOEkBu2UAbwCIdnDXm8JQErCZA0Ydm7PKGgjLbFsFGrVzqXHK\n6pdzJXlhr9yap3UpgQ/iO9JtoEYB2EXsnSrPc9JRjR30bNHHtnVql3fvinXrAEwq\n3xmN4p+R4VGzfdQN+8Kl/IPjqWB535twhFYEG/B7Ze8IwbygBjK3co/KnOPqMUrM\nBI8ztvPiogz+MvXb8WvarZ6TMTh8ifZI96r7zzqyzjR1hJulEy3IsMGvz8XS2J0X\n7sXoaqszEtXdq5ef5zKVxkiyIQZcbPgmpHLq4MgfdryuVVc/RPASoRIXG4lKaTJj\n1ANMFPxDQpHudCLxwCzjCb+sVa20HBRPTnzo8LSZkI6jAgMBAAE=\n-----END PUBLIC KEY-----" + //privPem := "-----BEGIN RSA PRIVATE KEY-----\nMIIG4wIBAAKCAYEAnKuXZeefa2LmgxaL5NsMzKOHNe+x/nL6ik+lDBCTV6OdcwAh\nHQS+PONGhrChIUVR6Vth3hUCrreLzPO73Oo5VSCuRJ53UronENl6lsa5mFKP8StY\nLvIDITNvkoT3j52BJIjyNUK9UKY9As2TNqDfBEPIRp28ev/NViwGOEkBu2UAbwCI\ndnDXm8JQErCZA0Ydm7PKGgjLbFsFGrVzqXHK6pdzJXlhr9yap3UpgQ/iO9JtoEYB\n2EXsnSrPc9JRjR30bNHHtnVql3fvinXrAEwq3xmN4p+R4VGzfdQN+8Kl/IPjqWB5\n35twhFYEG/B7Ze8IwbygBjK3co/KnOPqMUrMBI8ztvPiogz+MvXb8WvarZ6TMTh8\nifZI96r7zzqyzjR1hJulEy3IsMGvz8XS2J0X7sXoaqszEtXdq5ef5zKVxkiyIQZc\nbPgmpHLq4MgfdryuVVc/RPASoRIXG4lKaTJj1ANMFPxDQpHudCLxwCzjCb+sVa20\nHBRPTnzo8LSZkI6jAgMBAAECggGAdzyI7z/HLt2IfoAsXDLynNRgVYZluzgawiU3\ngeUjnnGhpSKWERXJC2IWDPBk0YOGgcnQxErNTdfXiFZ/xfRlSgqjVwob2lRe4w4B\npLr+CZXcgznv1VrPUvdolOSp3R2Mahfn7u0qVDUQ/g8jWVI6KW7FACmQhzQkPM8o\ntLGrpcmK+PA465uaHKtYccEB02ILqrK8v++tknv7eIZczrsSKlS1h/HHjSaidYxP\n2DAUiF7wnChrwwQEvuEUHhwVgQcoDMBoow0zwHdbFiFO2ZT54H2oiJWLhpR/x6RK\ngM1seqoPH2sYErPJACMcYsMtF4Tx7b5c4WSj3vDCGb+jeqnNS6nFC3aMnv75mUS2\nYDPU1heJFd8pNHVf0RDejLZZUiJSnXf3vpOxt9Xv2+4He0jeMfLV7zX0mO2Ni3MJ\nx6PiVy4xerHImOuuHzSla5crOq2ECiAxd1wEOFDRD2LRHzfhpk1ghiA5xA1qwc7Z\neRnkVfoy6PPZ4lZakZTm0p8YCQURAoHBAMUIC/7vnayLae7POmgy+np/ty7iMfyd\nV1eO6LTO21KAaGGlhaY26WD/5LcG2FUgc5jKKahprGrmiNLzLUeQPckJmuijSEVM\nl/4DlRvCo867l7fLaVqYzsQBBdeGIFNiT+FBOd8atff87ZBEfH/rXbDi7METD/VR\n4TdblnCsKYAXEJUdkw3IK7SUGERiQZIwKXrH/Map4ibDrljJ71iCgEureU0DBwcg\nwLftmjGMISoLscdRxeubX5uf/yxtHBJeRwKBwQDLjzHhb4gNGdBHUl4hZPAGCq1V\nLX/GpfoOVObW64Lud+tI6N9GNua5/vWduL7MWWOzDTMZysganhKwsJCY5SqAA9p0\nb6ohusf9i1nUnOa2F2j+weuYPXrTYm+ZrESBBdaEJPuj3R5YHVujrBA9Xe0kVOe3\nne151A+0xJOI3tX9CttIaQAsXR7cMDinkDITw6i7X4olRMPCSixHLW97cDsVDRGt\necO1d4dP3OGscN+vKCoL6tDKDotzWHYPwjH47sUCgcEAoVI8WCiipbKkMnaTsNsE\ngKXvO0DSgq3k5HjLCbdQldUzIbgfnH7bSKNcBYtiNxjR7OihgRW8qO5GWsnmafCs\n1dy6a/2835id3cnbHRaZflvUFhVDFn2E1bCsstFLyFn3Y0w/cO9yzC/X5sZcVXRF\nit3R0Selakv3JZckru4XMJwx5JWJYMBjIIAc+miknWg3niL+UT6pPun65xG3mXWI\nS+yC7c4rw+dKQ44UMLs2MDHRBoxqi8T0W/x9NkfDszpjAoHAclH7S4ZdvC3RIR0L\nLGoJuvroGbwx1JiGdOINuooNwGuswge2zTIsJi0gN/H3hcB2E6rIFiYid4BrMrwW\nmSeq1LZVS6siu0qw4p4OVy+/CmjfWKQD8j4k6u6PipiK6IMk1JYIlSCr2AS04JjT\njgNgGVVtxVt2cUM9huIXkXjEaRZdzK7boA60NCkIyGJdHWh3LLQdW4zg/A64C0lj\nIMoJBGuQkAKgfRuh7KI6Q6Qom7BM3OCFXdUJUEBQHc2MTyeZAoHAJdBQGBn1RFZ+\nn75AnbTMZJ6Twp2fVjzWUz/+rnXFlo87ynA18MR2BzaDST4Bvda29UBFGb32Mux9\nOHukqLgIE5jDuqWjy4B5eCoxZf/OvwlgXkX9+gprGR3axn/PZBFPbFB4ZmjbWLzn\nbocn7FJCXf+Cm0cMmv1jIIxej19MUU/duq9iq4RkHY2LG+KrSEQIUVmImCftXdN3\n/qNP5JetY0eH6C+KRc8JqDB0nvbqZNOgYXOfYXo/5Gk8XIHTFihm\n-----END RSA PRIVATE KEY-----" + testStr := "The quick brown fox jumps over the lazy dog." + sigHex := "4e05ee9e435653549ac4eddbc43e1a6868636e8ea6dbec2564435afcb0de47e0824cddbd88776ddb20728c53ecc90b5d543d5c37575fda8bd0317025fc07de62ee8084b1a75203b1a23d1ef4ac285da3d1fc63317d5b2cf1aafa3e522acedd366ccd5fe4a7f02a42922237426ca3dc154c57408638b9bfaf0d0213855d4e9ee621db204151bcb13d4dbb18f930ec601469c992c84b14e9e0b6f91ac9517bb3b749dd117e1cbac2e4acb0e549f44558a2005898a226d5b6c8b9291d7abae0d9e0a16858b89662a085f74a202deb867acab792bdbd2c36731217caea8b17bd210c29b890472f11e5afdd1dd7b69004db070e04201778f2c49f5758643881403d45a58d08f51b5c63910c6185892f0b590f191d760b669eff2464456f130239bba94acf54a0cb98f6939ff84ae26a37f9b890be259d9b5d636f6eb367b53e895227d7d79a3a88afd6d28c198ee80f6527437c5fbf63accb81709925c4e03d1c9eaee86f58e4bd1c669d6af042dbd412de0d13b98b1111e2fadbe34b45de52125e9a" + k := data.NewPublicKey(data.RSAKey, []byte(pubPem)) + + sigBytes, err := hex.DecodeString(sigHex) + if err != nil { + t.Fatal(err) + } + v := signed.RSAPyCryptoVerifier{} + err = v.Verify(k, sigBytes, []byte(testStr)) + if err != nil { + t.Fatal(err) + } +} + +func TestPyNaCled25519Compat(t *testing.T) { + pubHex := "846612b43cef909a0e4ea9c818379bca4723a2020619f95e7a0ccc6f0850b7dc" + //privHex := "bf3cdb9b2a664b0460e6755cb689ffca15b6e294f79f9f1fcf90b52e5b063a76" + testStr := "The quick brown fox jumps over the lazy dog." + sigHex := "166e7013e48f26dccb4e68fe4cf558d1cd3af902f8395534336a7f8b4c56588694aa3ac671767246298a59d5ef4224f02c854f41bfcfe70241db4be1546d6a00" + + pub, _ := hex.DecodeString(pubHex) + k := data.NewPublicKey(data.ED25519Key, pub) + + sigBytes, _ := hex.DecodeString(sigHex) + + err := signed.Verifiers[data.EDDSASignature].Verify(k, sigBytes, []byte(testStr)) + if err != nil { + t.Fatal(err) + } +} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/interfaces.go b/tuf/store/interfaces.go similarity index 96% rename from Godeps/_workspace/src/github.com/endophage/gotuf/store/interfaces.go rename to tuf/store/interfaces.go index 0be5f60d19..13bffccbdb 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/store/interfaces.go +++ b/tuf/store/interfaces.go @@ -3,7 +3,7 @@ package store import ( "io" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) type targetsWalkFunc func(path string, meta data.FileMeta) error diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/store/memorystore.go b/tuf/store/memorystore.go similarity index 94% rename from Godeps/_workspace/src/github.com/endophage/gotuf/store/memorystore.go rename to tuf/store/memorystore.go index 8adddebe38..89284a80f2 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/store/memorystore.go +++ b/tuf/store/memorystore.go @@ -5,9 +5,9 @@ import ( "fmt" "io" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/errors" - "github.com/endophage/gotuf/utils" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/errors" + "github.com/docker/notary/tuf/utils" ) // NewMemoryStore returns a MetadataStore that operates entirely in memory. diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/repo.go b/tuf/testutils/repo.go similarity index 93% rename from Godeps/_workspace/src/github.com/endophage/gotuf/testutils/repo.go rename to tuf/testutils/repo.go index 451714193a..847398161a 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/repo.go +++ b/tuf/testutils/repo.go @@ -5,13 +5,13 @@ import ( "math/rand" "time" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/utils" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/utils" fuzz "github.com/google/gofuzz" - tuf "github.com/endophage/gotuf" - "github.com/endophage/gotuf/keys" - "github.com/endophage/gotuf/signed" + tuf "github.com/docker/notary/tuf" + "github.com/docker/notary/tuf/keys" + "github.com/docker/notary/tuf/signed" ) // EmptyRepo creates an in memory key database, crypto service diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/utils.go b/tuf/testutils/utils.go similarity index 97% rename from Godeps/_workspace/src/github.com/endophage/gotuf/testutils/utils.go rename to tuf/testutils/utils.go index 2dec7ce4a0..795be489ba 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/testutils/utils.go +++ b/tuf/testutils/utils.go @@ -5,7 +5,7 @@ import ( "fmt" "os" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" // need to initialize sqlite for tests _ "github.com/mattn/go-sqlite3" ) diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go b/tuf/tuf.go similarity index 98% rename from Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go rename to tuf/tuf.go index a797e8b53c..c6a60411a4 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/tuf.go +++ b/tuf/tuf.go @@ -12,11 +12,11 @@ import ( "time" "github.com/Sirupsen/logrus" - "github.com/endophage/gotuf/data" - "github.com/endophage/gotuf/errors" - "github.com/endophage/gotuf/keys" - "github.com/endophage/gotuf/signed" - "github.com/endophage/gotuf/utils" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/errors" + "github.com/docker/notary/tuf/keys" + "github.com/docker/notary/tuf/signed" + "github.com/docker/notary/tuf/utils" ) // ErrSigVerifyFail - signature verification failed diff --git a/tuf/tuf_test.go b/tuf/tuf_test.go new file mode 100644 index 0000000000..19751deba3 --- /dev/null +++ b/tuf/tuf_test.go @@ -0,0 +1,165 @@ +package tuf + +import ( + "encoding/json" + "io/ioutil" + "os" + "path" + "path/filepath" + "testing" + + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/keys" + "github.com/docker/notary/tuf/signed" +) + +func initRepo(t *testing.T, cryptoService signed.CryptoService, keyDB *keys.KeyDB) *Repo { + rootKey, err := cryptoService.Create("root", data.ED25519Key) + if err != nil { + t.Fatal(err) + } + targetsKey, err := cryptoService.Create("targets", data.ED25519Key) + if err != nil { + t.Fatal(err) + } + snapshotKey, err := cryptoService.Create("snapshot", data.ED25519Key) + if err != nil { + t.Fatal(err) + } + timestampKey, err := cryptoService.Create("timestamp", data.ED25519Key) + if err != nil { + t.Fatal(err) + } + + keyDB.AddKey(rootKey) + keyDB.AddKey(targetsKey) + keyDB.AddKey(snapshotKey) + keyDB.AddKey(timestampKey) + + rootRole := &data.Role{ + Name: "root", + RootRole: data.RootRole{ + KeyIDs: []string{rootKey.ID()}, + Threshold: 1, + }, + } + targetsRole := &data.Role{ + Name: "targets", + RootRole: data.RootRole{ + KeyIDs: []string{targetsKey.ID()}, + Threshold: 1, + }, + } + snapshotRole := &data.Role{ + Name: "snapshot", + RootRole: data.RootRole{ + KeyIDs: []string{snapshotKey.ID()}, + Threshold: 1, + }, + } + timestampRole := &data.Role{ + Name: "timestamp", + RootRole: data.RootRole{ + KeyIDs: []string{timestampKey.ID()}, + Threshold: 1, + }, + } + + keyDB.AddRole(rootRole) + keyDB.AddRole(targetsRole) + keyDB.AddRole(snapshotRole) + keyDB.AddRole(timestampRole) + + repo := NewRepo(keyDB, cryptoService) + err = repo.InitRepo(false) + if err != nil { + t.Fatal(err) + } + return repo +} + +func writeRepo(t *testing.T, dir string, repo *Repo) { + //err := os.Remove(dir) + //if err != nil { + // t.Fatal(err) + //} + err := os.MkdirAll(dir, 0755) + if err != nil { + t.Fatal(err) + } + signedRoot, err := repo.SignRoot(data.DefaultExpires("root"), nil) + if err != nil { + t.Fatal(err) + } + rootJSON, _ := json.Marshal(signedRoot) + ioutil.WriteFile(dir+"/root.json", rootJSON, 0755) + + for r := range repo.Targets { + signedTargets, err := repo.SignTargets(r, data.DefaultExpires("targets"), nil) + if err != nil { + t.Fatal(err) + } + targetsJSON, _ := json.Marshal(signedTargets) + p := path.Join(dir, r+".json") + parentDir := filepath.Dir(p) + os.MkdirAll(parentDir, 0755) + ioutil.WriteFile(p, targetsJSON, 0755) + } + + signedSnapshot, err := repo.SignSnapshot(data.DefaultExpires("snapshot"), nil) + if err != nil { + t.Fatal(err) + } + snapshotJSON, _ := json.Marshal(signedSnapshot) + ioutil.WriteFile(dir+"/snapshot.json", snapshotJSON, 0755) + + signedTimestamp, err := repo.SignTimestamp(data.DefaultExpires("timestamp"), nil) + if err != nil { + t.Fatal(err) + } + timestampJSON, _ := json.Marshal(signedTimestamp) + ioutil.WriteFile(dir+"/timestamp.json", timestampJSON, 0755) +} + +func TestInitRepo(t *testing.T) { + ed25519 := signed.NewEd25519() + keyDB := keys.NewDB() + repo := initRepo(t, ed25519, keyDB) + writeRepo(t, "/tmp/tufrepo", repo) +} + +func TestUpdateDelegations(t *testing.T) { + ed25519 := signed.NewEd25519() + keyDB := keys.NewDB() + repo := initRepo(t, ed25519, keyDB) + + testKey, err := ed25519.Create("targets/test", data.ED25519Key) + if err != nil { + t.Fatal(err) + } + role, err := data.NewRole("targets/test", 1, []string{testKey.ID()}, []string{"test"}, []string{}) + if err != nil { + t.Fatal(err) + } + + err = repo.UpdateDelegations(role, []data.Key{testKey}, "") + if err != nil { + t.Fatal(err) + } + + testDeepKey, err := ed25519.Create("targets/test/deep", data.ED25519Key) + if err != nil { + t.Fatal(err) + } + roleDeep, err := data.NewRole("targets/test/deep", 1, []string{testDeepKey.ID()}, []string{"test/deep"}, []string{}) + if err != nil { + t.Fatal(err) + } + + err = repo.UpdateDelegations(roleDeep, []data.Key{testDeepKey}, "") + if err != nil { + t.Fatal(err) + } + + writeRepo(t, "/tmp/tufdelegation", repo) +} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/utils/util.go b/tuf/utils/util.go similarity index 98% rename from Godeps/_workspace/src/github.com/endophage/gotuf/utils/util.go rename to tuf/utils/util.go index 1282fb7215..fe5d559897 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/utils/util.go +++ b/tuf/utils/util.go @@ -9,7 +9,7 @@ import ( "path/filepath" "github.com/docker/notary/trustmanager" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) // ErrWrongLength indicates the length was different to that expected diff --git a/tuf/utils/util_test.go b/tuf/utils/util_test.go new file mode 100644 index 0000000000..fbe55ac9eb --- /dev/null +++ b/tuf/utils/util_test.go @@ -0,0 +1,91 @@ +package utils + +import ( + "encoding/hex" + "testing" + + "github.com/docker/notary/tuf/data" + "github.com/stretchr/testify/assert" +) + +func TestFileMetaEqual(t *testing.T) { + type test struct { + name string + b data.FileMeta + a data.FileMeta + err func(test) error + } + fileMeta := func(length int64, hashes map[string]string) data.FileMeta { + m := data.FileMeta{Length: length, Hashes: make(map[string][]byte, len(hashes))} + for typ, hash := range hashes { + v, err := hex.DecodeString(hash) + assert.NoError(t, err, "hash not in hex") + m.Hashes[typ] = v + } + return m + } + tests := []test{ + { + name: "wrong length", + a: data.FileMeta{Length: 1}, + b: data.FileMeta{Length: 2}, + err: func(test) error { return ErrWrongLength }, + }, + { + name: "wrong sha512 hash", + a: fileMeta(10, map[string]string{"sha512": "111111"}), + b: fileMeta(10, map[string]string{"sha512": "222222"}), + err: func(t test) error { return ErrWrongHash{"sha512", t.b.Hashes["sha512"], t.a.Hashes["sha512"]} }, + }, + { + name: "intersecting hashes", + a: fileMeta(10, map[string]string{"sha512": "111111", "md5": "222222"}), + b: fileMeta(10, map[string]string{"sha512": "111111", "sha256": "333333"}), + err: func(test) error { return nil }, + }, + { + name: "no common hashes", + a: fileMeta(10, map[string]string{"sha512": "111111"}), + b: fileMeta(10, map[string]string{"sha256": "222222", "md5": "333333"}), + err: func(t test) error { return ErrNoCommonHash{t.b.Hashes, t.a.Hashes} }, + }, + } + for _, run := range tests { + assert.Equal(t, FileMetaEqual(run.a, run.b), run.err(run), "Files not equivalent") + } +} + +func TestNormalizeTarget(t *testing.T) { + for before, after := range map[string]string{ + "": "/", + "foo.txt": "/foo.txt", + "/bar.txt": "/bar.txt", + "foo//bar.txt": "/foo/bar.txt", + "/with/./a/dot": "/with/a/dot", + "/with/double/../dot": "/with/dot", + } { + assert.Equal(t, NormalizeTarget(before), after, "Path normalization did not output expected.") + } +} + +func TestHashedPaths(t *testing.T) { + hexBytes := func(s string) []byte { + v, err := hex.DecodeString(s) + assert.NoError(t, err, "String was not hex") + return v + } + hashes := data.Hashes{ + "sha512": hexBytes("abc123"), + "sha256": hexBytes("def456"), + } + paths := HashedPaths("foo/bar.txt", hashes) + // cannot use DeepEquals as the returned order is non-deterministic + assert.Len(t, paths, 2, "Expected 2 paths") + expected := map[string]struct{}{"foo/abc123.bar.txt": {}, "foo/def456.bar.txt": {}} + for _, path := range paths { + if _, ok := expected[path]; !ok { + t.Fatalf("unexpected path: %s", path) + } + delete(expected, path) + } +} diff --git a/Godeps/_workspace/src/github.com/endophage/gotuf/utils/utils.go b/tuf/utils/utils.go similarity index 98% rename from Godeps/_workspace/src/github.com/endophage/gotuf/utils/utils.go rename to tuf/utils/utils.go index 4e9b28f8f7..a647e3fafa 100644 --- a/Godeps/_workspace/src/github.com/endophage/gotuf/utils/utils.go +++ b/tuf/utils/utils.go @@ -12,7 +12,7 @@ import ( "os" "strings" - "github.com/endophage/gotuf/data" + "github.com/docker/notary/tuf/data" ) // Download does a simple download from a URL diff --git a/utils/http.go b/utils/http.go index c8e8bdfddb..6efd0b6f04 100644 --- a/utils/http.go +++ b/utils/http.go @@ -9,7 +9,7 @@ import ( "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/auth" "github.com/docker/notary/errors" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/signed" "github.com/gorilla/mux" "golang.org/x/net/context" ) diff --git a/utils/http_test.go b/utils/http_test.go index f72ef31678..d2d1ef799e 100644 --- a/utils/http_test.go +++ b/utils/http_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/endophage/gotuf/signed" + "github.com/docker/notary/tuf/signed" "golang.org/x/net/context" "github.com/docker/notary/errors"