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{}, } }