...

Source file src/github.com/sassoftware/relic/lib/signxap/sign.go

Documentation: github.com/sassoftware/relic/lib/signxap

     1  //
     2  // Copyright (c) SAS Institute Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package signxap
    18  
    19  import (
    20  	"archive/tar"
    21  	"bytes"
    22  	"context"
    23  	"crypto"
    24  	"encoding/binary"
    25  	"errors"
    26  	"fmt"
    27  	"io"
    28  	"io/ioutil"
    29  
    30  	"github.com/sassoftware/relic/lib/authenticode"
    31  	"github.com/sassoftware/relic/lib/binpatch"
    32  	"github.com/sassoftware/relic/lib/certloader"
    33  	"github.com/sassoftware/relic/lib/pkcs9"
    34  	"github.com/sassoftware/relic/lib/zipslicer"
    35  )
    36  
    37  type XapDigest struct {
    38  	Hash       crypto.Hash
    39  	Imprint    []byte
    40  	PatchStart int64
    41  	PatchLen   int64
    42  }
    43  
    44  func DigestXapTar(r io.Reader, hash crypto.Hash, doPageHash bool) (*XapDigest, error) {
    45  	tr := tar.NewReader(r)
    46  	var cd []byte
    47  	var totalSize int64
    48  	for {
    49  		hdr, err := tr.Next()
    50  		if err == io.EOF {
    51  			return nil, errors.New("invalid tarzip")
    52  		} else if err != nil {
    53  			return nil, fmt.Errorf("error reading tar: %s", err)
    54  		}
    55  		if hdr.Name == zipslicer.TarMemberCD {
    56  			cd, err = ioutil.ReadAll(tr)
    57  			if err != nil {
    58  				return nil, fmt.Errorf("error reading tar: %s", err)
    59  			}
    60  		} else if hdr.Name == zipslicer.TarMemberZip {
    61  			totalSize = hdr.Size
    62  			break
    63  		}
    64  	}
    65  	bodySize := totalSize - int64(len(cd))
    66  	d := hash.New()
    67  	if _, err := io.CopyN(d, tr, bodySize); err != nil {
    68  		return nil, err
    69  	}
    70  	cd = removeSignature(cd)
    71  	d.Write(cd)
    72  	zipSize := bodySize + int64(len(cd))
    73  	return &XapDigest{
    74  		Hash:       hash,
    75  		Imprint:    d.Sum(nil),
    76  		PatchStart: zipSize,
    77  		PatchLen:   totalSize - zipSize,
    78  	}, nil
    79  }
    80  
    81  func removeSignature(cd []byte) []byte {
    82  	size := len(cd)
    83  	var tr xapTrailer
    84  	binary.Read(bytes.NewReader(cd[size-10:size]), binary.LittleEndian, &tr)
    85  	if tr.Magic == trailerMagic {
    86  		size -= int(tr.TrailerSize) + 10
    87  		return cd[:size]
    88  	}
    89  	return cd
    90  }
    91  
    92  func (d *XapDigest) Sign(ctx context.Context, cert *certloader.Certificate) (*binpatch.PatchSet, *pkcs9.TimestampedSignature, error) {
    93  	ts, err := authenticode.SignSip(ctx, d.Imprint, d.Hash, xapSipInfo, cert)
    94  	if err != nil {
    95  		return nil, nil, err
    96  	}
    97  	var w bytes.Buffer
    98  	hdr := xapHeader{
    99  		Unknown1:      1,
   100  		Unknown2:      1,
   101  		SignatureSize: uint32(len(ts.Raw)),
   102  	}
   103  	binary.Write(&w, binary.LittleEndian, hdr)
   104  	w.Write(ts.Raw)
   105  	tr := xapTrailer{
   106  		Magic:       trailerMagic,
   107  		Unknown1:    1,
   108  		TrailerSize: uint32(len(ts.Raw) + 8),
   109  	}
   110  	binary.Write(&w, binary.LittleEndian, tr)
   111  	patch := binpatch.New()
   112  	patch.Add(d.PatchStart, d.PatchLen, w.Bytes())
   113  	return patch, ts, nil
   114  }
   115  

View as plain text