mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
vendor: update buildkit to master@31c870e82a48
Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
21
vendor/github.com/secure-systems-lab/go-securesystemslib/LICENSE
generated
vendored
Normal file
21
vendor/github.com/secure-systems-lab/go-securesystemslib/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 NYU Secure Systems Lab
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
145
vendor/github.com/secure-systems-lab/go-securesystemslib/cjson/canonicaljson.go
generated
vendored
Normal file
145
vendor/github.com/secure-systems-lab/go-securesystemslib/cjson/canonicaljson.go
generated
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
package cjson
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
)
|
||||
|
||||
/*
|
||||
encodeCanonicalString is a helper function to canonicalize the passed string
|
||||
according to the OLPC canonical JSON specification for strings (see
|
||||
http://wiki.laptop.org/go/Canonical_JSON). String canonicalization consists of
|
||||
escaping backslashes ("\") and double quotes (") and wrapping the resulting
|
||||
string in double quotes (").
|
||||
*/
|
||||
func encodeCanonicalString(s string) string {
|
||||
re := regexp.MustCompile(`([\"\\])`)
|
||||
return fmt.Sprintf("\"%s\"", re.ReplaceAllString(s, "\\$1"))
|
||||
}
|
||||
|
||||
/*
|
||||
encodeCanonical is a helper function to recursively canonicalize the passed
|
||||
object according to the OLPC canonical JSON specification (see
|
||||
http://wiki.laptop.org/go/Canonical_JSON) and write it to the passed
|
||||
*bytes.Buffer. If canonicalization fails it returns an error.
|
||||
*/
|
||||
func encodeCanonical(obj interface{}, result *bytes.Buffer) (err error) {
|
||||
// Since this function is called recursively, we use panic if an error occurs
|
||||
// and recover in a deferred function, which is always called before
|
||||
// returning. There we set the error that is returned eventually.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = errors.New(r.(string))
|
||||
}
|
||||
}()
|
||||
|
||||
switch objAsserted := obj.(type) {
|
||||
case string:
|
||||
result.WriteString(encodeCanonicalString(objAsserted))
|
||||
|
||||
case bool:
|
||||
if objAsserted {
|
||||
result.WriteString("true")
|
||||
} else {
|
||||
result.WriteString("false")
|
||||
}
|
||||
|
||||
// The wrapping `EncodeCanonical` function decodes the passed json data with
|
||||
// `decoder.UseNumber` so that any numeric value is stored as `json.Number`
|
||||
// (instead of the default `float64`). This allows us to assert that it is a
|
||||
// non-floating point number, which are the only numbers allowed by the used
|
||||
// canonicalization specification.
|
||||
case json.Number:
|
||||
if _, err := objAsserted.Int64(); err != nil {
|
||||
panic(fmt.Sprintf("Can't canonicalize floating point number '%s'",
|
||||
objAsserted))
|
||||
}
|
||||
result.WriteString(objAsserted.String())
|
||||
|
||||
case nil:
|
||||
result.WriteString("null")
|
||||
|
||||
// Canonicalize slice
|
||||
case []interface{}:
|
||||
result.WriteString("[")
|
||||
for i, val := range objAsserted {
|
||||
if err := encodeCanonical(val, result); err != nil {
|
||||
return err
|
||||
}
|
||||
if i < (len(objAsserted) - 1) {
|
||||
result.WriteString(",")
|
||||
}
|
||||
}
|
||||
result.WriteString("]")
|
||||
|
||||
case map[string]interface{}:
|
||||
result.WriteString("{")
|
||||
|
||||
// Make a list of keys
|
||||
var mapKeys []string
|
||||
for key := range objAsserted {
|
||||
mapKeys = append(mapKeys, key)
|
||||
}
|
||||
// Sort keys
|
||||
sort.Strings(mapKeys)
|
||||
|
||||
// Canonicalize map
|
||||
for i, key := range mapKeys {
|
||||
// Note: `key` must be a `string` (see `case map[string]interface{}`) and
|
||||
// canonicalization of strings cannot err out (see `case string`), thus
|
||||
// no error handling is needed here.
|
||||
encodeCanonical(key, result)
|
||||
|
||||
result.WriteString(":")
|
||||
if err := encodeCanonical(objAsserted[key], result); err != nil {
|
||||
return err
|
||||
}
|
||||
if i < (len(mapKeys) - 1) {
|
||||
result.WriteString(",")
|
||||
}
|
||||
i++
|
||||
}
|
||||
result.WriteString("}")
|
||||
|
||||
default:
|
||||
// We recover in a deferred function defined above
|
||||
panic(fmt.Sprintf("Can't canonicalize '%s' of type '%s'",
|
||||
objAsserted, reflect.TypeOf(objAsserted)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
EncodeCanonical JSON canonicalizes the passed object and returns it as a byte
|
||||
slice. It uses the OLPC canonical JSON specification (see
|
||||
http://wiki.laptop.org/go/Canonical_JSON). If canonicalization fails the byte
|
||||
slice is nil and the second return value contains the error.
|
||||
*/
|
||||
func EncodeCanonical(obj interface{}) ([]byte, error) {
|
||||
// FIXME: Terrible hack to turn the passed struct into a map, converting
|
||||
// the struct's variable names to the json key names defined in the struct
|
||||
data, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var jsonMap interface{}
|
||||
|
||||
dec := json.NewDecoder(bytes.NewReader(data))
|
||||
dec.UseNumber()
|
||||
if err := dec.Decode(&jsonMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create a buffer and write the canonicalized JSON bytes to it
|
||||
var result bytes.Buffer
|
||||
if err := encodeCanonical(jsonMap, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result.Bytes(), nil
|
||||
}
|
197
vendor/github.com/secure-systems-lab/go-securesystemslib/dsse/sign.go
generated
vendored
Normal file
197
vendor/github.com/secure-systems-lab/go-securesystemslib/dsse/sign.go
generated
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
Package dsse implements the Dead Simple Signing Envelope (DSSE)
|
||||
https://github.com/secure-systems-lab/dsse
|
||||
*/
|
||||
package dsse
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ErrUnknownKey indicates that the implementation does not recognize the
|
||||
// key.
|
||||
var ErrUnknownKey = errors.New("unknown key")
|
||||
|
||||
// ErrNoSignature indicates that an envelope did not contain any signatures.
|
||||
var ErrNoSignature = errors.New("no signature found")
|
||||
|
||||
// ErrNoSigners indicates that no signer was provided.
|
||||
var ErrNoSigners = errors.New("no signers provided")
|
||||
|
||||
/*
|
||||
Envelope captures an envelope as described by the Secure Systems Lab
|
||||
Signing Specification. See here:
|
||||
https://github.com/secure-systems-lab/signing-spec/blob/master/envelope.md
|
||||
*/
|
||||
type Envelope struct {
|
||||
PayloadType string `json:"payloadType"`
|
||||
Payload string `json:"payload"`
|
||||
Signatures []Signature `json:"signatures"`
|
||||
}
|
||||
|
||||
/*
|
||||
DecodeB64Payload returns the serialized body, decoded
|
||||
from the envelope's payload field. A flexible
|
||||
decoder is used, first trying standard base64, then
|
||||
URL-encoded base64.
|
||||
*/
|
||||
func (e *Envelope) DecodeB64Payload() ([]byte, error) {
|
||||
return b64Decode(e.Payload)
|
||||
}
|
||||
|
||||
/*
|
||||
Signature represents a generic in-toto signature that contains the identifier
|
||||
of the key which was used to create the signature.
|
||||
The used signature scheme has to be agreed upon by the signer and verifer
|
||||
out of band.
|
||||
The signature is a base64 encoding of the raw bytes from the signature
|
||||
algorithm.
|
||||
*/
|
||||
type Signature struct {
|
||||
KeyID string `json:"keyid"`
|
||||
Sig string `json:"sig"`
|
||||
}
|
||||
|
||||
/*
|
||||
PAE implementes the DSSE Pre-Authentic Encoding
|
||||
https://github.com/secure-systems-lab/dsse/blob/master/protocol.md#signature-definition
|
||||
*/
|
||||
func PAE(payloadType string, payload []byte) []byte {
|
||||
return []byte(fmt.Sprintf("DSSEv1 %d %s %d %s",
|
||||
len(payloadType), payloadType,
|
||||
len(payload), payload))
|
||||
}
|
||||
|
||||
/*
|
||||
Signer defines the interface for an abstract signing algorithm.
|
||||
The Signer interface is used to inject signature algorithm implementations
|
||||
into the EnevelopeSigner. This decoupling allows for any signing algorithm
|
||||
and key management system can be used.
|
||||
The full message is provided as the parameter. If the signature algorithm
|
||||
depends on hashing of the message prior to signature calculation, the
|
||||
implementor of this interface must perform such hashing.
|
||||
The function must return raw bytes representing the calculated signature
|
||||
using the current algorithm, and the key used (if applicable).
|
||||
For an example see EcdsaSigner in sign_test.go.
|
||||
*/
|
||||
type Signer interface {
|
||||
Sign(data []byte) ([]byte, error)
|
||||
KeyID() (string, error)
|
||||
}
|
||||
|
||||
// SignVerifer provides both the signing and verification interface.
|
||||
type SignVerifier interface {
|
||||
Signer
|
||||
Verifier
|
||||
}
|
||||
|
||||
// EnvelopeSigner creates signed Envelopes.
|
||||
type EnvelopeSigner struct {
|
||||
providers []SignVerifier
|
||||
ev *EnvelopeVerifier
|
||||
}
|
||||
|
||||
/*
|
||||
NewEnvelopeSigner creates an EnvelopeSigner that uses 1+ Signer
|
||||
algorithms to sign the data.
|
||||
Creates a verifier with threshold=1, at least one of the providers must validate signitures successfully.
|
||||
*/
|
||||
func NewEnvelopeSigner(p ...SignVerifier) (*EnvelopeSigner, error) {
|
||||
return NewMultiEnvelopeSigner(1, p...)
|
||||
}
|
||||
|
||||
/*
|
||||
NewMultiEnvelopeSigner creates an EnvelopeSigner that uses 1+ Signer
|
||||
algorithms to sign the data.
|
||||
Creates a verifier with threshold.
|
||||
threashold indicates the amount of providers that must validate the envelope.
|
||||
*/
|
||||
func NewMultiEnvelopeSigner(threshold int, p ...SignVerifier) (*EnvelopeSigner, error) {
|
||||
var providers []SignVerifier
|
||||
|
||||
for _, sv := range p {
|
||||
if sv != nil {
|
||||
providers = append(providers, sv)
|
||||
}
|
||||
}
|
||||
|
||||
if len(providers) == 0 {
|
||||
return nil, ErrNoSigners
|
||||
}
|
||||
|
||||
evps := []Verifier{}
|
||||
for _, p := range providers {
|
||||
evps = append(evps, p.(Verifier))
|
||||
}
|
||||
|
||||
ev, err := NewMultiEnvelopeVerifier(threshold, evps...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &EnvelopeSigner{
|
||||
providers: providers,
|
||||
ev: ev,
|
||||
}, nil
|
||||
}
|
||||
|
||||
/*
|
||||
SignPayload signs a payload and payload type according to DSSE.
|
||||
Returned is an envelope as defined here:
|
||||
https://github.com/secure-systems-lab/dsse/blob/master/envelope.md
|
||||
One signature will be added for each Signer in the EnvelopeSigner.
|
||||
*/
|
||||
func (es *EnvelopeSigner) SignPayload(payloadType string, body []byte) (*Envelope, error) {
|
||||
var e = Envelope{
|
||||
Payload: base64.StdEncoding.EncodeToString(body),
|
||||
PayloadType: payloadType,
|
||||
}
|
||||
|
||||
paeEnc := PAE(payloadType, body)
|
||||
|
||||
for _, signer := range es.providers {
|
||||
sig, err := signer.Sign(paeEnc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keyID, err := signer.KeyID()
|
||||
if err != nil {
|
||||
keyID = ""
|
||||
}
|
||||
|
||||
e.Signatures = append(e.Signatures, Signature{
|
||||
KeyID: keyID,
|
||||
Sig: base64.StdEncoding.EncodeToString(sig),
|
||||
})
|
||||
}
|
||||
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
/*
|
||||
Verify decodes the payload and verifies the signature.
|
||||
Any domain specific validation such as parsing the decoded body and
|
||||
validating the payload type is left out to the caller.
|
||||
Verify returns a list of accepted keys each including a keyid, public and signiture of the accepted provider keys.
|
||||
*/
|
||||
func (es *EnvelopeSigner) Verify(e *Envelope) ([]AcceptedKey, error) {
|
||||
return es.ev.Verify(e)
|
||||
}
|
||||
|
||||
/*
|
||||
Both standard and url encoding are allowed:
|
||||
https://github.com/secure-systems-lab/dsse/blob/master/envelope.md
|
||||
*/
|
||||
func b64Decode(s string) ([]byte, error) {
|
||||
b, err := base64.StdEncoding.DecodeString(s)
|
||||
if err != nil {
|
||||
b, err = base64.URLEncoding.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
146
vendor/github.com/secure-systems-lab/go-securesystemslib/dsse/verify.go
generated
vendored
Normal file
146
vendor/github.com/secure-systems-lab/go-securesystemslib/dsse/verify.go
generated
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
package dsse
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
/*
|
||||
Verifier verifies a complete message against a signature and key.
|
||||
If the message was hashed prior to signature generation, the verifier
|
||||
must perform the same steps.
|
||||
If KeyID returns successfully, only signature matching the key ID will be verified.
|
||||
*/
|
||||
type Verifier interface {
|
||||
Verify(data, sig []byte) error
|
||||
KeyID() (string, error)
|
||||
Public() crypto.PublicKey
|
||||
}
|
||||
|
||||
type EnvelopeVerifier struct {
|
||||
providers []Verifier
|
||||
threshold int
|
||||
}
|
||||
|
||||
type AcceptedKey struct {
|
||||
Public crypto.PublicKey
|
||||
KeyID string
|
||||
Sig Signature
|
||||
}
|
||||
|
||||
func (ev *EnvelopeVerifier) Verify(e *Envelope) ([]AcceptedKey, error) {
|
||||
if e == nil {
|
||||
return nil, errors.New("cannot verify a nil envelope")
|
||||
}
|
||||
|
||||
if len(e.Signatures) == 0 {
|
||||
return nil, ErrNoSignature
|
||||
}
|
||||
|
||||
// Decode payload (i.e serialized body)
|
||||
body, err := e.DecodeB64Payload()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Generate PAE(payloadtype, serialized body)
|
||||
paeEnc := PAE(e.PayloadType, body)
|
||||
|
||||
// If *any* signature is found to be incorrect, it is skipped
|
||||
var acceptedKeys []AcceptedKey
|
||||
usedKeyids := make(map[string]string)
|
||||
unverified_providers := ev.providers
|
||||
for _, s := range e.Signatures {
|
||||
sig, err := b64Decode(s.Sig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Loop over the providers.
|
||||
// If provider and signature include key IDs but do not match skip.
|
||||
// If a provider recognizes the key, we exit
|
||||
// the loop and use the result.
|
||||
providers := unverified_providers
|
||||
for i, v := range providers {
|
||||
keyID, err := v.KeyID()
|
||||
|
||||
// Verifiers that do not provide a keyid will be generated one using public.
|
||||
if err != nil || keyID == "" {
|
||||
keyID, err = SHA256KeyID(v.Public())
|
||||
if err != nil {
|
||||
keyID = ""
|
||||
}
|
||||
}
|
||||
|
||||
if s.KeyID != "" && keyID != "" && err == nil && s.KeyID != keyID {
|
||||
continue
|
||||
}
|
||||
|
||||
err = v.Verify(paeEnc, sig)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
acceptedKey := AcceptedKey{
|
||||
Public: v.Public(),
|
||||
KeyID: keyID,
|
||||
Sig: s,
|
||||
}
|
||||
unverified_providers = removeIndex(providers, i)
|
||||
|
||||
// See https://github.com/in-toto/in-toto/pull/251
|
||||
if _, ok := usedKeyids[keyID]; ok {
|
||||
fmt.Printf("Found envelope signed by different subkeys of the same main key, Only one of them is counted towards the step threshold, KeyID=%s\n", keyID)
|
||||
continue
|
||||
}
|
||||
|
||||
usedKeyids[keyID] = ""
|
||||
acceptedKeys = append(acceptedKeys, acceptedKey)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity if with some reflect magic this happens.
|
||||
if ev.threshold <= 0 || ev.threshold > len(ev.providers) {
|
||||
return nil, errors.New("Invalid threshold")
|
||||
}
|
||||
|
||||
if len(usedKeyids) < ev.threshold {
|
||||
return acceptedKeys, errors.New(fmt.Sprintf("Accepted signatures do not match threshold, Found: %d, Expected %d", len(acceptedKeys), ev.threshold))
|
||||
}
|
||||
|
||||
return acceptedKeys, nil
|
||||
}
|
||||
|
||||
func NewEnvelopeVerifier(v ...Verifier) (*EnvelopeVerifier, error) {
|
||||
return NewMultiEnvelopeVerifier(1, v...)
|
||||
}
|
||||
|
||||
func NewMultiEnvelopeVerifier(threshold int, p ...Verifier) (*EnvelopeVerifier, error) {
|
||||
|
||||
if threshold <= 0 || threshold > len(p) {
|
||||
return nil, errors.New("Invalid threshold")
|
||||
}
|
||||
|
||||
ev := EnvelopeVerifier{
|
||||
providers: p,
|
||||
threshold: threshold,
|
||||
}
|
||||
return &ev, nil
|
||||
}
|
||||
|
||||
func SHA256KeyID(pub crypto.PublicKey) (string, error) {
|
||||
// Generate public key fingerprint
|
||||
sshpk, err := ssh.NewPublicKey(pub)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fingerprint := ssh.FingerprintSHA256(sshpk)
|
||||
return fingerprint, nil
|
||||
}
|
||||
|
||||
func removeIndex(v []Verifier, index int) []Verifier {
|
||||
return append(v[:index], v[index+1:]...)
|
||||
}
|
Reference in New Issue
Block a user