pkcs7: sync with upstream

This commit is contained in:
Sun Yimin 2025-01-16 16:04:45 +08:00 committed by GitHub
parent cf6e203d06
commit cb51b3657a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 125 additions and 15 deletions

View File

@ -5,8 +5,6 @@ import (
"errors"
)
var encodeIndent = 0
type asn1Object interface {
EncodeTo(writer *bytes.Buffer) error
}
@ -17,8 +15,6 @@ type asn1Structured struct {
}
func (s asn1Structured) EncodeTo(out *bytes.Buffer) error {
//fmt.Printf("%s--> tag: % X\n", strings.Repeat("| ", encodeIndent), s.tagBytes)
encodeIndent++
inner := new(bytes.Buffer)
for _, obj := range s.content {
err := obj.EncodeTo(inner)
@ -26,7 +22,6 @@ func (s asn1Structured) EncodeTo(out *bytes.Buffer) error {
return err
}
}
encodeIndent--
out.Write(s.tagBytes)
encodeLength(out, inner.Len())
out.Write(inner.Bytes())
@ -47,10 +42,7 @@ func (p asn1Primitive) EncodeTo(out *bytes.Buffer) error {
if err = encodeLength(out, p.length); err != nil {
return err
}
//fmt.Printf("%s--> tag: % X length: %d\n", strings.Repeat("| ", encodeIndent), p.tagBytes, p.length)
//fmt.Printf("%s--> content length: %d\n", strings.Repeat("| ", encodeIndent), len(p.content))
out.Write(p.content)
return nil
}
@ -58,7 +50,6 @@ func ber2der(ber []byte) ([]byte, error) {
if len(ber) == 0 {
return nil, errors.New("ber2der: input ber is empty")
}
//fmt.Printf("--> ber2der: Transcoding %d bytes\n", len(ber))
out := new(bytes.Buffer)
obj, _, err := readObject(ber, 0)

View File

@ -10,6 +10,7 @@ import (
)
func TestBer2Der(t *testing.T) {
t.Parallel()
// indefinite length fixture
ber := []byte{0x30, 0x80, 0x02, 0x01, 0x01, 0x00, 0x00}
expected := []byte{0x30, 0x03, 0x02, 0x01, 0x01}
@ -40,6 +41,7 @@ func TestBer2Der(t *testing.T) {
}
func TestBer2Der_Negatives(t *testing.T) {
t.Parallel()
fixtures := []struct {
Input []byte
ErrorContains string
@ -65,6 +67,7 @@ func TestBer2Der_Negatives(t *testing.T) {
}
func TestBer2Der_NestedMultipleIndefinite(t *testing.T) {
t.Parallel()
// indefinite length fixture
ber := []byte{0x30, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x00, 0x00, 0x30, 0x80, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00}
expected := []byte{0x30, 0x0A, 0x30, 0x03, 0x02, 0x01, 0x01, 0x30, 0x03, 0x02, 0x01, 0x02}
@ -101,6 +104,7 @@ func TestBer2Der_NestedMultipleIndefinite(t *testing.T) {
}
func TestVerifyIndefiniteLengthBer(t *testing.T) {
t.Parallel()
decoded := mustDecodePEM([]byte(testPKCS7))
_, err := ber2der(decoded)

View File

@ -11,7 +11,6 @@ import (
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"log"
"math/big"
"os"
"time"
@ -262,7 +261,6 @@ func createTestCertificateByIssuer(name string, issuer *certKeyPair, sigAlg x509
issuerKey = priv
}
log.Println("creating cert", name, "issued by", issuerCert.Subject.CommonName, "with sigalg", sigAlg)
switch pkey := priv.(type) {
case *rsa.PrivateKey:
derCert, err = smx509.CreateCertificate(rand.Reader, &template, (*x509.Certificate)(issuerCert), pkey.Public(), issuerKey)

View File

@ -76,6 +76,21 @@ func (p7 *PKCS7) verifyWithChainAtTime(truststore *smx509.CertPool, currentTime
return nil
}
// InvalidSigningTimeError is returned when the signing time attribute
// falls outside of the signer certificate validity.
type InvalidSigningTimeError struct {
SigningTime time.Time
NotBefore time.Time // NotBefore of signer
NotAfter time.Time // NotAfter of signer
}
func (e *InvalidSigningTimeError) Error() string {
return fmt.Sprintf("pkcs7: signing time %q is outside of certificate validity %q to %q",
e.SigningTime.Format(time.RFC3339),
e.NotBefore.Format(time.RFC3339),
e.NotAfter.Format(time.RFC3339))
}
func verifySignature(p7 *PKCS7, signer signerInfo, truststore *smx509.CertPool, currentTime *time.Time, isDigest bool) (err error) {
signedData := p7.Content
ee := getCertFromCertsByIssuerAndSerial(p7.Certificates, signer.IssuerAndSerialNumber)
@ -118,10 +133,11 @@ func verifySignature(p7 *PKCS7, signer signerInfo, truststore *smx509.CertPool,
if err == nil {
// signing time found, performing validity check
if signingTime.After(ee.NotAfter) || signingTime.Before(ee.NotBefore) {
return fmt.Errorf("pkcs7: signing time %q is outside of certificate validity %q to %q",
signingTime.Format(time.RFC3339),
ee.NotBefore.Format(time.RFC3339),
ee.NotAfter.Format(time.RFC3339))
return &InvalidSigningTimeError{
SigningTime: signingTime,
NotBefore: ee.NotBefore,
NotAfter: ee.NotAfter,
}
}
}
}

View File

@ -3,6 +3,8 @@ package pkcs7
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
@ -10,6 +12,7 @@ import (
"encoding/base64"
"encoding/pem"
"io/ioutil"
"math/big"
"os"
"os/exec"
"testing"
@ -35,6 +38,104 @@ func TestVerify(t *testing.T) {
}
}
func TestInvalidSigningTime(t *testing.T) {
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatalf("failed generating ECDSA key: %v", err)
}
// define certificate validity to a timeframe in the past, so that
// the certificate itself is not valid at the time of signing.
notBefore := time.Now().UTC().Round(time.Minute).Add(-2 * time.Hour)
notAfter := time.Now().UTC().Round(time.Minute).Add(-1 * time.Hour)
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "TestInvalidSigningtime",
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageEmailProtection},
}
der, err := smx509.CreateCertificate(rand.Reader, template, template, key.Public(), key)
if err != nil {
t.Fatalf("failed creating certificate: %v", err)
}
cert, err := smx509.ParseCertificate(der)
if err != nil {
t.Fatalf("failed parsing certificate: %v", err)
}
toBeSignedData, err := NewSignedData([]byte("test-invalid-signing-time"))
if err != nil {
t.Fatalf("failed creating signed data: %v", err)
}
// add the signer cert, and add attributes, including the signing
// time attribute, containing the current time
if err := toBeSignedData.AddSigner(cert, key, SignerInfoConfig{}); err != nil {
t.Fatalf("failed adding signer: %v", err)
}
// finalizes the signed data
signedData, err := toBeSignedData.Finish()
if err != nil {
t.Fatalf("failed signing data: %v", err)
}
p7, err := Parse(signedData)
if err != nil {
t.Fatalf("failed parsing signed data: %v", err)
}
signerCert := p7.GetOnlySigner()
if !bytes.Equal(cert.Signature, signerCert.Signature) {
t.Fatal("unexpected signer certificate obtained from P7 data")
}
// verify without a chain (self-signed cert), at time.Now()
now := time.Now()
err = p7.VerifyWithChainAtTime(nil, &now)
if err == nil {
t.Fatal("expected verification error, but got nil")
}
signingTimeErr, ok := err.(*InvalidSigningTimeError)
if !ok {
t.Fatalf("expected *InvalidSigningTimeError, but got %T", err)
}
if signingTimeErr.NotBefore != notBefore {
t.Errorf("expected notBefore to be %q, but got %q", notBefore, signingTimeErr.NotBefore)
}
if signingTimeErr.NotAfter != notAfter {
t.Errorf("expected notAfter to be %q, but got %q", notAfter, signingTimeErr.NotAfter)
}
// verify without a chain (self-signed cert), but without specifying the time
err = p7.VerifyWithChain(nil)
if err == nil {
t.Fatal("expected verification error, but got nil")
}
signingTimeErr, ok = err.(*InvalidSigningTimeError)
if !ok {
t.Fatalf("expected *InvalidSigningTimeError, but got %T", err)
}
if signingTimeErr.NotBefore != notBefore {
t.Errorf("expected notBefore to be %q, but got %q", notBefore, signingTimeErr.NotBefore)
}
if signingTimeErr.NotAfter != notAfter {
t.Errorf("expected notAfter to be %q, but got %q", notAfter, signingTimeErr.NotAfter)
}
}
var SignedTestFixture = `
-----BEGIN PKCS7-----
MIIDVgYJKoZIhvcNAQcCoIIDRzCCA0MCAQExCTAHBgUrDgMCGjAcBgkqhkiG9w0B