From 947cd01b843851b3452c71ec04f8a5b20806d9a9 Mon Sep 17 00:00:00 2001 From: Gareth <31602864+gmacf@users.noreply.github.com> Date: Wed, 1 Nov 2023 05:48:54 +0000 Subject: [PATCH] Refactor ownership voucher --- common/ownership_voucher/ownership_voucher.go | 57 +------------------ .../ownership_voucher_test.go | 2 +- testdata/artifacts.go | 53 ++++++++++++++++- 3 files changed, 55 insertions(+), 57 deletions(-) diff --git a/common/ownership_voucher/ownership_voucher.go b/common/ownership_voucher/ownership_voucher.go index 877a9f5..c40445c 100644 --- a/common/ownership_voucher/ownership_voucher.go +++ b/common/ownership_voucher/ownership_voucher.go @@ -16,37 +16,18 @@ package ownershipvoucher import ( - "crypto" "crypto/x509" "encoding/json" "fmt" - "time" "go.mozilla.org/pkcs7" -) -const ( - ovExpiry = time.Hour * 24 * 365 + artifacts "github.com/openconfig/bootz/testdata" ) -// OwnershipVoucher wraps Inner. -type OwnershipVoucher struct { - OV Inner `json:"ietf-voucher:voucher"` -} - -// Inner defines the Ownership Voucher format. See https://www.rfc-editor.org/rfc/rfc8366.html. -type Inner struct { - CreatedOn string `json:"created-on"` - ExpiresOn string `json:"expires-on"` - SerialNumber string `json:"serial-number"` - Assertion string `json:"assertion"` - PinnedDomainCert []byte `json:"pinned-domain-cert"` - DomainCertRevocationChecks bool `json:"domain-cert-revocation-checks"` -} - // Unmarshal unmarshals the contents of an Ownership Voucher. If a certPool is provided, // it is used to verify the contents. -func Unmarshal(in []byte, certPool *x509.CertPool) (*OwnershipVoucher, error) { +func Unmarshal(in []byte, certPool *x509.CertPool) (*artifacts.OwnershipVoucher, error) { if len(in) == 0 { return nil, fmt.Errorf("ownership voucher is empty") } @@ -54,7 +35,7 @@ func Unmarshal(in []byte, certPool *x509.CertPool) (*OwnershipVoucher, error) { if err != nil { return nil, fmt.Errorf("unable to parse into pkcs7 format: %v", err) } - ov := OwnershipVoucher{} + ov := artifacts.OwnershipVoucher{} err = json.Unmarshal(p7.Content, &ov) if err != nil { return nil, fmt.Errorf("failed unmarshalling ownership voucher: %v", err) @@ -66,35 +47,3 @@ func Unmarshal(in []byte, certPool *x509.CertPool) (*OwnershipVoucher, error) { } return &ov, nil } - -// New generates an Ownership Voucher which is signed by the vendor's CA. -func New(serial string, pdcDER []byte, vendorCACert *x509.Certificate, vendorCAPriv crypto.PrivateKey) ([]byte, error) { - currentTime := time.Now() - ov := OwnershipVoucher{ - OV: Inner{ - CreatedOn: currentTime.Format(time.RFC3339), - ExpiresOn: currentTime.Add(ovExpiry).Format(time.RFC3339), - SerialNumber: serial, - PinnedDomainCert: pdcDER, - }, - } - - ovBytes, err := json.Marshal(ov) - if err != nil { - return nil, err - } - - signedMessage, err := pkcs7.NewSignedData(ovBytes) - if err != nil { - return nil, err - } - signedMessage.SetDigestAlgorithm(pkcs7.OIDDigestAlgorithmSHA256) - signedMessage.SetEncryptionAlgorithm(pkcs7.OIDEncryptionAlgorithmRSA) - - err = signedMessage.AddSigner(vendorCACert, vendorCAPriv, pkcs7.SignerInfoConfig{}) - if err != nil { - return nil, err - } - - return signedMessage.Finish() -} diff --git a/common/ownership_voucher/ownership_voucher_test.go b/common/ownership_voucher/ownership_voucher_test.go index 2c6ed84..338b30c 100644 --- a/common/ownership_voucher/ownership_voucher_test.go +++ b/common/ownership_voucher/ownership_voucher_test.go @@ -37,7 +37,7 @@ func TestEndToEnd(t *testing.T) { t.Fatalf("unable to generate Vendor CA: %v", err) } - ov, err := New(wantSerial, pdc.Raw, vendorca, vendorcaPrivateKey) + ov, err := artifacts.NewOwnershipVoucher(wantSerial, pdc, vendorca, vendorcaPrivateKey) if err != nil { t.Errorf("New err = %v, want nil", err) } diff --git a/testdata/artifacts.go b/testdata/artifacts.go index 240cbf3..10170e1 100644 --- a/testdata/artifacts.go +++ b/testdata/artifacts.go @@ -24,12 +24,13 @@ import ( "crypto/tls" "crypto/x509" "crypto/x509/pkix" + "encoding/json" "encoding/pem" "math/big" "time" - ownershipvoucher "github.com/openconfig/bootz/common/ownership_voucher" "github.com/openconfig/bootz/server/service" + "go.mozilla.org/pkcs7" ) const ( @@ -37,8 +38,24 @@ const ( caCountry = "US" caProvince = "CA" caLocality = "Mountain View" + ovExpiry = time.Hour * 24 * 365 ) +// OwnershipVoucher wraps Inner. +type OwnershipVoucher struct { + OV Inner `json:"ietf-voucher:voucher"` +} + +// Inner defines the Ownership Voucher format. See https://www.rfc-editor.org/rfc/rfc8366.html. +type Inner struct { + CreatedOn string `json:"created-on"` + ExpiresOn string `json:"expires-on"` + SerialNumber string `json:"serial-number"` + Assertion string `json:"assertion"` + PinnedDomainCert []byte `json:"pinned-domain-cert"` + DomainCertRevocationChecks bool `json:"domain-cert-revocation-checks"` +} + // NewCertificateAuthority creates a new self-signed CA for the chosen organization. func NewCertificateAuthority(commonName, org, serverName string) (*x509.Certificate, *rsa.PrivateKey, error) { // Create the certificate authority. @@ -138,6 +155,38 @@ func TLSCertificate(cert *x509.Certificate, privateKey *rsa.PrivateKey) (*tls.Ce return &tlsCert, nil } +// NewOwnershipVoucher generates an Ownership Voucher which is signed by the vendor's CA. +func NewOwnershipVoucher(serial string, pdc, vendorCACert *x509.Certificate, vendorCAPriv crypto.PrivateKey) ([]byte, error) { + currentTime := time.Now() + ov := OwnershipVoucher{ + OV: Inner{ + CreatedOn: currentTime.Format(time.RFC3339), + ExpiresOn: currentTime.Add(ovExpiry).Format(time.RFC3339), + SerialNumber: serial, + PinnedDomainCert: pdc.Raw, + }, + } + + ovBytes, err := json.Marshal(ov) + if err != nil { + return nil, err + } + + signedMessage, err := pkcs7.NewSignedData(ovBytes) + if err != nil { + return nil, err + } + signedMessage.SetDigestAlgorithm(pkcs7.OIDDigestAlgorithmSHA256) + signedMessage.SetEncryptionAlgorithm(pkcs7.OIDEncryptionAlgorithmRSA) + + err = signedMessage.AddSigner(vendorCACert, vendorCAPriv, pkcs7.SignerInfoConfig{}) + if err != nil { + return nil, err + } + + return signedMessage.Finish() +} + // GenerateSecurityArtifacts generates security artifacts. func GenerateSecurityArtifacts(controlCardSerials []string, ownerOrg string, vendorOrg string) (*service.SecurityArtifacts, error) { pdc, pdcPrivateKey, err := NewCertificateAuthority("Pinned Domain Cert", ownerOrg, "localhost") @@ -158,7 +207,7 @@ func GenerateSecurityArtifacts(controlCardSerials []string, ownerOrg string, ven } ovs := service.OVList{} for _, serial := range controlCardSerials { - ov, err := ownershipvoucher.New(serial, pdc.Raw, vendorCA, vendorCAPrivateKey) + ov, err := NewOwnershipVoucher(serial, pdc, vendorCA, vendorCAPrivateKey) if err != nil { return nil, err }