Skip to content

Commit

Permalink
fix: verification of attestations from rekor
Browse files Browse the repository at this point in the history
Few different issues here

* Intermediates from rekor need to be base64 decoded before using them.
* Trusted time stamps were only being considered while parsing entries
  from rekor but not while verifying envelopes in witness.Verify. To get
  around this I added an option to attach a trusted time to a specific
  DSSE signature which makes sure this gets used when verifying the
  envelopes.

Signed-off-by: Mikhail Swift <[email protected]>
  • Loading branch information
mikhailswift authored and colek42 committed Mar 1, 2022
1 parent 75f7868 commit 7fd0ecc
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 15 deletions.
1 change: 1 addition & 0 deletions pkg/cryptoutil/x509.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func (v *X509Verifier) BelongsToRoot(root *x509.Certificate) error {
_, err := v.cert.Verify(x509.VerifyOptions{
Roots: rootPool,
Intermediates: intermediatePool,
CurrentTime: v.trustedTime,
})

return err
Expand Down
50 changes: 42 additions & 8 deletions pkg/dsse/dsse.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ type Signature struct {
Signature []byte `json:"sig"`
Certificate []byte `json:"certificate,omitempty"`
Intermediates [][]byte `json:"intermediates,omitempty"`

trustedTime time.Time
}

// preauthEncode wraps the data to be signed or verified and it's type in the DSSE protocol's
Expand Down Expand Up @@ -112,7 +114,6 @@ type verificationOptions struct {
roots []*x509.Certificate
intermediates []*x509.Certificate
verifiers []cryptoutil.Verifier
trustedTime time.Time
}

func WithRoots(roots []*x509.Certificate) VerificationOption {
Expand All @@ -133,12 +134,6 @@ func WithVerifiers(verifiers []cryptoutil.Verifier) VerificationOption {
}
}

func WithTrustedTime(time time.Time) VerificationOption {
return func(vo *verificationOptions) {
vo.trustedTime = time
}
}

func (e Envelope) Verify(opts ...VerificationOption) ([]cryptoutil.Verifier, error) {
options := &verificationOptions{}
for _, opt := range opts {
Expand Down Expand Up @@ -170,7 +165,7 @@ func (e Envelope) Verify(opts ...VerificationOption) ([]cryptoutil.Verifier, err
}

sigIntermediates = append(sigIntermediates, options.intermediates...)
verifier, err := cryptoutil.NewX509Verifier(cert, sigIntermediates, options.roots, options.trustedTime)
verifier, err := cryptoutil.NewX509Verifier(cert, sigIntermediates, options.roots, sig.trustedTime)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -213,3 +208,42 @@ func TryParseCertificate(data []byte) (*x509.Certificate, error) {

return cert, nil
}

type SignatureOption func(so *signatureOptions)

type signatureOptions struct {
cert []byte
intermediates [][]byte
trustedTime time.Time
}

func SignatureWithCertificate(certBytes []byte) SignatureOption {
return func(so *signatureOptions) {
so.cert = certBytes
}
}

func SignatureWithIntermediates(intermediates [][]byte) SignatureOption {
return func(so *signatureOptions) {
so.intermediates = intermediates
}
}
func SignatureWithTrustedTime(trustedTime time.Time) SignatureOption {
return func(so *signatureOptions) {
so.trustedTime = trustedTime
}
}
func NewSignature(keyID string, sig []byte, opts ...SignatureOption) Signature {
so := signatureOptions{}
for _, opt := range opts {
opt(&so)
}

return Signature{
KeyID: keyID,
Signature: sig,
Certificate: so.cert,
Intermediates: so.intermediates,
trustedTime: so.trustedTime,
}
}
16 changes: 9 additions & 7 deletions pkg/rekor/rekor.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,21 +161,23 @@ func ParseEnvelopeFromEntry(entry *models.LogEntryAnon) (dsse.Envelope, error) {
return env, fmt.Errorf("failed to decode signature: %w", err)
}

verifier, err := cryptoutil.NewVerifierFromReader(bytes.NewReader(sig.PublicKey), cryptoutil.VerifyWithTrustedTime(time.Unix(*entry.IntegratedTime, 0)))
trustedTime := time.Unix(*entry.IntegratedTime, 0)
verifier, err := cryptoutil.NewVerifierFromReader(bytes.NewReader(sig.PublicKey), cryptoutil.VerifyWithTrustedTime(trustedTime))
if err != nil {
return env, fmt.Errorf("failed to create verifier from public key on rekor entry: %w", err)
}

envSig := dsse.Signature{
Signature: decodedSig,
KeyID: sig.Keyid,
}

envSig := dsse.NewSignature(sig.Keyid, decodedSig, dsse.SignatureWithTrustedTime(trustedTime))
_, ok := verifier.(*cryptoutil.X509Verifier)
if ok {
envSig.Certificate = sig.PublicKey
for _, intermediate := range sig.Intermediates {
envSig.Intermediates = append(envSig.Intermediates, intermediate)
decoded, err := base64.StdEncoding.DecodeString(string(intermediate))
if err != nil {
continue
}

envSig.Intermediates = append(envSig.Intermediates, decoded)
}
}

Expand Down

0 comments on commit 7fd0ecc

Please sign in to comment.