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.

identifier.go 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package ber
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. )
  7. func readIdentifier(reader io.Reader) (Identifier, int, error) {
  8. identifier := Identifier{}
  9. read := 0
  10. // identifier byte
  11. b, err := readByte(reader)
  12. if err != nil {
  13. if Debug {
  14. fmt.Printf("error reading identifier byte: %v\n", err)
  15. }
  16. return Identifier{}, read, err
  17. }
  18. read++
  19. identifier.ClassType = Class(b) & ClassBitmask
  20. identifier.TagType = Type(b) & TypeBitmask
  21. if tag := Tag(b) & TagBitmask; tag != HighTag {
  22. // short-form tag
  23. identifier.Tag = tag
  24. return identifier, read, nil
  25. }
  26. // high-tag-number tag
  27. tagBytes := 0
  28. for {
  29. b, err := readByte(reader)
  30. if err != nil {
  31. if Debug {
  32. fmt.Printf("error reading high-tag-number tag byte %d: %v\n", tagBytes, err)
  33. }
  34. return Identifier{}, read, err
  35. }
  36. tagBytes++
  37. read++
  38. // Lowest 7 bits get appended to the tag value (x.690, 8.1.2.4.2.b)
  39. identifier.Tag <<= 7
  40. identifier.Tag |= Tag(b) & HighTagValueBitmask
  41. // First byte may not be all zeros (x.690, 8.1.2.4.2.c)
  42. if tagBytes == 1 && identifier.Tag == 0 {
  43. return Identifier{}, read, errors.New("invalid first high-tag-number tag byte")
  44. }
  45. // Overflow of int64
  46. // TODO: support big int tags?
  47. if tagBytes > 9 {
  48. return Identifier{}, read, errors.New("high-tag-number tag overflow")
  49. }
  50. // Top bit of 0 means this is the last byte in the high-tag-number tag (x.690, 8.1.2.4.2.a)
  51. if Tag(b)&HighTagContinueBitmask == 0 {
  52. break
  53. }
  54. }
  55. return identifier, read, nil
  56. }
  57. func encodeIdentifier(identifier Identifier) []byte {
  58. b := []byte{0x0}
  59. b[0] |= byte(identifier.ClassType)
  60. b[0] |= byte(identifier.TagType)
  61. if identifier.Tag < HighTag {
  62. // Short-form
  63. b[0] |= byte(identifier.Tag)
  64. } else {
  65. // high-tag-number
  66. b[0] |= byte(HighTag)
  67. tag := identifier.Tag
  68. b = append(b, encodeHighTag(tag)...)
  69. }
  70. return b
  71. }
  72. func encodeHighTag(tag Tag) []byte {
  73. // set cap=4 to hopefully avoid additional allocations
  74. b := make([]byte, 0, 4)
  75. for tag != 0 {
  76. // t := last 7 bits of tag (HighTagValueBitmask = 0x7F)
  77. t := tag & HighTagValueBitmask
  78. // right shift tag 7 to remove what was just pulled off
  79. tag >>= 7
  80. // if b already has entries this entry needs a continuation bit (0x80)
  81. if len(b) != 0 {
  82. t |= HighTagContinueBitmask
  83. }
  84. b = append(b, byte(t))
  85. }
  86. // reverse
  87. // since bits were pulled off 'tag' small to high the byte slice is in reverse order.
  88. // example: tag = 0xFF results in {0x7F, 0x01 + 0x80 (continuation bit)}
  89. // this needs to be reversed into 0x81 0x7F
  90. for i, j := 0, len(b)-1; i < len(b)/2; i++ {
  91. b[i], b[j-i] = b[j-i], b[i]
  92. }
  93. return b
  94. }