@@ -165,6 +165,33 @@ type CheckOpts struct {
165165 ExperimentalOCI11 bool
166166}
167167
168+ type validateCertOpts struct {
169+ chain []* x509.Certificate
170+ svOpts []signature.SignerVerifierOption
171+ }
172+
173+ type ValidateAndUnpackCertOption func (* validateCertOpts )
174+
175+ func WithChain (chain []* x509.Certificate ) ValidateAndUnpackCertOption {
176+ return func (o * validateCertOpts ) {
177+ o .chain = chain
178+ }
179+ }
180+
181+ func WithSignerVerifierOptions (svOpts ... signature.SignerVerifierOption ) ValidateAndUnpackCertOption {
182+ return func (o * validateCertOpts ) {
183+ o .svOpts = svOpts
184+ }
185+ }
186+
187+ func makeValidateAndUnpackCertOpts (opts ... ValidateAndUnpackCertOption ) * validateCertOpts {
188+ o := & validateCertOpts {}
189+ for _ , opt := range opts {
190+ opt (o )
191+ }
192+ return o
193+ }
194+
168195// This is a substitutable signature verification function that can be used for verifying
169196// attestations of blobs.
170197type signatureVerificationFn func (
@@ -223,11 +250,35 @@ func ValidateAndUnpackCert(cert *x509.Certificate, co *CheckOpts) (signature.Ver
223250 return ValidateAndUnpackCertWithOpts (cert , co )
224251}
225252
253+ // ValidateAndUnpackCertWithChain creates a Verifier from a certificate. Verifies that the certificate
254+ // chains up to the provided root. Chain should start with the parent of the certificate and end with the root.
255+ // Optionally verifies the subject and issuer of the certificate.
256+ func ValidateAndUnpackCertWithChain (cert * x509.Certificate , chain []* x509.Certificate , co * CheckOpts ) (signature.Verifier , error ) {
257+ return ValidateAndUnpackCertWithOpts (cert , co , WithChain (chain ))
258+ }
259+
226260// ValidateAndUnpackCertWithOpts creates a Verifier from a certificate. Verifies that the certificate
227261// chains up to a trusted root. Optionally verifies the subject and issuer of the certificate.
228- // Accept SignerVerifier options to customize the verifier.
229- func ValidateAndUnpackCertWithOpts (cert * x509.Certificate , co * CheckOpts , svOpts ... signature.SignerVerifierOption ) (signature.Verifier , error ) {
230- verifier , err := signature .LoadVerifierWithOpts (cert .PublicKey , crypto .SHA256 , svOpts ... )
262+ // Accept chain and signerVerifierOptions as optional parameters.
263+ func ValidateAndUnpackCertWithOpts (cert * x509.Certificate , co * CheckOpts , opts ... ValidateAndUnpackCertOption ) (signature.Verifier , error ) {
264+ o := makeValidateAndUnpackCertOpts (opts ... )
265+
266+ if o .chain != nil {
267+ if len (o .chain ) == 0 {
268+ return nil , errors .New ("no chain provided to validate certificate" )
269+ }
270+ rootPool := x509 .NewCertPool ()
271+ rootPool .AddCert (o .chain [len (o .chain )- 1 ])
272+ co .RootCerts = rootPool
273+
274+ subPool := x509 .NewCertPool ()
275+ for _ , c := range o .chain [:len (o .chain )- 1 ] {
276+ subPool .AddCert (c )
277+ }
278+ co .IntermediateCerts = subPool
279+ }
280+
281+ verifier , err := signature .LoadVerifierWithOpts (cert .PublicKey , crypto .SHA256 , o .svOpts ... )
231282 if err != nil {
232283 return nil , fmt .Errorf ("invalid certificate found on signature: %w" , err )
233284 }
@@ -411,26 +462,6 @@ func validateCertExtensions(ce CertExtensions, co *CheckOpts) error {
411462 return nil
412463}
413464
414- // ValidateAndUnpackCertWithChain creates a Verifier from a certificate. Verifies that the certificate
415- // chains up to the provided root. Chain should start with the parent of the certificate and end with the root.
416- // Optionally verifies the subject and issuer of the certificate.
417- func ValidateAndUnpackCertWithChain (cert * x509.Certificate , chain []* x509.Certificate , co * CheckOpts ) (signature.Verifier , error ) {
418- if len (chain ) == 0 {
419- return nil , errors .New ("no chain provided to validate certificate" )
420- }
421- rootPool := x509 .NewCertPool ()
422- rootPool .AddCert (chain [len (chain )- 1 ])
423- co .RootCerts = rootPool
424-
425- subPool := x509 .NewCertPool ()
426- for _ , c := range chain [:len (chain )- 1 ] {
427- subPool .AddCert (c )
428- }
429- co .IntermediateCerts = subPool
430-
431- return ValidateAndUnpackCert (cert , co )
432- }
433-
434465func tlogValidateEntry (ctx context.Context , client * client.Rekor , rekorPubKeys * TrustedTransparencyLogPubKeys ,
435466 sig oci.Signature , pem []byte ) (* models.LogEntryAnon , error ) {
436467 b64sig , err := sig .Base64Signature ()
@@ -741,7 +772,7 @@ func verifyInternal(ctx context.Context, sig oci.Signature, h v1.Hash,
741772 co .IntermediateCerts = pool
742773 }
743774 }
744- verifier , err = ValidateAndUnpackCertWithOpts (cert , co , svOpts ... )
775+ verifier , err = ValidateAndUnpackCertWithOpts (cert , co , WithSignerVerifierOptions ( svOpts ... ) )
745776 if err != nil {
746777 return false , err
747778 }
@@ -824,7 +855,7 @@ func VerifyBlobSignature(ctx context.Context, sig oci.Signature, co *CheckOpts)
824855
825856// VerifyImageSignature verifies a signature
826857func VerifyImageSignature (ctx context.Context , sig oci.Signature , h v1.Hash , co * CheckOpts ) (bundleVerified bool , err error ) {
827- return verifyInternal (ctx , sig , h , verifyOCISignature , co )
858+ return verifyInternal (ctx , sig , h , verifyOCISignature , co , signature . WithED25519ph () )
828859}
829860
830861func loadSignatureFromFile (ctx context.Context , sigRef string , signedImgRef name.Reference , co * CheckOpts ) (oci.Signatures , error ) {
0 commit comments