Add Nix flake for mciasctl and mciasgrpcctl
Vendor dependencies and expose control program binaries via nix build. Uses nixpkgs-unstable for Go 1.26 support. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
27
vendor/golang.org/x/crypto/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/crypto/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright 2009 The Go Authors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
22
vendor/golang.org/x/crypto/PATENTS
generated
vendored
Normal file
22
vendor/golang.org/x/crypto/PATENTS
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
|
||||
"This implementation" means the copyrightable works distributed by
|
||||
Google as part of the Go project.
|
||||
|
||||
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section)
|
||||
patent license to make, have made, use, offer to sell, sell, import,
|
||||
transfer and otherwise run, modify and propagate the contents of this
|
||||
implementation of Go, where such license applies only to those patent
|
||||
claims, both currently owned or controlled by Google and acquired in
|
||||
the future, licensable by Google that are necessarily infringed by this
|
||||
implementation of Go. This grant does not include claims that would be
|
||||
infringed only as a consequence of further modification of this
|
||||
implementation. If you or your agent or exclusive licensee institute or
|
||||
order or agree to the institution of patent litigation against any
|
||||
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
||||
that this implementation of Go or any code incorporated within this
|
||||
implementation of Go constitutes direct or contributory patent
|
||||
infringement, or inducement of patent infringement, then any patent
|
||||
rights granted to you under this License for this implementation of Go
|
||||
shall terminate as of the date such litigation is filed.
|
||||
287
vendor/golang.org/x/crypto/argon2/argon2.go
generated
vendored
Normal file
287
vendor/golang.org/x/crypto/argon2/argon2.go
generated
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
// Copyright 2017 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 argon2 implements the key derivation function Argon2.
|
||||
// Argon2 was selected as the winner of the Password Hashing Competition and can
|
||||
// be used to derive cryptographic keys from passwords.
|
||||
//
|
||||
// For a detailed specification of Argon2 see [argon2-specs.pdf].
|
||||
//
|
||||
// If you aren't sure which function you need, use Argon2id (IDKey) and
|
||||
// the parameter recommendations for your scenario.
|
||||
//
|
||||
// # Argon2i
|
||||
//
|
||||
// Argon2i (implemented by Key) is the side-channel resistant version of Argon2.
|
||||
// It uses data-independent memory access, which is preferred for password
|
||||
// hashing and password-based key derivation. Argon2i requires more passes over
|
||||
// memory than Argon2id to protect from trade-off attacks. The recommended
|
||||
// parameters (taken from [RFC 9106 Section 7.3]) for non-interactive operations are time=3 and to
|
||||
// use the maximum available memory.
|
||||
//
|
||||
// # Argon2id
|
||||
//
|
||||
// Argon2id (implemented by IDKey) is a hybrid version of Argon2 combining
|
||||
// Argon2i and Argon2d. It uses data-independent memory access for the first
|
||||
// half of the first iteration over the memory and data-dependent memory access
|
||||
// for the rest. Argon2id is side-channel resistant and provides better brute-
|
||||
// force cost savings due to time-memory tradeoffs than Argon2i. The recommended
|
||||
// parameters for non-interactive operations (taken from [RFC 9106 Section 7.3]) are time=1 and to
|
||||
// use the maximum available memory.
|
||||
//
|
||||
// [argon2-specs.pdf]: https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf
|
||||
// [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3
|
||||
package argon2
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
)
|
||||
|
||||
// The Argon2 version implemented by this package.
|
||||
const Version = 0x13
|
||||
|
||||
const (
|
||||
argon2d = iota
|
||||
argon2i
|
||||
argon2id
|
||||
)
|
||||
|
||||
// Key derives a key from the password, salt, and cost parameters using Argon2i
|
||||
// returning a byte slice of length keyLen that can be used as cryptographic
|
||||
// key. The CPU cost and parallelism degree must be greater than zero.
|
||||
//
|
||||
// For example, you can get a derived key for e.g. AES-256 (which needs a
|
||||
// 32-byte key) by doing:
|
||||
//
|
||||
// key := argon2.Key([]byte("some password"), salt, 3, 32*1024, 4, 32)
|
||||
//
|
||||
// [RFC 9106 Section 7.3] recommends time=3, and memory=32*1024 as a sensible number.
|
||||
// If using that amount of memory (32 MB) is not possible in some contexts then
|
||||
// the time parameter can be increased to compensate.
|
||||
//
|
||||
// The time parameter specifies the number of passes over the memory and the
|
||||
// memory parameter specifies the size of the memory in KiB. For example
|
||||
// memory=32*1024 sets the memory cost to ~32 MB. The number of threads can be
|
||||
// adjusted to the number of available CPUs. The cost parameters should be
|
||||
// increased as memory latency and CPU parallelism increases. Remember to get a
|
||||
// good random salt.
|
||||
//
|
||||
// [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3
|
||||
func Key(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
|
||||
return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen)
|
||||
}
|
||||
|
||||
// IDKey derives a key from the password, salt, and cost parameters using
|
||||
// Argon2id returning a byte slice of length keyLen that can be used as
|
||||
// cryptographic key. The CPU cost and parallelism degree must be greater than
|
||||
// zero.
|
||||
//
|
||||
// For example, you can get a derived key for e.g. AES-256 (which needs a
|
||||
// 32-byte key) by doing:
|
||||
//
|
||||
// key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32)
|
||||
//
|
||||
// [RFC 9106 Section 7.3] recommends time=1, and memory=64*1024 as a sensible number.
|
||||
// If using that amount of memory (64 MB) is not possible in some contexts then
|
||||
// the time parameter can be increased to compensate.
|
||||
//
|
||||
// The time parameter specifies the number of passes over the memory and the
|
||||
// memory parameter specifies the size of the memory in KiB. For example
|
||||
// memory=64*1024 sets the memory cost to ~64 MB. The number of threads can be
|
||||
// adjusted to the numbers of available CPUs. The cost parameters should be
|
||||
// increased as memory latency and CPU parallelism increases. Remember to get a
|
||||
// good random salt.
|
||||
//
|
||||
// [RFC 9106 Section 7.3]: https://www.rfc-editor.org/rfc/rfc9106.html#section-7.3
|
||||
func IDKey(password, salt []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
|
||||
return deriveKey(argon2id, password, salt, nil, nil, time, memory, threads, keyLen)
|
||||
}
|
||||
|
||||
func deriveKey(mode int, password, salt, secret, data []byte, time, memory uint32, threads uint8, keyLen uint32) []byte {
|
||||
if time < 1 {
|
||||
panic("argon2: number of rounds too small")
|
||||
}
|
||||
if threads < 1 {
|
||||
panic("argon2: parallelism degree too low")
|
||||
}
|
||||
h0 := initHash(password, salt, secret, data, time, memory, uint32(threads), keyLen, mode)
|
||||
|
||||
memory = memory / (syncPoints * uint32(threads)) * (syncPoints * uint32(threads))
|
||||
if memory < 2*syncPoints*uint32(threads) {
|
||||
memory = 2 * syncPoints * uint32(threads)
|
||||
}
|
||||
B := initBlocks(&h0, memory, uint32(threads))
|
||||
processBlocks(B, time, memory, uint32(threads), mode)
|
||||
return extractKey(B, memory, uint32(threads), keyLen)
|
||||
}
|
||||
|
||||
const (
|
||||
blockLength = 128
|
||||
syncPoints = 4
|
||||
)
|
||||
|
||||
type block [blockLength]uint64
|
||||
|
||||
func initHash(password, salt, key, data []byte, time, memory, threads, keyLen uint32, mode int) [blake2b.Size + 8]byte {
|
||||
var (
|
||||
h0 [blake2b.Size + 8]byte
|
||||
params [24]byte
|
||||
tmp [4]byte
|
||||
)
|
||||
|
||||
b2, _ := blake2b.New512(nil)
|
||||
binary.LittleEndian.PutUint32(params[0:4], threads)
|
||||
binary.LittleEndian.PutUint32(params[4:8], keyLen)
|
||||
binary.LittleEndian.PutUint32(params[8:12], memory)
|
||||
binary.LittleEndian.PutUint32(params[12:16], time)
|
||||
binary.LittleEndian.PutUint32(params[16:20], uint32(Version))
|
||||
binary.LittleEndian.PutUint32(params[20:24], uint32(mode))
|
||||
b2.Write(params[:])
|
||||
binary.LittleEndian.PutUint32(tmp[:], uint32(len(password)))
|
||||
b2.Write(tmp[:])
|
||||
b2.Write(password)
|
||||
binary.LittleEndian.PutUint32(tmp[:], uint32(len(salt)))
|
||||
b2.Write(tmp[:])
|
||||
b2.Write(salt)
|
||||
binary.LittleEndian.PutUint32(tmp[:], uint32(len(key)))
|
||||
b2.Write(tmp[:])
|
||||
b2.Write(key)
|
||||
binary.LittleEndian.PutUint32(tmp[:], uint32(len(data)))
|
||||
b2.Write(tmp[:])
|
||||
b2.Write(data)
|
||||
b2.Sum(h0[:0])
|
||||
return h0
|
||||
}
|
||||
|
||||
func initBlocks(h0 *[blake2b.Size + 8]byte, memory, threads uint32) []block {
|
||||
var block0 [1024]byte
|
||||
B := make([]block, memory)
|
||||
for lane := uint32(0); lane < threads; lane++ {
|
||||
j := lane * (memory / threads)
|
||||
binary.LittleEndian.PutUint32(h0[blake2b.Size+4:], lane)
|
||||
|
||||
binary.LittleEndian.PutUint32(h0[blake2b.Size:], 0)
|
||||
blake2bHash(block0[:], h0[:])
|
||||
for i := range B[j+0] {
|
||||
B[j+0][i] = binary.LittleEndian.Uint64(block0[i*8:])
|
||||
}
|
||||
|
||||
binary.LittleEndian.PutUint32(h0[blake2b.Size:], 1)
|
||||
blake2bHash(block0[:], h0[:])
|
||||
for i := range B[j+1] {
|
||||
B[j+1][i] = binary.LittleEndian.Uint64(block0[i*8:])
|
||||
}
|
||||
}
|
||||
return B
|
||||
}
|
||||
|
||||
func processBlocks(B []block, time, memory, threads uint32, mode int) {
|
||||
lanes := memory / threads
|
||||
segments := lanes / syncPoints
|
||||
|
||||
processSegment := func(n, slice, lane uint32, wg *sync.WaitGroup) {
|
||||
var addresses, in, zero block
|
||||
if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) {
|
||||
in[0] = uint64(n)
|
||||
in[1] = uint64(lane)
|
||||
in[2] = uint64(slice)
|
||||
in[3] = uint64(memory)
|
||||
in[4] = uint64(time)
|
||||
in[5] = uint64(mode)
|
||||
}
|
||||
|
||||
index := uint32(0)
|
||||
if n == 0 && slice == 0 {
|
||||
index = 2 // we have already generated the first two blocks
|
||||
if mode == argon2i || mode == argon2id {
|
||||
in[6]++
|
||||
processBlock(&addresses, &in, &zero)
|
||||
processBlock(&addresses, &addresses, &zero)
|
||||
}
|
||||
}
|
||||
|
||||
offset := lane*lanes + slice*segments + index
|
||||
var random uint64
|
||||
for index < segments {
|
||||
prev := offset - 1
|
||||
if index == 0 && slice == 0 {
|
||||
prev += lanes // last block in lane
|
||||
}
|
||||
if mode == argon2i || (mode == argon2id && n == 0 && slice < syncPoints/2) {
|
||||
if index%blockLength == 0 {
|
||||
in[6]++
|
||||
processBlock(&addresses, &in, &zero)
|
||||
processBlock(&addresses, &addresses, &zero)
|
||||
}
|
||||
random = addresses[index%blockLength]
|
||||
} else {
|
||||
random = B[prev][0]
|
||||
}
|
||||
newOffset := indexAlpha(random, lanes, segments, threads, n, slice, lane, index)
|
||||
processBlockXOR(&B[offset], &B[prev], &B[newOffset])
|
||||
index, offset = index+1, offset+1
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
for n := uint32(0); n < time; n++ {
|
||||
for slice := uint32(0); slice < syncPoints; slice++ {
|
||||
var wg sync.WaitGroup
|
||||
for lane := uint32(0); lane < threads; lane++ {
|
||||
wg.Add(1)
|
||||
go processSegment(n, slice, lane, &wg)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func extractKey(B []block, memory, threads, keyLen uint32) []byte {
|
||||
lanes := memory / threads
|
||||
for lane := uint32(0); lane < threads-1; lane++ {
|
||||
for i, v := range B[(lane*lanes)+lanes-1] {
|
||||
B[memory-1][i] ^= v
|
||||
}
|
||||
}
|
||||
|
||||
var block [1024]byte
|
||||
for i, v := range B[memory-1] {
|
||||
binary.LittleEndian.PutUint64(block[i*8:], v)
|
||||
}
|
||||
key := make([]byte, keyLen)
|
||||
blake2bHash(key, block[:])
|
||||
return key
|
||||
}
|
||||
|
||||
func indexAlpha(rand uint64, lanes, segments, threads, n, slice, lane, index uint32) uint32 {
|
||||
refLane := uint32(rand>>32) % threads
|
||||
if n == 0 && slice == 0 {
|
||||
refLane = lane
|
||||
}
|
||||
m, s := 3*segments, ((slice+1)%syncPoints)*segments
|
||||
if lane == refLane {
|
||||
m += index
|
||||
}
|
||||
if n == 0 {
|
||||
m, s = slice*segments, 0
|
||||
if slice == 0 || lane == refLane {
|
||||
m += index
|
||||
}
|
||||
}
|
||||
if index == 0 || lane == refLane {
|
||||
m--
|
||||
}
|
||||
return phi(rand, uint64(m), uint64(s), refLane, lanes)
|
||||
}
|
||||
|
||||
func phi(rand, m, s uint64, lane, lanes uint32) uint32 {
|
||||
p := rand & 0xFFFFFFFF
|
||||
p = (p * p) >> 32
|
||||
p = (p * m) >> 32
|
||||
return lane*lanes + uint32((s+m-(p+1))%uint64(lanes))
|
||||
}
|
||||
53
vendor/golang.org/x/crypto/argon2/blake2b.go
generated
vendored
Normal file
53
vendor/golang.org/x/crypto/argon2/blake2b.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright 2017 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 argon2
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
)
|
||||
|
||||
// blake2bHash computes an arbitrary long hash value of in
|
||||
// and writes the hash to out.
|
||||
func blake2bHash(out []byte, in []byte) {
|
||||
var b2 hash.Hash
|
||||
if n := len(out); n < blake2b.Size {
|
||||
b2, _ = blake2b.New(n, nil)
|
||||
} else {
|
||||
b2, _ = blake2b.New512(nil)
|
||||
}
|
||||
|
||||
var buffer [blake2b.Size]byte
|
||||
binary.LittleEndian.PutUint32(buffer[:4], uint32(len(out)))
|
||||
b2.Write(buffer[:4])
|
||||
b2.Write(in)
|
||||
|
||||
if len(out) <= blake2b.Size {
|
||||
b2.Sum(out[:0])
|
||||
return
|
||||
}
|
||||
|
||||
outLen := len(out)
|
||||
b2.Sum(buffer[:0])
|
||||
b2.Reset()
|
||||
copy(out, buffer[:32])
|
||||
out = out[32:]
|
||||
for len(out) > blake2b.Size {
|
||||
b2.Write(buffer[:])
|
||||
b2.Sum(buffer[:0])
|
||||
copy(out, buffer[:32])
|
||||
out = out[32:]
|
||||
b2.Reset()
|
||||
}
|
||||
|
||||
if outLen%blake2b.Size > 0 { // outLen > 64
|
||||
r := ((outLen + 31) / 32) - 2 // ⌈τ /32⌉-2
|
||||
b2, _ = blake2b.New(outLen-32*r, nil)
|
||||
}
|
||||
b2.Write(buffer[:])
|
||||
b2.Sum(out[:0])
|
||||
}
|
||||
60
vendor/golang.org/x/crypto/argon2/blamka_amd64.go
generated
vendored
Normal file
60
vendor/golang.org/x/crypto/argon2/blamka_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
//go:build amd64 && gc && !purego
|
||||
|
||||
package argon2
|
||||
|
||||
import "golang.org/x/sys/cpu"
|
||||
|
||||
func init() {
|
||||
useSSE4 = cpu.X86.HasSSE41
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func mixBlocksSSE2(out, a, b, c *block)
|
||||
|
||||
//go:noescape
|
||||
func xorBlocksSSE2(out, a, b, c *block)
|
||||
|
||||
//go:noescape
|
||||
func blamkaSSE4(b *block)
|
||||
|
||||
func processBlockSSE(out, in1, in2 *block, xor bool) {
|
||||
var t block
|
||||
mixBlocksSSE2(&t, in1, in2, &t)
|
||||
if useSSE4 {
|
||||
blamkaSSE4(&t)
|
||||
} else {
|
||||
for i := 0; i < blockLength; i += 16 {
|
||||
blamkaGeneric(
|
||||
&t[i+0], &t[i+1], &t[i+2], &t[i+3],
|
||||
&t[i+4], &t[i+5], &t[i+6], &t[i+7],
|
||||
&t[i+8], &t[i+9], &t[i+10], &t[i+11],
|
||||
&t[i+12], &t[i+13], &t[i+14], &t[i+15],
|
||||
)
|
||||
}
|
||||
for i := 0; i < blockLength/8; i += 2 {
|
||||
blamkaGeneric(
|
||||
&t[i], &t[i+1], &t[16+i], &t[16+i+1],
|
||||
&t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1],
|
||||
&t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1],
|
||||
&t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1],
|
||||
)
|
||||
}
|
||||
}
|
||||
if xor {
|
||||
xorBlocksSSE2(out, in1, in2, &t)
|
||||
} else {
|
||||
mixBlocksSSE2(out, in1, in2, &t)
|
||||
}
|
||||
}
|
||||
|
||||
func processBlock(out, in1, in2 *block) {
|
||||
processBlockSSE(out, in1, in2, false)
|
||||
}
|
||||
|
||||
func processBlockXOR(out, in1, in2 *block) {
|
||||
processBlockSSE(out, in1, in2, true)
|
||||
}
|
||||
2791
vendor/golang.org/x/crypto/argon2/blamka_amd64.s
generated
vendored
Normal file
2791
vendor/golang.org/x/crypto/argon2/blamka_amd64.s
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
163
vendor/golang.org/x/crypto/argon2/blamka_generic.go
generated
vendored
Normal file
163
vendor/golang.org/x/crypto/argon2/blamka_generic.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
// Copyright 2017 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 argon2
|
||||
|
||||
var useSSE4 bool
|
||||
|
||||
func processBlockGeneric(out, in1, in2 *block, xor bool) {
|
||||
var t block
|
||||
for i := range t {
|
||||
t[i] = in1[i] ^ in2[i]
|
||||
}
|
||||
for i := 0; i < blockLength; i += 16 {
|
||||
blamkaGeneric(
|
||||
&t[i+0], &t[i+1], &t[i+2], &t[i+3],
|
||||
&t[i+4], &t[i+5], &t[i+6], &t[i+7],
|
||||
&t[i+8], &t[i+9], &t[i+10], &t[i+11],
|
||||
&t[i+12], &t[i+13], &t[i+14], &t[i+15],
|
||||
)
|
||||
}
|
||||
for i := 0; i < blockLength/8; i += 2 {
|
||||
blamkaGeneric(
|
||||
&t[i], &t[i+1], &t[16+i], &t[16+i+1],
|
||||
&t[32+i], &t[32+i+1], &t[48+i], &t[48+i+1],
|
||||
&t[64+i], &t[64+i+1], &t[80+i], &t[80+i+1],
|
||||
&t[96+i], &t[96+i+1], &t[112+i], &t[112+i+1],
|
||||
)
|
||||
}
|
||||
if xor {
|
||||
for i := range t {
|
||||
out[i] ^= in1[i] ^ in2[i] ^ t[i]
|
||||
}
|
||||
} else {
|
||||
for i := range t {
|
||||
out[i] = in1[i] ^ in2[i] ^ t[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func blamkaGeneric(t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15 *uint64) {
|
||||
v00, v01, v02, v03 := *t00, *t01, *t02, *t03
|
||||
v04, v05, v06, v07 := *t04, *t05, *t06, *t07
|
||||
v08, v09, v10, v11 := *t08, *t09, *t10, *t11
|
||||
v12, v13, v14, v15 := *t12, *t13, *t14, *t15
|
||||
|
||||
v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04))
|
||||
v12 ^= v00
|
||||
v12 = v12>>32 | v12<<32
|
||||
v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12))
|
||||
v04 ^= v08
|
||||
v04 = v04>>24 | v04<<40
|
||||
|
||||
v00 += v04 + 2*uint64(uint32(v00))*uint64(uint32(v04))
|
||||
v12 ^= v00
|
||||
v12 = v12>>16 | v12<<48
|
||||
v08 += v12 + 2*uint64(uint32(v08))*uint64(uint32(v12))
|
||||
v04 ^= v08
|
||||
v04 = v04>>63 | v04<<1
|
||||
|
||||
v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05))
|
||||
v13 ^= v01
|
||||
v13 = v13>>32 | v13<<32
|
||||
v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13))
|
||||
v05 ^= v09
|
||||
v05 = v05>>24 | v05<<40
|
||||
|
||||
v01 += v05 + 2*uint64(uint32(v01))*uint64(uint32(v05))
|
||||
v13 ^= v01
|
||||
v13 = v13>>16 | v13<<48
|
||||
v09 += v13 + 2*uint64(uint32(v09))*uint64(uint32(v13))
|
||||
v05 ^= v09
|
||||
v05 = v05>>63 | v05<<1
|
||||
|
||||
v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06))
|
||||
v14 ^= v02
|
||||
v14 = v14>>32 | v14<<32
|
||||
v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14))
|
||||
v06 ^= v10
|
||||
v06 = v06>>24 | v06<<40
|
||||
|
||||
v02 += v06 + 2*uint64(uint32(v02))*uint64(uint32(v06))
|
||||
v14 ^= v02
|
||||
v14 = v14>>16 | v14<<48
|
||||
v10 += v14 + 2*uint64(uint32(v10))*uint64(uint32(v14))
|
||||
v06 ^= v10
|
||||
v06 = v06>>63 | v06<<1
|
||||
|
||||
v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07))
|
||||
v15 ^= v03
|
||||
v15 = v15>>32 | v15<<32
|
||||
v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15))
|
||||
v07 ^= v11
|
||||
v07 = v07>>24 | v07<<40
|
||||
|
||||
v03 += v07 + 2*uint64(uint32(v03))*uint64(uint32(v07))
|
||||
v15 ^= v03
|
||||
v15 = v15>>16 | v15<<48
|
||||
v11 += v15 + 2*uint64(uint32(v11))*uint64(uint32(v15))
|
||||
v07 ^= v11
|
||||
v07 = v07>>63 | v07<<1
|
||||
|
||||
v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05))
|
||||
v15 ^= v00
|
||||
v15 = v15>>32 | v15<<32
|
||||
v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15))
|
||||
v05 ^= v10
|
||||
v05 = v05>>24 | v05<<40
|
||||
|
||||
v00 += v05 + 2*uint64(uint32(v00))*uint64(uint32(v05))
|
||||
v15 ^= v00
|
||||
v15 = v15>>16 | v15<<48
|
||||
v10 += v15 + 2*uint64(uint32(v10))*uint64(uint32(v15))
|
||||
v05 ^= v10
|
||||
v05 = v05>>63 | v05<<1
|
||||
|
||||
v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06))
|
||||
v12 ^= v01
|
||||
v12 = v12>>32 | v12<<32
|
||||
v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12))
|
||||
v06 ^= v11
|
||||
v06 = v06>>24 | v06<<40
|
||||
|
||||
v01 += v06 + 2*uint64(uint32(v01))*uint64(uint32(v06))
|
||||
v12 ^= v01
|
||||
v12 = v12>>16 | v12<<48
|
||||
v11 += v12 + 2*uint64(uint32(v11))*uint64(uint32(v12))
|
||||
v06 ^= v11
|
||||
v06 = v06>>63 | v06<<1
|
||||
|
||||
v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07))
|
||||
v13 ^= v02
|
||||
v13 = v13>>32 | v13<<32
|
||||
v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13))
|
||||
v07 ^= v08
|
||||
v07 = v07>>24 | v07<<40
|
||||
|
||||
v02 += v07 + 2*uint64(uint32(v02))*uint64(uint32(v07))
|
||||
v13 ^= v02
|
||||
v13 = v13>>16 | v13<<48
|
||||
v08 += v13 + 2*uint64(uint32(v08))*uint64(uint32(v13))
|
||||
v07 ^= v08
|
||||
v07 = v07>>63 | v07<<1
|
||||
|
||||
v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04))
|
||||
v14 ^= v03
|
||||
v14 = v14>>32 | v14<<32
|
||||
v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14))
|
||||
v04 ^= v09
|
||||
v04 = v04>>24 | v04<<40
|
||||
|
||||
v03 += v04 + 2*uint64(uint32(v03))*uint64(uint32(v04))
|
||||
v14 ^= v03
|
||||
v14 = v14>>16 | v14<<48
|
||||
v09 += v14 + 2*uint64(uint32(v09))*uint64(uint32(v14))
|
||||
v04 ^= v09
|
||||
v04 = v04>>63 | v04<<1
|
||||
|
||||
*t00, *t01, *t02, *t03 = v00, v01, v02, v03
|
||||
*t04, *t05, *t06, *t07 = v04, v05, v06, v07
|
||||
*t08, *t09, *t10, *t11 = v08, v09, v10, v11
|
||||
*t12, *t13, *t14, *t15 = v12, v13, v14, v15
|
||||
}
|
||||
15
vendor/golang.org/x/crypto/argon2/blamka_ref.go
generated
vendored
Normal file
15
vendor/golang.org/x/crypto/argon2/blamka_ref.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
//go:build !amd64 || purego || !gc
|
||||
|
||||
package argon2
|
||||
|
||||
func processBlock(out, in1, in2 *block) {
|
||||
processBlockGeneric(out, in1, in2, false)
|
||||
}
|
||||
|
||||
func processBlockXOR(out, in1, in2 *block) {
|
||||
processBlockGeneric(out, in1, in2, true)
|
||||
}
|
||||
291
vendor/golang.org/x/crypto/blake2b/blake2b.go
generated
vendored
Normal file
291
vendor/golang.org/x/crypto/blake2b/blake2b.go
generated
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
// Copyright 2016 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 blake2b implements the BLAKE2b hash algorithm defined by RFC 7693
|
||||
// and the extendable output function (XOF) BLAKE2Xb.
|
||||
//
|
||||
// BLAKE2b is optimized for 64-bit platforms—including NEON-enabled ARMs—and
|
||||
// produces digests of any size between 1 and 64 bytes.
|
||||
// For a detailed specification of BLAKE2b see https://blake2.net/blake2.pdf
|
||||
// and for BLAKE2Xb see https://blake2.net/blake2x.pdf
|
||||
//
|
||||
// If you aren't sure which function you need, use BLAKE2b (Sum512 or New512).
|
||||
// If you need a secret-key MAC (message authentication code), use the New512
|
||||
// function with a non-nil key.
|
||||
//
|
||||
// BLAKE2X is a construction to compute hash values larger than 64 bytes. It
|
||||
// can produce hash values between 0 and 4 GiB.
|
||||
package blake2b
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"hash"
|
||||
)
|
||||
|
||||
const (
|
||||
// The blocksize of BLAKE2b in bytes.
|
||||
BlockSize = 128
|
||||
// The hash size of BLAKE2b-512 in bytes.
|
||||
Size = 64
|
||||
// The hash size of BLAKE2b-384 in bytes.
|
||||
Size384 = 48
|
||||
// The hash size of BLAKE2b-256 in bytes.
|
||||
Size256 = 32
|
||||
)
|
||||
|
||||
var (
|
||||
useAVX2 bool
|
||||
useAVX bool
|
||||
useSSE4 bool
|
||||
)
|
||||
|
||||
var (
|
||||
errKeySize = errors.New("blake2b: invalid key size")
|
||||
errHashSize = errors.New("blake2b: invalid hash size")
|
||||
)
|
||||
|
||||
var iv = [8]uint64{
|
||||
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
|
||||
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
|
||||
}
|
||||
|
||||
// Sum512 returns the BLAKE2b-512 checksum of the data.
|
||||
func Sum512(data []byte) [Size]byte {
|
||||
var sum [Size]byte
|
||||
checkSum(&sum, Size, data)
|
||||
return sum
|
||||
}
|
||||
|
||||
// Sum384 returns the BLAKE2b-384 checksum of the data.
|
||||
func Sum384(data []byte) [Size384]byte {
|
||||
var sum [Size]byte
|
||||
var sum384 [Size384]byte
|
||||
checkSum(&sum, Size384, data)
|
||||
copy(sum384[:], sum[:Size384])
|
||||
return sum384
|
||||
}
|
||||
|
||||
// Sum256 returns the BLAKE2b-256 checksum of the data.
|
||||
func Sum256(data []byte) [Size256]byte {
|
||||
var sum [Size]byte
|
||||
var sum256 [Size256]byte
|
||||
checkSum(&sum, Size256, data)
|
||||
copy(sum256[:], sum[:Size256])
|
||||
return sum256
|
||||
}
|
||||
|
||||
// New512 returns a new hash.Hash computing the BLAKE2b-512 checksum. A non-nil
|
||||
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
|
||||
func New512(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
|
||||
|
||||
// New384 returns a new hash.Hash computing the BLAKE2b-384 checksum. A non-nil
|
||||
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
|
||||
func New384(key []byte) (hash.Hash, error) { return newDigest(Size384, key) }
|
||||
|
||||
// New256 returns a new hash.Hash computing the BLAKE2b-256 checksum. A non-nil
|
||||
// key turns the hash into a MAC. The key must be between zero and 64 bytes long.
|
||||
func New256(key []byte) (hash.Hash, error) { return newDigest(Size256, key) }
|
||||
|
||||
// New returns a new hash.Hash computing the BLAKE2b checksum with a custom length.
|
||||
// A non-nil key turns the hash into a MAC. The key must be between zero and 64 bytes long.
|
||||
// The hash size can be a value between 1 and 64 but it is highly recommended to use
|
||||
// values equal or greater than:
|
||||
// - 32 if BLAKE2b is used as a hash function (The key is zero bytes long).
|
||||
// - 16 if BLAKE2b is used as a MAC function (The key is at least 16 bytes long).
|
||||
// When the key is nil, the returned hash.Hash implements BinaryMarshaler
|
||||
// and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash.
|
||||
func New(size int, key []byte) (hash.Hash, error) { return newDigest(size, key) }
|
||||
|
||||
func newDigest(hashSize int, key []byte) (*digest, error) {
|
||||
if hashSize < 1 || hashSize > Size {
|
||||
return nil, errHashSize
|
||||
}
|
||||
if len(key) > Size {
|
||||
return nil, errKeySize
|
||||
}
|
||||
d := &digest{
|
||||
size: hashSize,
|
||||
keyLen: len(key),
|
||||
}
|
||||
copy(d.key[:], key)
|
||||
d.Reset()
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func checkSum(sum *[Size]byte, hashSize int, data []byte) {
|
||||
h := iv
|
||||
h[0] ^= uint64(hashSize) | (1 << 16) | (1 << 24)
|
||||
var c [2]uint64
|
||||
|
||||
if length := len(data); length > BlockSize {
|
||||
n := length &^ (BlockSize - 1)
|
||||
if length == n {
|
||||
n -= BlockSize
|
||||
}
|
||||
hashBlocks(&h, &c, 0, data[:n])
|
||||
data = data[n:]
|
||||
}
|
||||
|
||||
var block [BlockSize]byte
|
||||
offset := copy(block[:], data)
|
||||
remaining := uint64(BlockSize - offset)
|
||||
if c[0] < remaining {
|
||||
c[1]--
|
||||
}
|
||||
c[0] -= remaining
|
||||
|
||||
hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
|
||||
|
||||
for i, v := range h[:(hashSize+7)/8] {
|
||||
binary.LittleEndian.PutUint64(sum[8*i:], v)
|
||||
}
|
||||
}
|
||||
|
||||
type digest struct {
|
||||
h [8]uint64
|
||||
c [2]uint64
|
||||
size int
|
||||
block [BlockSize]byte
|
||||
offset int
|
||||
|
||||
key [BlockSize]byte
|
||||
keyLen int
|
||||
}
|
||||
|
||||
const (
|
||||
magic = "b2b"
|
||||
marshaledSize = len(magic) + 8*8 + 2*8 + 1 + BlockSize + 1
|
||||
)
|
||||
|
||||
func (d *digest) MarshalBinary() ([]byte, error) {
|
||||
if d.keyLen != 0 {
|
||||
return nil, errors.New("crypto/blake2b: cannot marshal MACs")
|
||||
}
|
||||
b := make([]byte, 0, marshaledSize)
|
||||
b = append(b, magic...)
|
||||
for i := 0; i < 8; i++ {
|
||||
b = appendUint64(b, d.h[i])
|
||||
}
|
||||
b = appendUint64(b, d.c[0])
|
||||
b = appendUint64(b, d.c[1])
|
||||
// Maximum value for size is 64
|
||||
b = append(b, byte(d.size))
|
||||
b = append(b, d.block[:]...)
|
||||
b = append(b, byte(d.offset))
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (d *digest) UnmarshalBinary(b []byte) error {
|
||||
if len(b) < len(magic) || string(b[:len(magic)]) != magic {
|
||||
return errors.New("crypto/blake2b: invalid hash state identifier")
|
||||
}
|
||||
if len(b) != marshaledSize {
|
||||
return errors.New("crypto/blake2b: invalid hash state size")
|
||||
}
|
||||
b = b[len(magic):]
|
||||
for i := 0; i < 8; i++ {
|
||||
b, d.h[i] = consumeUint64(b)
|
||||
}
|
||||
b, d.c[0] = consumeUint64(b)
|
||||
b, d.c[1] = consumeUint64(b)
|
||||
d.size = int(b[0])
|
||||
b = b[1:]
|
||||
copy(d.block[:], b[:BlockSize])
|
||||
b = b[BlockSize:]
|
||||
d.offset = int(b[0])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *digest) BlockSize() int { return BlockSize }
|
||||
|
||||
func (d *digest) Size() int { return d.size }
|
||||
|
||||
func (d *digest) Reset() {
|
||||
d.h = iv
|
||||
d.h[0] ^= uint64(d.size) | (uint64(d.keyLen) << 8) | (1 << 16) | (1 << 24)
|
||||
d.offset, d.c[0], d.c[1] = 0, 0, 0
|
||||
if d.keyLen > 0 {
|
||||
d.block = d.key
|
||||
d.offset = BlockSize
|
||||
}
|
||||
}
|
||||
|
||||
func (d *digest) Write(p []byte) (n int, err error) {
|
||||
n = len(p)
|
||||
|
||||
if d.offset > 0 {
|
||||
remaining := BlockSize - d.offset
|
||||
if n <= remaining {
|
||||
d.offset += copy(d.block[d.offset:], p)
|
||||
return
|
||||
}
|
||||
copy(d.block[d.offset:], p[:remaining])
|
||||
hashBlocks(&d.h, &d.c, 0, d.block[:])
|
||||
d.offset = 0
|
||||
p = p[remaining:]
|
||||
}
|
||||
|
||||
if length := len(p); length > BlockSize {
|
||||
nn := length &^ (BlockSize - 1)
|
||||
if length == nn {
|
||||
nn -= BlockSize
|
||||
}
|
||||
hashBlocks(&d.h, &d.c, 0, p[:nn])
|
||||
p = p[nn:]
|
||||
}
|
||||
|
||||
if len(p) > 0 {
|
||||
d.offset += copy(d.block[:], p)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (d *digest) Sum(sum []byte) []byte {
|
||||
var hash [Size]byte
|
||||
d.finalize(&hash)
|
||||
return append(sum, hash[:d.size]...)
|
||||
}
|
||||
|
||||
func (d *digest) finalize(hash *[Size]byte) {
|
||||
var block [BlockSize]byte
|
||||
copy(block[:], d.block[:d.offset])
|
||||
remaining := uint64(BlockSize - d.offset)
|
||||
|
||||
c := d.c
|
||||
if c[0] < remaining {
|
||||
c[1]--
|
||||
}
|
||||
c[0] -= remaining
|
||||
|
||||
h := d.h
|
||||
hashBlocks(&h, &c, 0xFFFFFFFFFFFFFFFF, block[:])
|
||||
|
||||
for i, v := range h {
|
||||
binary.LittleEndian.PutUint64(hash[8*i:], v)
|
||||
}
|
||||
}
|
||||
|
||||
func appendUint64(b []byte, x uint64) []byte {
|
||||
var a [8]byte
|
||||
binary.BigEndian.PutUint64(a[:], x)
|
||||
return append(b, a[:]...)
|
||||
}
|
||||
|
||||
func appendUint32(b []byte, x uint32) []byte {
|
||||
var a [4]byte
|
||||
binary.BigEndian.PutUint32(a[:], x)
|
||||
return append(b, a[:]...)
|
||||
}
|
||||
|
||||
func consumeUint64(b []byte) ([]byte, uint64) {
|
||||
x := binary.BigEndian.Uint64(b)
|
||||
return b[8:], x
|
||||
}
|
||||
|
||||
func consumeUint32(b []byte) ([]byte, uint32) {
|
||||
x := binary.BigEndian.Uint32(b)
|
||||
return b[4:], x
|
||||
}
|
||||
37
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
generated
vendored
Normal file
37
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
//go:build amd64 && gc && !purego
|
||||
|
||||
package blake2b
|
||||
|
||||
import "golang.org/x/sys/cpu"
|
||||
|
||||
func init() {
|
||||
useAVX2 = cpu.X86.HasAVX2
|
||||
useAVX = cpu.X86.HasAVX
|
||||
useSSE4 = cpu.X86.HasSSE41
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func hashBlocksAVX2(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
|
||||
|
||||
//go:noescape
|
||||
func hashBlocksAVX(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
|
||||
|
||||
//go:noescape
|
||||
func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
|
||||
|
||||
func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
|
||||
switch {
|
||||
case useAVX2:
|
||||
hashBlocksAVX2(h, c, flag, blocks)
|
||||
case useAVX:
|
||||
hashBlocksAVX(h, c, flag, blocks)
|
||||
case useSSE4:
|
||||
hashBlocksSSE4(h, c, flag, blocks)
|
||||
default:
|
||||
hashBlocksGeneric(h, c, flag, blocks)
|
||||
}
|
||||
}
|
||||
4559
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
generated
vendored
Normal file
4559
vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1441
vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s
generated
vendored
Normal file
1441
vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
182
vendor/golang.org/x/crypto/blake2b/blake2b_generic.go
generated
vendored
Normal file
182
vendor/golang.org/x/crypto/blake2b/blake2b_generic.go
generated
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
// Copyright 2016 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 blake2b
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// the precomputed values for BLAKE2b
|
||||
// there are 12 16-byte arrays - one for each round
|
||||
// the entries are calculated from the sigma constants.
|
||||
var precomputed = [12][16]byte{
|
||||
{0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15},
|
||||
{14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3},
|
||||
{11, 12, 5, 15, 8, 0, 2, 13, 10, 3, 7, 9, 14, 6, 1, 4},
|
||||
{7, 3, 13, 11, 9, 1, 12, 14, 2, 5, 4, 15, 6, 10, 0, 8},
|
||||
{9, 5, 2, 10, 0, 7, 4, 15, 14, 11, 6, 3, 1, 12, 8, 13},
|
||||
{2, 6, 0, 8, 12, 10, 11, 3, 4, 7, 15, 1, 13, 5, 14, 9},
|
||||
{12, 1, 14, 4, 5, 15, 13, 10, 0, 6, 9, 8, 7, 3, 2, 11},
|
||||
{13, 7, 12, 3, 11, 14, 1, 9, 5, 15, 8, 2, 0, 4, 6, 10},
|
||||
{6, 14, 11, 0, 15, 9, 3, 8, 12, 13, 1, 10, 2, 7, 4, 5},
|
||||
{10, 8, 7, 1, 2, 4, 6, 5, 15, 9, 3, 13, 11, 14, 12, 0},
|
||||
{0, 2, 4, 6, 1, 3, 5, 7, 8, 10, 12, 14, 9, 11, 13, 15}, // equal to the first
|
||||
{14, 4, 9, 13, 10, 8, 15, 6, 1, 0, 11, 5, 12, 2, 7, 3}, // equal to the second
|
||||
}
|
||||
|
||||
func hashBlocksGeneric(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
|
||||
var m [16]uint64
|
||||
c0, c1 := c[0], c[1]
|
||||
|
||||
for i := 0; i < len(blocks); {
|
||||
c0 += BlockSize
|
||||
if c0 < BlockSize {
|
||||
c1++
|
||||
}
|
||||
|
||||
v0, v1, v2, v3, v4, v5, v6, v7 := h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]
|
||||
v8, v9, v10, v11, v12, v13, v14, v15 := iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7]
|
||||
v12 ^= c0
|
||||
v13 ^= c1
|
||||
v14 ^= flag
|
||||
|
||||
for j := range m {
|
||||
m[j] = binary.LittleEndian.Uint64(blocks[i:])
|
||||
i += 8
|
||||
}
|
||||
|
||||
for j := range precomputed {
|
||||
s := &(precomputed[j])
|
||||
|
||||
v0 += m[s[0]]
|
||||
v0 += v4
|
||||
v12 ^= v0
|
||||
v12 = bits.RotateLeft64(v12, -32)
|
||||
v8 += v12
|
||||
v4 ^= v8
|
||||
v4 = bits.RotateLeft64(v4, -24)
|
||||
v1 += m[s[1]]
|
||||
v1 += v5
|
||||
v13 ^= v1
|
||||
v13 = bits.RotateLeft64(v13, -32)
|
||||
v9 += v13
|
||||
v5 ^= v9
|
||||
v5 = bits.RotateLeft64(v5, -24)
|
||||
v2 += m[s[2]]
|
||||
v2 += v6
|
||||
v14 ^= v2
|
||||
v14 = bits.RotateLeft64(v14, -32)
|
||||
v10 += v14
|
||||
v6 ^= v10
|
||||
v6 = bits.RotateLeft64(v6, -24)
|
||||
v3 += m[s[3]]
|
||||
v3 += v7
|
||||
v15 ^= v3
|
||||
v15 = bits.RotateLeft64(v15, -32)
|
||||
v11 += v15
|
||||
v7 ^= v11
|
||||
v7 = bits.RotateLeft64(v7, -24)
|
||||
|
||||
v0 += m[s[4]]
|
||||
v0 += v4
|
||||
v12 ^= v0
|
||||
v12 = bits.RotateLeft64(v12, -16)
|
||||
v8 += v12
|
||||
v4 ^= v8
|
||||
v4 = bits.RotateLeft64(v4, -63)
|
||||
v1 += m[s[5]]
|
||||
v1 += v5
|
||||
v13 ^= v1
|
||||
v13 = bits.RotateLeft64(v13, -16)
|
||||
v9 += v13
|
||||
v5 ^= v9
|
||||
v5 = bits.RotateLeft64(v5, -63)
|
||||
v2 += m[s[6]]
|
||||
v2 += v6
|
||||
v14 ^= v2
|
||||
v14 = bits.RotateLeft64(v14, -16)
|
||||
v10 += v14
|
||||
v6 ^= v10
|
||||
v6 = bits.RotateLeft64(v6, -63)
|
||||
v3 += m[s[7]]
|
||||
v3 += v7
|
||||
v15 ^= v3
|
||||
v15 = bits.RotateLeft64(v15, -16)
|
||||
v11 += v15
|
||||
v7 ^= v11
|
||||
v7 = bits.RotateLeft64(v7, -63)
|
||||
|
||||
v0 += m[s[8]]
|
||||
v0 += v5
|
||||
v15 ^= v0
|
||||
v15 = bits.RotateLeft64(v15, -32)
|
||||
v10 += v15
|
||||
v5 ^= v10
|
||||
v5 = bits.RotateLeft64(v5, -24)
|
||||
v1 += m[s[9]]
|
||||
v1 += v6
|
||||
v12 ^= v1
|
||||
v12 = bits.RotateLeft64(v12, -32)
|
||||
v11 += v12
|
||||
v6 ^= v11
|
||||
v6 = bits.RotateLeft64(v6, -24)
|
||||
v2 += m[s[10]]
|
||||
v2 += v7
|
||||
v13 ^= v2
|
||||
v13 = bits.RotateLeft64(v13, -32)
|
||||
v8 += v13
|
||||
v7 ^= v8
|
||||
v7 = bits.RotateLeft64(v7, -24)
|
||||
v3 += m[s[11]]
|
||||
v3 += v4
|
||||
v14 ^= v3
|
||||
v14 = bits.RotateLeft64(v14, -32)
|
||||
v9 += v14
|
||||
v4 ^= v9
|
||||
v4 = bits.RotateLeft64(v4, -24)
|
||||
|
||||
v0 += m[s[12]]
|
||||
v0 += v5
|
||||
v15 ^= v0
|
||||
v15 = bits.RotateLeft64(v15, -16)
|
||||
v10 += v15
|
||||
v5 ^= v10
|
||||
v5 = bits.RotateLeft64(v5, -63)
|
||||
v1 += m[s[13]]
|
||||
v1 += v6
|
||||
v12 ^= v1
|
||||
v12 = bits.RotateLeft64(v12, -16)
|
||||
v11 += v12
|
||||
v6 ^= v11
|
||||
v6 = bits.RotateLeft64(v6, -63)
|
||||
v2 += m[s[14]]
|
||||
v2 += v7
|
||||
v13 ^= v2
|
||||
v13 = bits.RotateLeft64(v13, -16)
|
||||
v8 += v13
|
||||
v7 ^= v8
|
||||
v7 = bits.RotateLeft64(v7, -63)
|
||||
v3 += m[s[15]]
|
||||
v3 += v4
|
||||
v14 ^= v3
|
||||
v14 = bits.RotateLeft64(v14, -16)
|
||||
v9 += v14
|
||||
v4 ^= v9
|
||||
v4 = bits.RotateLeft64(v4, -63)
|
||||
|
||||
}
|
||||
|
||||
h[0] ^= v0 ^ v8
|
||||
h[1] ^= v1 ^ v9
|
||||
h[2] ^= v2 ^ v10
|
||||
h[3] ^= v3 ^ v11
|
||||
h[4] ^= v4 ^ v12
|
||||
h[5] ^= v5 ^ v13
|
||||
h[6] ^= v6 ^ v14
|
||||
h[7] ^= v7 ^ v15
|
||||
}
|
||||
c[0], c[1] = c0, c1
|
||||
}
|
||||
11
vendor/golang.org/x/crypto/blake2b/blake2b_ref.go
generated
vendored
Normal file
11
vendor/golang.org/x/crypto/blake2b/blake2b_ref.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
//go:build !amd64 || purego || !gc
|
||||
|
||||
package blake2b
|
||||
|
||||
func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
|
||||
hashBlocksGeneric(h, c, flag, blocks)
|
||||
}
|
||||
185
vendor/golang.org/x/crypto/blake2b/blake2x.go
generated
vendored
Normal file
185
vendor/golang.org/x/crypto/blake2b/blake2x.go
generated
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
// Copyright 2017 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 blake2b
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
// XOF defines the interface to hash functions that
|
||||
// support arbitrary-length output.
|
||||
//
|
||||
// New callers should prefer the standard library [hash.XOF].
|
||||
type XOF interface {
|
||||
// Write absorbs more data into the hash's state. It panics if called
|
||||
// after Read.
|
||||
io.Writer
|
||||
|
||||
// Read reads more output from the hash. It returns io.EOF if the limit
|
||||
// has been reached.
|
||||
io.Reader
|
||||
|
||||
// Clone returns a copy of the XOF in its current state.
|
||||
Clone() XOF
|
||||
|
||||
// Reset resets the XOF to its initial state.
|
||||
Reset()
|
||||
}
|
||||
|
||||
// OutputLengthUnknown can be used as the size argument to NewXOF to indicate
|
||||
// the length of the output is not known in advance.
|
||||
const OutputLengthUnknown = 0
|
||||
|
||||
// magicUnknownOutputLength is a magic value for the output size that indicates
|
||||
// an unknown number of output bytes.
|
||||
const magicUnknownOutputLength = (1 << 32) - 1
|
||||
|
||||
// maxOutputLength is the absolute maximum number of bytes to produce when the
|
||||
// number of output bytes is unknown.
|
||||
const maxOutputLength = (1 << 32) * 64
|
||||
|
||||
// NewXOF creates a new variable-output-length hash. The hash either produce a
|
||||
// known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes
|
||||
// (size == OutputLengthUnknown). In the latter case, an absolute limit of
|
||||
// 256GiB applies.
|
||||
//
|
||||
// A non-nil key turns the hash into a MAC. The key must between
|
||||
// zero and 32 bytes long.
|
||||
//
|
||||
// The result can be safely interface-upgraded to [hash.XOF].
|
||||
func NewXOF(size uint32, key []byte) (XOF, error) {
|
||||
if len(key) > Size {
|
||||
return nil, errKeySize
|
||||
}
|
||||
if size == magicUnknownOutputLength {
|
||||
// 2^32-1 indicates an unknown number of bytes and thus isn't a
|
||||
// valid length.
|
||||
return nil, errors.New("blake2b: XOF length too large")
|
||||
}
|
||||
if size == OutputLengthUnknown {
|
||||
size = magicUnknownOutputLength
|
||||
}
|
||||
x := &xof{
|
||||
d: digest{
|
||||
size: Size,
|
||||
keyLen: len(key),
|
||||
},
|
||||
length: size,
|
||||
}
|
||||
copy(x.d.key[:], key)
|
||||
x.Reset()
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type xof struct {
|
||||
d digest
|
||||
length uint32
|
||||
remaining uint64
|
||||
cfg, root, block [Size]byte
|
||||
offset int
|
||||
nodeOffset uint32
|
||||
readMode bool
|
||||
}
|
||||
|
||||
func (x *xof) Write(p []byte) (n int, err error) {
|
||||
if x.readMode {
|
||||
panic("blake2b: write to XOF after read")
|
||||
}
|
||||
return x.d.Write(p)
|
||||
}
|
||||
|
||||
func (x *xof) Clone() XOF {
|
||||
clone := *x
|
||||
return &clone
|
||||
}
|
||||
|
||||
func (x *xof) BlockSize() int {
|
||||
return x.d.BlockSize()
|
||||
}
|
||||
|
||||
func (x *xof) Reset() {
|
||||
x.cfg[0] = byte(Size)
|
||||
binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length
|
||||
binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length
|
||||
x.cfg[17] = byte(Size) // inner hash size
|
||||
|
||||
x.d.Reset()
|
||||
x.d.h[1] ^= uint64(x.length) << 32
|
||||
|
||||
x.remaining = uint64(x.length)
|
||||
if x.remaining == magicUnknownOutputLength {
|
||||
x.remaining = maxOutputLength
|
||||
}
|
||||
x.offset, x.nodeOffset = 0, 0
|
||||
x.readMode = false
|
||||
}
|
||||
|
||||
func (x *xof) Read(p []byte) (n int, err error) {
|
||||
if !x.readMode {
|
||||
x.d.finalize(&x.root)
|
||||
x.readMode = true
|
||||
}
|
||||
|
||||
if x.remaining == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
n = len(p)
|
||||
if uint64(n) > x.remaining {
|
||||
n = int(x.remaining)
|
||||
p = p[:n]
|
||||
}
|
||||
|
||||
if x.offset > 0 {
|
||||
blockRemaining := Size - x.offset
|
||||
if n < blockRemaining {
|
||||
x.offset += copy(p, x.block[x.offset:])
|
||||
x.remaining -= uint64(n)
|
||||
return
|
||||
}
|
||||
copy(p, x.block[x.offset:])
|
||||
p = p[blockRemaining:]
|
||||
x.offset = 0
|
||||
x.remaining -= uint64(blockRemaining)
|
||||
}
|
||||
|
||||
for len(p) >= Size {
|
||||
binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset)
|
||||
x.nodeOffset++
|
||||
|
||||
x.d.initConfig(&x.cfg)
|
||||
x.d.Write(x.root[:])
|
||||
x.d.finalize(&x.block)
|
||||
|
||||
copy(p, x.block[:])
|
||||
p = p[Size:]
|
||||
x.remaining -= uint64(Size)
|
||||
}
|
||||
|
||||
if todo := len(p); todo > 0 {
|
||||
if x.remaining < uint64(Size) {
|
||||
x.cfg[0] = byte(x.remaining)
|
||||
}
|
||||
binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset)
|
||||
x.nodeOffset++
|
||||
|
||||
x.d.initConfig(&x.cfg)
|
||||
x.d.Write(x.root[:])
|
||||
x.d.finalize(&x.block)
|
||||
|
||||
x.offset = copy(p, x.block[:todo])
|
||||
x.remaining -= uint64(todo)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *digest) initConfig(cfg *[Size]byte) {
|
||||
d.offset, d.c[0], d.c[1] = 0, 0, 0
|
||||
for i := range d.h {
|
||||
d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:])
|
||||
}
|
||||
}
|
||||
11
vendor/golang.org/x/crypto/blake2b/go125.go
generated
vendored
Normal file
11
vendor/golang.org/x/crypto/blake2b/go125.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2025 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.
|
||||
|
||||
//go:build go1.25
|
||||
|
||||
package blake2b
|
||||
|
||||
import "hash"
|
||||
|
||||
var _ hash.XOF = (*xof)(nil)
|
||||
30
vendor/golang.org/x/crypto/blake2b/register.go
generated
vendored
Normal file
30
vendor/golang.org/x/crypto/blake2b/register.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2017 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 blake2b
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"hash"
|
||||
)
|
||||
|
||||
func init() {
|
||||
newHash256 := func() hash.Hash {
|
||||
h, _ := New256(nil)
|
||||
return h
|
||||
}
|
||||
newHash384 := func() hash.Hash {
|
||||
h, _ := New384(nil)
|
||||
return h
|
||||
}
|
||||
|
||||
newHash512 := func() hash.Hash {
|
||||
h, _ := New512(nil)
|
||||
return h
|
||||
}
|
||||
|
||||
crypto.RegisterHash(crypto.BLAKE2b_256, newHash256)
|
||||
crypto.RegisterHash(crypto.BLAKE2b_384, newHash384)
|
||||
crypto.RegisterHash(crypto.BLAKE2b_512, newHash512)
|
||||
}
|
||||
793
vendor/golang.org/x/crypto/ocsp/ocsp.go
generated
vendored
Normal file
793
vendor/golang.org/x/crypto/ocsp/ocsp.go
generated
vendored
Normal file
@@ -0,0 +1,793 @@
|
||||
// Copyright 2013 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 ocsp parses OCSP responses as specified in RFC 2560. OCSP responses
|
||||
// are signed messages attesting to the validity of a certificate for a small
|
||||
// period of time. This is used to manage revocation for X.509 certificates.
|
||||
package ocsp
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
_ "crypto/sha1"
|
||||
_ "crypto/sha256"
|
||||
_ "crypto/sha512"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
var idPKIXOCSPBasic = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 5, 5, 7, 48, 1, 1})
|
||||
|
||||
// ResponseStatus contains the result of an OCSP request. See
|
||||
// https://tools.ietf.org/html/rfc6960#section-2.3
|
||||
type ResponseStatus int
|
||||
|
||||
const (
|
||||
Success ResponseStatus = 0
|
||||
Malformed ResponseStatus = 1
|
||||
InternalError ResponseStatus = 2
|
||||
TryLater ResponseStatus = 3
|
||||
// Status code four is unused in OCSP. See
|
||||
// https://tools.ietf.org/html/rfc6960#section-4.2.1
|
||||
SignatureRequired ResponseStatus = 5
|
||||
Unauthorized ResponseStatus = 6
|
||||
)
|
||||
|
||||
func (r ResponseStatus) String() string {
|
||||
switch r {
|
||||
case Success:
|
||||
return "success"
|
||||
case Malformed:
|
||||
return "malformed"
|
||||
case InternalError:
|
||||
return "internal error"
|
||||
case TryLater:
|
||||
return "try later"
|
||||
case SignatureRequired:
|
||||
return "signature required"
|
||||
case Unauthorized:
|
||||
return "unauthorized"
|
||||
default:
|
||||
return "unknown OCSP status: " + strconv.Itoa(int(r))
|
||||
}
|
||||
}
|
||||
|
||||
// ResponseError is an error that may be returned by ParseResponse to indicate
|
||||
// that the response itself is an error, not just that it's indicating that a
|
||||
// certificate is revoked, unknown, etc.
|
||||
type ResponseError struct {
|
||||
Status ResponseStatus
|
||||
}
|
||||
|
||||
func (r ResponseError) Error() string {
|
||||
return "ocsp: error from server: " + r.Status.String()
|
||||
}
|
||||
|
||||
// These are internal structures that reflect the ASN.1 structure of an OCSP
|
||||
// response. See RFC 2560, section 4.2.
|
||||
|
||||
type certID struct {
|
||||
HashAlgorithm pkix.AlgorithmIdentifier
|
||||
NameHash []byte
|
||||
IssuerKeyHash []byte
|
||||
SerialNumber *big.Int
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc2560#section-4.1.1
|
||||
type ocspRequest struct {
|
||||
TBSRequest tbsRequest
|
||||
}
|
||||
|
||||
type tbsRequest struct {
|
||||
Version int `asn1:"explicit,tag:0,default:0,optional"`
|
||||
RequestorName pkix.RDNSequence `asn1:"explicit,tag:1,optional"`
|
||||
RequestList []request
|
||||
}
|
||||
|
||||
type request struct {
|
||||
Cert certID
|
||||
}
|
||||
|
||||
type responseASN1 struct {
|
||||
Status asn1.Enumerated
|
||||
Response responseBytes `asn1:"explicit,tag:0,optional"`
|
||||
}
|
||||
|
||||
type responseBytes struct {
|
||||
ResponseType asn1.ObjectIdentifier
|
||||
Response []byte
|
||||
}
|
||||
|
||||
type basicResponse struct {
|
||||
TBSResponseData responseData
|
||||
SignatureAlgorithm pkix.AlgorithmIdentifier
|
||||
Signature asn1.BitString
|
||||
Certificates []asn1.RawValue `asn1:"explicit,tag:0,optional"`
|
||||
}
|
||||
|
||||
type responseData struct {
|
||||
Raw asn1.RawContent
|
||||
Version int `asn1:"optional,default:0,explicit,tag:0"`
|
||||
RawResponderID asn1.RawValue
|
||||
ProducedAt time.Time `asn1:"generalized"`
|
||||
Responses []singleResponse
|
||||
}
|
||||
|
||||
type singleResponse struct {
|
||||
CertID certID
|
||||
Good asn1.Flag `asn1:"tag:0,optional"`
|
||||
Revoked revokedInfo `asn1:"tag:1,optional"`
|
||||
Unknown asn1.Flag `asn1:"tag:2,optional"`
|
||||
ThisUpdate time.Time `asn1:"generalized"`
|
||||
NextUpdate time.Time `asn1:"generalized,explicit,tag:0,optional"`
|
||||
SingleExtensions []pkix.Extension `asn1:"explicit,tag:1,optional"`
|
||||
}
|
||||
|
||||
type revokedInfo struct {
|
||||
RevocationTime time.Time `asn1:"generalized"`
|
||||
Reason asn1.Enumerated `asn1:"explicit,tag:0,optional"`
|
||||
}
|
||||
|
||||
var (
|
||||
oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
|
||||
oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
|
||||
oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
|
||||
oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
|
||||
oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
|
||||
oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
|
||||
oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
|
||||
oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2}
|
||||
oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
|
||||
oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
|
||||
oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
|
||||
oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
|
||||
)
|
||||
|
||||
var hashOIDs = map[crypto.Hash]asn1.ObjectIdentifier{
|
||||
crypto.SHA1: asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26}),
|
||||
crypto.SHA256: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 1}),
|
||||
crypto.SHA384: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 2}),
|
||||
crypto.SHA512: asn1.ObjectIdentifier([]int{2, 16, 840, 1, 101, 3, 4, 2, 3}),
|
||||
}
|
||||
|
||||
// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below
|
||||
var signatureAlgorithmDetails = []struct {
|
||||
algo x509.SignatureAlgorithm
|
||||
oid asn1.ObjectIdentifier
|
||||
pubKeyAlgo x509.PublicKeyAlgorithm
|
||||
hash crypto.Hash
|
||||
}{
|
||||
{x509.MD2WithRSA, oidSignatureMD2WithRSA, x509.RSA, crypto.Hash(0) /* no value for MD2 */},
|
||||
{x509.MD5WithRSA, oidSignatureMD5WithRSA, x509.RSA, crypto.MD5},
|
||||
{x509.SHA1WithRSA, oidSignatureSHA1WithRSA, x509.RSA, crypto.SHA1},
|
||||
{x509.SHA256WithRSA, oidSignatureSHA256WithRSA, x509.RSA, crypto.SHA256},
|
||||
{x509.SHA384WithRSA, oidSignatureSHA384WithRSA, x509.RSA, crypto.SHA384},
|
||||
{x509.SHA512WithRSA, oidSignatureSHA512WithRSA, x509.RSA, crypto.SHA512},
|
||||
{x509.DSAWithSHA1, oidSignatureDSAWithSHA1, x509.DSA, crypto.SHA1},
|
||||
{x509.DSAWithSHA256, oidSignatureDSAWithSHA256, x509.DSA, crypto.SHA256},
|
||||
{x509.ECDSAWithSHA1, oidSignatureECDSAWithSHA1, x509.ECDSA, crypto.SHA1},
|
||||
{x509.ECDSAWithSHA256, oidSignatureECDSAWithSHA256, x509.ECDSA, crypto.SHA256},
|
||||
{x509.ECDSAWithSHA384, oidSignatureECDSAWithSHA384, x509.ECDSA, crypto.SHA384},
|
||||
{x509.ECDSAWithSHA512, oidSignatureECDSAWithSHA512, x509.ECDSA, crypto.SHA512},
|
||||
}
|
||||
|
||||
// TODO(rlb): This is also from crypto/x509, so same comment as AGL's below
|
||||
func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
|
||||
var pubType x509.PublicKeyAlgorithm
|
||||
|
||||
switch pub := pub.(type) {
|
||||
case *rsa.PublicKey:
|
||||
pubType = x509.RSA
|
||||
hashFunc = crypto.SHA256
|
||||
sigAlgo.Algorithm = oidSignatureSHA256WithRSA
|
||||
sigAlgo.Parameters = asn1.RawValue{
|
||||
Tag: 5,
|
||||
}
|
||||
|
||||
case *ecdsa.PublicKey:
|
||||
pubType = x509.ECDSA
|
||||
|
||||
switch pub.Curve {
|
||||
case elliptic.P224(), elliptic.P256():
|
||||
hashFunc = crypto.SHA256
|
||||
sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
|
||||
case elliptic.P384():
|
||||
hashFunc = crypto.SHA384
|
||||
sigAlgo.Algorithm = oidSignatureECDSAWithSHA384
|
||||
case elliptic.P521():
|
||||
hashFunc = crypto.SHA512
|
||||
sigAlgo.Algorithm = oidSignatureECDSAWithSHA512
|
||||
default:
|
||||
err = errors.New("x509: unknown elliptic curve")
|
||||
}
|
||||
|
||||
default:
|
||||
err = errors.New("x509: only RSA and ECDSA keys supported")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if requestedSigAlgo == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, details := range signatureAlgorithmDetails {
|
||||
if details.algo == requestedSigAlgo {
|
||||
if details.pubKeyAlgo != pubType {
|
||||
err = errors.New("x509: requested SignatureAlgorithm does not match private key type")
|
||||
return
|
||||
}
|
||||
sigAlgo.Algorithm, hashFunc = details.oid, details.hash
|
||||
if hashFunc == 0 {
|
||||
err = errors.New("x509: cannot sign with hash function requested")
|
||||
return
|
||||
}
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
err = errors.New("x509: unknown SignatureAlgorithm")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(agl): this is taken from crypto/x509 and so should probably be exported
|
||||
// from crypto/x509 or crypto/x509/pkix.
|
||||
func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) x509.SignatureAlgorithm {
|
||||
for _, details := range signatureAlgorithmDetails {
|
||||
if oid.Equal(details.oid) {
|
||||
return details.algo
|
||||
}
|
||||
}
|
||||
return x509.UnknownSignatureAlgorithm
|
||||
}
|
||||
|
||||
// TODO(rlb): This is not taken from crypto/x509, but it's of the same general form.
|
||||
func getHashAlgorithmFromOID(target asn1.ObjectIdentifier) crypto.Hash {
|
||||
for hash, oid := range hashOIDs {
|
||||
if oid.Equal(target) {
|
||||
return hash
|
||||
}
|
||||
}
|
||||
return crypto.Hash(0)
|
||||
}
|
||||
|
||||
func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier {
|
||||
for hash, oid := range hashOIDs {
|
||||
if hash == target {
|
||||
return oid
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This is the exposed reflection of the internal OCSP structures.
|
||||
|
||||
// The status values that can be expressed in OCSP. See RFC 6960.
|
||||
// These are used for the Response.Status field.
|
||||
const (
|
||||
// Good means that the certificate is valid.
|
||||
Good = 0
|
||||
// Revoked means that the certificate has been deliberately revoked.
|
||||
Revoked = 1
|
||||
// Unknown means that the OCSP responder doesn't know about the certificate.
|
||||
Unknown = 2
|
||||
// ServerFailed is unused and was never used (see
|
||||
// https://go-review.googlesource.com/#/c/18944). ParseResponse will
|
||||
// return a ResponseError when an error response is parsed.
|
||||
ServerFailed = 3
|
||||
)
|
||||
|
||||
// The enumerated reasons for revoking a certificate. See RFC 5280.
|
||||
const (
|
||||
Unspecified = 0
|
||||
KeyCompromise = 1
|
||||
CACompromise = 2
|
||||
AffiliationChanged = 3
|
||||
Superseded = 4
|
||||
CessationOfOperation = 5
|
||||
CertificateHold = 6
|
||||
|
||||
RemoveFromCRL = 8
|
||||
PrivilegeWithdrawn = 9
|
||||
AACompromise = 10
|
||||
)
|
||||
|
||||
// Request represents an OCSP request. See RFC 6960.
|
||||
type Request struct {
|
||||
HashAlgorithm crypto.Hash
|
||||
IssuerNameHash []byte
|
||||
IssuerKeyHash []byte
|
||||
SerialNumber *big.Int
|
||||
}
|
||||
|
||||
// Marshal marshals the OCSP request to ASN.1 DER encoded form.
|
||||
func (req *Request) Marshal() ([]byte, error) {
|
||||
hashAlg := getOIDFromHashAlgorithm(req.HashAlgorithm)
|
||||
if hashAlg == nil {
|
||||
return nil, errors.New("Unknown hash algorithm")
|
||||
}
|
||||
return asn1.Marshal(ocspRequest{
|
||||
tbsRequest{
|
||||
Version: 0,
|
||||
RequestList: []request{
|
||||
{
|
||||
Cert: certID{
|
||||
pkix.AlgorithmIdentifier{
|
||||
Algorithm: hashAlg,
|
||||
Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
|
||||
},
|
||||
req.IssuerNameHash,
|
||||
req.IssuerKeyHash,
|
||||
req.SerialNumber,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Response represents an OCSP response containing a single SingleResponse. See
|
||||
// RFC 6960.
|
||||
type Response struct {
|
||||
Raw []byte
|
||||
|
||||
// Status is one of {Good, Revoked, Unknown}
|
||||
Status int
|
||||
SerialNumber *big.Int
|
||||
ProducedAt, ThisUpdate, NextUpdate, RevokedAt time.Time
|
||||
RevocationReason int
|
||||
Certificate *x509.Certificate
|
||||
// TBSResponseData contains the raw bytes of the signed response. If
|
||||
// Certificate is nil then this can be used to verify Signature.
|
||||
TBSResponseData []byte
|
||||
Signature []byte
|
||||
SignatureAlgorithm x509.SignatureAlgorithm
|
||||
|
||||
// IssuerHash is the hash used to compute the IssuerNameHash and IssuerKeyHash.
|
||||
// Valid values are crypto.SHA1, crypto.SHA256, crypto.SHA384, and crypto.SHA512.
|
||||
// If zero, the default is crypto.SHA1.
|
||||
IssuerHash crypto.Hash
|
||||
|
||||
// RawResponderName optionally contains the DER-encoded subject of the
|
||||
// responder certificate. Exactly one of RawResponderName and
|
||||
// ResponderKeyHash is set.
|
||||
RawResponderName []byte
|
||||
// ResponderKeyHash optionally contains the SHA-1 hash of the
|
||||
// responder's public key. Exactly one of RawResponderName and
|
||||
// ResponderKeyHash is set.
|
||||
ResponderKeyHash []byte
|
||||
|
||||
// Extensions contains raw X.509 extensions from the singleExtensions field
|
||||
// of the OCSP response. When parsing certificates, this can be used to
|
||||
// extract non-critical extensions that are not parsed by this package. When
|
||||
// marshaling OCSP responses, the Extensions field is ignored, see
|
||||
// ExtraExtensions.
|
||||
Extensions []pkix.Extension
|
||||
|
||||
// ExtraExtensions contains extensions to be copied, raw, into any marshaled
|
||||
// OCSP response (in the singleExtensions field). Values override any
|
||||
// extensions that would otherwise be produced based on the other fields. The
|
||||
// ExtraExtensions field is not populated when parsing certificates, see
|
||||
// Extensions.
|
||||
ExtraExtensions []pkix.Extension
|
||||
}
|
||||
|
||||
// These are pre-serialized error responses for the various non-success codes
|
||||
// defined by OCSP. The Unauthorized code in particular can be used by an OCSP
|
||||
// responder that supports only pre-signed responses as a response to requests
|
||||
// for certificates with unknown status. See RFC 5019.
|
||||
var (
|
||||
MalformedRequestErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x01}
|
||||
InternalErrorErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x02}
|
||||
TryLaterErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x03}
|
||||
SigRequredErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x05}
|
||||
UnauthorizedErrorResponse = []byte{0x30, 0x03, 0x0A, 0x01, 0x06}
|
||||
)
|
||||
|
||||
// CheckSignatureFrom checks that the signature in resp is a valid signature
|
||||
// from issuer. This should only be used if resp.Certificate is nil. Otherwise,
|
||||
// the OCSP response contained an intermediate certificate that created the
|
||||
// signature. That signature is checked by ParseResponse and only
|
||||
// resp.Certificate remains to be validated.
|
||||
func (resp *Response) CheckSignatureFrom(issuer *x509.Certificate) error {
|
||||
return issuer.CheckSignature(resp.SignatureAlgorithm, resp.TBSResponseData, resp.Signature)
|
||||
}
|
||||
|
||||
// ParseError results from an invalid OCSP response.
|
||||
type ParseError string
|
||||
|
||||
func (p ParseError) Error() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
// ParseRequest parses an OCSP request in DER form. It only supports
|
||||
// requests for a single certificate. Signed requests are not supported.
|
||||
// If a request includes a signature, it will result in a ParseError.
|
||||
func ParseRequest(bytes []byte) (*Request, error) {
|
||||
var req ocspRequest
|
||||
rest, err := asn1.Unmarshal(bytes, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(rest) > 0 {
|
||||
return nil, ParseError("trailing data in OCSP request")
|
||||
}
|
||||
|
||||
if len(req.TBSRequest.RequestList) == 0 {
|
||||
return nil, ParseError("OCSP request contains no request body")
|
||||
}
|
||||
innerRequest := req.TBSRequest.RequestList[0]
|
||||
|
||||
hashFunc := getHashAlgorithmFromOID(innerRequest.Cert.HashAlgorithm.Algorithm)
|
||||
if hashFunc == crypto.Hash(0) {
|
||||
return nil, ParseError("OCSP request uses unknown hash function")
|
||||
}
|
||||
|
||||
return &Request{
|
||||
HashAlgorithm: hashFunc,
|
||||
IssuerNameHash: innerRequest.Cert.NameHash,
|
||||
IssuerKeyHash: innerRequest.Cert.IssuerKeyHash,
|
||||
SerialNumber: innerRequest.Cert.SerialNumber,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ParseResponse parses an OCSP response in DER form. The response must contain
|
||||
// only one certificate status. To parse the status of a specific certificate
|
||||
// from a response which may contain multiple statuses, use ParseResponseForCert
|
||||
// instead.
|
||||
//
|
||||
// If the response contains an embedded certificate, then that certificate will
|
||||
// be used to verify the response signature. If the response contains an
|
||||
// embedded certificate and issuer is not nil, then issuer will be used to verify
|
||||
// the signature on the embedded certificate.
|
||||
//
|
||||
// If the response does not contain an embedded certificate and issuer is not
|
||||
// nil, then issuer will be used to verify the response signature.
|
||||
//
|
||||
// Invalid responses and parse failures will result in a ParseError.
|
||||
// Error responses will result in a ResponseError.
|
||||
func ParseResponse(bytes []byte, issuer *x509.Certificate) (*Response, error) {
|
||||
return ParseResponseForCert(bytes, nil, issuer)
|
||||
}
|
||||
|
||||
// ParseResponseForCert acts identically to ParseResponse, except it supports
|
||||
// parsing responses that contain multiple statuses. If the response contains
|
||||
// multiple statuses and cert is not nil, then ParseResponseForCert will return
|
||||
// the first status which contains a matching serial, otherwise it will return an
|
||||
// error. If cert is nil, then the first status in the response will be returned.
|
||||
func ParseResponseForCert(bytes []byte, cert, issuer *x509.Certificate) (*Response, error) {
|
||||
var resp responseASN1
|
||||
rest, err := asn1.Unmarshal(bytes, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(rest) > 0 {
|
||||
return nil, ParseError("trailing data in OCSP response")
|
||||
}
|
||||
|
||||
if status := ResponseStatus(resp.Status); status != Success {
|
||||
return nil, ResponseError{status}
|
||||
}
|
||||
|
||||
if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) {
|
||||
return nil, ParseError("bad OCSP response type")
|
||||
}
|
||||
|
||||
var basicResp basicResponse
|
||||
rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(rest) > 0 {
|
||||
return nil, ParseError("trailing data in OCSP response")
|
||||
}
|
||||
|
||||
if n := len(basicResp.TBSResponseData.Responses); n == 0 || cert == nil && n > 1 {
|
||||
return nil, ParseError("OCSP response contains bad number of responses")
|
||||
}
|
||||
|
||||
var singleResp singleResponse
|
||||
if cert == nil {
|
||||
singleResp = basicResp.TBSResponseData.Responses[0]
|
||||
} else {
|
||||
match := false
|
||||
for _, resp := range basicResp.TBSResponseData.Responses {
|
||||
if cert.SerialNumber.Cmp(resp.CertID.SerialNumber) == 0 {
|
||||
singleResp = resp
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
return nil, ParseError("no response matching the supplied certificate")
|
||||
}
|
||||
}
|
||||
|
||||
ret := &Response{
|
||||
Raw: bytes,
|
||||
TBSResponseData: basicResp.TBSResponseData.Raw,
|
||||
Signature: basicResp.Signature.RightAlign(),
|
||||
SignatureAlgorithm: getSignatureAlgorithmFromOID(basicResp.SignatureAlgorithm.Algorithm),
|
||||
Extensions: singleResp.SingleExtensions,
|
||||
SerialNumber: singleResp.CertID.SerialNumber,
|
||||
ProducedAt: basicResp.TBSResponseData.ProducedAt,
|
||||
ThisUpdate: singleResp.ThisUpdate,
|
||||
NextUpdate: singleResp.NextUpdate,
|
||||
}
|
||||
|
||||
// Handle the ResponderID CHOICE tag. ResponderID can be flattened into
|
||||
// TBSResponseData once https://go-review.googlesource.com/34503 has been
|
||||
// released.
|
||||
rawResponderID := basicResp.TBSResponseData.RawResponderID
|
||||
switch rawResponderID.Tag {
|
||||
case 1: // Name
|
||||
var rdn pkix.RDNSequence
|
||||
if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &rdn); err != nil || len(rest) != 0 {
|
||||
return nil, ParseError("invalid responder name")
|
||||
}
|
||||
ret.RawResponderName = rawResponderID.Bytes
|
||||
case 2: // KeyHash
|
||||
if rest, err := asn1.Unmarshal(rawResponderID.Bytes, &ret.ResponderKeyHash); err != nil || len(rest) != 0 {
|
||||
return nil, ParseError("invalid responder key hash")
|
||||
}
|
||||
default:
|
||||
return nil, ParseError("invalid responder id tag")
|
||||
}
|
||||
|
||||
if len(basicResp.Certificates) > 0 {
|
||||
// Responders should only send a single certificate (if they
|
||||
// send any) that connects the responder's certificate to the
|
||||
// original issuer. We accept responses with multiple
|
||||
// certificates due to a number responders sending them[1], but
|
||||
// ignore all but the first.
|
||||
//
|
||||
// [1] https://github.com/golang/go/issues/21527
|
||||
ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := ret.CheckSignatureFrom(ret.Certificate); err != nil {
|
||||
return nil, ParseError("bad signature on embedded certificate: " + err.Error())
|
||||
}
|
||||
|
||||
if issuer != nil {
|
||||
if err := issuer.CheckSignature(ret.Certificate.SignatureAlgorithm, ret.Certificate.RawTBSCertificate, ret.Certificate.Signature); err != nil {
|
||||
return nil, ParseError("bad OCSP signature: " + err.Error())
|
||||
}
|
||||
}
|
||||
} else if issuer != nil {
|
||||
if err := ret.CheckSignatureFrom(issuer); err != nil {
|
||||
return nil, ParseError("bad OCSP signature: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
for _, ext := range singleResp.SingleExtensions {
|
||||
if ext.Critical {
|
||||
return nil, ParseError("unsupported critical extension")
|
||||
}
|
||||
}
|
||||
|
||||
for h, oid := range hashOIDs {
|
||||
if singleResp.CertID.HashAlgorithm.Algorithm.Equal(oid) {
|
||||
ret.IssuerHash = h
|
||||
break
|
||||
}
|
||||
}
|
||||
if ret.IssuerHash == 0 {
|
||||
return nil, ParseError("unsupported issuer hash algorithm")
|
||||
}
|
||||
|
||||
switch {
|
||||
case bool(singleResp.Good):
|
||||
ret.Status = Good
|
||||
case bool(singleResp.Unknown):
|
||||
ret.Status = Unknown
|
||||
default:
|
||||
ret.Status = Revoked
|
||||
ret.RevokedAt = singleResp.Revoked.RevocationTime
|
||||
ret.RevocationReason = int(singleResp.Revoked.Reason)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// RequestOptions contains options for constructing OCSP requests.
|
||||
type RequestOptions struct {
|
||||
// Hash contains the hash function that should be used when
|
||||
// constructing the OCSP request. If zero, SHA-1 will be used.
|
||||
Hash crypto.Hash
|
||||
}
|
||||
|
||||
func (opts *RequestOptions) hash() crypto.Hash {
|
||||
if opts == nil || opts.Hash == 0 {
|
||||
// SHA-1 is nearly universally used in OCSP.
|
||||
return crypto.SHA1
|
||||
}
|
||||
return opts.Hash
|
||||
}
|
||||
|
||||
// CreateRequest returns a DER-encoded, OCSP request for the status of cert. If
|
||||
// opts is nil then sensible defaults are used.
|
||||
func CreateRequest(cert, issuer *x509.Certificate, opts *RequestOptions) ([]byte, error) {
|
||||
hashFunc := opts.hash()
|
||||
|
||||
// OCSP seems to be the only place where these raw hash identifiers are
|
||||
// used. I took the following from
|
||||
// http://msdn.microsoft.com/en-us/library/ff635603.aspx
|
||||
_, ok := hashOIDs[hashFunc]
|
||||
if !ok {
|
||||
return nil, x509.ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
if !hashFunc.Available() {
|
||||
return nil, x509.ErrUnsupportedAlgorithm
|
||||
}
|
||||
h := opts.hash().New()
|
||||
|
||||
var publicKeyInfo struct {
|
||||
Algorithm pkix.AlgorithmIdentifier
|
||||
PublicKey asn1.BitString
|
||||
}
|
||||
if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
h.Write(publicKeyInfo.PublicKey.RightAlign())
|
||||
issuerKeyHash := h.Sum(nil)
|
||||
|
||||
h.Reset()
|
||||
h.Write(issuer.RawSubject)
|
||||
issuerNameHash := h.Sum(nil)
|
||||
|
||||
req := &Request{
|
||||
HashAlgorithm: hashFunc,
|
||||
IssuerNameHash: issuerNameHash,
|
||||
IssuerKeyHash: issuerKeyHash,
|
||||
SerialNumber: cert.SerialNumber,
|
||||
}
|
||||
return req.Marshal()
|
||||
}
|
||||
|
||||
// CreateResponse returns a DER-encoded OCSP response with the specified contents.
|
||||
// The fields in the response are populated as follows:
|
||||
//
|
||||
// The responder cert is used to populate the responder's name field, and the
|
||||
// certificate itself is provided alongside the OCSP response signature.
|
||||
//
|
||||
// The issuer cert is used to populate the IssuerNameHash and IssuerKeyHash fields.
|
||||
//
|
||||
// The template is used to populate the SerialNumber, Status, RevokedAt,
|
||||
// RevocationReason, ThisUpdate, and NextUpdate fields.
|
||||
//
|
||||
// If template.IssuerHash is not set, SHA1 will be used.
|
||||
//
|
||||
// The ProducedAt date is automatically set to the current date, to the nearest minute.
|
||||
func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) {
|
||||
var publicKeyInfo struct {
|
||||
Algorithm pkix.AlgorithmIdentifier
|
||||
PublicKey asn1.BitString
|
||||
}
|
||||
if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if template.IssuerHash == 0 {
|
||||
template.IssuerHash = crypto.SHA1
|
||||
}
|
||||
hashOID := getOIDFromHashAlgorithm(template.IssuerHash)
|
||||
if hashOID == nil {
|
||||
return nil, errors.New("unsupported issuer hash algorithm")
|
||||
}
|
||||
|
||||
if !template.IssuerHash.Available() {
|
||||
return nil, fmt.Errorf("issuer hash algorithm %v not linked into binary", template.IssuerHash)
|
||||
}
|
||||
h := template.IssuerHash.New()
|
||||
h.Write(publicKeyInfo.PublicKey.RightAlign())
|
||||
issuerKeyHash := h.Sum(nil)
|
||||
|
||||
h.Reset()
|
||||
h.Write(issuer.RawSubject)
|
||||
issuerNameHash := h.Sum(nil)
|
||||
|
||||
innerResponse := singleResponse{
|
||||
CertID: certID{
|
||||
HashAlgorithm: pkix.AlgorithmIdentifier{
|
||||
Algorithm: hashOID,
|
||||
Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
|
||||
},
|
||||
NameHash: issuerNameHash,
|
||||
IssuerKeyHash: issuerKeyHash,
|
||||
SerialNumber: template.SerialNumber,
|
||||
},
|
||||
ThisUpdate: template.ThisUpdate.UTC(),
|
||||
NextUpdate: template.NextUpdate.UTC(),
|
||||
SingleExtensions: template.ExtraExtensions,
|
||||
}
|
||||
|
||||
switch template.Status {
|
||||
case Good:
|
||||
innerResponse.Good = true
|
||||
case Unknown:
|
||||
innerResponse.Unknown = true
|
||||
case Revoked:
|
||||
innerResponse.Revoked = revokedInfo{
|
||||
RevocationTime: template.RevokedAt.UTC(),
|
||||
Reason: asn1.Enumerated(template.RevocationReason),
|
||||
}
|
||||
}
|
||||
|
||||
rawResponderID := asn1.RawValue{
|
||||
Class: 2, // context-specific
|
||||
Tag: 1, // Name (explicit tag)
|
||||
IsCompound: true,
|
||||
Bytes: responderCert.RawSubject,
|
||||
}
|
||||
tbsResponseData := responseData{
|
||||
Version: 0,
|
||||
RawResponderID: rawResponderID,
|
||||
ProducedAt: time.Now().Truncate(time.Minute).UTC(),
|
||||
Responses: []singleResponse{innerResponse},
|
||||
}
|
||||
|
||||
tbsResponseDataDER, err := asn1.Marshal(tbsResponseData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
responseHash := hashFunc.New()
|
||||
responseHash.Write(tbsResponseDataDER)
|
||||
signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := basicResponse{
|
||||
TBSResponseData: tbsResponseData,
|
||||
SignatureAlgorithm: signatureAlgorithm,
|
||||
Signature: asn1.BitString{
|
||||
Bytes: signature,
|
||||
BitLength: 8 * len(signature),
|
||||
},
|
||||
}
|
||||
if template.Certificate != nil {
|
||||
response.Certificates = []asn1.RawValue{
|
||||
{FullBytes: template.Certificate.Raw},
|
||||
}
|
||||
}
|
||||
responseDER, err := asn1.Marshal(response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return asn1.Marshal(responseASN1{
|
||||
Status: asn1.Enumerated(Success),
|
||||
Response: responseBytes{
|
||||
ResponseType: idPKIXOCSPBasic,
|
||||
Response: responseDER,
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user