serialization.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package ct
  2. // This file contains selectively chosen snippets of
  3. // github.com/google/certificate-transparency-go@ 5cfe585726ad9d990d4db524d6ce2567b13e2f80
  4. //
  5. // These snippets only perform deserialization for SCTs and are recreated here to prevent pulling in the whole of the ct
  6. // which contains yet another version of x509,asn1 and tls
  7. import (
  8. "encoding/binary"
  9. "errors"
  10. "fmt"
  11. "io"
  12. )
  13. // Variable size structure prefix-header byte lengths
  14. const (
  15. CertificateLengthBytes = 3
  16. PreCertificateLengthBytes = 3
  17. ExtensionsLengthBytes = 2
  18. CertificateChainLengthBytes = 3
  19. SignatureLengthBytes = 2
  20. )
  21. func writeUint(w io.Writer, value uint64, numBytes int) error {
  22. buf := make([]uint8, numBytes)
  23. for i := 0; i < numBytes; i++ {
  24. buf[numBytes-i-1] = uint8(value & 0xff)
  25. value >>= 8
  26. }
  27. if value != 0 {
  28. return errors.New("numBytes was insufficiently large to represent value")
  29. }
  30. if _, err := w.Write(buf); err != nil {
  31. return err
  32. }
  33. return nil
  34. }
  35. func writeVarBytes(w io.Writer, value []byte, numLenBytes int) error {
  36. if err := writeUint(w, uint64(len(value)), numLenBytes); err != nil {
  37. return err
  38. }
  39. if _, err := w.Write(value); err != nil {
  40. return err
  41. }
  42. return nil
  43. }
  44. func readUint(r io.Reader, numBytes int) (uint64, error) {
  45. var l uint64
  46. for i := 0; i < numBytes; i++ {
  47. l <<= 8
  48. var t uint8
  49. if err := binary.Read(r, binary.BigEndian, &t); err != nil {
  50. return 0, err
  51. }
  52. l |= uint64(t)
  53. }
  54. return l, nil
  55. }
  56. // Reads a variable length array of bytes from |r|. |numLenBytes| specifies the
  57. // number of (BigEndian) prefix-bytes which contain the length of the actual
  58. // array data bytes that follow.
  59. // Allocates an array to hold the contents and returns a slice view into it if
  60. // the read was successful, or an error otherwise.
  61. func readVarBytes(r io.Reader, numLenBytes int) ([]byte, error) {
  62. switch {
  63. case numLenBytes > 8:
  64. return nil, fmt.Errorf("numLenBytes too large (%d)", numLenBytes)
  65. case numLenBytes == 0:
  66. return nil, errors.New("numLenBytes should be > 0")
  67. }
  68. l, err := readUint(r, numLenBytes)
  69. if err != nil {
  70. return nil, err
  71. }
  72. data := make([]byte, l)
  73. if n, err := io.ReadFull(r, data); err != nil {
  74. if err == io.EOF || err == io.ErrUnexpectedEOF {
  75. return nil, fmt.Errorf("short read: expected %d but got %d", l, n)
  76. }
  77. return nil, err
  78. }
  79. return data, nil
  80. }
  81. // UnmarshalDigitallySigned reconstructs a DigitallySigned structure from a Reader
  82. func UnmarshalDigitallySigned(r io.Reader) (*DigitallySigned, error) {
  83. var h byte
  84. if err := binary.Read(r, binary.BigEndian, &h); err != nil {
  85. return nil, fmt.Errorf("failed to read HashAlgorithm: %v", err)
  86. }
  87. var s byte
  88. if err := binary.Read(r, binary.BigEndian, &s); err != nil {
  89. return nil, fmt.Errorf("failed to read SignatureAlgorithm: %v", err)
  90. }
  91. sig, err := readVarBytes(r, SignatureLengthBytes)
  92. if err != nil {
  93. return nil, fmt.Errorf("failed to read Signature bytes: %v", err)
  94. }
  95. return &DigitallySigned{
  96. HashAlgorithm: HashAlgorithm(h),
  97. SignatureAlgorithm: SignatureAlgorithm(s),
  98. Signature: sig,
  99. }, nil
  100. }
  101. func marshalDigitallySignedHere(ds DigitallySigned, here []byte) ([]byte, error) {
  102. sigLen := len(ds.Signature)
  103. dsOutLen := 2 + SignatureLengthBytes + sigLen
  104. if here == nil {
  105. here = make([]byte, dsOutLen)
  106. }
  107. if len(here) < dsOutLen {
  108. return nil, ErrNotEnoughBuffer
  109. }
  110. here = here[0:dsOutLen]
  111. here[0] = byte(ds.HashAlgorithm)
  112. here[1] = byte(ds.SignatureAlgorithm)
  113. binary.BigEndian.PutUint16(here[2:4], uint16(sigLen))
  114. copy(here[4:], ds.Signature)
  115. return here, nil
  116. }
  117. // MarshalDigitallySigned marshalls a DigitallySigned structure into a byte array
  118. func MarshalDigitallySigned(ds DigitallySigned) ([]byte, error) {
  119. return marshalDigitallySignedHere(ds, nil)
  120. }
  121. func deserializeSCTV1(r io.Reader, sct *SignedCertificateTimestamp) error {
  122. if err := binary.Read(r, binary.BigEndian, &sct.LogID); err != nil {
  123. return err
  124. }
  125. if err := binary.Read(r, binary.BigEndian, &sct.Timestamp); err != nil {
  126. return err
  127. }
  128. ext, err := readVarBytes(r, ExtensionsLengthBytes)
  129. if err != nil {
  130. return err
  131. }
  132. sct.Extensions = ext
  133. ds, err := UnmarshalDigitallySigned(r)
  134. if err != nil {
  135. return err
  136. }
  137. sct.Signature = *ds
  138. return nil
  139. }
  140. func DeserializeSCT(r io.Reader) (*SignedCertificateTimestamp, error) {
  141. var sct SignedCertificateTimestamp
  142. if err := binary.Read(r, binary.BigEndian, &sct.SCTVersion); err != nil {
  143. return nil, err
  144. }
  145. switch sct.SCTVersion {
  146. case V1:
  147. return &sct, deserializeSCTV1(r, &sct)
  148. default:
  149. return nil, fmt.Errorf("unknown SCT version %d", sct.SCTVersion)
  150. }
  151. }