diff --git a/cmd/clientsim/main.go b/cmd/clientsim/main.go index fdac7ca..ed090d3 100644 --- a/cmd/clientsim/main.go +++ b/cmd/clientsim/main.go @@ -22,9 +22,11 @@ package main import ( "context" "crypto/rand" + "crypto/x509" "fmt" "io" "os" + "sort" "time" "github.com/shamaton/msgpackgen/msgpack" @@ -167,7 +169,9 @@ func (c *clientSimulator) Run(ctx context.Context) error { } type ClientHandler struct { - logger *logrus.Logger + logger *logrus.Logger + commands chan *protocol.Command + caList []string } func (c *ClientHandler) Send(ctx context.Context, command *protocol.Command, out chan []byte) error { @@ -244,6 +248,29 @@ func (c *ClientHandler) ResponseData(ctx context.Context, in chan []byte, respon return fmt.Errorf("could not unmarshal health response data: %w", err) } + c.updateCAs(ctx, c.commands, resp.Info) + + response.Response = &resp + case messages.RespCAInfo: + var resp messages.CAInfoResponse + if err := msgpack.Unmarshal(frame, &resp); err != nil { + return fmt.Errorf("could not unmarshal CA info response data: %w", err) + } + + certificate, err := x509.ParseCertificate(resp.Certificate) + if err != nil { + return fmt.Errorf("could not parse certificate data: %w", err) + } + + c.logger.Infof( + "certificate for %s: subject=%s, issuer=%s, serial=0x%x, valid from %s to %s", + resp.Name, + certificate.Subject, + certificate.Issuer, + certificate.SerialNumber, + certificate.NotBefore, + certificate.NotAfter) + response.Response = &resp case messages.RespFetchCRL: var resp messages.FetchCRLResponse @@ -269,8 +296,40 @@ func (c *ClientHandler) HandleResponse(_ context.Context, response *protocol.Res return nil } -func newClientHandler(logger *logrus.Logger) *ClientHandler { - return &ClientHandler{logger: logger} +func (c *ClientHandler) updateCAs(ctx context.Context, out chan *protocol.Command, info []*messages.HealthInfo) { + caList := make([]string, 0) + + for _, i := range info { + if i.Source == "HSM" { + c.logger.Debugf("info from HSM: %s", i) + + for caName := range i.MoreInfo { + caList = append(caList, caName) + } + } + } + + sort.Strings(caList) + + if len(caList) != len(c.caList) { + c.caList = caList + + for _, ca := range c.caList { + select { + case <-ctx.Done(): + return + case out <- &protocol.Command{ + Announce: messages.BuildCommandAnnounce(messages.CmdCAInfo), + Command: &messages.CAInfoCommand{Name: ca}, + }: + continue + } + } + } +} + +func newClientHandler(logger *logrus.Logger, commands chan *protocol.Command) *ClientHandler { + return &ClientHandler{logger: logger, commands: commands} } func main() { @@ -285,16 +344,20 @@ func main() { logger.WithError(err).Fatal("could not create COBS framer") } + commandBufferSize := 50 + + commandCh := make(chan *protocol.Command, commandBufferSize) + sim := &clientSimulator{ commandGenerator: &TestCommandGenerator{ logger: logger, - commands: make(chan *protocol.Command), + commands: commandCh, }, logger: logger, framesIn: make(chan []byte), framesOut: make(chan []byte), framer: cobsFramer, - clientHandler: newClientHandler(logger), + clientHandler: newClientHandler(logger, commandCh), } err = sim.Run(context.Background()) diff --git a/cmd/signer/main.go b/cmd/signer/main.go index d4ec95c..68943f1 100644 --- a/cmd/signer/main.go +++ b/cmd/signer/main.go @@ -105,6 +105,7 @@ func main() { logger, handler.RegisterHealthHandler(healthHandler), handler.RegisterFetchCRLHandler(fetchCRLHandler), + handler.RegisterCAInfoHandler(access), ) if err != nil { logger.WithError(err).Fatal("could not setup protocol handler") diff --git a/internal/cainfo/cainfo.go b/internal/cainfo/cainfo.go new file mode 100644 index 0000000..60edfad --- /dev/null +++ b/internal/cainfo/cainfo.go @@ -0,0 +1,29 @@ +/* +Copyright 2022 CAcert Inc. +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cainfo + +import "git.cacert.org/cacert-gosigner/pkg/messages" + +type Result struct { + Certificate []byte + Profiles []messages.CAProfile +} + +type Handler interface { + GetCAInfo(string) (*Result, error) +} diff --git a/internal/handler/msgpack.go b/internal/handler/msgpack.go index 23d0357..2963b92 100644 --- a/internal/handler/msgpack.go +++ b/internal/handler/msgpack.go @@ -27,11 +27,11 @@ import ( "github.com/shamaton/msgpackgen/msgpack" "github.com/sirupsen/logrus" - "git.cacert.org/cacert-gosigner/pkg/protocol" - + "git.cacert.org/cacert-gosigner/internal/cainfo" "git.cacert.org/cacert-gosigner/internal/health" "git.cacert.org/cacert-gosigner/internal/x509/revoking" "git.cacert.org/cacert-gosigner/pkg/messages" + "git.cacert.org/cacert-gosigner/pkg/protocol" ) const readCommandTimeOut = 5 * time.Second @@ -40,9 +40,10 @@ var errReadCommandTimeout = errors.New("read command timeout expired") // MsgPackHandler is a ServerHandler implementation for the msgpack serialization format. type MsgPackHandler struct { - logger *logrus.Logger - healthHandler *health.Handler - fetchCRLHandler *revoking.FetchCRLHandler + logger *logrus.Logger + healthHandler *health.Handler + certificateAuthorityInfoHandler cainfo.Handler + fetchCRLHandler *revoking.FetchCRLHandler } func (m *MsgPackHandler) CommandAnnounce(ctx context.Context, frames chan []byte) (*protocol.Command, error) { @@ -149,6 +150,18 @@ func (m *MsgPackHandler) parseHealthCommand(frame []byte) (*messages.HealthComma return &command, nil } +func (m *MsgPackHandler) parseCAInfoCommand(frame []byte) (*messages.CAInfoCommand, error) { + var command messages.CAInfoCommand + + if err := msgpack.Unmarshal(frame, &command); err != nil { + m.logger.WithError(err).Error("unmarshal failed") + + return nil, errors.New("could not unmarshal CA info command") + } + + return &command, nil +} + func (m *MsgPackHandler) parseFetchCRLCommand(frame []byte) (*messages.FetchCRLCommand, error) { var command messages.FetchCRLCommand @@ -175,6 +188,13 @@ func (m *MsgPackHandler) handleCommand(command *protocol.Command) (*protocol.Res } responseCode, responseData = messages.RespHealth, response + case *messages.CAInfoCommand: + response, err := m.handleCAInfoCommand(cmd) + if err != nil { + return nil, err + } + + responseCode, responseData = messages.RespCAInfo, response case *messages.FetchCRLCommand: response, err := m.handleFetchCRLCommand(cmd) if err != nil { @@ -208,6 +228,13 @@ func (m *MsgPackHandler) parseCommand(frame []byte, command *protocol.Command) e } command.Command = healthCommand + case messages.CmdCAInfo: + caInfoCommand, err := m.parseCAInfoCommand(frame) + if err != nil { + return err + } + + command.Command = caInfoCommand case messages.CmdFetchCRL: fetchCRLCommand, err := m.parseFetchCRLCommand(frame) if err != nil { @@ -244,6 +271,22 @@ func (m *MsgPackHandler) handleHealthCommand() (*messages.HealthResponse, error) return response, nil } +func (m *MsgPackHandler) handleCAInfoCommand(command *messages.CAInfoCommand) (*messages.CAInfoResponse, error) { + res, err := m.certificateAuthorityInfoHandler.GetCAInfo(command.Name) + if err != nil { + return nil, fmt.Errorf("could not get CA information") + } + + response := &messages.CAInfoResponse{ + Name: command.Name, + Certificate: res.Certificate, + Signing: res.Certificate != nil && len(res.Profiles) > 0, + Profiles: res.Profiles, + } + + return response, nil +} + func (m *MsgPackHandler) handleFetchCRLCommand(command *messages.FetchCRLCommand) (*messages.FetchCRLResponse, error) { var crlNumber *big.Int @@ -299,3 +342,9 @@ func RegisterFetchCRLHandler(fetchCRLHandler *revoking.FetchCRLHandler) func(han h.fetchCRLHandler = fetchCRLHandler } } + +func RegisterCAInfoHandler(caInfoHandler cainfo.Handler) func(handler *MsgPackHandler) { + return func(h *MsgPackHandler) { + h.certificateAuthorityInfoHandler = caInfoHandler + } +} diff --git a/internal/hsm/hsm.go b/internal/hsm/hsm.go index b8fafa3..b18cdb3 100644 --- a/internal/hsm/hsm.go +++ b/internal/hsm/hsm.go @@ -36,10 +36,10 @@ import ( "github.com/ThalesIgnite/crypto11" "github.com/sirupsen/logrus" - "git.cacert.org/cacert-gosigner/pkg/messages" - + "git.cacert.org/cacert-gosigner/internal/cainfo" "git.cacert.org/cacert-gosigner/internal/config" "git.cacert.org/cacert-gosigner/internal/health" + "git.cacert.org/cacert-gosigner/pkg/messages" ) var ( @@ -55,6 +55,56 @@ type caFile struct { label string } +func (c *caFile) buildCertificatePath(caDirectory string) string { + fileName := c.sc.CertificateFileName(c.label) + + if caDirectory == "" { + return fileName + } + + return path.Join(caDirectory, fileName) +} + +func (c *caFile) loadCertificate(caDirectory string) (*x509.Certificate, error) { + certFile := c.buildCertificatePath(caDirectory) + + certFileInfo, err := os.Stat(certFile) + if err != nil { + if errors.Is(err, syscall.ENOENT) { + return nil, nil + } + + return nil, fmt.Errorf("could not get info for %s: %w", certFile, err) + } + + if !certFileInfo.Mode().IsRegular() { + return nil, fmt.Errorf("certificate file %s is not a regular file", certFile) + } + + certData, err := os.ReadFile(certFile) + if err != nil { + return nil, fmt.Errorf("could not read %s: %w", certFile, err) + } + + certificate, err := x509.ParseCertificate(certData) + if err != nil { + return nil, fmt.Errorf("could not parse certificate from %s: %w", certFile, err) + } + + return certificate, nil +} + +func (c *caFile) storeCertificate(caDirectory string, certificate []byte) error { + certFile := c.buildCertificatePath(caDirectory) + + err := os.WriteFile(certFile, certificate, 0o600) + if err != nil { + return fmt.Errorf("could not write certificate file %s: %w", certFile, err) + } + + return nil +} + type Access struct { logger *logrus.Logger caDirectory string @@ -70,33 +120,24 @@ func (a *Access) Healthy() (*health.Info, error) { moreInfo := make(map[string]string) for _, ca := range a.signerConfig.RootCAs() { - infoKey := fmt.Sprintf("root-%s", ca) - - cert, err := a.GetRootCACertificate(ca) + _, err := a.GetRootCACertificate(ca) if err != nil { healthy = false - moreInfo[infoKey] = messages.CertificateInfoFailed.String() + moreInfo[ca] = string(messages.CertStatusFailed) continue } - moreInfo[infoKey] = messages.CertificateInfo{ - Status: messages.CertStatusOk, - Signing: false, - Profiles: []messages.CAProfile{}, - ValidUntil: cert.NotAfter.UTC(), - }.String() + moreInfo[ca] = string(messages.CertStatusOk) } for _, ca := range a.signerConfig.SubordinateCAs() { - infoKey := fmt.Sprintf("sub-%s", ca) - - cert, err := a.GetSubordinateCACertificate(ca) + _, err := a.GetSubordinateCACertificate(ca) if err != nil { healthy = false - moreInfo[infoKey] = messages.CertificateInfoFailed.String() + moreInfo[ca] = string(messages.CertStatusFailed) continue } @@ -105,7 +146,7 @@ func (a *Access) Healthy() (*health.Info, error) { if err != nil { healthy = false - moreInfo[infoKey] = messages.CertificateInfoFailed.String() + moreInfo[ca] = string(messages.CertStatusFailed) continue } @@ -114,17 +155,12 @@ func (a *Access) Healthy() (*health.Info, error) { if err != nil { healthy = false - moreInfo[infoKey] = messages.CertificateInfoFailed.String() + moreInfo[ca] = string(messages.CertStatusFailed) continue } - moreInfo[infoKey] = messages.CertificateInfo{ - Status: messages.CertStatusOk, - Signing: true, - Profiles: def.Profiles, - ValidUntil: cert.NotAfter.UTC(), - }.String() + moreInfo[ca] = string(messages.CertStatusOk) } return &health.Info{ @@ -141,54 +177,25 @@ func NewAccess(logger *logrus.Logger, options ...ConfigOption) (*Access, error) return access, nil } -func (c *caFile) buildCertificatePath(caDirectory string) string { - fileName := c.sc.CertificateFileName(c.label) - - if caDirectory == "" { - return fileName - } - - return path.Join(caDirectory, fileName) -} - -func (c *caFile) loadCertificate(caDirectory string) (*x509.Certificate, error) { - certFile := c.buildCertificatePath(caDirectory) - - certFileInfo, err := os.Stat(certFile) - if err != nil { - if errors.Is(err, syscall.ENOENT) { - return nil, nil - } - - return nil, fmt.Errorf("could not get info for %s: %w", certFile, err) - } - - if !certFileInfo.Mode().IsRegular() { - return nil, fmt.Errorf("certificate file %s is not a regular file", certFile) - } +func (a *Access) GetCAInfo(name string) (*cainfo.Result, error) { + sc := a.GetSignerConfig() - certData, err := os.ReadFile(certFile) - if err != nil { - return nil, fmt.Errorf("could not read %s: %w", certFile, err) - } + caFile := &caFile{sc: sc, label: name} - certificate, err := x509.ParseCertificate(certData) + def, err := sc.GetCADefinition(name) if err != nil { - return nil, fmt.Errorf("could not parse certificate from %s: %w", certFile, err) + return nil, fmt.Errorf("certificate %s unknown: %w", name, err) } - return certificate, nil -} - -func (c *caFile) storeCertificate(caDirectory string, certificate []byte) error { - certFile := c.buildCertificatePath(caDirectory) - - err := os.WriteFile(certFile, certificate, 0o600) + certificate, err := caFile.loadCertificate(a.caDirectory) if err != nil { - return fmt.Errorf("could not write certificate file %s: %w", certFile, err) + return nil, fmt.Errorf("certificate %s not available: %w", name, err) } - return nil + return &cainfo.Result{ + Certificate: certificate.Raw, + Profiles: def.Profiles, + }, nil } func (a *Access) GetRootCACertificate(label string) (*x509.Certificate, error) { diff --git a/pkg/messages/messages.go b/pkg/messages/messages.go index 3257367..f208c9e 100644 --- a/pkg/messages/messages.go +++ b/pkg/messages/messages.go @@ -22,7 +22,6 @@ package messages import ( "crypto/x509" - "encoding/json" "encoding/pem" "fmt" "math/big" @@ -40,13 +39,21 @@ type CommandCode int8 const ( CmdUndef CommandCode = iota CmdHealth + CmdCAInfo CmdFetchCRL + CmdSignCertificate + CmdSignOpenPGP + CmdRevokeCertificate ) var commandNames = map[CommandCode]string{ - CmdUndef: "UNDEFINED", - CmdHealth: "HEALTH", - CmdFetchCRL: "FETCH CRL", + CmdUndef: "UNDEFINED", + CmdHealth: "HEALTH", + CmdFetchCRL: "FETCH CRL", + CmdCAInfo: "CA INFO", + CmdSignCertificate: "SIG CERT", + CmdSignOpenPGP: "SIG OPENPGP", + CmdRevokeCertificate: "REV CERT", } func (c CommandCode) String() string { @@ -63,14 +70,22 @@ const ( RespError ResponseCode = -1 RespUndef ResponseCode = iota RespHealth + RespCAInfo RespFetchCRL + RespSignCertificate + RespSignOpenPGP + RespRevokeCertificate ) var responseNames = map[ResponseCode]string{ - RespError: "ERROR", - RespUndef: "UNDEFINED", - RespHealth: "HEALTH", - RespFetchCRL: "FETCH CRL", + RespError: "ERROR", + RespUndef: "UNDEFINED", + RespHealth: "HEALTH", + RespCAInfo: "CA INFO", + RespFetchCRL: "FETCH CRL", + RespSignCertificate: "SIG CERT", + RespSignOpenPGP: "SIG OPENPGP", + RespRevokeCertificate: "REV CERT", } func (c ResponseCode) String() string { @@ -111,13 +126,20 @@ func BuildResponseAnnounce(code ResponseCode, commandID string) *ResponseAnnounc return &ResponseAnnounce{Code: code, ID: commandID, Created: time.Now().UTC()} } -type HealthCommand struct { -} +type HealthCommand struct{} func (h *HealthCommand) String() string { return "" } +type CAInfoCommand struct { + Name string `msgpack:"name"` +} + +func (r *CAInfoCommand) String() string { + return fmt.Sprintf("name=%s", r.Name) +} + type FetchCRLCommand struct { IssuerID string `msgpack:"issuer_id"` LastKnownID []byte `msgpack:"last_known_id"` @@ -226,8 +248,8 @@ func ParseUsage(u string) (ProfileUsage, error) { } type CAProfile struct { - Name string `json:"name"` - UseFor ProfileUsage `json:"use-for"` + Name string `msgpack:"name"` + UseFor ProfileUsage `msgpack:"use-for"` } func (p CAProfile) String() string { @@ -241,33 +263,15 @@ const ( CertStatusFailed CertificateStatus = "failed" ) -type CertificateInfo struct { - Status CertificateStatus `json:"status"` - Signing bool `json:"signing"` - Profiles []CAProfile `json:"profiles,omitempty"` - ValidUntil time.Time `json:"valid-until"` -} - -func (i CertificateInfo) String() string { - marshal, _ := json.Marshal(i) - - return string(marshal) -} - -var CertificateInfoFailed = CertificateInfo{ - Status: CertStatusFailed, - Signing: false, +type CAInfoResponse struct { + Name string `msgpack:"name"` + Certificate []byte `msgpack:"certificate"` + Signing bool `msgpack:"signing"` + Profiles []CAProfile `msgpack:"profiles,omitempty"` } -func ParseCertificateInfo(info string) (*CertificateInfo, error) { - certInfo := CertificateInfo{} - - err := json.Unmarshal([]byte(info), &certInfo) - if err != nil { - return nil, fmt.Errorf("could not parse certificate information: %w", err) - } - - return &certInfo, nil +func (i CAInfoResponse) String() string { + return fmt.Sprintf("certificate name=%s, signing=%t, profiles=[%s]", i.Name, i.Signing, i.Profiles) } type HealthInfo struct { diff --git a/pkg/messages/messages_test.go b/pkg/messages/messages_test.go index be5a195..b795e07 100644 --- a/pkg/messages/messages_test.go +++ b/pkg/messages/messages_test.go @@ -18,6 +18,7 @@ limitations under the License. package messages import ( + "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" @@ -328,81 +329,38 @@ func TestCAProfile_String(t *testing.T) { } } -func TestCertificateInfo_String(t *testing.T) { - infoInstances := []struct { - Name string - info CertificateInfo - }{ - {"failed", CertificateInfoFailed}, - {"ok", - CertificateInfo{ - Status: CertStatusOk, - Signing: true, - Profiles: []CAProfile{{ - Name: "test", - UseFor: UsageServer, - }}, - ValidUntil: time.Now().UTC(), - }, - }, - } +func TestCAInfoCommand_String(t *testing.T) { + c := CAInfoCommand{Name: "test"} - for _, i := range infoInstances { - t.Run(i.Name, func(t *testing.T) { - str := i.info.String() + str := c.String() - assert.NotEmpty(t, str) - assert.Contains(t, str, fmt.Sprintf("%t", i.info.Signing)) - assert.True(t, strings.HasPrefix(str, "{")) - assert.True(t, strings.HasSuffix(str, "}")) - assert.Contains(t, str, "status") - assert.Contains(t, str, "signing") - - if len(i.info.Profiles) == 0 { - assert.NotContains(t, str, "profiles") - } else { - assert.Contains(t, str, "profiles") - } - - if i.info.ValidUntil.IsZero() { - assert.Contains(t, str, `"valid-until":"0001-01-01T00:00:00Z"`) - } else { - assert.Contains(t, str, "valid-until") - } - }) - } + assert.NotEmpty(t, str) + assert.Contains(t, str, "test") + assert.Contains(t, str, "name") } -func TestParseCertificateInfo(t *testing.T) { - brokenVariants := []struct{ Name, Value string }{ - {"no json", "no json for you"}, - {"invalid-status", `{"status":"foo"`}, - {"invalid-date", `{"status":"failed","valid-until":"foo"`}, +func TestCAInfoResponse_String(t *testing.T) { + _, certBytes := createTestCertificate(t) + + info := CAInfoResponse{ + Name: "testca", + Signing: true, + Profiles: []CAProfile{{ + Name: "test", + UseFor: UsageServer, + }}, + Certificate: certBytes, } - for _, v := range brokenVariants { - t.Run(v.Name, func(t *testing.T) { - i, err := ParseCertificateInfo(v.Value) - - assert.Error(t, err) - assert.Nil(t, i) - }) - } - - okVariants := []struct{ Name, Value string }{ - {"minimal", `{"status":"failed"}`}, - {"signing", `{"status":"ok","signing":true}`}, - {"with-date", `{"status":"ok","signing":false,"valid-until":"2022-12-31T23:59:59+01:00"}`}, - } + str := info.String() - for _, v := range okVariants { - t.Run(v.Name, func(t *testing.T) { - i, err := ParseCertificateInfo(v.Value) + assert.NotEmpty(t, str) + assert.Contains(t, str, fmt.Sprintf("signing=%t", info.Signing)) + assert.Contains(t, str, "certificate name") + assert.Contains(t, str, "profiles") - assert.NoError(t, err) - require.NotNil(t, i) - assert.NotEmpty(t, i.Status) - }) + if len(info.Profiles) == 0 { + assert.Contains(t, str, "[]") } } @@ -545,27 +503,7 @@ func TestFetchCRLResponse_String(t *testing.T) { }) t.Run("good-crl", func(t *testing.T) { - keyPair, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - - require.NoError(t, err) - - certTemplate := &x509.Certificate{ - BasicConstraintsValid: true, - IsCA: true, - Issuer: pkix.Name{Country: []string{"un"}, Organization: []string{"Acme Ltd."}, CommonName: "foo CA"}, - KeyUsage: x509.KeyUsageCRLSign | x509.KeyUsageCertSign, - MaxPathLen: 0, - MaxPathLenZero: false, - NotAfter: time.Now().AddDate(5, 0, 0), - NotBefore: time.Now(), - SerialNumber: big.NewInt(1), - SignatureAlgorithm: x509.ECDSAWithSHA256, - Subject: pkix.Name{Country: []string{"un"}, Organization: []string{"Acme Ltd."}, CommonName: "foo CA"}, - } - - certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, keyPair.Public(), keyPair) - - require.NoError(t, err) + keyPair, certBytes := createTestCertificate(t) cert, _ := x509.ParseCertificate(certBytes) @@ -597,6 +535,34 @@ func TestFetchCRLResponse_String(t *testing.T) { }) } +func createTestCertificate(t *testing.T) (crypto.Signer, []byte) { + t.Helper() + + keyPair, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + + require.NoError(t, err) + + certTemplate := &x509.Certificate{ + BasicConstraintsValid: true, + IsCA: true, + Issuer: pkix.Name{Country: []string{"un"}, Organization: []string{"Acme Ltd."}, CommonName: "foo CA"}, + KeyUsage: x509.KeyUsageCRLSign | x509.KeyUsageCertSign, + MaxPathLen: 0, + MaxPathLenZero: false, + NotAfter: time.Now().AddDate(5, 0, 0), + NotBefore: time.Now(), + SerialNumber: big.NewInt(1), + SignatureAlgorithm: x509.ECDSAWithSHA256, + Subject: pkix.Name{Country: []string{"un"}, Organization: []string{"Acme Ltd."}, CommonName: "foo CA"}, + } + + certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, keyPair.Public(), keyPair) + + require.NoError(t, err) + + return keyPair, certBytes +} + func TestErrorResponse_String(t *testing.T) { r := &ErrorResponse{Message: "kaput"} diff --git a/pkg/messages/resolver.msgpackgen.go b/pkg/messages/resolver.msgpackgen.go index 1be380e..068705c 100644 --- a/pkg/messages/resolver.msgpackgen.go +++ b/pkg/messages/resolver.msgpackgen.go @@ -56,6 +56,36 @@ func ___encodeAsArray(i interface{}) ([]byte, error) { return nil, fmt.Errorf("%s size / offset different %d : %d", "HealthCommand", size, offset) } return b, err + case CAInfoCommand: + encoder := enc.NewEncoder() + size, err := ___calcArraySizeCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder) + if err != nil { + return nil, err + } + encoder.MakeBytes(size) + b, offset, err := ___encodeArrayCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder, 0) + if err != nil { + return nil, err + } + if size != offset { + return nil, fmt.Errorf("%s size / offset different %d : %d", "CAInfoCommand", size, offset) + } + return b, err + case *CAInfoCommand: + encoder := enc.NewEncoder() + size, err := ___calcArraySizeCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder) + if err != nil { + return nil, err + } + encoder.MakeBytes(size) + b, offset, err := ___encodeArrayCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder, 0) + if err != nil { + return nil, err + } + if size != offset { + return nil, fmt.Errorf("%s size / offset different %d : %d", "CAInfoCommand", size, offset) + } + return b, err case FetchCRLCommand: encoder := enc.NewEncoder() size, err := ___calcArraySizeFetchCRLCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder) @@ -243,6 +273,36 @@ func ___encodeAsMap(i interface{}) ([]byte, error) { return nil, fmt.Errorf("%s size / offset different %d : %d", "HealthCommand", size, offset) } return b, err + case CAInfoCommand: + encoder := enc.NewEncoder() + size, err := ___calcMapSizeCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder) + if err != nil { + return nil, err + } + encoder.MakeBytes(size) + b, offset, err := ___encodeMapCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder, 0) + if err != nil { + return nil, err + } + if size != offset { + return nil, fmt.Errorf("%s size / offset different %d : %d", "CAInfoCommand", size, offset) + } + return b, err + case *CAInfoCommand: + encoder := enc.NewEncoder() + size, err := ___calcMapSizeCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder) + if err != nil { + return nil, err + } + encoder.MakeBytes(size) + b, offset, err := ___encodeMapCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, encoder, 0) + if err != nil { + return nil, err + } + if size != offset { + return nil, fmt.Errorf("%s size / offset different %d : %d", "CAInfoCommand", size, offset) + } + return b, err case FetchCRLCommand: encoder := enc.NewEncoder() size, err := ___calcMapSizeFetchCRLCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, encoder) @@ -423,6 +483,20 @@ func ___decodeAsArray(data []byte, i interface{}) (bool, error) { return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len()) } return true, err + case *CAInfoCommand: + decoder := dec.NewDecoder(data) + offset, err := ___decodeArrayCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0) + if err == nil && offset != decoder.Len() { + return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len()) + } + return true, err + case **CAInfoCommand: + decoder := dec.NewDecoder(data) + offset, err := ___decodeArrayCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, decoder, 0) + if err == nil && offset != decoder.Len() { + return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len()) + } + return true, err case *FetchCRLCommand: decoder := dec.NewDecoder(data) offset, err := ___decodeArrayFetchCRLCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0) @@ -514,6 +588,20 @@ func ___decodeAsMap(data []byte, i interface{}) (bool, error) { return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len()) } return true, err + case *CAInfoCommand: + decoder := dec.NewDecoder(data) + offset, err := ___decodeMapCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0) + if err == nil && offset != decoder.Len() { + return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len()) + } + return true, err + case **CAInfoCommand: + decoder := dec.NewDecoder(data) + offset, err := ___decodeMapCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(*v, decoder, 0) + if err == nil && offset != decoder.Len() { + return true, fmt.Errorf("read length is different [%d] [%d] ", offset, decoder.Len()) + } + return true, err case *FetchCRLCommand: decoder := dec.NewDecoder(data) offset, err := ___decodeMapFetchCRLCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v, decoder, 0) @@ -663,6 +751,107 @@ func ___decodeMapHealthCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f8 return offset, err } +// calculate size from git.cacert.org/cacert-gosigner/pkg/messages.CAInfoCommand +func ___calcArraySizeCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v CAInfoCommand, encoder *enc.Encoder) (int, error) { + size := 0 + size += encoder.CalcStructHeaderFix(1) + size += encoder.CalcString(v.Name) + return size, nil +} + +// calculate size from git.cacert.org/cacert-gosigner/pkg/messages.CAInfoCommand +func ___calcMapSizeCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v CAInfoCommand, encoder *enc.Encoder) (int, error) { + size := 0 + size += encoder.CalcStructHeaderFix(1) + size += encoder.CalcStringFix(4) + size += encoder.CalcString(v.Name) + return size, nil +} + +// encode from git.cacert.org/cacert-gosigner/pkg/messages.CAInfoCommand +func ___encodeArrayCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v CAInfoCommand, encoder *enc.Encoder, offset int) ([]byte, int, error) { + var err error + offset = encoder.WriteStructHeaderFixAsArray(1, offset) + offset = encoder.WriteString(v.Name, offset) + return encoder.EncodedBytes(), offset, err +} + +// encode from git.cacert.org/cacert-gosigner/pkg/messages.CAInfoCommand +func ___encodeMapCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v CAInfoCommand, encoder *enc.Encoder, offset int) ([]byte, int, error) { + var err error + offset = encoder.WriteStructHeaderFixAsMap(1, offset) + offset = encoder.WriteStringFix("name", 4, offset) + offset = encoder.WriteString(v.Name, offset) + return encoder.EncodedBytes(), offset, err +} + +// decode to git.cacert.org/cacert-gosigner/pkg/messages.CAInfoCommand +func ___decodeArrayCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v *CAInfoCommand, decoder *dec.Decoder, offset int) (int, error) { + offset, err := decoder.CheckStructHeader(1, offset) + if err != nil { + return 0, err + } + { + var vv string + vv, offset, err = decoder.AsString(offset) + if err != nil { + return 0, err + } + v.Name = vv + } + return offset, err +} + +// decode to git.cacert.org/cacert-gosigner/pkg/messages.CAInfoCommand +func ___decodeMapCAInfoCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v *CAInfoCommand, decoder *dec.Decoder, offset int) (int, error) { + keys := [][]byte{ + {uint8(0x6e), uint8(0x61), uint8(0x6d), uint8(0x65)}, // name + } + offset, err := decoder.CheckStructHeader(1, offset) + if err != nil { + return 0, err + } + count := 0 + for count < 1 { + var dataKey []byte + dataKey, offset, err = decoder.AsStringBytes(offset) + if err != nil { + return 0, err + } + fieldIndex := -1 + for i, key := range keys { + if len(dataKey) != len(key) { + continue + } + fieldIndex = i + for dataKeyIndex := range dataKey { + if dataKey[dataKeyIndex] != key[dataKeyIndex] { + fieldIndex = -1 + break + } + } + if fieldIndex >= 0 { + break + } + } + switch fieldIndex { + case 0: + { + var vv string + vv, offset, err = decoder.AsString(offset) + if err != nil { + return 0, err + } + v.Name = vv + } + count++ + default: + return 0, fmt.Errorf("unknown key[%s] found", string(dataKey)) + } + } + return offset, err +} + // calculate size from git.cacert.org/cacert-gosigner/pkg/messages.FetchCRLCommand func ___calcArraySizeFetchCRLCommand_e587a81c7cb163b35488bdef0f58c292f99f4bd65a81377f81e5b18c3d86855d(v FetchCRLCommand, encoder *enc.Encoder) (int, error) { size := 0