Skip to content

Commit

Permalink
Refactor ownership voucher
Browse files Browse the repository at this point in the history
  • Loading branch information
gmacf committed Nov 1, 2023
1 parent cd87d29 commit 947cd01
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 57 deletions.
57 changes: 3 additions & 54 deletions common/ownership_voucher/ownership_voucher.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,26 @@
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")
}
p7, err := pkcs7.Parse(in)
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)
Expand All @@ -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()
}
2 changes: 1 addition & 1 deletion common/ownership_voucher/ownership_voucher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
53 changes: 51 additions & 2 deletions testdata/artifacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,38 @@ 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 (
// Default values for the Root CA certificates.
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.
Expand Down Expand Up @@ -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")
Expand All @@ -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
}
Expand Down

0 comments on commit 947cd01

Please sign in to comment.