cacert-gosigner/datastructures/signerresponse.go

112 lines
2.8 KiB
Go

package datastructures
import (
"bytes"
"errors"
"fmt"
"git.cacert.org/cacert-gosigner/shared"
)
const (
headerPosVersion = 0
headerPosAction = 1
headerPosReserved1 = 2
headerPosReserved2 = 3
blockPosContent = 0
blockPosArgument1 = 1
blockPosArgument2 = 2
)
type SignerResponse struct {
Version uint8
Action shared.Action
Reserved1 uint8
Reserved2 uint8
Content []byte
Argument1 []byte
Argument2 []byte
}
func SignerResponseFromData(lengthBytes []byte, blockData []byte, checkSum byte) (*SignerResponse, error) {
if len(blockData) < shared.LengthFieldSize {
return nil, errors.New("begin of structure corrupt")
}
offset := 0
headerLength := Decode24BitLength(blockData[offset : offset+shared.LengthFieldSize])
offset += shared.LengthFieldSize
headerBytes := blockData[offset : offset+headerLength]
offset += headerLength
content := make([][]byte, 0)
for offset < len(blockData) {
dataLength := Decode24BitLength(blockData[offset : offset+3])
if len(blockData)-shared.LengthFieldSize < dataLength {
return nil, errors.New("structure cut off")
}
offset += shared.LengthFieldSize
content = append(content, blockData[offset:offset+dataLength])
offset += dataLength
}
calculated := CalculateXorCheckSum([][]byte{lengthBytes, blockData})
if checkSum != calculated {
return nil, fmt.Errorf("invalid checksum expected 0x%x got 0x%x", calculated, checkSum)
}
return &SignerResponse{
Version: headerBytes[headerPosVersion],
Action: shared.Action(headerBytes[headerPosAction]),
Reserved1: headerBytes[headerPosReserved1],
Reserved2: headerBytes[headerPosReserved2],
Content: content[blockPosContent],
Argument1: content[blockPosArgument1],
Argument2: content[blockPosArgument2],
}, nil
}
func (r SignerResponse) Serialize() []byte {
headerBytes := []byte{r.Version, byte(r.Action), r.Reserved1, r.Reserved2}
blockBytes := bytes.Join([][]byte{
Encode24BitLength(headerBytes), headerBytes,
Encode24BitLength(r.Content), r.Content,
Encode24BitLength(r.Argument1), r.Argument1,
Encode24BitLength(r.Argument2), r.Argument2,
}, []byte{})
return bytes.Join([][]byte{Encode24BitLength(blockBytes), blockBytes}, []byte{})
}
func NewNulResponse(version byte) *SignerResponse {
return &SignerResponse{
Version: version,
Action: shared.ActionNul,
Content: []byte{},
Argument1: []byte{},
Argument2: []byte{},
}
}
func NewRevokeResponse(version byte, content []byte) *SignerResponse {
return &SignerResponse{
Version: version,
Action: shared.ActionRevoke,
Content: content,
Argument1: []byte{},
Argument2: []byte{},
}
}
func NewSignResponse(version byte, content []byte) *SignerResponse {
return &SignerResponse{
Version: version,
Action: shared.ActionSign,
Content: content,
Argument1: []byte{},
Argument2: []byte{},
}
}