diff --git a/cmd/main.go b/cmd/main.go index 19a3796..461f51d 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -12,8 +12,8 @@ import ( "os" "strings" + "github.com/blocky/nitrite" "github.com/tinfoilanalytics/verifier/pkg/models" - "github.com/tinfoilanalytics/verifier/pkg/nitro" "github.com/tinfoilanalytics/verifier/pkg/sigstore" ) @@ -108,10 +108,11 @@ func main() { } } - nitroMeasurements, err = nitro.VerifyAttestation(attDocBytes) + att, err := nitrite.Verify(attDocBytes, nitrite.VerifyOptions{}) if err != nil { panic(err) } + nitroMeasurements = models.MeasurementFromDoc(att.Document) log.Println("Nitro", nitroMeasurements) } diff --git a/go.mod b/go.mod index afe6f56..e09caaf 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,9 @@ module github.com/tinfoilanalytics/verifier go 1.23.2 require ( - github.com/fxamacker/cbor/v2 v2.7.0 + github.com/blocky/nitrite v0.0.1 github.com/sigstore/protobuf-specs v0.3.2 github.com/sigstore/sigstore-go v0.6.2 - github.com/veraison/go-cose v1.2.1 ) require ( @@ -16,6 +15,7 @@ require ( github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-chi/chi v4.1.2+incompatible // indirect github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/go.sum b/go.sum index b5b052d..b717786 100644 --- a/go.sum +++ b/go.sum @@ -61,6 +61,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blocky/nitrite v0.0.1 h1:pw3sZWFu5ADubW5JOUI5WM1JJSZZqyGTwn/nMR12DEM= +github.com/blocky/nitrite v0.0.1/go.mod h1:Ava0jYckAHUqLIeROgFXzqlWJFdf/SdknIDrgmwOhB4= github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -308,8 +310,6 @@ github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs= github.com/transparency-dev/merkle v0.0.2 h1:Q9nBoQcZcgPamMkGn7ghV8XiTZ/kRxn1yCG81+twTK4= github.com/transparency-dev/merkle v0.0.2/go.mod h1:pqSy+OXefQ1EDUVmAJ8MUhHB9TXGuzVAT58PqBoHz1A= -github.com/veraison/go-cose v1.2.1 h1:Gj4x20D0YP79J2+cK3anjGEMwIkg2xX+TKVVGUXwNAc= -github.com/veraison/go-cose v1.2.1/go.mod h1:t6V8WJzHm1PD5HNsuDjW3KLv577uWb6UTzbZGvdQHD8= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms= diff --git a/pkg/models/models.go b/pkg/models/models.go index c5b1ca7..e0ea76d 100644 --- a/pkg/models/models.go +++ b/pkg/models/models.go @@ -1,6 +1,11 @@ package models -import "fmt" +import ( + "encoding/hex" + "fmt" + + "github.com/blocky/nitrite" +) type Measurements struct { PCR0 string @@ -15,3 +20,11 @@ func (m *Measurements) Equals(other *Measurements) bool { func (m *Measurements) String() string { return fmt.Sprintf(`{"PCR0":"%s", "PCR1":"%s", "PCR2":"%s"}`, m.PCR0, m.PCR1, m.PCR2) } + +func MeasurementFromDoc(doc *nitrite.Document) *Measurements { + return &Measurements{ + PCR0: hex.EncodeToString(doc.PCRs[0]), + PCR1: hex.EncodeToString(doc.PCRs[1]), + PCR2: hex.EncodeToString(doc.PCRs[2]), + } +} diff --git a/pkg/nitro/aws-nitro-root-g1.pem b/pkg/nitro/aws-nitro-root-g1.pem deleted file mode 100644 index 221cc0b..0000000 --- a/pkg/nitro/aws-nitro-root-g1.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICETCCAZagAwIBAgIRAPkxdWgbkK/hHUbMtOTn+FYwCgYIKoZIzj0EAwMwSTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoMBkFtYXpvbjEMMAoGA1UECwwDQVdTMRswGQYD -VQQDDBJhd3Mubml0cm8tZW5jbGF2ZXMwHhcNMTkxMDI4MTMyODA1WhcNNDkxMDI4 -MTQyODA1WjBJMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGQW1hem9uMQwwCgYDVQQL -DANBV1MxGzAZBgNVBAMMEmF3cy5uaXRyby1lbmNsYXZlczB2MBAGByqGSM49AgEG -BSuBBAAiA2IABPwCVOumCMHzaHDimtqQvkY4MpJzbolL//Zy2YlES1BR5TSksfbb -48C8WBoyt7F2Bw7eEtaaP+ohG2bnUs990d0JX28TcPQXCEPZ3BABIeTPYwEoCWZE -h8l5YoQwTcU/9KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkCW1DdkF -R+eWw5b6cp3PmanfS5YwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYC -MQCjfy+Rocm9Xue4YnwWmNJVA44fA0P5W2OpYow9OYCVRaEevL8uO1XYru5xtMPW -rfMCMQCi85sWBbJwKKXdS6BptQFuZbT73o/gBh1qUxl/nNr12UO8Yfwr6wPLb+6N -IwLz3/Y= ------END CERTIFICATE----- diff --git a/pkg/nitro/nitro.go b/pkg/nitro/nitro.go deleted file mode 100644 index 5dfed90..0000000 --- a/pkg/nitro/nitro.go +++ /dev/null @@ -1,101 +0,0 @@ -package nitro - -import ( - "crypto/x509" - _ "embed" - "encoding/hex" - "encoding/pem" - "fmt" - - "github.com/fxamacker/cbor/v2" - "github.com/veraison/go-cose" - - "github.com/tinfoilanalytics/verifier/pkg/models" -) - -// AWS Nitro Enclaves root certificate from: https://aws-nitro-enclaves.amazonaws.com/AWS_NitroEnclaves_Root-G1.zip -// https://github.com/aws/aws-nitro-enclaves-nsm-api/blob/main/docs/attestation_process.md#21-attestation-document-definition - -//go:embed aws-nitro-root-g1.pem -var awsRootCertBytes []byte - -var rootCert *x509.Certificate - -func init() { - // Parse AWS root cert - b, _ := pem.Decode(awsRootCertBytes) - if b == nil { - panic("parsing root cert") - } - - var err error - rootCert, err = x509.ParseCertificate(b.Bytes) - if err != nil { - panic("parsing root cert: " + err.Error()) - } -} - -// AttestationDocument represents an AWS Nitro Enclave attestation document in CBOR format -type AttestationDocument struct { - ModuleID string `cbor:"module_id"` - Timestamp uint64 `cbor:"timestamp"` - Digest string `cbor:"digest"` - PCRs map[uint][]byte `cbor:"pcrs"` - Certificate []byte `cbor:"certificate"` - CABundle [][]byte `cbor:"cabundle"` - PublicKey []byte `cbor:"public_key"` - UserData []byte `cbor:"user_data"` - Nonce []byte `cbor:"nonce"` -} - -// VerifyAttestation verifies an AWS Nitro Enclave attestation document and returns the PCR measurements -func VerifyAttestation(attDocBytes []byte) (*models.Measurements, error) { - // Decode attestation document from CBOR - var msg cose.UntaggedSign1Message - if err := msg.UnmarshalCBOR(attDocBytes); err != nil { - return nil, fmt.Errorf("parsing signature: %w", err) - } - var attDoc AttestationDocument - if err := cbor.Unmarshal(msg.Payload, &attDoc); err != nil { - return nil, fmt.Errorf("parsing inner attestation document: %w", err) - } - - // Parse inner certificate to extract pubkey - cert, err := x509.ParseCertificate(attDoc.Certificate) - if err != nil { - return nil, fmt.Errorf("parsing certificate: %w", err) - } - - // Verify COSE signature - verifier, err := cose.NewVerifier(cose.AlgorithmES384, cert.PublicKey) - if err != nil { - return nil, fmt.Errorf("creating verifier: %w", err) - } - if err := msg.Verify(nil, verifier); err != nil { - return nil, fmt.Errorf("verifying signature: %w", err) - } - - roots := x509.NewCertPool() - roots.AddCert(rootCert) - - intermediates := x509.NewCertPool() - for _, ca := range attDoc.CABundle { - if caCert, err := x509.ParseCertificate(ca); err == nil { - intermediates.AddCert(caCert) - } - } - - opts := x509.VerifyOptions{ - Roots: roots, - Intermediates: intermediates, - } - if _, err := cert.Verify(opts); err != nil { - return nil, fmt.Errorf("verifying certificate: %w", err) - } - - return &models.Measurements{ - PCR0: hex.EncodeToString(attDoc.PCRs[0]), - PCR1: hex.EncodeToString(attDoc.PCRs[1]), - PCR2: hex.EncodeToString(attDoc.PCRs[2]), - }, nil -} diff --git a/vendor/github.com/blocky/nitrite/.editorconfig b/vendor/github.com/blocky/nitrite/.editorconfig new file mode 100644 index 0000000..acf396c --- /dev/null +++ b/vendor/github.com/blocky/nitrite/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*.go] +indent_style = tab +indent_size = 4 + +[*.{js,json,yml,yaml}] +indent_style = space +indent_size = 2 diff --git a/vendor/github.com/blocky/nitrite/.vimrc b/vendor/github.com/blocky/nitrite/.vimrc new file mode 100644 index 0000000..d0bee16 --- /dev/null +++ b/vendor/github.com/blocky/nitrite/.vimrc @@ -0,0 +1,4 @@ +let NERDTreeIgnore = ['.git$', '.cache$', 'node_modules$'] +let NERDTreeShowHidden = 1 + +:set backupcopy=yes diff --git a/vendor/github.com/blocky/nitrite/LICENSE b/vendor/github.com/blocky/nitrite/LICENSE new file mode 100644 index 0000000..3e6b3f7 --- /dev/null +++ b/vendor/github.com/blocky/nitrite/LICENSE @@ -0,0 +1,19 @@ +Copyright 2020 Stojan Dimitrovski + +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. diff --git a/vendor/github.com/blocky/nitrite/README.md b/vendor/github.com/blocky/nitrite/README.md new file mode 100644 index 0000000..f59e4b5 --- /dev/null +++ b/vendor/github.com/blocky/nitrite/README.md @@ -0,0 +1,55 @@ +Nitrite +======= + +[![Go Report Card][go-reportcard-badge]][go-reportcard] [![Go Reference][pkg.go.dev-badge]][pkg.go.dev] + +A library for verifying [AWS Nitro Enclave][aws-nitro-enclaves] +[attestations][aws-nitro-attestation] for Go. + +## Usage + +It's fairly simple to use it, so here's an example: + +```go +import ( + "bytes" + "github.com/hf/nitrite" + "time" +) + +func verifyAttestation(attestation []byte) error { + res, err := nitrite.Verify( + bytes.NewReader(attestation), + nitrite.VerifyOptions{ + CurrentTime: time.Now(), + }) + + if nil != err { + return err + } + + return nil +} +``` + +This package includes the Nitro Enclave [Root CA certificates][aws-nitro-root-ca]. + +It's recommended you explicitly calculate the SHA256 sum of the `DefaultRootCA` +string and match it according to the [AWS +documentation][aws-nitro-verify-root] at the start of your application. +Alternatively, you can supply your own copy of the root CA. + +## License + +Copyright © 2021 Stojan Dimitrovski. Licensed under the MIT License. See +`LICENSE` for more information. + +[go-reportcard-badge]: https://goreportcard.com/badge/github.com/hf/nitrite +[go-reportcard]: https://goreportcard.com/report/github.com/hf/nitrite +[pkg.go.dev-badge]: https://pkg.go.dev/badge/github.com/hf/nitrite.svg +[pkg.go.dev]: https://pkg.go.dev/github.com/hf/nitrite + +[aws-nitro-enclaves]: https://docs.aws.amazon.com/enclaves/latest/user/nitro-enclave.html +[aws-nitro-attestation]: https://docs.aws.amazon.com/enclaves/latest/user/verify-root.html +[aws-nitro-root-ca]: https://aws-nitro-enclaves.amazonaws.com/AWS_NitroEnclaves_Root-G1.zip +[aws-nitro-verify-root]: https://docs.aws.amazon.com/enclaves/latest/user/verify-root.html diff --git a/vendor/github.com/blocky/nitrite/nitrite.go b/vendor/github.com/blocky/nitrite/nitrite.go new file mode 100644 index 0000000..c5a9983 --- /dev/null +++ b/vendor/github.com/blocky/nitrite/nitrite.go @@ -0,0 +1,400 @@ +// Package nitrite implements attestation verification for AWS Nitro Enclaves. +package nitrite + +import ( + "crypto/ecdsa" + "crypto/sha256" + "crypto/sha512" + "crypto/x509" + "errors" + "fmt" + "github.com/fxamacker/cbor/v2" + "math/big" + "time" +) + +// Document represents the AWS Nitro Enclave Attestation Document. +type Document struct { + ModuleID string `cbor:"module_id" json:"module_id"` + Timestamp uint64 `cbor:"timestamp" json:"timestamp"` + Digest string `cbor:"digest" json:"digest"` + PCRs map[uint][]byte `cbor:"pcrs" json:"pcrs"` + Certificate []byte `cbor:"certificate" json:"certificate"` + CABundle [][]byte `cbor:"cabundle" json:"cabundle"` + + PublicKey []byte `cbor:"public_key" json:"public_key,omitempty"` + UserData []byte `cbor:"user_data" json:"user_data,omitempty"` + Nonce []byte `cbor:"nonce" json:"nonce,omitempty"` +} + +// Result is a successful verification result of an attestation payload. +type Result struct { + // Document contains the attestation document. + Document *Document `json:"document,omitempty"` + + // Certificates contains all of the certificates except the root. + Certificates []*x509.Certificate `json:"certificates,omitempty"` + + // Protected section from the COSE Sign1 payload. + Protected []byte `json:"protected,omitempty"` + // Unprotected section from the COSE Sign1 payload. + Unprotected []byte `json:"unprotected,omitempty"` + // Payload section from the COSE Sign1 payload. + Payload []byte `json:"payload,omitempty"` + // Signature section from the COSE Sign1 payload. + Signature []byte `json:"signature,omitempty"` + + // SignatureOK designates if the signature was OK (but certificate could be + // invalid, not trusted, expired, etc.) + SignatureOK bool `json:"signature_ok"` + + // COSESign1 contains the COSE Signature Structure which was used to + // calculate the `Signature`. + COSESign1 []byte `json:"cose_sign1,omitempty"` +} + +// VerifyOptions specifies the options for verifying the attestation payload. +// If `Roots` is nil, the `DefaultCARoot` is used. If `CurrentTime` is 0, +// `time.Now()` will be used. It is a strong recommendation you explicitly +// supply this value. +type VerifyOptions struct { + Roots *x509.CertPool + CurrentTime time.Time +} + +type coseHeader struct { + Alg interface{} `cbor:"1,keyasint,omitempty" json:"alg,omitempty"` +} + +func (h *coseHeader) AlgorithmString() (string, bool) { + switch h.Alg.(type) { + case string: + return h.Alg.(string), true + } + + return "", false +} + +func (h *coseHeader) AlgorithmInt() (int64, bool) { + switch h.Alg.(type) { + case int64: + return h.Alg.(int64), true + } + + return 0, false +} + +type cosePayload struct { + _ struct{} `cbor:",toarray"` + + Protected []byte + Unprotected cbor.RawMessage + Payload []byte + Signature []byte +} + +type coseSignature struct { + _ struct{} `cbor:",toarray"` + + Context string + Protected []byte + ExternalAAD []byte + Payload []byte +} + +// Errors that are encountered when manipulating the COSESign1 structure. +var ( + ErrBadCOSESign1Structure error = errors.New("Data is not a COSESign1 array") + ErrCOSESign1EmptyProtectedSection error = errors.New("COSESign1 protected section is nil or empty") + ErrCOSESign1EmptyPayloadSection error = errors.New("COSESign1 payload section is nil or empty") + ErrCOSESign1EmptySignatureSection error = errors.New("COSESign1 signature section is nil or empty") + ErrCOSESign1BadAlgorithm error = errors.New("COSESign1 algorithm not ECDSA384") +) + +// Errors encountered when parsing the CBOR attestation document. +var ( + ErrBadAttestationDocument error = errors.New("Bad attestation document") + ErrMandatoryFieldsMissing error = errors.New("One or more of mandatory fields missing") + ErrBadDigest error = errors.New("Payload 'digest' is not SHA384") + ErrBadTimestamp error = errors.New("Payload 'timestamp' is 0 or less") + ErrBadPCRs error = errors.New("Payload 'pcrs' is less than 1 or more than 32") + ErrBadPCRIndex error = errors.New("Payload 'pcrs' key index is not in [0, 32)") + ErrBadPCRValue error = errors.New("Payload 'pcrs' value is nil or not of length {32,48,64}") + ErrBadCABundle error = errors.New("Payload 'cabundle' has 0 elements") + ErrBadCABundleItem error = errors.New("Payload 'cabundle' has a nil item or of length not in [1, 1024]") + ErrBadPublicKey error = errors.New("Payload 'public_key' has a value of length not in [1, 1024]") + ErrBadUserData error = errors.New("Payload 'user_data' has a value of length not in [1, 512]") + ErrBadNonce error = errors.New("Payload 'nonce' has a value of length not in [1, 512]") + ErrBadCertificatePublicKeyAlgorithm error = errors.New("Payload 'certificate' has a bad public key algorithm (not ECDSA)") + ErrBadCertificateSigningAlgorithm error = errors.New("Payload 'certificate' has a bad public key signing algorithm (not ECDSAWithSHA384)") + ErrBadSignature error = errors.New("Payload's signature does not match signature from certificate") +) + +const ( + // DefaultCARoots contains the PEM encoded roots for verifying Nitro + // Enclave attestation signatures. You can download them from + // https://aws-nitro-enclaves.amazonaws.com/AWS_NitroEnclaves_Root-G1.zip + // It's recommended you calculate the SHA256 sum of this string and match + // it to the one supplied in the AWS documentation + // https://docs.aws.amazon.com/enclaves/latest/user/verify-root.html + DefaultCARoots string = "-----BEGIN CERTIFICATE-----\nMIICETCCAZagAwIBAgIRAPkxdWgbkK/hHUbMtOTn+FYwCgYIKoZIzj0EAwMwSTEL\nMAkGA1UEBhMCVVMxDzANBgNVBAoMBkFtYXpvbjEMMAoGA1UECwwDQVdTMRswGQYD\nVQQDDBJhd3Mubml0cm8tZW5jbGF2ZXMwHhcNMTkxMDI4MTMyODA1WhcNNDkxMDI4\nMTQyODA1WjBJMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGQW1hem9uMQwwCgYDVQQL\nDANBV1MxGzAZBgNVBAMMEmF3cy5uaXRyby1lbmNsYXZlczB2MBAGByqGSM49AgEG\nBSuBBAAiA2IABPwCVOumCMHzaHDimtqQvkY4MpJzbolL//Zy2YlES1BR5TSksfbb\n48C8WBoyt7F2Bw7eEtaaP+ohG2bnUs990d0JX28TcPQXCEPZ3BABIeTPYwEoCWZE\nh8l5YoQwTcU/9KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkCW1DdkF\nR+eWw5b6cp3PmanfS5YwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYC\nMQCjfy+Rocm9Xue4YnwWmNJVA44fA0P5W2OpYow9OYCVRaEevL8uO1XYru5xtMPW\nrfMCMQCi85sWBbJwKKXdS6BptQFuZbT73o/gBh1qUxl/nNr12UO8Yfwr6wPLb+6N\nIwLz3/Y=\n-----END CERTIFICATE-----\n" +) + +var ( + defaultRoot *x509.CertPool = createAWSNitroRoot() +) + +func createAWSNitroRoot() *x509.CertPool { + pool := x509.NewCertPool() + + ok := pool.AppendCertsFromPEM([]byte(DefaultCARoots)) + if !ok { + return nil + } + + return pool +} + +func reverse(enc []byte) []byte { + rev := make([]byte, len(enc)) + + for i, b := range enc { + rev[len(enc)-i-1] = b + } + + return rev +} + +// Verify verifies the attestation payload from `data` with the provided +// verification options. If the options specify `Roots` as `nil`, the +// `DefaultCARoot` will be used. If you do not specify `CurrentTime`, +// `time.Now()` will be used. It is strongly recommended you specifically +// supply the time. If the returned error is non-nil, it is either one of the +// `Err` codes specified in this package, or is an error from the `crypto/x509` +// package. Revocation checks are NOT performed and you should check for +// revoked certificates by looking at the `Certificates` field in the `Result`. +// Result will be non-null if and only if either of these are true: certificate +// verification has passed, certificate verification has failed (expired, not +// trusted, etc.), signature is OK or signature is not OK. If either signature +// is not OK or certificate can't be verified, both Result and error will be +// set! You can use the SignatureOK field from the result to distinguish +// errors. +func Verify(data []byte, options VerifyOptions) (*Result, error) { + cose := cosePayload{} + + err := cbor.Unmarshal(data, &cose) + if nil != err { + return nil, ErrBadCOSESign1Structure + } + + if nil == cose.Protected || 0 == len(cose.Protected) { + return nil, ErrCOSESign1EmptyProtectedSection + } + + if nil == cose.Payload || 0 == len(cose.Payload) { + return nil, ErrCOSESign1EmptyPayloadSection + } + + if nil == cose.Signature || 0 == len(cose.Signature) { + return nil, ErrCOSESign1EmptySignatureSection + } + + header := coseHeader{} + err = cbor.Unmarshal(cose.Protected, &header) + if nil != err { + return nil, ErrBadCOSESign1Structure + } + + intAlg, ok := header.AlgorithmInt() + + // https://datatracker.ietf.org/doc/html/rfc8152#section-8.1 + if ok { + switch intAlg { + case -35: + // do nothing -- OK + + default: + return nil, ErrCOSESign1BadAlgorithm + } + } else { + strAlg, ok := header.AlgorithmString() + + if ok { + switch strAlg { + case "ES384": + // do nothing -- OK + + default: + return nil, ErrCOSESign1BadAlgorithm + } + } else { + return nil, ErrCOSESign1BadAlgorithm + } + } + + doc := Document{} + + err = cbor.Unmarshal(cose.Payload, &doc) + if nil != err { + return nil, ErrBadAttestationDocument + } + + if "" == doc.ModuleID || "" == doc.Digest || 0 == doc.Timestamp || nil == doc.PCRs || nil == doc.Certificate || nil == doc.CABundle { + return nil, ErrMandatoryFieldsMissing + } + + if "SHA384" != doc.Digest { + return nil, ErrBadDigest + } + + if doc.Timestamp < 1 { + return nil, ErrBadTimestamp + } + + if len(doc.PCRs) < 1 || len(doc.PCRs) > 32 { + return nil, ErrBadPCRs + } + + for key, value := range doc.PCRs { + if key < 0 || key > 31 { + return nil, ErrBadPCRIndex + } + + if nil == value || !(32 == len(value) || 48 == len(value) || 64 == len(value)) { + return nil, ErrBadPCRValue + } + } + + if len(doc.CABundle) < 1 { + return nil, ErrBadCABundle + } + + for _, item := range doc.CABundle { + if nil == item || len(item) < 1 || len(item) > 1024 { + return nil, ErrBadCABundleItem + } + } + + if nil != doc.PublicKey && (len(doc.PublicKey) < 1 || len(doc.PublicKey) > 1024) { + return nil, ErrBadPublicKey + } + + if nil != doc.UserData && (len(doc.UserData) < 1 || len(doc.UserData) > 512) { + return nil, ErrBadUserData + } + + if nil != doc.Nonce && (len(doc.Nonce) < 1 || len(doc.Nonce) > 512) { + return nil, ErrBadNonce + } + + certificates := make([]*x509.Certificate, 0, len(doc.CABundle)+1) + + cert, err := x509.ParseCertificate(doc.Certificate) + if nil != err { + return nil, err + } + + if x509.ECDSA != cert.PublicKeyAlgorithm { + return nil, ErrBadCertificatePublicKeyAlgorithm + } + + if x509.ECDSAWithSHA384 != cert.SignatureAlgorithm { + return nil, ErrBadCertificateSigningAlgorithm + } + + certificates = append(certificates, cert) + + intermediates := x509.NewCertPool() + + for _, item := range doc.CABundle { + cert, err := x509.ParseCertificate(item) + if nil != err { + return nil, err + } + + intermediates.AddCert(cert) + certificates = append(certificates, cert) + } + + roots := options.Roots + if nil == roots { + roots = defaultRoot + } + + currentTime := options.CurrentTime + if currentTime.IsZero() { + currentTime = time.Now() + } + + _, err = cert.Verify(x509.VerifyOptions{ + Intermediates: intermediates, + Roots: roots, + CurrentTime: currentTime, + KeyUsages: []x509.ExtKeyUsage{ + x509.ExtKeyUsageAny, + }, + }) + + sigStruct, _ := cbor.Marshal(&coseSignature{ + Context: "Signature1", + Protected: cose.Protected, + ExternalAAD: []byte{}, + Payload: cose.Payload, + }) + + signatureOk := checkECDSASignature(cert.PublicKey.(*ecdsa.PublicKey), sigStruct, cose.Signature) + + if !signatureOk && nil == err { + err = ErrBadSignature + } + + return &Result{ + Document: &doc, + Certificates: certificates, + Protected: cose.Protected, + Unprotected: cose.Unprotected, + Payload: cose.Payload, + Signature: cose.Signature, + SignatureOK: signatureOk, + COSESign1: sigStruct, + }, err +} + +func checkECDSASignature(publicKey *ecdsa.PublicKey, sigStruct, signature []byte) bool { + // https://datatracker.ietf.org/doc/html/rfc8152#section-8.1 + + var hashSigStruct []byte = nil + + switch publicKey.Curve.Params().Name { + case "P-224": + h := sha256.Sum224(sigStruct) + hashSigStruct = h[:] + + case "P-256": + h := sha256.Sum256(sigStruct) + hashSigStruct = h[:] + + case "P-384": + h := sha512.Sum384(sigStruct) + hashSigStruct = h[:] + + case "P-512": + h := sha512.Sum512(sigStruct) + hashSigStruct = h[:] + + default: + panic(fmt.Sprintf("unknown ECDSA curve name %v", publicKey.Curve.Params().Name)) + } + + if len(signature) != 2*len(hashSigStruct) { + return false + } + + r := big.NewInt(0) + s := big.NewInt(0) + + r = r.SetBytes(signature[:len(hashSigStruct)]) + s = s.SetBytes(signature[len(hashSigStruct):]) + + return ecdsa.Verify(publicKey, hashSigStruct, r, s) +} diff --git a/vendor/github.com/veraison/go-cose/.gitignore b/vendor/github.com/veraison/go-cose/.gitignore deleted file mode 100644 index 4d0f184..0000000 --- a/vendor/github.com/veraison/go-cose/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -# Binaries for programs and plugins -*.exe -*.dll -*.so -*.dylib - -# Test binary, build with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 -.glide/ - -# test deps -test/cose-rust/ -test/cose-wg-examples/ - -# go deps -vendor/ - -# OSX fs files -.DS_Store -/cose-fuzz.zip -/workdir/ diff --git a/vendor/github.com/veraison/go-cose/.golangci.yml b/vendor/github.com/veraison/go-cose/.golangci.yml deleted file mode 100644 index 5bfb8b4..0000000 --- a/vendor/github.com/veraison/go-cose/.golangci.yml +++ /dev/null @@ -1,81 +0,0 @@ -# Do not delete linter settings. Linters like gocritic can be enabled on the command line. - -linters-settings: - dupl: - threshold: 100 - funlen: - lines: 100 - statements: 50 - goconst: - min-len: 2 - min-occurrences: 3 - gocritic: - enabled-tags: - - diagnostic - - experimental - - opinionated - - performance - - style - disabled-checks: - - dupImport # https://github.com/go-critic/go-critic/issues/845 - - ifElseChain - - octalLiteral - - paramTypeCombine - - whyNoLint - - wrapperFunc - gofmt: - simplify: false - goimports: - local-prefixes: github.com/fxamacker/cbor - golint: - min-confidence: 0 - govet: - check-shadowing: true - lll: - line-length: 140 - maligned: - suggest-new: true - misspell: - locale: US - -linters: - disable-all: true - enable: - - deadcode - - errcheck - - goconst - - gocyclo - - gofmt - - goimports - - golint - - gosec - - govet - - ineffassign - - maligned - - misspell - - staticcheck - - structcheck - - typecheck - - unconvert - - unused - - varcheck - - -issues: - # max-issues-per-linter default is 50. Set to 0 to disable limit. - max-issues-per-linter: 0 - # max-same-issues default is 3. Set to 0 to disable limit. - max-same-issues: 0 - # Excluding configuration per-path, per-linter, per-text and per-source - exclude-rules: - - path: _test\.go - linters: - - goconst - - dupl - - gomnd - - lll - - path: doc\.go - linters: - - goimports - - gomnd - - lll diff --git a/vendor/github.com/veraison/go-cose/CODEOWNERS b/vendor/github.com/veraison/go-cose/CODEOWNERS deleted file mode 100644 index 767969e..0000000 --- a/vendor/github.com/veraison/go-cose/CODEOWNERS +++ /dev/null @@ -1,4 +0,0 @@ -# To be kept in sync with: [community/OWNERS](https://github.com/veraison/community/blob/main/OWNERS) -# and the GitHub Team: [go-cose-maintainers](https://github.com/orgs/veraison/teams/go-cose-maintainers) - -* henkbirkholz qmuntal roywill setrofim shizhMSFT simonfrost-arm SteveLasker thomas-fossati yogeshbdeshpande diff --git a/vendor/github.com/veraison/go-cose/LICENSE b/vendor/github.com/veraison/go-cose/LICENSE deleted file mode 100644 index a612ad9..0000000 --- a/vendor/github.com/veraison/go-cose/LICENSE +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/vendor/github.com/veraison/go-cose/README.md b/vendor/github.com/veraison/go-cose/README.md deleted file mode 100644 index 74a8f77..0000000 --- a/vendor/github.com/veraison/go-cose/README.md +++ /dev/null @@ -1,215 +0,0 @@ -# go-cose - -[![go.dev](https://pkg.go.dev/badge/github.com/veraison/go-cose.svg)](https://pkg.go.dev/github.com/veraison/go-cose) -[![tests](https://github.com/veraison/go-cose/workflows/ci/badge.svg)](https://github.com/veraison/go-cose/actions?query=workflow%3Aci) -[![codecov](https://codecov.io/gh/veraison/go-cose/branch/main/graph/badge.svg?token=SL18TCTC03)](https://codecov.io/gh/veraison/go-cose) - -A golang library for the [COSE specification][cose-spec] - -## Project Status - -**Current Release**: [go-cose v1.0.0][current-release] - -The project was *initially* forked from the upstream [mozilla-services/go-cose][mozilla-go-cose] project, however the Veraison and Mozilla maintainers have agreed to retire the mozilla-services/go-cose project and focus on [veraison/go-cose][veraison-go-cose] as the active project. - -We thank the [Mozilla maintainers and contributors][mozilla-contributors] for their great work that formed the base of the [veraison/go-cose][veraison-go-cose] project. - -## Community - -The [veraison/go-cose](https://github.com/veraison/go-cose) project is an open source community effort. - -You can reach the go-cose community via:: - -- [Mailing List](veraison-project@confidentialcomputing.io) -- Bi-weekly meetings: 08:00-09:00 Pacific - - [Zoom meeting link](https://us02web.zoom.us/j/81054434992?pwd=YjNBU21seU5VcGdtVXY3VHVjS251Zz09) - - [Calendar ics link](https://zoom.us/meeting/tZUtcu2srT8jE9YFubXn-lC9upuwUiiev52G/ics) -- [Meeting Notes](https://veraison.zulipchat.com/#narrow/stream/317999-go-cose-meetings) -- [Meeting Recordings](https://www.youtube.com/@go-cose-community3000) - -Participation in the go-cose community is governed by the Veraison [CODE_OF_CONDUCT.md](https://github.com/veraison/.github/blob/main/CODE_OF_CONDUCT.md) and [GOVERNANCE.md](https://github.com/veraison/community/blob/main/GOVERNANCE.md) - -## Code of Conduct - -This project has adopted the [Contributor Covenant Code of Conduct](https://github.com/veraison/.github/blob/main/CODE_OF_CONDUCT.md). - -## Installation - -go-cose is compatible with modern Go releases in module mode, with Go installed: - -```bash -go get github.com/veraison/go-cose -``` - -will resolve and add the package to the current development module, along with its dependencies. - -Alternatively the same can be achieved if you use import in a package: - -```go -import "github.com/veraison/go-cose" -``` - -and run `go get` without parameters. - -Finally, to use the top-of-trunk version of this repo, use the following command: - -```bash -go get github.com/veraison/go-cose@main -``` - -## Usage - -### Signing and Verification - -```go -import "github.com/veraison/go-cose" -``` - -Construct a new COSE_Sign1_Tagged message, then sign it using ECDSA w/ SHA-256 and finally marshal it. For example: - -```go -package main - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - _ "crypto/sha256" - - "github.com/veraison/go-cose" -) - -func SignP256(data []byte) ([]byte, error) { - // create a signer - privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - if err != nil { - return nil, err - } - signer, err := cose.NewSigner(cose.AlgorithmES256, privateKey) - if err != nil { - return nil, err - } - - // create message header - headers := cose.Headers{ - Protected: cose.ProtectedHeader{ - cose.HeaderLabelAlgorithm: cose.AlgorithmES256, - }, - } - - // sign and marshal message - return cose.Sign1(rand.Reader, signer, headers, data, nil) -} -``` - -Verify a raw COSE_Sign1_Tagged message. For example: - -```go -package main - -import ( - "crypto" - _ "crypto/sha256" - - "github.com/veraison/go-cose" -) - -func VerifyP256(publicKey crypto.PublicKey, sig []byte) error { - // create a verifier from a trusted private key - verifier, err := cose.NewVerifier(cose.AlgorithmES256, publicKey) - if err != nil { - return err - } - - // create a sign message from a raw COSE_Sign1 payload - var msg cose.Sign1Message - if err = msg.UnmarshalCBOR(sig); err != nil { - return err - } - return msg.Verify(nil, verifier) -} -``` - -See [example_test.go](./example_test.go) for more examples. - -#### Untagged Signing and Verification - -Untagged COSE_Sign1 messages can be signed and verified as above, using -`cose.UntaggedSign1Message` instead of `cose.Sign1Message`. - -### About hashing - -`go-cose` does not import any hash package by its own to avoid linking unnecessary algorithms to the final binary. -It is the the responsibility of the `go-cose` user to make the necessary hash functions available at runtime, i.e., -by using a blank import: - -```go -import ( - _ "crypto/sha256" - _ "crypto/sha512" -) -``` - -These are the required packages for each built-in cose.Algorithm: - -- cose.AlgorithmPS256, cose.AlgorithmES256: `crypto/sha256` -- cose.AlgorithmPS384, cose.AlgorithmPS512, cose.AlgorithmES384, cose.AlgorithmES512: `crypto/sha512` -- cose.AlgorithmEd25519: none - -## Features - -### Signing and Verifying Objects - -go-cose supports two different signature structures: -- [cose.Sign1Message](https://pkg.go.dev/github.com/veraison/go-cose#Sign1Message) implements [COSE_Sign1](https://datatracker.ietf.org/doc/html/rfc8152#section-4.2). -- [cose.SignMessage](https://pkg.go.dev/github.com/veraison/go-cose#SignMessage) implements [COSE_Sign](https://datatracker.ietf.org/doc/html/rfc8152#section-4.1). -> :warning: The COSE_Sign API is currently **EXPERIMENTAL** and may be changed or removed in a later release. In addition, the amount of functional and security testing it has received so far is significantly lower than the COSE_Sign1 API. - -### Built-in Algorithms - -go-cose has built-in supports the following algorithms: -- PS{256,384,512}: RSASSA-PSS w/ SHA as defined in RFC 8230. -- ES{256,384,512}: ECDSA w/ SHA as defined in RFC 8152. -- Ed25519: PureEdDSA as defined in RFC 8152. - -### Custom Algorithms - -The supported algorithms can be extended at runtime by using [cose.RegisterAlgorithm](https://pkg.go.dev/github.com/veraison/go-cose#RegisterAlgorithm). - -[API docs](https://pkg.go.dev/github.com/veraison/go-cose) - -### Integer Ranges - -CBOR supports integers in the range [-264, -1] ∪ [0, 264 - 1]. - -This does not map onto a single Go integer type. - -`go-cose` uses `int64` to encompass both positive and negative values to keep data sizes smaller and easy to use. - -The main effect is that integer label values in the [-264, -263 - 1] and the [263, 264 - 1] ranges, which are nominally valid -per RFC 8152, are rejected by the go-cose library. - -### Conformance Tests - -`go-cose` runs the [GlueCOSE](https://github.com/gluecose/test-vectors) test suite on every local `go test` execution. -These are also executed on every CI job. - -### Fuzz Tests - -`go-cose` implements several fuzz tests using [Go's native fuzzing](https://go.dev/doc/fuzz). - -Fuzzing requires Go 1.18 or higher, and can be executed as follows: - -```bash -go test -fuzz=FuzzSign1 -``` - -### Security Reviews - -`go-cose` undergoes periodic security review. The security review reports are located [here](./reports) - -[cose-spec]: https://datatracker.ietf.org/doc/rfc9052/ -[mozilla-contributors]: https://github.com/mozilla-services/go-cose/graphs/contributors -[mozilla-go-cose]: http://github.com/mozilla-services/go-cose -[veraison-go-cose]: https://github.com/veraison/go-cose -[current-release]: https://github.com/veraison/go-cose/releases/tag/v1.0.0 diff --git a/vendor/github.com/veraison/go-cose/SECURITY.md b/vendor/github.com/veraison/go-cose/SECURITY.md deleted file mode 100644 index d4ab969..0000000 --- a/vendor/github.com/veraison/go-cose/SECURITY.md +++ /dev/null @@ -1,89 +0,0 @@ -# Security Process and Policy - -This document provides the details on the veraison/go-cose security policy and details the processes surrounding security handling. - -## Supported Versions - -The current stable release of [go-cose][go-cose] is [v1.0.0][v1.0.0-release]. Please upgrade to [v1.0.0][v1.0.0-release] if you are using a pre-release version. - -| Version | Supported | -| ------- | ------------------ | -| [v1.0.0][v1.0.0-release] | Yes | - -## Report A Vulnerability - -We’re extremely grateful for security researchers and users who report vulnerabilities -to the [veraison/go-cose][go-cose] community. All reports are thoroughly investigated by a set of [veraison/go-cose maintainers][go-cose-maintainers]. - -To make a report please email the private security list at go-cose-security@googlegroups.com with details using the following template: - -### Reporting Template - -```console -[TO:]: go-cose-security@googlegroups.com -[SUBJECT]: go-cose Security Notification -[BODY]: -Release: v1.0.0 - -Summary: -A quick summary of the issue - -Impact: -Details on how to reproduce the security issue. - -Contact: -Information on who to contact for additional information -``` - -### When To Send a Report - -You think you have found a vulnerability in the [veraison/go-cose][go-cose] project. - -### Security Vulnerability Response - -Each report will be reviewed and receipt acknowledged in a timely manner. This will set off the security review process detailed below. - -Any vulnerability information shared with the security team stays within the [veraison/go-cose][go-cose] project and will not be shared with others unless it is necessary to fix the issue. Information is shared only on a need to know basis. - -We ask that vulnerability reporter(s) act in good faith by not disclosing the issue to others. And we strive to act in good faith by acting swiftly, and by justly crediting the vulnerability reporter(s) in writing (see [Public Disclosure](#public-disclosure)). - -As the security issue moves through triage, identification, and release the reporter of the security vulnerability will be notified. Additional questions about the vulnerability map may also be asked from the reporter. - -### Public Disclosure - -A public disclosure of security vulnerabilities is released alongside release updates or details that fix the vulnerability. We try to fully disclose vulnerabilities once a mitigation strategy is available. Our goal is to perform a release and public disclosure quickly and in a timetable that works well for users. For example, a release may be ready on a Friday but for the sake of users may be delayed to a Monday. - -When needed, CVEs will be assigned to vulnerabilities. Due to the process and time it takes to obtain a CVE ID, disclosures will happen first. Once the disclosure is public the process will begin to obtain a CVE ID. Once the ID has been assigned the disclosure will be updated. - -If the vulnerability reporter would like their name and details shared as part of the disclosure process we are happy to. We will ask permission and for the way the reporter would like to be identified. We appreciate vulnerability reports and would like to credit reporters if they would like the credit. - -## Security Team Membership - -The security team is made up of a subset of the Veraison project maintainers who are willing and able to respond to vulnerability reports. - -### Responsibilities - -* Members MUST be active project maintainers on active (non-deprecated) Veraison projects as defined in the [governance](https://github.com/veraison/community/blob/main/GOVERNANCE.md) -* Members SHOULD engage in each reported vulnerability, at a minimum to make sure it is being handled -* Members MUST keep the vulnerability details private and only share on a need to know basis - -### Membership - -New members are required to be active maintainers of Veraison projects who are willing to perform the responsibilities outlined above. The security team is a subset of the maintainers across Veraison sub-projects. Members can step down at any time and may join at any time. - -If at any time a security team member is found to be no longer an active maintainer on active Veraison sub-projects, this individual will be removed from the security team. - -## Patch and Release Team - -When a vulnerability comes in and is acknowledged, a team - including maintainers of the Veraison project affected - will be assembled to patch the vulnerability, release an update, and publish the vulnerability disclosure. This may expand beyond the security team as needed but will stay within the pool of Veraison project maintainers. - -## Disclosures - -Vulnerability disclosures are published to [security-advisories][security-advisories]. The disclosures will contain an overview, details about the vulnerability, a fix for the vulnerability that will typically be an update, and optionally a workaround if one is available. - -Disclosures will be published on the same day as a release fixing the vulnerability after the release is published. - -[go-cose]: https://github.com/veraison/go-cose -[security-advisories]: https://github.com/veraison/go-cose/security/advisories -[v1.0.0-release]: https://github.com/veraison/go-cose/releases/tag/v1.0.0 -[go-cose-maintainers]: https://github.com/veraison/community/blob/main/OWNERS diff --git a/vendor/github.com/veraison/go-cose/algorithm.go b/vendor/github.com/veraison/go-cose/algorithm.go deleted file mode 100644 index 7e68535..0000000 --- a/vendor/github.com/veraison/go-cose/algorithm.go +++ /dev/null @@ -1,142 +0,0 @@ -package cose - -import ( - "crypto" - "fmt" - "strconv" -) - -// Algorithms supported by this library. -// -// When using an algorithm which requires hashing, -// make sure the associated hash function is linked to the binary. -const ( - // RSASSA-PSS w/ SHA-256 by RFC 8230. - // Requires an available crypto.SHA256. - AlgorithmPS256 Algorithm = -37 - - // RSASSA-PSS w/ SHA-384 by RFC 8230. - // Requires an available crypto.SHA384. - AlgorithmPS384 Algorithm = -38 - - // RSASSA-PSS w/ SHA-512 by RFC 8230. - // Requires an available crypto.SHA512. - AlgorithmPS512 Algorithm = -39 - - // ECDSA w/ SHA-256 by RFC 8152. - // Requires an available crypto.SHA256. - AlgorithmES256 Algorithm = -7 - - // ECDSA w/ SHA-384 by RFC 8152. - // Requires an available crypto.SHA384. - AlgorithmES384 Algorithm = -35 - - // ECDSA w/ SHA-512 by RFC 8152. - // Requires an available crypto.SHA512. - AlgorithmES512 Algorithm = -36 - - // PureEdDSA by RFC 8152. - AlgorithmEd25519 Algorithm = -8 - - // An invalid/unrecognised algorithm. - AlgorithmInvalid Algorithm = 0 -) - -// Algorithm represents an IANA algorithm entry in the COSE Algorithms registry. -// -// # See Also -// -// COSE Algorithms: https://www.iana.org/assignments/cose/cose.xhtml#algorithms -// -// RFC 8152 16.4: https://datatracker.ietf.org/doc/html/rfc8152#section-16.4 -type Algorithm int64 - -// String returns the name of the algorithm -func (a Algorithm) String() string { - switch a { - case AlgorithmPS256: - return "PS256" - case AlgorithmPS384: - return "PS384" - case AlgorithmPS512: - return "PS512" - case AlgorithmES256: - return "ES256" - case AlgorithmES384: - return "ES384" - case AlgorithmES512: - return "ES512" - case AlgorithmEd25519: - // As stated in RFC 8152 8.2, only the pure EdDSA version is used for - // COSE. - return "EdDSA" - default: - return "unknown algorithm value " + strconv.Itoa(int(a)) - } -} - -// MarshalCBOR marshals the Algorithm as a CBOR int. -func (a Algorithm) MarshalCBOR() ([]byte, error) { - return encMode.Marshal(int64(a)) -} - -// UnmarshalCBOR populates the Algorithm from the provided CBOR value (must be -// int or tstr). -func (a *Algorithm) UnmarshalCBOR(data []byte) error { - var raw intOrStr - - if err := raw.UnmarshalCBOR(data); err != nil { - return fmt.Errorf("invalid algorithm value: %w", err) - } - - if raw.IsString() { - v := algorithmFromString(raw.String()) - if v == AlgorithmInvalid { - return fmt.Errorf("unknown algorithm value %q", raw.String()) - } - - *a = v - } else { - v := raw.Int() - *a = Algorithm(v) - } - - return nil -} - -// hashFunc returns the hash associated with the algorithm supported by this -// library. -func (a Algorithm) hashFunc() crypto.Hash { - switch a { - case AlgorithmPS256, AlgorithmES256: - return crypto.SHA256 - case AlgorithmPS384, AlgorithmES384: - return crypto.SHA384 - case AlgorithmPS512, AlgorithmES512: - return crypto.SHA512 - default: - return 0 - } -} - -// computeHash computes the digest using the hash specified in the algorithm. -func (a Algorithm) computeHash(data []byte) ([]byte, error) { - return computeHash(a.hashFunc(), data) -} - -// computeHash computes the digest using the given hash. -func computeHash(h crypto.Hash, data []byte) ([]byte, error) { - if !h.Available() { - return nil, ErrUnavailableHashFunc - } - hh := h.New() - if _, err := hh.Write(data); err != nil { - return nil, err - } - return hh.Sum(nil), nil -} - -// NOTE: there are currently no registered string values for an algorithm. -func algorithmFromString(v string) Algorithm { - return AlgorithmInvalid -} diff --git a/vendor/github.com/veraison/go-cose/cbor.go b/vendor/github.com/veraison/go-cose/cbor.go deleted file mode 100644 index 15bdc54..0000000 --- a/vendor/github.com/veraison/go-cose/cbor.go +++ /dev/null @@ -1,129 +0,0 @@ -package cose - -import ( - "bytes" - "errors" - "io" - - "github.com/fxamacker/cbor/v2" -) - -// CBOR Tags for COSE signatures registered in the IANA "CBOR Tags" registry. -// -// Reference: https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml#tags -const ( - CBORTagSignMessage = 98 - CBORTagSign1Message = 18 -) - -// Pre-configured modes for CBOR encoding and decoding. -var ( - encMode cbor.EncMode - decMode cbor.DecMode - decModeWithTagsForbidden cbor.DecMode -) - -func init() { - var err error - - // init encode mode - encOpts := cbor.EncOptions{ - Sort: cbor.SortCoreDeterministic, // sort map keys - IndefLength: cbor.IndefLengthForbidden, // no streaming - } - encMode, err = encOpts.EncMode() - if err != nil { - panic(err) - } - - // init decode mode - decOpts := cbor.DecOptions{ - DupMapKey: cbor.DupMapKeyEnforcedAPF, // duplicated key not allowed - IndefLength: cbor.IndefLengthForbidden, // no streaming - IntDec: cbor.IntDecConvertSigned, // decode CBOR uint/int to Go int64 - } - decMode, err = decOpts.DecMode() - if err != nil { - panic(err) - } - decOpts.TagsMd = cbor.TagsForbidden - decModeWithTagsForbidden, err = decOpts.DecMode() - if err != nil { - panic(err) - } -} - -// byteString represents a "bstr / nil" type. -type byteString []byte - -// UnmarshalCBOR decodes data into a "bstr / nil" type. -// It also ensures the data is of major type 2 since []byte can be alternatively -// interpreted as an array of bytes. -// -// Note: `github.com/fxamacker/cbor/v2` considers the primitive value -// `undefined` (major type 7, value 23) as nil, which is not recognized by COSE. -// -// Related Code: https://github.com/fxamacker/cbor/blob/v2.4.0/decode.go#L709 -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-1.3 -func (s *byteString) UnmarshalCBOR(data []byte) error { - if s == nil { - return errors.New("cbor: UnmarshalCBOR on nil byteString pointer") - } - if len(data) == 0 { - return io.EOF // same error as returned by cbor.Unmarshal() - } - if bytes.Equal(data, []byte{0xf6}) { - *s = nil - return nil - } - if data[0]>>5 != 2 { // major type 2: bstr - return errors.New("cbor: require bstr type") - } - return decModeWithTagsForbidden.Unmarshal(data, (*[]byte)(s)) -} - -// deterministicBinaryString converts a bstr into the deterministic encoding. -// -// Reference: https://www.rfc-editor.org/rfc/rfc9052.html#section-9 -func deterministicBinaryString(data cbor.RawMessage) (cbor.RawMessage, error) { - if len(data) == 0 { - return nil, io.EOF - } - if data[0]>>5 != 2 { // major type 2: bstr - return nil, errors.New("cbor: require bstr type") - } - - // fast path: return immediately if bstr is already deterministic - if err := decModeWithTagsForbidden.Valid(data); err != nil { - return nil, err - } - ai := data[0] & 0x1f - if ai < 24 { - return data, nil - } - switch ai { - case 24: - if data[1] >= 24 { - return data, nil - } - case 25: - if data[1] != 0 { - return data, nil - } - case 26: - if data[1] != 0 || data[2] != 0 { - return data, nil - } - case 27: - if data[1] != 0 || data[2] != 0 || data[3] != 0 || data[4] != 0 { - return data, nil - } - } - - // slow path: convert by re-encoding - // error checking is not required since `data` has been validataed - var s []byte - _ = decModeWithTagsForbidden.Unmarshal(data, &s) - return encMode.Marshal(s) -} diff --git a/vendor/github.com/veraison/go-cose/common.go b/vendor/github.com/veraison/go-cose/common.go deleted file mode 100644 index 32294a5..0000000 --- a/vendor/github.com/veraison/go-cose/common.go +++ /dev/null @@ -1,96 +0,0 @@ -package cose - -import ( - "errors" - "fmt" -) - -// intOrStr is a value that can be either an int or a tstr when serialized to -// CBOR. -type intOrStr struct { - intVal int64 - strVal string - isString bool -} - -func newIntOrStr(v interface{}) *intOrStr { - var ios intOrStr - if err := ios.Set(v); err != nil { - return nil - } - return &ios -} - -func (ios intOrStr) Int() int64 { - return ios.intVal -} - -func (ios intOrStr) String() string { - if ios.IsString() { - return ios.strVal - } - return fmt.Sprint(ios.intVal) -} - -func (ios intOrStr) IsInt() bool { - return !ios.isString -} - -func (ios intOrStr) IsString() bool { - return ios.isString -} - -func (ios intOrStr) Value() interface{} { - if ios.IsInt() { - return ios.intVal - } - - return ios.strVal -} - -func (ios *intOrStr) Set(v interface{}) error { - switch t := v.(type) { - case int64: - ios.intVal = t - ios.strVal = "" - ios.isString = false - case int: - ios.intVal = int64(t) - ios.strVal = "" - ios.isString = false - case string: - ios.strVal = t - ios.intVal = 0 - ios.isString = true - default: - return fmt.Errorf("must be int or string, found %T", t) - } - - return nil -} - -// MarshalCBOR returns the encoded CBOR representation of the intOrString, as -// either int or tstr, depending on the value. If no value has been set, -// intOrStr is encoded as a zero-length tstr. -func (ios intOrStr) MarshalCBOR() ([]byte, error) { - if ios.IsInt() { - return encMode.Marshal(ios.intVal) - } - - return encMode.Marshal(ios.strVal) -} - -// UnmarshalCBOR unmarshals the provided CBOR encoded data (must be an int, -// uint, or tstr). -func (ios *intOrStr) UnmarshalCBOR(data []byte) error { - if len(data) == 0 { - return errors.New("zero length buffer") - } - - var val interface{} - if err := decMode.Unmarshal(data, &val); err != nil { - return err - } - - return ios.Set(val) -} diff --git a/vendor/github.com/veraison/go-cose/ecdsa.go b/vendor/github.com/veraison/go-cose/ecdsa.go deleted file mode 100644 index 7e426be..0000000 --- a/vendor/github.com/veraison/go-cose/ecdsa.go +++ /dev/null @@ -1,166 +0,0 @@ -package cose - -import ( - "crypto" - "crypto/ecdsa" - "crypto/elliptic" - "encoding/asn1" - "errors" - "fmt" - "io" - "math/big" -) - -// I2OSP - Integer-to-Octet-String primitive converts a nonnegative integer to -// an octet string of a specified length `len(buf)`, and stores it in `buf`. -// I2OSP is used for encoding ECDSA signature (r, s) into byte strings. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8017#section-4.1 -func I2OSP(x *big.Int, buf []byte) error { - if x.Sign() < 0 { - return errors.New("I2OSP: negative integer") - } - if x.BitLen() > len(buf)*8 { - return errors.New("I2OSP: integer too large") - } - x.FillBytes(buf) - return nil -} - -// OS2IP - Octet-String-to-Integer primitive converts an octet string to a -// nonnegative integer. -// OS2IP is used for decoding ECDSA signature (r, s) from byte strings. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8017#section-4.2 -func OS2IP(x []byte) *big.Int { - return new(big.Int).SetBytes(x) -} - -// ecdsaKeySigner is a ECDSA-based signer with golang built-in keys. -type ecdsaKeySigner struct { - alg Algorithm - key *ecdsa.PrivateKey -} - -// Algorithm returns the signing algorithm associated with the private key. -func (es *ecdsaKeySigner) Algorithm() Algorithm { - return es.alg -} - -// Sign signs message content with the private key using entropy from rand. -// The resulting signature should follow RFC 8152 section 8.1, -// although it does not follow the recommendation of being deterministic. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8.1 -func (es *ecdsaKeySigner) Sign(rand io.Reader, content []byte) ([]byte, error) { - digest, err := es.alg.computeHash(content) - if err != nil { - return nil, err - } - r, s, err := ecdsa.Sign(rand, es.key, digest) - if err != nil { - return nil, err - } - return encodeECDSASignature(es.key.Curve, r, s) -} - -// ecdsaKeySigner is a ECDSA based signer with a generic crypto.Signer. -type ecdsaCryptoSigner struct { - alg Algorithm - key *ecdsa.PublicKey - signer crypto.Signer -} - -// Algorithm returns the signing algorithm associated with the private key. -func (es *ecdsaCryptoSigner) Algorithm() Algorithm { - return es.alg -} - -// Sign signs message content with the private key, possibly using entropy from -// rand. -// The resulting signature should follow RFC 8152 section 8.1. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8.1 -func (es *ecdsaCryptoSigner) Sign(rand io.Reader, content []byte) ([]byte, error) { - digest, err := es.alg.computeHash(content) - if err != nil { - return nil, err - } - sigASN1, err := es.signer.Sign(rand, digest, nil) - if err != nil { - return nil, err - } - - // decode ASN.1 decoded signature - var sig struct { - R, S *big.Int - } - if _, err := asn1.Unmarshal(sigASN1, &sig); err != nil { - return nil, err - } - - // encode signature in the COSE form - return encodeECDSASignature(es.key.Curve, sig.R, sig.S) -} - -// encodeECDSASignature encodes (r, s) into a signature binary string using the -// method specified by RFC 8152 section 8.1. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8.1 -func encodeECDSASignature(curve elliptic.Curve, r, s *big.Int) ([]byte, error) { - n := (curve.Params().N.BitLen() + 7) / 8 - sig := make([]byte, n*2) - if err := I2OSP(r, sig[:n]); err != nil { - return nil, err - } - if err := I2OSP(s, sig[n:]); err != nil { - return nil, err - } - return sig, nil -} - -// decodeECDSASignature decodes (r, s) from a signature binary string using the -// method specified by RFC 8152 section 8.1. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8.1 -func decodeECDSASignature(curve elliptic.Curve, sig []byte) (r, s *big.Int, err error) { - n := (curve.Params().N.BitLen() + 7) / 8 - if len(sig) != n*2 { - return nil, nil, fmt.Errorf("invalid signature length: %d", len(sig)) - } - return OS2IP(sig[:n]), OS2IP(sig[n:]), nil -} - -// ecdsaVerifier is a ECDSA based verifier with golang built-in keys. -type ecdsaVerifier struct { - alg Algorithm - key *ecdsa.PublicKey -} - -// Algorithm returns the signing algorithm associated with the public key. -func (ev *ecdsaVerifier) Algorithm() Algorithm { - return ev.alg -} - -// Verify verifies message content with the public key, returning nil for -// success. -// Otherwise, it returns ErrVerification. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8.1 -func (ev *ecdsaVerifier) Verify(content []byte, signature []byte) error { - // compute digest - digest, err := ev.alg.computeHash(content) - if err != nil { - return err - } - - // verify signature - r, s, err := decodeECDSASignature(ev.key.Curve, signature) - if err != nil { - return ErrVerification - } - if verified := ecdsa.Verify(ev.key, digest, r, s); !verified { - return ErrVerification - } - return nil -} diff --git a/vendor/github.com/veraison/go-cose/ed25519.go b/vendor/github.com/veraison/go-cose/ed25519.go deleted file mode 100644 index ae88740..0000000 --- a/vendor/github.com/veraison/go-cose/ed25519.go +++ /dev/null @@ -1,50 +0,0 @@ -package cose - -import ( - "crypto" - "crypto/ed25519" - "io" -) - -// ed25519Signer is a Pure EdDSA based signer with a generic crypto.Signer. -type ed25519Signer struct { - key crypto.Signer -} - -// Algorithm returns the signing algorithm associated with the private key. -func (es *ed25519Signer) Algorithm() Algorithm { - return AlgorithmEd25519 -} - -// Sign signs message content with the private key, possibly using entropy from -// rand. -// The resulting signature should follow RFC 8152 section 8.2. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8.2 -func (es *ed25519Signer) Sign(rand io.Reader, content []byte) ([]byte, error) { - // crypto.Hash(0) must be passed as an option. - // Reference: https://pkg.go.dev/crypto/ed25519#PrivateKey.Sign - return es.key.Sign(rand, content, crypto.Hash(0)) -} - -// ed25519Verifier is a Pure EdDSA based verifier with golang built-in keys. -type ed25519Verifier struct { - key ed25519.PublicKey -} - -// Algorithm returns the signing algorithm associated with the public key. -func (ev *ed25519Verifier) Algorithm() Algorithm { - return AlgorithmEd25519 -} - -// Verify verifies message content with the public key, returning nil for -// success. -// Otherwise, it returns ErrVerification. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8.2 -func (ev *ed25519Verifier) Verify(content []byte, signature []byte) error { - if verified := ed25519.Verify(ev.key, content, signature); !verified { - return ErrVerification - } - return nil -} diff --git a/vendor/github.com/veraison/go-cose/errors.go b/vendor/github.com/veraison/go-cose/errors.go deleted file mode 100644 index 7d16741..0000000 --- a/vendor/github.com/veraison/go-cose/errors.go +++ /dev/null @@ -1,21 +0,0 @@ -package cose - -import "errors" - -// Common errors -var ( - ErrAlgorithmMismatch = errors.New("algorithm mismatch") - ErrAlgorithmNotFound = errors.New("algorithm not found") - ErrAlgorithmNotSupported = errors.New("algorithm not supported") - ErrEmptySignature = errors.New("empty signature") - ErrInvalidAlgorithm = errors.New("invalid algorithm") - ErrMissingPayload = errors.New("missing payload") - ErrNoSignatures = errors.New("no signatures attached") - ErrUnavailableHashFunc = errors.New("hash function is not available") - ErrVerification = errors.New("verification error") - ErrInvalidPubKey = errors.New("invalid public key") - ErrInvalidPrivKey = errors.New("invalid private key") - ErrNotPrivKey = errors.New("not a private key") - ErrSignOpNotSupported = errors.New("sign key_op not supported by key") - ErrVerifyOpNotSupported = errors.New("verify key_op not supported by key") -) diff --git a/vendor/github.com/veraison/go-cose/headers.go b/vendor/github.com/veraison/go-cose/headers.go deleted file mode 100644 index 4218eee..0000000 --- a/vendor/github.com/veraison/go-cose/headers.go +++ /dev/null @@ -1,572 +0,0 @@ -package cose - -import ( - "errors" - "fmt" - "math/big" - - "github.com/fxamacker/cbor/v2" -) - -// COSE Header labels registered in the IANA "COSE Header Parameters" registry. -// -// Reference: https://www.iana.org/assignments/cose/cose.xhtml#header-parameters -const ( - HeaderLabelAlgorithm int64 = 1 - HeaderLabelCritical int64 = 2 - HeaderLabelContentType int64 = 3 - HeaderLabelKeyID int64 = 4 - HeaderLabelIV int64 = 5 - HeaderLabelPartialIV int64 = 6 - HeaderLabelCounterSignature int64 = 7 - HeaderLabelCounterSignature0 int64 = 9 - HeaderLabelX5Bag int64 = 32 - HeaderLabelX5Chain int64 = 33 - HeaderLabelX5T int64 = 34 - HeaderLabelX5U int64 = 35 -) - -// ProtectedHeader contains parameters that are to be cryptographically -// protected. -type ProtectedHeader map[interface{}]interface{} - -// MarshalCBOR encodes the protected header into a CBOR bstr object. -// A zero-length header is encoded as a zero-length string rather than as a -// zero-length map (encoded as h'a0'). -func (h ProtectedHeader) MarshalCBOR() ([]byte, error) { - var encoded []byte - if len(h) == 0 { - encoded = []byte{} - } else { - err := validateHeaderParameters(h, true) - if err != nil { - return nil, fmt.Errorf("protected header: %w", err) - } - encoded, err = encMode.Marshal(map[interface{}]interface{}(h)) - if err != nil { - return nil, err - } - } - return encMode.Marshal(encoded) -} - -// UnmarshalCBOR decodes a CBOR bstr object into ProtectedHeader. -// -// ProtectedHeader is an empty_or_serialized_map where -// -// empty_or_serialized_map = bstr .cbor header_map / bstr .size 0 -func (h *ProtectedHeader) UnmarshalCBOR(data []byte) error { - if h == nil { - return errors.New("cbor: UnmarshalCBOR on nil ProtectedHeader pointer") - } - var encoded byteString - if err := encoded.UnmarshalCBOR(data); err != nil { - return err - } - if encoded == nil { - return errors.New("cbor: nil protected header") - } - if len(encoded) == 0 { - *h = make(ProtectedHeader) - } else { - if encoded[0]>>5 != 5 { // major type 5: map - return errors.New("cbor: protected header: require map type") - } - if err := validateHeaderLabelCBOR(encoded); err != nil { - return err - } - var header map[interface{}]interface{} - if err := decMode.Unmarshal(encoded, &header); err != nil { - return err - } - candidate := ProtectedHeader(header) - if err := validateHeaderParameters(candidate, true); err != nil { - return fmt.Errorf("protected header: %w", err) - } - - // cast to type Algorithm if `alg` presents - if alg, err := candidate.Algorithm(); err == nil { - candidate.SetAlgorithm(alg) - } - - *h = candidate - } - return nil -} - -// SetAlgorithm sets the algorithm value to the algorithm header. -func (h ProtectedHeader) SetAlgorithm(alg Algorithm) { - h[HeaderLabelAlgorithm] = alg -} - -// Algorithm gets the algorithm value from the algorithm header. -func (h ProtectedHeader) Algorithm() (Algorithm, error) { - value, ok := h[HeaderLabelAlgorithm] - if !ok { - return 0, ErrAlgorithmNotFound - } - switch alg := value.(type) { - case Algorithm: - return alg, nil - case int: - return Algorithm(alg), nil - case int8: - return Algorithm(alg), nil - case int16: - return Algorithm(alg), nil - case int32: - return Algorithm(alg), nil - case int64: - return Algorithm(alg), nil - case string: - v := algorithmFromString(alg) - - var err error - if v == AlgorithmInvalid { - err = fmt.Errorf("unknown algorithm value %q", alg) - } - - return v, err - default: - return AlgorithmInvalid, ErrInvalidAlgorithm - } -} - -// Critical indicates which protected header labels an application that is -// processing a message is required to understand. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-3.1 -func (h ProtectedHeader) Critical() ([]interface{}, error) { - value, ok := h[HeaderLabelCritical] - if !ok { - return nil, nil - } - err := ensureCritical(value, h) - if err != nil { - return nil, err - } - return value.([]interface{}), nil -} - -// ensureCritical ensures all critical headers are present in the protected bucket. -func ensureCritical(value interface{}, headers map[interface{}]interface{}) error { - labels, ok := value.([]interface{}) - if !ok { - return errors.New("invalid crit header") - } - // if present, the array MUST have at least one value in it. - if len(labels) == 0 { - return errors.New("empty crit header") - } - for _, label := range labels { - if !canInt(label) && !canTstr(label) { - return fmt.Errorf("require int / tstr type, got '%T': %v", label, label) - } - if _, ok := headers[label]; !ok { - return fmt.Errorf("missing critical header: %v", label) - } - } - return nil -} - -// UnprotectedHeader contains parameters that are not cryptographically -// protected. -type UnprotectedHeader map[interface{}]interface{} - -// MarshalCBOR encodes the unprotected header into a CBOR map object. -// A zero-length header is encoded as a zero-length map (encoded as h'a0'). -func (h UnprotectedHeader) MarshalCBOR() ([]byte, error) { - if len(h) == 0 { - return []byte{0xa0}, nil - } - if err := validateHeaderParameters(h, false); err != nil { - return nil, fmt.Errorf("unprotected header: %w", err) - } - return encMode.Marshal(map[interface{}]interface{}(h)) -} - -// UnmarshalCBOR decodes a CBOR map object into UnprotectedHeader. -// -// UnprotectedHeader is a header_map. -func (h *UnprotectedHeader) UnmarshalCBOR(data []byte) error { - if h == nil { - return errors.New("cbor: UnmarshalCBOR on nil UnprotectedHeader pointer") - } - if data == nil { - return errors.New("cbor: nil unprotected header") - } - if len(data) == 0 { - return errors.New("cbor: unprotected header: missing type") - } - if data[0]>>5 != 5 { // major type 5: map - return errors.New("cbor: unprotected header: require map type") - } - if err := validateHeaderLabelCBOR(data); err != nil { - return err - } - var header map[interface{}]interface{} - if err := decMode.Unmarshal(data, &header); err != nil { - return err - } - if err := validateHeaderParameters(header, false); err != nil { - return fmt.Errorf("unprotected header: %w", err) - } - *h = header - return nil -} - -// Headers represents "two buckets of information that are not -// considered to be part of the payload itself, but are used for -// holding information about content, algorithms, keys, or evaluation -// hints for the processing of the layer." -// -// It is represented by CDDL fragments: -// -// Headers = ( -// protected : empty_or_serialized_map, -// unprotected : header_map -// ) -// -// header_map = { -// Generic_Headers, -// * label => values -// } -// -// label = int / tstr -// values = any -// -// empty_or_serialized_map = bstr .cbor header_map / bstr .size 0 -// -// # See Also -// -// https://tools.ietf.org/html/rfc8152#section-3 -type Headers struct { - // RawProtected contains the raw CBOR encoded data for the protected header. - // It is populated when decoding. - // Applications can use this field for customized encoding / decoding of - // the protected header in case the default decoder provided by this library - // is not preferred. - RawProtected cbor.RawMessage - - // Protected contains parameters that are to be cryptographically protected. - // When encoding or signing, the protected header is encoded using the - // default CBOR encoder if RawProtected is set to nil. Otherwise, - // RawProtected will be used with Protected ignored. - Protected ProtectedHeader - - // RawUnprotected contains the raw CBOR encoded data for the unprotected - // header. It is populated when decoding. - // Applications can use this field for customized encoding / decoding of - // the unprotected header in case the default decoder provided by this - // library is not preferred. - RawUnprotected cbor.RawMessage - - // Unprotected contains parameters that are not cryptographically protected. - // When encoding, the unprotected header is encoded using the default CBOR - // encoder if RawUnprotected is set to nil. Otherwise, RawUnprotected will - // be used with Unprotected ignored. - Unprotected UnprotectedHeader -} - -// marshal encoded both headers. -// It returns RawProtected and RawUnprotected if those are set. -func (h *Headers) marshal() (cbor.RawMessage, cbor.RawMessage, error) { - if err := h.ensureIV(); err != nil { - return nil, nil, err - } - protected, err := h.MarshalProtected() - if err != nil { - return nil, nil, err - } - unprotected, err := h.MarshalUnprotected() - if err != nil { - return nil, nil, err - } - return protected, unprotected, nil -} - -// MarshalProtected encodes the protected header. -// RawProtected is returned if it is not set to nil. -func (h *Headers) MarshalProtected() ([]byte, error) { - if len(h.RawProtected) > 0 { - return h.RawProtected, nil - } - return encMode.Marshal(h.Protected) -} - -// MarshalUnprotected encodes the unprotected header. -// RawUnprotected is returned if it is not set to nil. -func (h *Headers) MarshalUnprotected() ([]byte, error) { - if len(h.RawUnprotected) > 0 { - return h.RawUnprotected, nil - } - return encMode.Marshal(h.Unprotected) -} - -// UnmarshalFromRaw decodes Protected from RawProtected and Unprotected from -// RawUnprotected. -func (h *Headers) UnmarshalFromRaw() error { - if err := decMode.Unmarshal(h.RawProtected, &h.Protected); err != nil { - return fmt.Errorf("cbor: invalid protected header: %w", err) - } - if err := decMode.Unmarshal(h.RawUnprotected, &h.Unprotected); err != nil { - return fmt.Errorf("cbor: invalid unprotected header: %w", err) - } - if err := h.ensureIV(); err != nil { - return err - } - return nil -} - -// ensureSigningAlgorithm ensures the presence of the `alg` header if there is -// no externally supplied data for signing. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func (h *Headers) ensureSigningAlgorithm(alg Algorithm, external []byte) error { - candidate, err := h.Protected.Algorithm() - switch err { - case nil: - if candidate != alg { - return fmt.Errorf("%w: signer %v: header %v", ErrAlgorithmMismatch, alg, candidate) - } - return nil - case ErrAlgorithmNotFound: - if len(external) > 0 { - return nil - } - if h.RawProtected != nil { - return ErrAlgorithmNotFound - } - if h.Protected == nil { - h.Protected = make(ProtectedHeader) - } - h.Protected.SetAlgorithm(alg) - return nil - } - return err -} - -// ensureVerificationAlgorithm ensures the presence of the `alg` header if there -// is no externally supplied data for verification. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func (h *Headers) ensureVerificationAlgorithm(alg Algorithm, external []byte) error { - candidate, err := h.Protected.Algorithm() - switch err { - case nil: - if candidate != alg { - return fmt.Errorf("%w: verifier %v: header %v", ErrAlgorithmMismatch, alg, candidate) - } - return nil - case ErrAlgorithmNotFound: - if len(external) > 0 { - return nil - } - } - return err -} - -// ensureIV ensures IV and Partial IV are not both present -// in the protected and unprotected headers. -// It does not check if they are both present within one header, -// as it will be checked later on. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-3.1 -func (h *Headers) ensureIV() error { - if hasLabel(h.Protected, HeaderLabelIV) && hasLabel(h.Unprotected, HeaderLabelPartialIV) { - return errors.New("IV (protected) and PartialIV (unprotected) parameters must not both be present") - } - if hasLabel(h.Protected, HeaderLabelPartialIV) && hasLabel(h.Unprotected, HeaderLabelIV) { - return errors.New("IV (unprotected) and PartialIV (protected) parameters must not both be present") - } - return nil -} - -// hasLabel returns true if h contains label. -func hasLabel(h map[interface{}]interface{}, label interface{}) bool { - _, ok := h[label] - return ok -} - -// validateHeaderParameters validates all headers conform to the spec. -func validateHeaderParameters(h map[interface{}]interface{}, protected bool) error { - existing := make(map[interface{}]struct{}, len(h)) - for label, value := range h { - // Validate that all header labels are integers or strings. - // Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-1.4 - label, ok := normalizeLabel(label) - if !ok { - return errors.New("header label: require int / tstr type") - } - - // Validate that there are no duplicated labels. - // Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-3 - if _, ok := existing[label]; ok { - return fmt.Errorf("header label: duplicated label: %v", label) - } else { - existing[label] = struct{}{} - } - - // Validate the generic parameters. - // Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-3.1 - switch label { - case HeaderLabelAlgorithm: - _, is_alg := value.(Algorithm) - if !is_alg && !canInt(value) && !canTstr(value) { - return errors.New("header parameter: alg: require int / tstr type") - } - case HeaderLabelCritical: - if !protected { - return errors.New("header parameter: crit: not allowed") - } - if err := ensureCritical(value, h); err != nil { - return fmt.Errorf("header parameter: crit: %w", err) - } - case HeaderLabelContentType: - if !canTstr(value) && !canUint(value) { - return errors.New("header parameter: content type: require tstr / uint type") - } - case HeaderLabelKeyID: - if !canBstr(value) { - return errors.New("header parameter: kid: require bstr type") - } - case HeaderLabelIV: - if !canBstr(value) { - return errors.New("header parameter: IV: require bstr type") - } - if hasLabel(h, HeaderLabelPartialIV) { - return errors.New("header parameter: IV and PartialIV: parameters must not both be present") - } - case HeaderLabelPartialIV: - if !canBstr(value) { - return errors.New("header parameter: Partial IV: require bstr type") - } - if hasLabel(h, HeaderLabelIV) { - return errors.New("header parameter: IV and PartialIV: parameters must not both be present") - } - } - } - return nil -} - -// canUint reports whether v can be used as a CBOR uint type. -func canUint(v interface{}) bool { - switch v := v.(type) { - case uint, uint8, uint16, uint32, uint64: - return true - case int: - return v >= 0 - case int8: - return v >= 0 - case int16: - return v >= 0 - case int32: - return v >= 0 - case int64: - return v >= 0 - } - return false -} - -// canInt reports whether v can be used as a CBOR int type. -func canInt(v interface{}) bool { - switch v.(type) { - case int, int8, int16, int32, int64, - uint, uint8, uint16, uint32, uint64: - return true - } - return false -} - -// canTstr reports whether v can be used as a CBOR tstr type. -func canTstr(v interface{}) bool { - _, ok := v.(string) - return ok -} - -// canBstr reports whether v can be used as a CBOR bstr type. -func canBstr(v interface{}) bool { - _, ok := v.([]byte) - return ok -} - -// normalizeLabel tries to cast label into a int64 or a string. -// Returns (nil, false) if the label type is not valid. -func normalizeLabel(label interface{}) (interface{}, bool) { - switch v := label.(type) { - case int: - label = int64(v) - case int8: - label = int64(v) - case int16: - label = int64(v) - case int32: - label = int64(v) - case int64: - label = int64(v) - case uint: - label = int64(v) - case uint8: - label = int64(v) - case uint16: - label = int64(v) - case uint32: - label = int64(v) - case uint64: - label = int64(v) - case string: - // no conversion - default: - return nil, false - } - return label, true -} - -// headerLabelValidator is used to validate the header label of a COSE header. -type headerLabelValidator struct { - value interface{} -} - -// String prints the value without brackets `{}`. Useful in error printing. -func (hlv headerLabelValidator) String() string { - return fmt.Sprint(hlv.value) -} - -// UnmarshalCBOR decodes the label value of a COSE header, and returns error if -// label is not a int (major type 0, 1) or string (major type 3). -func (hlv *headerLabelValidator) UnmarshalCBOR(data []byte) error { - if len(data) == 0 { - return errors.New("cbor: header label: missing type") - } - switch data[0] >> 5 { - case 0, 1, 3: - err := decMode.Unmarshal(data, &hlv.value) - if err != nil { - return err - } - if _, ok := hlv.value.(big.Int); ok { - return errors.New("cbor: header label: int key must not be higher than 1<<63 - 1") - } - return nil - } - return errors.New("cbor: header label: require int / tstr type") -} - -// discardedCBORMessage is used to read CBOR message and discard it. -type discardedCBORMessage struct{} - -// UnmarshalCBOR discards the read CBOR object. -func (discardedCBORMessage) UnmarshalCBOR(data []byte) error { - return nil -} - -// validateHeaderLabelCBOR validates if all header labels are integers or -// strings of a CBOR map object. -// -// label = int / tstr -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-1.4 -func validateHeaderLabelCBOR(data []byte) error { - var header map[headerLabelValidator]discardedCBORMessage - return decMode.Unmarshal(data, &header) -} diff --git a/vendor/github.com/veraison/go-cose/key.go b/vendor/github.com/veraison/go-cose/key.go deleted file mode 100644 index 741eaf3..0000000 --- a/vendor/github.com/veraison/go-cose/key.go +++ /dev/null @@ -1,802 +0,0 @@ -package cose - -import ( - "crypto" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/elliptic" - "errors" - "fmt" - "math/big" - "strconv" - - cbor "github.com/fxamacker/cbor/v2" -) - -const ( - // An inviald key_op value - KeyOpInvalid KeyOp = 0 - - // The key is used to create signatures. Requires private key fields. - KeyOpSign KeyOp = 1 - - // The key is used for verification of signatures. - KeyOpVerify KeyOp = 2 - - // The key is used for key transport encryption. - KeyOpEncrypt KeyOp = 3 - - // The key is used for key transport decryption. Requires private key fields. - KeyOpDecrypt KeyOp = 4 - - // The key is used for key wrap encryption. - KeyOpWrapKey KeyOp = 5 - - // The key is used for key wrap decryption. - KeyOpUnwrapKey KeyOp = 6 - - // The key is used for deriving keys. Requires private key fields. - KeyOpDeriveKey KeyOp = 7 - - // The key is used for deriving bits not to be used as a key. Requires - // private key fields. - KeyOpDeriveBits KeyOp = 8 - - // The key is used for creating MACs. - KeyOpMACCreate KeyOp = 9 - - // The key is used for validating MACs. - KeyOpMACVerify KeyOp = 10 -) - -// KeyOp represents a key_ops value used to restrict purposes for which a Key -// may be used. -type KeyOp int64 - -// KeyOpFromString returns the KeyOp corresponding to the specified name. -// The values are taken from https://www.rfc-editor.org/rfc/rfc7517#section-4.3 -func KeyOpFromString(val string) (KeyOp, error) { - switch val { - case "sign": - return KeyOpSign, nil - case "verify": - return KeyOpVerify, nil - case "encrypt": - return KeyOpEncrypt, nil - case "decrypt": - return KeyOpDecrypt, nil - case "wrapKey": - return KeyOpWrapKey, nil - case "unwrapKey": - return KeyOpUnwrapKey, nil - case "deriveKey": - return KeyOpDeriveKey, nil - case "deriveBits": - return KeyOpDeriveBits, nil - default: - return KeyOpInvalid, fmt.Errorf("unknown key_ops value %q", val) - } -} - -// String returns a string representation of the KeyType. Note does not -// represent a valid value of the corresponding serialized entry, and must not -// be used as such. (The values returned _mostly_ correspond to those accepted -// by KeyOpFromString, except for MAC create/verify, which are not defined by -// RFC7517). -func (ko KeyOp) String() string { - switch ko { - case KeyOpSign: - return "sign" - case KeyOpVerify: - return "verify" - case KeyOpEncrypt: - return "encrypt" - case KeyOpDecrypt: - return "decrypt" - case KeyOpWrapKey: - return "wrapKey" - case KeyOpUnwrapKey: - return "unwrapKey" - case KeyOpDeriveKey: - return "deriveKey" - case KeyOpDeriveBits: - return "deriveBits" - case KeyOpMACCreate: - return "MAC create" - case KeyOpMACVerify: - return "MAC verify" - default: - return "unknown key_op value " + strconv.Itoa(int(ko)) - } -} - -// IsSupported returnns true if the specified value is represents one of the -// key_ops defined in -// https://www.rfc-editor.org/rfc/rfc9052.html#name-cose-key-common-parameters -func (ko KeyOp) IsSupported() bool { - return ko >= 1 && ko <= 10 -} - -// MarshalCBOR marshals the KeyOp as a CBOR int. -func (ko KeyOp) MarshalCBOR() ([]byte, error) { - return encMode.Marshal(int64(ko)) -} - -// UnmarshalCBOR populates the KeyOp from the provided CBOR value (must be int -// or tstr). -func (ko *KeyOp) UnmarshalCBOR(data []byte) error { - var raw intOrStr - - if err := raw.UnmarshalCBOR(data); err != nil { - return fmt.Errorf("invalid key_ops value %w", err) - } - - if raw.IsString() { - v, err := KeyOpFromString(raw.String()) - if err != nil { - return err - } - - *ko = v - } else { - v := raw.Int() - *ko = KeyOp(v) - - if !ko.IsSupported() { - return fmt.Errorf("unknown key_ops value %d", v) - } - } - - return nil -} - -// KeyType identifies the family of keys represented by the associated Key. -// This determines which files within the Key must be set in order for it to be -// valid. -type KeyType int64 - -const ( - // Invlaid key type - KeyTypeInvalid KeyType = 0 - // Octet Key Pair - KeyTypeOKP KeyType = 1 - // Elliptic Curve Keys w/ x- and y-coordinate pair - KeyTypeEC2 KeyType = 2 - // Symmetric Keys - KeyTypeSymmetric KeyType = 4 -) - -// String returns a string representation of the KeyType. Note does not -// represent a valid value of the corresponding serialized entry, and must -// not be used as such. -func (kt KeyType) String() string { - switch kt { - case KeyTypeOKP: - return "OKP" - case KeyTypeEC2: - return "EC2" - case KeyTypeSymmetric: - return "Symmetric" - default: - return "unknown key type value " + strconv.Itoa(int(kt)) - } -} - -// MarshalCBOR marshals the KeyType as a CBOR int. -func (kt KeyType) MarshalCBOR() ([]byte, error) { - return encMode.Marshal(int(kt)) -} - -// UnmarshalCBOR populates the KeyType from the provided CBOR value (must be -// int or tstr). -func (kt *KeyType) UnmarshalCBOR(data []byte) error { - var raw intOrStr - - if err := raw.UnmarshalCBOR(data); err != nil { - return fmt.Errorf("invalid key type value: %w", err) - } - - if raw.IsString() { - v, err := keyTypeFromString(raw.String()) - - if err != nil { - return err - } - - *kt = v - } else { - v := raw.Int() - - if v == 0 { - // 0 is reserved, and so can never be valid - return fmt.Errorf("invalid key type value 0") - } - - if v > 4 || v < 0 || v == 3 { - return fmt.Errorf("unknown key type value %d", v) - } - - *kt = KeyType(v) - } - - return nil -} - -// NOTE: there are currently no registered string key type values. -func keyTypeFromString(v string) (KeyType, error) { - return KeyTypeInvalid, fmt.Errorf("unknown key type value %q", v) -} - -const ( - - // Invalid/unrecognised curve - CurveInvalid Curve = 0 - - // NIST P-256 also known as secp256r1 - CurveP256 Curve = 1 - - // NIST P-384 also known as secp384r1 - CurveP384 Curve = 2 - - // NIST P-521 also known as secp521r1 - CurveP521 Curve = 3 - - // X25519 for use w/ ECDH only - CurveX25519 Curve = 4 - - // X448 for use w/ ECDH only - CurveX448 Curve = 5 - - // Ed25519 for use /w EdDSA only - CurveEd25519 Curve = 6 - - // Ed448 for use /w EdDSA only - CurveEd448 Curve = 7 -) - -// Curve represents the EC2/OKP key's curve. See: -// https://datatracker.ietf.org/doc/html/rfc8152#section-13.1 -type Curve int64 - -// String returns a string representation of the Curve. Note does not -// represent a valid value of the corresponding serialized entry, and must -// not be used as such. -func (c Curve) String() string { - switch c { - case CurveP256: - return "P-256" - case CurveP384: - return "P-384" - case CurveP521: - return "P-521" - case CurveX25519: - return "X25519" - case CurveX448: - return "X448" - case CurveEd25519: - return "Ed25519" - case CurveEd448: - return "Ed448" - default: - return "unknown curve value " + strconv.Itoa(int(c)) - } -} - -// MarshalCBOR marshals the KeyType as a CBOR int. -func (c Curve) MarshalCBOR() ([]byte, error) { - return encMode.Marshal(int(c)) -} - -// UnmarshalCBOR populates the KeyType from the provided CBOR value (must be -// int or tstr). -func (c *Curve) UnmarshalCBOR(data []byte) error { - var raw intOrStr - - if err := raw.UnmarshalCBOR(data); err != nil { - return fmt.Errorf("invalid curve value: %w", err) - } - - if raw.IsString() { - v, err := curveFromString(raw.String()) - - if err != nil { - return err - } - - *c = v - } else { - v := raw.Int() - - if v < 1 || v > 7 { - return fmt.Errorf("unknown curve value %d", v) - } - - *c = Curve(v) - } - - return nil -} - -// NOTE: there are currently no registered string values for curves. -func curveFromString(v string) (Curve, error) { - return CurveInvalid, fmt.Errorf("unknown curve value %q", v) -} - -// Key represents a COSE_Key structure, as defined by RFC8152. -// Note: currently, this does NOT support RFC8230 (RSA algorithms). -type Key struct { - // Common parameters. These are independent of the key type. Only - // KeyType common parameter MUST be set. - - // KeyType identifies the family of keys for this structure, and thus, - // which of the key-type-specific parameters need to be set. - KeyType KeyType `cbor:"1,keyasint"` - // KeyID is the identification value matched to the kid in the message. - KeyID []byte `cbor:"2,keyasint,omitempty"` - // KeyOps can be set to restrict the set of operations that the Key is used for. - KeyOps []KeyOp `cbor:"4,keyasint,omitempty"` - // BaseIV is the Base IV to be xor-ed with Partial IVs. - BaseIV []byte `cbor:"5,keyasint,omitempty"` - - // Algorithm is used to restrict the algorithm that is used with the - // key. If it is set, the application MUST verify that it matches the - // algorithm for which the Key is being used. - Algorithm Algorithm `cbor:"-"` - // Curve is EC identifier -- taken form "COSE Elliptic Curves" IANA registry. - // Populated from keyStruct.RawKeyParam when key type is EC2 or OKP. - Curve Curve `cbor:"-"` - // K is the key value. Populated from keyStruct.RawKeyParam when key - // type is Symmetric. - K []byte `cbor:"-"` - - // EC2/OKP params - - // X is the x-coordinate - X []byte `cbor:"-2,keyasint,omitempty"` - // Y is the y-coordinate (sign bits are not supported) - Y []byte `cbor:"-3,keyasint,omitempty"` - // D is the private key - D []byte `cbor:"-4,keyasint,omitempty"` -} - -// NewOKPKey returns a Key created using the provided Octet Key Pair data. -func NewOKPKey(alg Algorithm, x, d []byte) (*Key, error) { - if alg != AlgorithmEd25519 { - return nil, fmt.Errorf("unsupported algorithm %q", alg) - } - - key := &Key{ - KeyType: KeyTypeOKP, - Algorithm: alg, - Curve: CurveEd25519, - X: x, - D: d, - } - return key, key.Validate() -} - -// NewEC2Key returns a Key created using the provided elliptic curve key -// data. -func NewEC2Key(alg Algorithm, x, y, d []byte) (*Key, error) { - var curve Curve - - switch alg { - case AlgorithmES256: - curve = CurveP256 - case AlgorithmES384: - curve = CurveP384 - case AlgorithmES512: - curve = CurveP521 - default: - return nil, fmt.Errorf("unsupported algorithm %q", alg) - } - - key := &Key{ - KeyType: KeyTypeEC2, - Algorithm: alg, - Curve: curve, - X: x, - Y: y, - D: d, - } - return key, key.Validate() -} - -// NewSymmetricKey returns a Key created using the provided Symmetric key -// bytes. -func NewSymmetricKey(k []byte) (*Key, error) { - key := &Key{ - KeyType: KeyTypeSymmetric, - K: k, - } - return key, key.Validate() -} - -// NewKeyFromPublic returns a Key created using the provided crypto.PublicKey -// and Algorithm. -func NewKeyFromPublic(alg Algorithm, pub crypto.PublicKey) (*Key, error) { - switch alg { - case AlgorithmES256, AlgorithmES384, AlgorithmES512: - vk, ok := pub.(*ecdsa.PublicKey) - if !ok { - return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) - } - - return NewEC2Key(alg, vk.X.Bytes(), vk.Y.Bytes(), nil) - case AlgorithmEd25519: - vk, ok := pub.(ed25519.PublicKey) - if !ok { - return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) - } - - return NewOKPKey(alg, []byte(vk), nil) - default: - return nil, ErrAlgorithmNotSupported - } -} - -// NewKeyFromPrivate returns a Key created using provided crypto.PrivateKey -// and Algorithm. -func NewKeyFromPrivate(alg Algorithm, priv crypto.PrivateKey) (*Key, error) { - switch alg { - case AlgorithmES256, AlgorithmES384, AlgorithmES512: - sk, ok := priv.(*ecdsa.PrivateKey) - if !ok { - return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPrivKey) - } - - return NewEC2Key(alg, sk.X.Bytes(), sk.Y.Bytes(), sk.D.Bytes()) - case AlgorithmEd25519: - sk, ok := priv.(ed25519.PrivateKey) - if !ok { - return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPrivKey) - } - return NewOKPKey(alg, []byte(sk[32:]), []byte(sk[:32])) - default: - return nil, ErrAlgorithmNotSupported - } -} - -// Validate ensures that the parameters set inside the Key are internally -// consistent (e.g., that the key type is appropriate to the curve.) -func (k Key) Validate() error { - switch k.KeyType { - case KeyTypeEC2: - switch k.Curve { - case CurveP256, CurveP384, CurveP521: - // ok - default: - return fmt.Errorf( - "EC2 curve must be P-256, P-384, or P-521; found %q", - k.Curve.String(), - ) - } - case KeyTypeOKP: - switch k.Curve { - case CurveX25519, CurveX448, CurveEd25519, CurveEd448: - // ok - default: - return fmt.Errorf( - "OKP curve must be X25519, X448, Ed25519, or Ed448; found %q", - k.Curve.String(), - ) - } - case KeyTypeSymmetric: - default: - return errors.New(k.KeyType.String()) - } - - // If Algorithm is set, it must match the specified key parameters. - if k.Algorithm != AlgorithmInvalid { - expectedAlg, err := k.deriveAlgorithm() - if err != nil { - return err - } - - if k.Algorithm != expectedAlg { - return fmt.Errorf( - "found algorithm %q (expected %q)", - k.Algorithm.String(), - expectedAlg.String(), - ) - } - } - - return nil -} - -type keyalias Key - -type marshaledKey struct { - keyalias - - // RawAlgorithm contains the raw Algorithm value, this is necessary - // because cbor library ignores omitempty on types that implement the - // cbor.Marshaler interface. - RawAlgorithm cbor.RawMessage `cbor:"3,keyasint,omitempty"` - - // RawKeyParam contains the raw CBOR encoded data for the label -1. - // Depending on the KeyType this is used to populate either Curve or K - // below. - RawKeyParam cbor.RawMessage `cbor:"-1,keyasint,omitempty"` -} - -// MarshalCBOR encodes Key into a COSE_Key object. -func (k *Key) MarshalCBOR() ([]byte, error) { - tmp := marshaledKey{ - keyalias: keyalias(*k), - } - var err error - - switch k.KeyType { - case KeyTypeSymmetric: - if tmp.RawKeyParam, err = encMode.Marshal(k.K); err != nil { - return nil, err - } - case KeyTypeEC2, KeyTypeOKP: - if tmp.RawKeyParam, err = encMode.Marshal(k.Curve); err != nil { - return nil, err - } - default: - return nil, fmt.Errorf("invalid key type: %q", k.KeyType.String()) - } - - if k.Algorithm != AlgorithmInvalid { - if tmp.RawAlgorithm, err = encMode.Marshal(k.Algorithm); err != nil { - return nil, err - } - } - - return encMode.Marshal(tmp) -} - -// UnmarshalCBOR decodes a COSE_Key object into Key. -func (k *Key) UnmarshalCBOR(data []byte) error { - var tmp marshaledKey - - if err := decMode.Unmarshal(data, &tmp); err != nil { - return err - } - *k = Key(tmp.keyalias) - - if tmp.RawAlgorithm != nil { - if err := decMode.Unmarshal(tmp.RawAlgorithm, &k.Algorithm); err != nil { - return err - } - } - - switch k.KeyType { - case KeyTypeEC2: - if tmp.RawKeyParam == nil { - return errors.New("missing Curve parameter (required for EC2 key type)") - } - - if err := decMode.Unmarshal(tmp.RawKeyParam, &k.Curve); err != nil { - return err - } - case KeyTypeOKP: - if tmp.RawKeyParam == nil { - return errors.New("missing Curve parameter (required for OKP key type)") - } - - if err := decMode.Unmarshal(tmp.RawKeyParam, &k.Curve); err != nil { - return err - } - case KeyTypeSymmetric: - if tmp.RawKeyParam == nil { - return errors.New("missing K parameter (required for Symmetric key type)") - } - - if err := decMode.Unmarshal(tmp.RawKeyParam, &k.K); err != nil { - return err - } - default: - // this should not be reachable as KeyType.UnmarshalCBOR would - // result in an error during decMode.Unmarshal() above, if the - // value in the data doesn't correspond to one of the above - // types. - return fmt.Errorf("unexpected key type %q", k.KeyType.String()) - } - - return k.Validate() -} - -// PublicKey returns a crypto.PublicKey generated using Key's parameters. -func (k *Key) PublicKey() (crypto.PublicKey, error) { - alg, err := k.deriveAlgorithm() - if err != nil { - return nil, err - } - - switch alg { - case AlgorithmES256, AlgorithmES384, AlgorithmES512: - var curve elliptic.Curve - - switch alg { - case AlgorithmES256: - curve = elliptic.P256() - case AlgorithmES384: - curve = elliptic.P384() - case AlgorithmES512: - curve = elliptic.P521() - } - - pub := &ecdsa.PublicKey{Curve: curve, X: new(big.Int), Y: new(big.Int)} - pub.X.SetBytes(k.X) - pub.Y.SetBytes(k.Y) - - return pub, nil - case AlgorithmEd25519: - return ed25519.PublicKey(k.X), nil - default: - return nil, ErrAlgorithmNotSupported - } -} - -// PrivateKey returns a crypto.PrivateKey generated using Key's parameters. -func (k *Key) PrivateKey() (crypto.PrivateKey, error) { - alg, err := k.deriveAlgorithm() - if err != nil { - return nil, err - } - - if len(k.D) == 0 { - return nil, ErrNotPrivKey - } - - switch alg { - case AlgorithmES256, AlgorithmES384, AlgorithmES512: - var curve elliptic.Curve - - switch alg { - case AlgorithmES256: - curve = elliptic.P256() - case AlgorithmES384: - curve = elliptic.P384() - case AlgorithmES512: - curve = elliptic.P521() - } - - priv := &ecdsa.PrivateKey{ - PublicKey: ecdsa.PublicKey{Curve: curve, X: new(big.Int), Y: new(big.Int)}, - D: new(big.Int), - } - priv.X.SetBytes(k.X) - priv.Y.SetBytes(k.Y) - priv.D.SetBytes(k.D) - - return priv, nil - case AlgorithmEd25519: - buf := make([]byte, ed25519.PrivateKeySize) - - copy(buf, k.D) - copy(buf[32:], k.X) - - return ed25519.PrivateKey(buf), nil - default: - return nil, ErrAlgorithmNotSupported - } -} - -// AlgorithmOrDefault returns the Algorithm associated with Key. If Key.Algorithm is -// set, that is what is returned. Otherwise, the algorithm is inferred using -// Key.Curve. This method does NOT validate that Key.Algorithm, if set, aligns -// with Key.Curve. -func (k *Key) AlgorithmOrDefault() (Algorithm, error) { - if k.Algorithm != AlgorithmInvalid { - return k.Algorithm, nil - } - - return k.deriveAlgorithm() -} - -// Signer returns a Signer created using Key. -func (k *Key) Signer() (Signer, error) { - if err := k.Validate(); err != nil { - return nil, err - } - - if k.KeyOps != nil { - signFound := false - - for _, kop := range k.KeyOps { - if kop == KeyOpSign { - signFound = true - break - } - } - - if !signFound { - return nil, ErrSignOpNotSupported - } - } - - priv, err := k.PrivateKey() - if err != nil { - return nil, err - } - - alg, err := k.AlgorithmOrDefault() - if err != nil { - return nil, err - } - - var signer crypto.Signer - var ok bool - - switch alg { - case AlgorithmES256, AlgorithmES384, AlgorithmES512: - signer, ok = priv.(*ecdsa.PrivateKey) - if !ok { - return nil, ErrInvalidPrivKey - } - case AlgorithmEd25519: - signer, ok = priv.(ed25519.PrivateKey) - if !ok { - return nil, ErrInvalidPrivKey - } - default: - return nil, ErrAlgorithmNotSupported - } - - return NewSigner(alg, signer) -} - -// Verifier returns a Verifier created using Key. -func (k *Key) Verifier() (Verifier, error) { - if err := k.Validate(); err != nil { - return nil, err - } - - if k.KeyOps != nil { - verifyFound := false - - for _, kop := range k.KeyOps { - if kop == KeyOpVerify { - verifyFound = true - break - } - } - - if !verifyFound { - return nil, ErrVerifyOpNotSupported - } - } - - pub, err := k.PublicKey() - if err != nil { - return nil, err - } - - alg, err := k.AlgorithmOrDefault() - if err != nil { - return nil, err - } - - return NewVerifier(alg, pub) -} - -// deriveAlgorithm derives the intended algorithm for the key from its curve. -// The deriviation is based on the recommendation in RFC8152 that SHA-256 is -// only used with P-256, etc. For other combinations, the Algorithm in the Key -// must be explicitly set,so that this derivation is not used. -func (k *Key) deriveAlgorithm() (Algorithm, error) { - switch k.KeyType { - case KeyTypeEC2, KeyTypeOKP: - switch k.Curve { - case CurveP256: - return AlgorithmES256, nil - case CurveP384: - return AlgorithmES384, nil - case CurveP521: - return AlgorithmES512, nil - case CurveEd25519: - return AlgorithmEd25519, nil - default: - return AlgorithmInvalid, fmt.Errorf("unsupported curve %q", k.Curve.String()) - } - default: - // Symmetric algorithms are not supported in the current inmplementation. - return AlgorithmInvalid, fmt.Errorf("unexpected key type %q", k.KeyType.String()) - } -} diff --git a/vendor/github.com/veraison/go-cose/rsa.go b/vendor/github.com/veraison/go-cose/rsa.go deleted file mode 100644 index b63098c..0000000 --- a/vendor/github.com/veraison/go-cose/rsa.go +++ /dev/null @@ -1,68 +0,0 @@ -package cose - -import ( - "crypto" - "crypto/rsa" - "io" -) - -// rsaSigner is a RSASSA-PSS based signer with a generic crypto.Signer. -// -// Reference: https://www.rfc-editor.org/rfc/rfc8230.html#section-2 -type rsaSigner struct { - alg Algorithm - key crypto.Signer -} - -// Algorithm returns the signing algorithm associated with the private key. -func (rs *rsaSigner) Algorithm() Algorithm { - return rs.alg -} - -// Sign signs message content with the private key, using entropy from rand. -// The resulting signature should follow RFC 8152 section 8. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8 -func (rs *rsaSigner) Sign(rand io.Reader, content []byte) ([]byte, error) { - hash := rs.alg.hashFunc() - digest, err := computeHash(hash, content) - if err != nil { - return nil, err - } - return rs.key.Sign(rand, digest, &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, // defined in RFC 8230 sec 2 - Hash: hash, - }) -} - -// rsaVerifier is a RSASSA-PSS based verifier with golang built-in keys. -// -// Reference: https://www.rfc-editor.org/rfc/rfc8230.html#section-2 -type rsaVerifier struct { - alg Algorithm - key *rsa.PublicKey -} - -// Algorithm returns the signing algorithm associated with the public key. -func (rv *rsaVerifier) Algorithm() Algorithm { - return rv.alg -} - -// Verify verifies message content with the public key, returning nil for -// success. -// Otherwise, it returns ErrVerification. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8 -func (rv *rsaVerifier) Verify(content []byte, signature []byte) error { - hash := rv.alg.hashFunc() - digest, err := computeHash(hash, content) - if err != nil { - return err - } - if err := rsa.VerifyPSS(rv.key, hash, digest, signature, &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, // defined in RFC 8230 sec 2 - }); err != nil { - return ErrVerification - } - return nil -} diff --git a/vendor/github.com/veraison/go-cose/sign.go b/vendor/github.com/veraison/go-cose/sign.go deleted file mode 100644 index cd86d11..0000000 --- a/vendor/github.com/veraison/go-cose/sign.go +++ /dev/null @@ -1,475 +0,0 @@ -package cose - -import ( - "bytes" - "errors" - "fmt" - "io" - - "github.com/fxamacker/cbor/v2" -) - -// signature represents a COSE_Signature CBOR object: -// -// COSE_Signature = [ -// Headers, -// signature : bstr -// ] -// -// Reference: https://tools.ietf.org/html/rfc8152#section-4.1 -type signature struct { - _ struct{} `cbor:",toarray"` - Protected cbor.RawMessage - Unprotected cbor.RawMessage - Signature byteString -} - -// signaturePrefix represents the fixed prefix of COSE_Signature. -var signaturePrefix = []byte{ - 0x83, // Array of length 3 -} - -// Signature represents a decoded COSE_Signature. -// -// Reference: https://tools.ietf.org/html/rfc8152#section-4.1 -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -type Signature struct { - Headers Headers - Signature []byte -} - -// NewSignature returns a Signature with header initialized. -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -func NewSignature() *Signature { - return &Signature{ - Headers: Headers{ - Protected: ProtectedHeader{}, - Unprotected: UnprotectedHeader{}, - }, - } -} - -// MarshalCBOR encodes Signature into a COSE_Signature object. -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -func (s *Signature) MarshalCBOR() ([]byte, error) { - if s == nil { - return nil, errors.New("cbor: MarshalCBOR on nil Signature pointer") - } - if len(s.Signature) == 0 { - return nil, ErrEmptySignature - } - protected, unprotected, err := s.Headers.marshal() - if err != nil { - return nil, err - } - sig := signature{ - Protected: protected, - Unprotected: unprotected, - Signature: s.Signature, - } - return encMode.Marshal(sig) -} - -// UnmarshalCBOR decodes a COSE_Signature object into Signature. -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -func (s *Signature) UnmarshalCBOR(data []byte) error { - if s == nil { - return errors.New("cbor: UnmarshalCBOR on nil Signature pointer") - } - - // fast signature check - if !bytes.HasPrefix(data, signaturePrefix) { - return errors.New("cbor: invalid Signature object") - } - - // decode to signature and parse - var raw signature - if err := decModeWithTagsForbidden.Unmarshal(data, &raw); err != nil { - return err - } - if len(raw.Signature) == 0 { - return ErrEmptySignature - } - sig := Signature{ - Headers: Headers{ - RawProtected: raw.Protected, - RawUnprotected: raw.Unprotected, - }, - Signature: raw.Signature, - } - if err := sig.Headers.UnmarshalFromRaw(); err != nil { - return err - } - - *s = sig - return nil -} - -// Sign signs a Signature using the provided Signer. -// Signing a COSE_Signature requires the encoded protected header and the -// payload of its parent message. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -func (s *Signature) Sign(rand io.Reader, signer Signer, protected cbor.RawMessage, payload, external []byte) error { - if s == nil { - return errors.New("signing nil Signature") - } - if payload == nil { - return ErrMissingPayload - } - if len(s.Signature) > 0 { - return errors.New("Signature already has signature bytes") - } - if len(protected) == 0 || protected[0]>>5 != 2 { // protected is a bstr - return errors.New("invalid body protected headers") - } - - // check algorithm if present. - // `alg` header MUST present if there is no externally supplied data. - alg := signer.Algorithm() - if err := s.Headers.ensureSigningAlgorithm(alg, external); err != nil { - return err - } - - // sign the message - toBeSigned, err := s.toBeSigned(protected, payload, external) - if err != nil { - return err - } - sig, err := signer.Sign(rand, toBeSigned) - if err != nil { - return err - } - - s.Signature = sig - return nil -} - -// Verify verifies the signature, returning nil on success or a suitable error -// if verification fails. -// Verifying a COSE_Signature requires the encoded protected header and the -// payload of its parent message. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -func (s *Signature) Verify(verifier Verifier, protected cbor.RawMessage, payload, external []byte) error { - if s == nil { - return errors.New("verifying nil Signature") - } - if payload == nil { - return ErrMissingPayload - } - if len(s.Signature) == 0 { - return ErrEmptySignature - } - if len(protected) == 0 || protected[0]>>5 != 2 { // protected is a bstr - return errors.New("invalid body protected headers") - } - - // check algorithm if present. - // `alg` header MUST present if there is no externally supplied data. - alg := verifier.Algorithm() - err := s.Headers.ensureVerificationAlgorithm(alg, external) - if err != nil { - return err - } - - // verify the message - toBeSigned, err := s.toBeSigned(protected, payload, external) - if err != nil { - return err - } - return verifier.Verify(toBeSigned, s.Signature) -} - -// toBeSigned constructs Sig_structure, computes and returns ToBeSigned. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func (s *Signature) toBeSigned(bodyProtected cbor.RawMessage, payload, external []byte) ([]byte, error) { - // create a Sig_structure and populate it with the appropriate fields. - // - // Sig_structure = [ - // context : "Signature", - // body_protected : empty_or_serialized_map, - // sign_protected : empty_or_serialized_map, - // external_aad : bstr, - // payload : bstr - // ] - bodyProtected, err := deterministicBinaryString(bodyProtected) - if err != nil { - return nil, err - } - var signProtected cbor.RawMessage - signProtected, err = s.Headers.MarshalProtected() - if err != nil { - return nil, err - } - signProtected, err = deterministicBinaryString(signProtected) - if err != nil { - return nil, err - } - if external == nil { - external = []byte{} - } - sigStructure := []interface{}{ - "Signature", // context - bodyProtected, // body_protected - signProtected, // sign_protected - external, // external_aad - payload, // payload - } - - // create the value ToBeSigned by encoding the Sig_structure to a byte - // string. - return encMode.Marshal(sigStructure) -} - -// signMessage represents a COSE_Sign CBOR object: -// -// COSE_Sign = [ -// Headers, -// payload : bstr / nil, -// signatures : [+ COSE_Signature] -// ] -// -// Reference: https://tools.ietf.org/html/rfc8152#section-4.1 -type signMessage struct { - _ struct{} `cbor:",toarray"` - Protected cbor.RawMessage - Unprotected cbor.RawMessage - Payload byteString - Signatures []cbor.RawMessage -} - -// signMessagePrefix represents the fixed prefix of COSE_Sign_Tagged. -var signMessagePrefix = []byte{ - 0xd8, 0x62, // #6.98 - 0x84, // Array of length 4 -} - -// SignMessage represents a decoded COSE_Sign message. -// -// Reference: https://tools.ietf.org/html/rfc8152#section-4.1 -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -type SignMessage struct { - Headers Headers - Payload []byte - Signatures []*Signature -} - -// NewSignMessage returns a SignMessage with header initialized. -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -func NewSignMessage() *SignMessage { - return &SignMessage{ - Headers: Headers{ - Protected: ProtectedHeader{}, - Unprotected: UnprotectedHeader{}, - }, - } -} - -// MarshalCBOR encodes SignMessage into a COSE_Sign_Tagged object. -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -func (m *SignMessage) MarshalCBOR() ([]byte, error) { - if m == nil { - return nil, errors.New("cbor: MarshalCBOR on nil SignMessage pointer") - } - if len(m.Signatures) == 0 { - return nil, ErrNoSignatures - } - protected, unprotected, err := m.Headers.marshal() - if err != nil { - return nil, err - } - signatures := make([]cbor.RawMessage, 0, len(m.Signatures)) - for _, sig := range m.Signatures { - sigCBOR, err := sig.MarshalCBOR() - if err != nil { - return nil, err - } - signatures = append(signatures, sigCBOR) - } - content := signMessage{ - Protected: protected, - Unprotected: unprotected, - Payload: m.Payload, - Signatures: signatures, - } - return encMode.Marshal(cbor.Tag{ - Number: CBORTagSignMessage, - Content: content, - }) -} - -// UnmarshalCBOR decodes a COSE_Sign_Tagged object into SignMessage. -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -func (m *SignMessage) UnmarshalCBOR(data []byte) error { - if m == nil { - return errors.New("cbor: UnmarshalCBOR on nil SignMessage pointer") - } - - // fast message check - if !bytes.HasPrefix(data, signMessagePrefix) { - return errors.New("cbor: invalid COSE_Sign_Tagged object") - } - - // decode to signMessage and parse - var raw signMessage - if err := decModeWithTagsForbidden.Unmarshal(data[2:], &raw); err != nil { - return err - } - if len(raw.Signatures) == 0 { - return ErrNoSignatures - } - signatures := make([]*Signature, 0, len(raw.Signatures)) - for _, sigCBOR := range raw.Signatures { - sig := &Signature{} - if err := sig.UnmarshalCBOR(sigCBOR); err != nil { - return err - } - signatures = append(signatures, sig) - } - msg := SignMessage{ - Headers: Headers{ - RawProtected: raw.Protected, - RawUnprotected: raw.Unprotected, - }, - Payload: raw.Payload, - Signatures: signatures, - } - if err := msg.Headers.UnmarshalFromRaw(); err != nil { - return err - } - - *m = msg - return nil -} - -// Sign signs a SignMessage using the provided signers corresponding to the -// signatures. -// -// See `Signature.Sign()` for advanced signing scenarios. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -func (m *SignMessage) Sign(rand io.Reader, external []byte, signers ...Signer) error { - if m == nil { - return errors.New("signing nil SignMessage") - } - if m.Payload == nil { - return ErrMissingPayload - } - switch len(m.Signatures) { - case 0: - return ErrNoSignatures - case len(signers): - // no ops - default: - return fmt.Errorf("%d signers for %d signatures", len(signers), len(m.Signatures)) - } - - // populate common parameters - var protected cbor.RawMessage - protected, err := m.Headers.MarshalProtected() - if err != nil { - return err - } - - // sign message accordingly - for i, signature := range m.Signatures { - if err := signature.Sign(rand, signers[i], protected, m.Payload, external); err != nil { - return err - } - } - - return nil -} - -// Verify verifies the signatures on the SignMessage against the corresponding -// verifier, returning nil on success or a suitable error if verification fails. -// -// See `Signature.Verify()` for advanced verification scenarios like threshold -// policies. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -// -// # Experimental -// -// Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a -// later release. -func (m *SignMessage) Verify(external []byte, verifiers ...Verifier) error { - if m == nil { - return errors.New("verifying nil SignMessage") - } - if m.Payload == nil { - return ErrMissingPayload - } - switch len(m.Signatures) { - case 0: - return ErrNoSignatures - case len(verifiers): - // no ops - default: - return fmt.Errorf("%d verifiers for %d signatures", len(verifiers), len(m.Signatures)) - } - - // populate common parameters - var protected cbor.RawMessage - protected, err := m.Headers.MarshalProtected() - if err != nil { - return err - } - - // verify message accordingly - for i, signature := range m.Signatures { - if err := signature.Verify(verifiers[i], protected, m.Payload, external); err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/veraison/go-cose/sign1.go b/vendor/github.com/veraison/go-cose/sign1.go deleted file mode 100644 index fa229e9..0000000 --- a/vendor/github.com/veraison/go-cose/sign1.go +++ /dev/null @@ -1,319 +0,0 @@ -package cose - -import ( - "bytes" - "errors" - "io" - - "github.com/fxamacker/cbor/v2" -) - -// sign1Message represents a COSE_Sign1 CBOR object: -// -// COSE_Sign1 = [ -// Headers, -// payload : bstr / nil, -// signature : bstr -// ] -// -// Reference: https://tools.ietf.org/html/rfc8152#section-4.2 -type sign1Message struct { - _ struct{} `cbor:",toarray"` - Protected cbor.RawMessage - Unprotected cbor.RawMessage - Payload byteString - Signature byteString -} - -// sign1MessagePrefix represents the fixed prefix of COSE_Sign1_Tagged. -var sign1MessagePrefix = []byte{ - 0xd2, // #6.18 - 0x84, // Array of length 4 -} - -// Sign1Message represents a decoded COSE_Sign1 message. -// -// Reference: https://tools.ietf.org/html/rfc8152#section-4.2 -type Sign1Message struct { - Headers Headers - Payload []byte - Signature []byte -} - -// NewSign1Message returns a Sign1Message with header initialized. -func NewSign1Message() *Sign1Message { - return &Sign1Message{ - Headers: Headers{ - Protected: ProtectedHeader{}, - Unprotected: UnprotectedHeader{}, - }, - } -} - -// MarshalCBOR encodes Sign1Message into a COSE_Sign1_Tagged object. -func (m *Sign1Message) MarshalCBOR() ([]byte, error) { - content, err := m.getContent() - if err != nil { - return nil, err - } - - return encMode.Marshal(cbor.Tag{ - Number: CBORTagSign1Message, - Content: content, - }) -} - -// UnmarshalCBOR decodes a COSE_Sign1_Tagged object into Sign1Message. -func (m *Sign1Message) UnmarshalCBOR(data []byte) error { - if m == nil { - return errors.New("cbor: UnmarshalCBOR on nil Sign1Message pointer") - } - - // fast message check - if !bytes.HasPrefix(data, sign1MessagePrefix) { - return errors.New("cbor: invalid COSE_Sign1_Tagged object") - } - - return m.doUnmarshal(data[1:]) -} - -// Sign signs a Sign1Message using the provided Signer. -// The signature is stored in m.Signature. -// -// Note that m.Signature is only valid as long as m.Headers.Protected and -// m.Payload remain unchanged after calling this method. -// It is possible to modify m.Headers.Unprotected after signing, -// i.e., add counter signatures or timestamps. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func (m *Sign1Message) Sign(rand io.Reader, external []byte, signer Signer) error { - if m == nil { - return errors.New("signing nil Sign1Message") - } - if m.Payload == nil { - return ErrMissingPayload - } - if len(m.Signature) > 0 { - return errors.New("Sign1Message signature already has signature bytes") - } - - // check algorithm if present. - // `alg` header MUST be present if there is no externally supplied data. - alg := signer.Algorithm() - err := m.Headers.ensureSigningAlgorithm(alg, external) - if err != nil { - return err - } - - // sign the message - toBeSigned, err := m.toBeSigned(external) - if err != nil { - return err - } - sig, err := signer.Sign(rand, toBeSigned) - if err != nil { - return err - } - - m.Signature = sig - return nil -} - -// Verify verifies the signature on the Sign1Message returning nil on success or -// a suitable error if verification fails. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func (m *Sign1Message) Verify(external []byte, verifier Verifier) error { - if m == nil { - return errors.New("verifying nil Sign1Message") - } - if m.Payload == nil { - return ErrMissingPayload - } - if len(m.Signature) == 0 { - return ErrEmptySignature - } - - // check algorithm if present. - // `alg` header MUST present if there is no externally supplied data. - alg := verifier.Algorithm() - err := m.Headers.ensureVerificationAlgorithm(alg, external) - if err != nil { - return err - } - - // verify the message - toBeSigned, err := m.toBeSigned(external) - if err != nil { - return err - } - return verifier.Verify(toBeSigned, m.Signature) -} - -// toBeSigned constructs Sig_structure, computes and returns ToBeSigned. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func (m *Sign1Message) toBeSigned(external []byte) ([]byte, error) { - // create a Sig_structure and populate it with the appropriate fields. - // - // Sig_structure = [ - // context : "Signature1", - // body_protected : empty_or_serialized_map, - // external_aad : bstr, - // payload : bstr - // ] - var protected cbor.RawMessage - protected, err := m.Headers.MarshalProtected() - if err != nil { - return nil, err - } - protected, err = deterministicBinaryString(protected) - if err != nil { - return nil, err - } - if external == nil { - external = []byte{} - } - sigStructure := []interface{}{ - "Signature1", // context - protected, // body_protected - external, // external_aad - m.Payload, // payload - } - - // create the value ToBeSigned by encoding the Sig_structure to a byte - // string. - return encMode.Marshal(sigStructure) -} - -func (m *Sign1Message) getContent() (sign1Message, error) { - if m == nil { - return sign1Message{}, errors.New("cbor: MarshalCBOR on nil Sign1Message pointer") - } - if len(m.Signature) == 0 { - return sign1Message{}, ErrEmptySignature - } - protected, unprotected, err := m.Headers.marshal() - if err != nil { - return sign1Message{}, err - } - - content := sign1Message{ - Protected: protected, - Unprotected: unprotected, - Payload: m.Payload, - Signature: m.Signature, - } - - return content, nil -} - -func (m *Sign1Message) doUnmarshal(data []byte) error { - // decode to sign1Message and parse - var raw sign1Message - if err := decModeWithTagsForbidden.Unmarshal(data, &raw); err != nil { - return err - } - if len(raw.Signature) == 0 { - return ErrEmptySignature - } - msg := Sign1Message{ - Headers: Headers{ - RawProtected: raw.Protected, - RawUnprotected: raw.Unprotected, - }, - Payload: raw.Payload, - Signature: raw.Signature, - } - if err := msg.Headers.UnmarshalFromRaw(); err != nil { - return err - } - - *m = msg - return nil -} - -// Sign1 signs a Sign1Message using the provided Signer. -// -// This method is a wrapper of `Sign1Message.Sign()`. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func Sign1(rand io.Reader, signer Signer, headers Headers, payload []byte, external []byte) ([]byte, error) { - msg := Sign1Message{ - Headers: headers, - Payload: payload, - } - err := msg.Sign(rand, external, signer) - if err != nil { - return nil, err - } - return msg.MarshalCBOR() -} - -type UntaggedSign1Message Sign1Message - -// MarshalCBOR encodes UntaggedSign1Message into a COSE_Sign1 object. -func (m *UntaggedSign1Message) MarshalCBOR() ([]byte, error) { - content, err := (*Sign1Message)(m).getContent() - if err != nil { - return nil, err - } - - return encMode.Marshal(content) -} - -// UnmarshalCBOR decodes a COSE_Sign1 object into an UnataggedSign1Message. -func (m *UntaggedSign1Message) UnmarshalCBOR(data []byte) error { - if m == nil { - return errors.New("cbor: UnmarshalCBOR on nil UntaggedSign1Message pointer") - } - - if len(data) == 0 { - return errors.New("cbor: zero length data") - } - - // fast message check - ensure the frist byte indicates a four-element array - if data[0] != sign1MessagePrefix[1] { - return errors.New("cbor: invalid COSE_Sign1 object") - } - - return (*Sign1Message)(m).doUnmarshal(data) -} - -// Sign signs an UnttaggedSign1Message using the provided Signer. -// The signature is stored in m.Signature. -// -// Note that m.Signature is only valid as long as m.Headers.Protected and -// m.Payload remain unchanged after calling this method. -// It is possible to modify m.Headers.Unprotected after signing, -// i.e., add counter signatures or timestamps. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func (m *UntaggedSign1Message) Sign(rand io.Reader, external []byte, signer Signer) error { - return (*Sign1Message)(m).Sign(rand, external, signer) -} - -// Verify verifies the signature on the UntaggedSign1Message returning nil on success or -// a suitable error if verification fails. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func (m *UntaggedSign1Message) Verify(external []byte, verifier Verifier) error { - return (*Sign1Message)(m).Verify(external, verifier) -} - -// Sign1Untagged signs an UntaggedSign1Message using the provided Signer. -// -// This method is a wrapper of `UntaggedSign1Message.Sign()`. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func Sign1Untagged(rand io.Reader, signer Signer, headers Headers, payload []byte, external []byte) ([]byte, error) { - msg := UntaggedSign1Message{ - Headers: headers, - Payload: payload, - } - err := msg.Sign(rand, external, signer) - if err != nil { - return nil, err - } - return msg.MarshalCBOR() -} diff --git a/vendor/github.com/veraison/go-cose/signer.go b/vendor/github.com/veraison/go-cose/signer.go deleted file mode 100644 index 6747546..0000000 --- a/vendor/github.com/veraison/go-cose/signer.go +++ /dev/null @@ -1,81 +0,0 @@ -package cose - -import ( - "crypto" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/rsa" - "errors" - "fmt" - "io" -) - -// Signer is an interface for private keys to sign COSE signatures. -type Signer interface { - // Algorithm returns the signing algorithm associated with the private key. - Algorithm() Algorithm - - // Sign signs message content with the private key, possibly using entropy - // from rand. - // The resulting signature should follow RFC 8152 section 8. - // - // Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8 - Sign(rand io.Reader, content []byte) ([]byte, error) -} - -// NewSigner returns a signer with a given signing key. -// The signing key can be a golang built-in crypto private key, a key in HSM, or -// a remote KMS. -// -// Developers are encouraged to implement the `cose.Signer` interface instead of -// the `crypto.Signer` interface for better performance. -// -// All signing keys implementing `crypto.Signer` with `Public()` returning a -// public key of type `*rsa.PublicKey`, `*ecdsa.PublicKey`, or -// `ed25519.PublicKey` are accepted. -// -// Note: `*rsa.PrivateKey`, `*ecdsa.PrivateKey`, and `ed25519.PrivateKey` -// implement `crypto.Signer`. -func NewSigner(alg Algorithm, key crypto.Signer) (Signer, error) { - switch alg { - case AlgorithmPS256, AlgorithmPS384, AlgorithmPS512: - vk, ok := key.Public().(*rsa.PublicKey) - if !ok { - return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) - } - // RFC 8230 6.1 requires RSA keys having a minimum size of 2048 bits. - // Reference: https://www.rfc-editor.org/rfc/rfc8230.html#section-6.1 - if vk.N.BitLen() < 2048 { - return nil, errors.New("RSA key must be at least 2048 bits long") - } - return &rsaSigner{ - alg: alg, - key: key, - }, nil - case AlgorithmES256, AlgorithmES384, AlgorithmES512: - vk, ok := key.Public().(*ecdsa.PublicKey) - if !ok { - return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) - } - if sk, ok := key.(*ecdsa.PrivateKey); ok { - return &ecdsaKeySigner{ - alg: alg, - key: sk, - }, nil - } - return &ecdsaCryptoSigner{ - alg: alg, - key: vk, - signer: key, - }, nil - case AlgorithmEd25519: - if _, ok := key.Public().(ed25519.PublicKey); !ok { - return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) - } - return &ed25519Signer{ - key: key, - }, nil - default: - return nil, ErrAlgorithmNotSupported - } -} diff --git a/vendor/github.com/veraison/go-cose/verifier.go b/vendor/github.com/veraison/go-cose/verifier.go deleted file mode 100644 index 1c6e83b..0000000 --- a/vendor/github.com/veraison/go-cose/verifier.go +++ /dev/null @@ -1,67 +0,0 @@ -package cose - -import ( - "crypto" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/rsa" - "errors" - "fmt" -) - -// Verifier is an interface for public keys to verify COSE signatures. -type Verifier interface { - // Algorithm returns the signing algorithm associated with the public key. - Algorithm() Algorithm - - // Verify verifies message content with the public key, returning nil for - // success. - // Otherwise, it returns ErrVerification. - // - // Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8 - Verify(content, signature []byte) error -} - -// NewVerifier returns a verifier with a given public key. -// Only golang built-in crypto public keys of type `*rsa.PublicKey`, -// `*ecdsa.PublicKey`, and `ed25519.PublicKey` are accepted. -func NewVerifier(alg Algorithm, key crypto.PublicKey) (Verifier, error) { - switch alg { - case AlgorithmPS256, AlgorithmPS384, AlgorithmPS512: - vk, ok := key.(*rsa.PublicKey) - if !ok { - return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) - } - // RFC 8230 6.1 requires RSA keys having a minimun size of 2048 bits. - // Reference: https://www.rfc-editor.org/rfc/rfc8230.html#section-6.1 - if vk.N.BitLen() < 2048 { - return nil, errors.New("RSA key must be at least 2048 bits long") - } - return &rsaVerifier{ - alg: alg, - key: vk, - }, nil - case AlgorithmES256, AlgorithmES384, AlgorithmES512: - vk, ok := key.(*ecdsa.PublicKey) - if !ok { - return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) - } - if !vk.Curve.IsOnCurve(vk.X, vk.Y) { - return nil, errors.New("public key point is not on curve") - } - return &ecdsaVerifier{ - alg: alg, - key: vk, - }, nil - case AlgorithmEd25519: - vk, ok := key.(ed25519.PublicKey) - if !ok { - return nil, fmt.Errorf("%v: %w", alg, ErrInvalidPubKey) - } - return &ed25519Verifier{ - key: vk, - }, nil - default: - return nil, ErrAlgorithmNotSupported - } -} diff --git a/vendor/modules.txt b/vendor/modules.txt index f12c5fd..0e8d32f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -4,6 +4,9 @@ github.com/asaskevich/govalidator # github.com/blang/semver v3.5.1+incompatible ## explicit github.com/blang/semver +# github.com/blocky/nitrite v0.0.1 +## explicit; go 1.17 +github.com/blocky/nitrite # github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7 ## explicit github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer @@ -306,9 +309,6 @@ github.com/transparency-dev/merkle github.com/transparency-dev/merkle/compact github.com/transparency-dev/merkle/proof github.com/transparency-dev/merkle/rfc6962 -# github.com/veraison/go-cose v1.2.1 -## explicit; go 1.18 -github.com/veraison/go-cose # github.com/x448/float16 v0.8.4 ## explicit; go 1.11 github.com/x448/float16 diff --git a/wasm/main.go b/wasm/main.go index f428c7d..4a93918 100644 --- a/wasm/main.go +++ b/wasm/main.go @@ -8,7 +8,9 @@ import ( "encoding/base64" "syscall/js" - "github.com/tinfoilanalytics/verifier/pkg/nitro" + "github.com/blocky/nitrite" + + "github.com/tinfoilanalytics/verifier/pkg/models" "github.com/tinfoilanalytics/verifier/pkg/sigstore" ) @@ -44,12 +46,11 @@ func verifyNitro() js.Func { panic(err) } - nitroMeasurements, err := nitro.VerifyAttestation(attDocBytes) + att, err := nitrite.Verify(attDocBytes, nitrite.VerifyOptions{}) if err != nil { panic(err) } - - return nitroMeasurements.String() + return models.MeasurementFromDoc(att.Document).String() }) }