You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

googletpm.go 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package googletpm
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "reflect"
  8. )
  9. // From github.com/google/go-tpm
  10. // Portions of existing package conflicted with existing build environment
  11. // and only needed very small amount of code for pubarea and certinfo structs
  12. // so copied them out to this package
  13. // Supported Algorithms.
  14. const (
  15. AlgUnknown Algorithm = 0x0000
  16. AlgRSA Algorithm = 0x0001
  17. AlgSHA1 Algorithm = 0x0004
  18. AlgAES Algorithm = 0x0006
  19. AlgKeyedHash Algorithm = 0x0008
  20. AlgSHA256 Algorithm = 0x000B
  21. AlgSHA384 Algorithm = 0x000C
  22. AlgSHA512 Algorithm = 0x000D
  23. AlgNull Algorithm = 0x0010
  24. AlgRSASSA Algorithm = 0x0014
  25. AlgRSAES Algorithm = 0x0015
  26. AlgRSAPSS Algorithm = 0x0016
  27. AlgOAEP Algorithm = 0x0017
  28. AlgECDSA Algorithm = 0x0018
  29. AlgECDH Algorithm = 0x0019
  30. AlgECDAA Algorithm = 0x001A
  31. AlgKDF2 Algorithm = 0x0021
  32. AlgECC Algorithm = 0x0023
  33. AlgCTR Algorithm = 0x0040
  34. AlgOFB Algorithm = 0x0041
  35. AlgCBC Algorithm = 0x0042
  36. AlgCFB Algorithm = 0x0043
  37. AlgECB Algorithm = 0x0044
  38. )
  39. // UnpackBuf recursively unpacks types from a reader just as encoding/binary
  40. // does under binary.BigEndian, but with one difference: it unpacks a byte
  41. // slice by first reading an integer with lengthPrefixSize bytes, then reading
  42. // that many bytes. It assumes that incoming values are pointers to values so
  43. // that, e.g., underlying slices can be resized as needed.
  44. func UnpackBuf(buf io.Reader, elts ...interface{}) error {
  45. for _, e := range elts {
  46. v := reflect.ValueOf(e)
  47. k := v.Kind()
  48. if k != reflect.Ptr {
  49. return fmt.Errorf("all values passed to Unpack must be pointers, got %v", k)
  50. }
  51. if v.IsNil() {
  52. return errors.New("can't fill a nil pointer")
  53. }
  54. iv := reflect.Indirect(v)
  55. switch iv.Kind() {
  56. case reflect.Struct:
  57. // Decompose the struct and copy over the values.
  58. for i := 0; i < iv.NumField(); i++ {
  59. if err := UnpackBuf(buf, iv.Field(i).Addr().Interface()); err != nil {
  60. return err
  61. }
  62. }
  63. case reflect.Slice:
  64. var size int
  65. _, isHandles := e.(*[]Handle)
  66. switch {
  67. // []Handle always uses 2-byte length, even with TPM 1.2.
  68. case isHandles:
  69. var tmpSize uint16
  70. if err := binary.Read(buf, binary.BigEndian, &tmpSize); err != nil {
  71. return err
  72. }
  73. size = int(tmpSize)
  74. // TPM 2.0
  75. case lengthPrefixSize == tpm20PrefixSize:
  76. var tmpSize uint16
  77. if err := binary.Read(buf, binary.BigEndian, &tmpSize); err != nil {
  78. return err
  79. }
  80. size = int(tmpSize)
  81. // TPM 1.2
  82. case lengthPrefixSize == tpm12PrefixSize:
  83. var tmpSize uint32
  84. if err := binary.Read(buf, binary.BigEndian, &tmpSize); err != nil {
  85. return err
  86. }
  87. size = int(tmpSize)
  88. default:
  89. return fmt.Errorf("lengthPrefixSize is %d, must be either 2 or 4", lengthPrefixSize)
  90. }
  91. // A zero size is used by the TPM to signal that certain elements
  92. // are not present.
  93. if size == 0 {
  94. continue
  95. }
  96. // Make len(e) match size exactly.
  97. switch b := e.(type) {
  98. case *[]byte:
  99. if len(*b) >= size {
  100. *b = (*b)[:size]
  101. } else {
  102. *b = append(*b, make([]byte, size-len(*b))...)
  103. }
  104. case *[]Handle:
  105. if len(*b) >= size {
  106. *b = (*b)[:size]
  107. } else {
  108. *b = append(*b, make([]Handle, size-len(*b))...)
  109. }
  110. default:
  111. return fmt.Errorf("can't fill pointer to %T, only []byte or []Handle slices", e)
  112. }
  113. if err := binary.Read(buf, binary.BigEndian, e); err != nil {
  114. return err
  115. }
  116. default:
  117. if err := binary.Read(buf, binary.BigEndian, e); err != nil {
  118. return err
  119. }
  120. }
  121. }
  122. return nil
  123. }
  124. // lengthPrefixSize is the size in bytes of length prefix for byte slices.
  125. //
  126. // In TPM 1.2 this is 4 bytes.
  127. // In TPM 2.0 this is 2 bytes.
  128. var lengthPrefixSize int
  129. const (
  130. tpm12PrefixSize = 4
  131. tpm20PrefixSize = 2
  132. )
  133. // UseTPM20LengthPrefixSize makes Pack/Unpack use TPM 2.0 encoding for byte
  134. // arrays.
  135. func UseTPM20LengthPrefixSize() {
  136. lengthPrefixSize = tpm20PrefixSize
  137. }