ber.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. package ber
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "io/ioutil"
  8. "math"
  9. "os"
  10. "reflect"
  11. "strconv"
  12. "strings"
  13. "time"
  14. "unicode/utf8"
  15. )
  16. // MaxPacketLengthBytes specifies the maximum allowed packet size when calling ReadPacket or DecodePacket. Set to 0 for
  17. // no limit.
  18. var MaxPacketLengthBytes int64 = math.MaxInt32
  19. type Packet struct {
  20. Identifier
  21. Value interface{}
  22. ByteValue []byte
  23. Data *bytes.Buffer
  24. Children []*Packet
  25. Description string
  26. }
  27. type Identifier struct {
  28. ClassType Class
  29. TagType Type
  30. Tag Tag
  31. }
  32. type Tag uint64
  33. const (
  34. TagEOC Tag = 0x00
  35. TagBoolean Tag = 0x01
  36. TagInteger Tag = 0x02
  37. TagBitString Tag = 0x03
  38. TagOctetString Tag = 0x04
  39. TagNULL Tag = 0x05
  40. TagObjectIdentifier Tag = 0x06
  41. TagObjectDescriptor Tag = 0x07
  42. TagExternal Tag = 0x08
  43. TagRealFloat Tag = 0x09
  44. TagEnumerated Tag = 0x0a
  45. TagEmbeddedPDV Tag = 0x0b
  46. TagUTF8String Tag = 0x0c
  47. TagRelativeOID Tag = 0x0d
  48. TagSequence Tag = 0x10
  49. TagSet Tag = 0x11
  50. TagNumericString Tag = 0x12
  51. TagPrintableString Tag = 0x13
  52. TagT61String Tag = 0x14
  53. TagVideotexString Tag = 0x15
  54. TagIA5String Tag = 0x16
  55. TagUTCTime Tag = 0x17
  56. TagGeneralizedTime Tag = 0x18
  57. TagGraphicString Tag = 0x19
  58. TagVisibleString Tag = 0x1a
  59. TagGeneralString Tag = 0x1b
  60. TagUniversalString Tag = 0x1c
  61. TagCharacterString Tag = 0x1d
  62. TagBMPString Tag = 0x1e
  63. TagBitmask Tag = 0x1f // xxx11111b
  64. // HighTag indicates the start of a high-tag byte sequence
  65. HighTag Tag = 0x1f // xxx11111b
  66. // HighTagContinueBitmask indicates the high-tag byte sequence should continue
  67. HighTagContinueBitmask Tag = 0x80 // 10000000b
  68. // HighTagValueBitmask obtains the tag value from a high-tag byte sequence byte
  69. HighTagValueBitmask Tag = 0x7f // 01111111b
  70. )
  71. const (
  72. // LengthLongFormBitmask is the mask to apply to the length byte to see if a long-form byte sequence is used
  73. LengthLongFormBitmask = 0x80
  74. // LengthValueBitmask is the mask to apply to the length byte to get the number of bytes in the long-form byte sequence
  75. LengthValueBitmask = 0x7f
  76. // LengthIndefinite is returned from readLength to indicate an indefinite length
  77. LengthIndefinite = -1
  78. )
  79. var tagMap = map[Tag]string{
  80. TagEOC: "EOC (End-of-Content)",
  81. TagBoolean: "Boolean",
  82. TagInteger: "Integer",
  83. TagBitString: "Bit String",
  84. TagOctetString: "Octet String",
  85. TagNULL: "NULL",
  86. TagObjectIdentifier: "Object Identifier",
  87. TagObjectDescriptor: "Object Descriptor",
  88. TagExternal: "External",
  89. TagRealFloat: "Real (float)",
  90. TagEnumerated: "Enumerated",
  91. TagEmbeddedPDV: "Embedded PDV",
  92. TagUTF8String: "UTF8 String",
  93. TagRelativeOID: "Relative-OID",
  94. TagSequence: "Sequence and Sequence of",
  95. TagSet: "Set and Set OF",
  96. TagNumericString: "Numeric String",
  97. TagPrintableString: "Printable String",
  98. TagT61String: "T61 String",
  99. TagVideotexString: "Videotex String",
  100. TagIA5String: "IA5 String",
  101. TagUTCTime: "UTC Time",
  102. TagGeneralizedTime: "Generalized Time",
  103. TagGraphicString: "Graphic String",
  104. TagVisibleString: "Visible String",
  105. TagGeneralString: "General String",
  106. TagUniversalString: "Universal String",
  107. TagCharacterString: "Character String",
  108. TagBMPString: "BMP String",
  109. }
  110. type Class uint8
  111. const (
  112. ClassUniversal Class = 0 // 00xxxxxxb
  113. ClassApplication Class = 64 // 01xxxxxxb
  114. ClassContext Class = 128 // 10xxxxxxb
  115. ClassPrivate Class = 192 // 11xxxxxxb
  116. ClassBitmask Class = 192 // 11xxxxxxb
  117. )
  118. var ClassMap = map[Class]string{
  119. ClassUniversal: "Universal",
  120. ClassApplication: "Application",
  121. ClassContext: "Context",
  122. ClassPrivate: "Private",
  123. }
  124. type Type uint8
  125. const (
  126. TypePrimitive Type = 0 // xx0xxxxxb
  127. TypeConstructed Type = 32 // xx1xxxxxb
  128. TypeBitmask Type = 32 // xx1xxxxxb
  129. )
  130. var TypeMap = map[Type]string{
  131. TypePrimitive: "Primitive",
  132. TypeConstructed: "Constructed",
  133. }
  134. var Debug = false
  135. func PrintBytes(out io.Writer, buf []byte, indent string) {
  136. dataLines := make([]string, (len(buf)/30)+1)
  137. numLines := make([]string, (len(buf)/30)+1)
  138. for i, b := range buf {
  139. dataLines[i/30] += fmt.Sprintf("%02x ", b)
  140. numLines[i/30] += fmt.Sprintf("%02d ", (i+1)%100)
  141. }
  142. for i := 0; i < len(dataLines); i++ {
  143. _, _ = out.Write([]byte(indent + dataLines[i] + "\n"))
  144. _, _ = out.Write([]byte(indent + numLines[i] + "\n\n"))
  145. }
  146. }
  147. func WritePacket(out io.Writer, p *Packet) {
  148. printPacket(out, p, 0, false)
  149. }
  150. func PrintPacket(p *Packet) {
  151. printPacket(os.Stdout, p, 0, false)
  152. }
  153. // Return a string describing packet content. This is not recursive,
  154. // If the packet is a sequence, use `printPacket()`, or browse
  155. // sequence yourself.
  156. func DescribePacket(p *Packet) string {
  157. classStr := ClassMap[p.ClassType]
  158. tagTypeStr := TypeMap[p.TagType]
  159. tagStr := fmt.Sprintf("0x%02X", p.Tag)
  160. if p.ClassType == ClassUniversal {
  161. tagStr = tagMap[p.Tag]
  162. }
  163. value := fmt.Sprint(p.Value)
  164. description := ""
  165. if p.Description != "" {
  166. description = p.Description + ": "
  167. }
  168. return fmt.Sprintf("%s(%s, %s, %s) Len=%d %q", description, classStr, tagTypeStr, tagStr, p.Data.Len(), value)
  169. }
  170. func printPacket(out io.Writer, p *Packet, indent int, printBytes bool) {
  171. indentStr := ""
  172. for len(indentStr) != indent {
  173. indentStr += " "
  174. }
  175. _, _ = fmt.Fprintf(out, "%s%s\n", indentStr, DescribePacket(p))
  176. if printBytes {
  177. PrintBytes(out, p.Bytes(), indentStr)
  178. }
  179. for _, child := range p.Children {
  180. printPacket(out, child, indent+1, printBytes)
  181. }
  182. }
  183. // ReadPacket reads a single Packet from the reader.
  184. func ReadPacket(reader io.Reader) (*Packet, error) {
  185. p, _, err := readPacket(reader)
  186. if err != nil {
  187. return nil, err
  188. }
  189. return p, nil
  190. }
  191. func DecodeString(data []byte) string {
  192. return string(data)
  193. }
  194. func ParseInt64(bytes []byte) (ret int64, err error) {
  195. if len(bytes) > 8 {
  196. // We'll overflow an int64 in this case.
  197. err = fmt.Errorf("integer too large")
  198. return
  199. }
  200. for bytesRead := 0; bytesRead < len(bytes); bytesRead++ {
  201. ret <<= 8
  202. ret |= int64(bytes[bytesRead])
  203. }
  204. // Shift up and down in order to sign extend the result.
  205. ret <<= 64 - uint8(len(bytes))*8
  206. ret >>= 64 - uint8(len(bytes))*8
  207. return
  208. }
  209. func encodeInteger(i int64) []byte {
  210. n := int64Length(i)
  211. out := make([]byte, n)
  212. var j int
  213. for ; n > 0; n-- {
  214. out[j] = byte(i >> uint((n-1)*8))
  215. j++
  216. }
  217. return out
  218. }
  219. func int64Length(i int64) (numBytes int) {
  220. numBytes = 1
  221. for i > 127 {
  222. numBytes++
  223. i >>= 8
  224. }
  225. for i < -128 {
  226. numBytes++
  227. i >>= 8
  228. }
  229. return
  230. }
  231. // DecodePacket decodes the given bytes into a single Packet
  232. // If a decode error is encountered, nil is returned.
  233. func DecodePacket(data []byte) *Packet {
  234. p, _, _ := readPacket(bytes.NewBuffer(data))
  235. return p
  236. }
  237. // DecodePacketErr decodes the given bytes into a single Packet
  238. // If a decode error is encountered, nil is returned.
  239. func DecodePacketErr(data []byte) (*Packet, error) {
  240. p, _, err := readPacket(bytes.NewBuffer(data))
  241. if err != nil {
  242. return nil, err
  243. }
  244. return p, nil
  245. }
  246. // readPacket reads a single Packet from the reader, returning the number of bytes read.
  247. func readPacket(reader io.Reader) (*Packet, int, error) {
  248. identifier, length, read, err := readHeader(reader)
  249. if err != nil {
  250. return nil, read, err
  251. }
  252. p := &Packet{
  253. Identifier: identifier,
  254. }
  255. p.Data = new(bytes.Buffer)
  256. p.Children = make([]*Packet, 0, 2)
  257. p.Value = nil
  258. if p.TagType == TypeConstructed {
  259. // TODO: if universal, ensure tag type is allowed to be constructed
  260. // Track how much content we've read
  261. contentRead := 0
  262. for {
  263. if length != LengthIndefinite {
  264. // End if we've read what we've been told to
  265. if contentRead == length {
  266. break
  267. }
  268. // Detect if a packet boundary didn't fall on the expected length
  269. if contentRead > length {
  270. return nil, read, fmt.Errorf("expected to read %d bytes, read %d", length, contentRead)
  271. }
  272. }
  273. // Read the next packet
  274. child, r, err := readPacket(reader)
  275. if err != nil {
  276. return nil, read, unexpectedEOF(err)
  277. }
  278. contentRead += r
  279. read += r
  280. // Test is this is the EOC marker for our packet
  281. if isEOCPacket(child) {
  282. if length == LengthIndefinite {
  283. break
  284. }
  285. return nil, read, errors.New("eoc child not allowed with definite length")
  286. }
  287. // Append and continue
  288. p.AppendChild(child)
  289. }
  290. return p, read, nil
  291. }
  292. if length == LengthIndefinite {
  293. return nil, read, errors.New("indefinite length used with primitive type")
  294. }
  295. // Read definite-length content
  296. if MaxPacketLengthBytes > 0 && int64(length) > MaxPacketLengthBytes {
  297. return nil, read, fmt.Errorf("length %d greater than maximum %d", length, MaxPacketLengthBytes)
  298. }
  299. var content []byte
  300. if length > 0 {
  301. // Read the content and limit it to the parsed length.
  302. // If the content is less than the length, we return an EOF error.
  303. content, err = ioutil.ReadAll(io.LimitReader(reader, int64(length)))
  304. if err == nil && len(content) < int(length) {
  305. err = io.EOF
  306. }
  307. if err != nil {
  308. return nil, read, unexpectedEOF(err)
  309. }
  310. read += len(content)
  311. } else {
  312. // If length == 0, we set the ByteValue to an empty slice
  313. content = make([]byte, 0)
  314. }
  315. if p.ClassType == ClassUniversal {
  316. p.Data.Write(content)
  317. p.ByteValue = content
  318. switch p.Tag {
  319. case TagEOC:
  320. case TagBoolean:
  321. val, _ := ParseInt64(content)
  322. p.Value = val != 0
  323. case TagInteger:
  324. p.Value, _ = ParseInt64(content)
  325. case TagBitString:
  326. case TagOctetString:
  327. // the actual string encoding is not known here
  328. // (e.g. for LDAP content is already an UTF8-encoded
  329. // string). Return the data without further processing
  330. p.Value = DecodeString(content)
  331. case TagNULL:
  332. case TagObjectIdentifier:
  333. oid, err := parseObjectIdentifier(content)
  334. if err == nil {
  335. p.Value = OIDToString(oid)
  336. }
  337. case TagObjectDescriptor:
  338. case TagExternal:
  339. case TagRealFloat:
  340. p.Value, err = ParseReal(content)
  341. case TagEnumerated:
  342. p.Value, _ = ParseInt64(content)
  343. case TagEmbeddedPDV:
  344. case TagUTF8String:
  345. val := DecodeString(content)
  346. if !utf8.Valid([]byte(val)) {
  347. err = errors.New("invalid UTF-8 string")
  348. } else {
  349. p.Value = val
  350. }
  351. case TagRelativeOID:
  352. oid, err := parseRelativeObjectIdentifier(content)
  353. if err == nil {
  354. p.Value = OIDToString(oid)
  355. }
  356. case TagSequence:
  357. case TagSet:
  358. case TagNumericString:
  359. case TagPrintableString:
  360. val := DecodeString(content)
  361. if err = isPrintableString(val); err == nil {
  362. p.Value = val
  363. }
  364. case TagT61String:
  365. case TagVideotexString:
  366. case TagIA5String:
  367. val := DecodeString(content)
  368. for i, c := range val {
  369. if c >= 0x7F {
  370. err = fmt.Errorf("invalid character for IA5String at pos %d: %c", i, c)
  371. break
  372. }
  373. }
  374. if err == nil {
  375. p.Value = val
  376. }
  377. case TagUTCTime:
  378. case TagGeneralizedTime:
  379. p.Value, err = ParseGeneralizedTime(content)
  380. case TagGraphicString:
  381. case TagVisibleString:
  382. case TagGeneralString:
  383. case TagUniversalString:
  384. case TagCharacterString:
  385. case TagBMPString:
  386. }
  387. } else {
  388. p.Data.Write(content)
  389. }
  390. return p, read, err
  391. }
  392. func isPrintableString(val string) error {
  393. for i, c := range val {
  394. switch {
  395. case c >= 'a' && c <= 'z':
  396. case c >= 'A' && c <= 'Z':
  397. case c >= '0' && c <= '9':
  398. default:
  399. switch c {
  400. case '\'', '(', ')', '+', ',', '-', '.', '=', '/', ':', '?', ' ':
  401. default:
  402. return fmt.Errorf("invalid character in position %d", i)
  403. }
  404. }
  405. }
  406. return nil
  407. }
  408. func (p *Packet) Bytes() []byte {
  409. var out bytes.Buffer
  410. out.Write(encodeIdentifier(p.Identifier))
  411. out.Write(encodeLength(p.Data.Len()))
  412. out.Write(p.Data.Bytes())
  413. return out.Bytes()
  414. }
  415. func (p *Packet) AppendChild(child *Packet) {
  416. p.Data.Write(child.Bytes())
  417. p.Children = append(p.Children, child)
  418. }
  419. func Encode(classType Class, tagType Type, tag Tag, value interface{}, description string) *Packet {
  420. p := new(Packet)
  421. p.ClassType = classType
  422. p.TagType = tagType
  423. p.Tag = tag
  424. p.Data = new(bytes.Buffer)
  425. p.Children = make([]*Packet, 0, 2)
  426. p.Value = value
  427. p.Description = description
  428. if value != nil {
  429. v := reflect.ValueOf(value)
  430. if classType == ClassUniversal {
  431. switch tag {
  432. case TagOctetString:
  433. sv, ok := v.Interface().(string)
  434. if ok {
  435. p.Data.Write([]byte(sv))
  436. }
  437. case TagEnumerated:
  438. bv, ok := v.Interface().([]byte)
  439. if ok {
  440. p.Data.Write(bv)
  441. }
  442. case TagEmbeddedPDV:
  443. bv, ok := v.Interface().([]byte)
  444. if ok {
  445. p.Data.Write(bv)
  446. }
  447. }
  448. } else if classType == ClassContext {
  449. switch tag {
  450. case TagEnumerated:
  451. bv, ok := v.Interface().([]byte)
  452. if ok {
  453. p.Data.Write(bv)
  454. }
  455. case TagEmbeddedPDV:
  456. bv, ok := v.Interface().([]byte)
  457. if ok {
  458. p.Data.Write(bv)
  459. }
  460. }
  461. }
  462. }
  463. return p
  464. }
  465. func NewSequence(description string) *Packet {
  466. return Encode(ClassUniversal, TypeConstructed, TagSequence, nil, description)
  467. }
  468. func NewBoolean(classType Class, tagType Type, tag Tag, value bool, description string) *Packet {
  469. intValue := int64(0)
  470. if value {
  471. intValue = 1
  472. }
  473. p := Encode(classType, tagType, tag, nil, description)
  474. p.Value = value
  475. p.Data.Write(encodeInteger(intValue))
  476. return p
  477. }
  478. // NewLDAPBoolean returns a RFC 4511-compliant Boolean packet.
  479. func NewLDAPBoolean(classType Class, tagType Type, tag Tag, value bool, description string) *Packet {
  480. p := Encode(classType, tagType, tag, nil, description)
  481. p.Value = value
  482. if value {
  483. p.Data.Write([]byte{255})
  484. } else {
  485. p.Data.Write([]byte{0})
  486. }
  487. return p
  488. }
  489. func NewInteger(classType Class, tagType Type, tag Tag, value interface{}, description string) *Packet {
  490. p := Encode(classType, tagType, tag, nil, description)
  491. p.Value = value
  492. switch v := value.(type) {
  493. case int:
  494. p.Data.Write(encodeInteger(int64(v)))
  495. case uint:
  496. p.Data.Write(encodeInteger(int64(v)))
  497. case int64:
  498. p.Data.Write(encodeInteger(v))
  499. case uint64:
  500. // TODO : check range or add encodeUInt...
  501. p.Data.Write(encodeInteger(int64(v)))
  502. case int32:
  503. p.Data.Write(encodeInteger(int64(v)))
  504. case uint32:
  505. p.Data.Write(encodeInteger(int64(v)))
  506. case int16:
  507. p.Data.Write(encodeInteger(int64(v)))
  508. case uint16:
  509. p.Data.Write(encodeInteger(int64(v)))
  510. case int8:
  511. p.Data.Write(encodeInteger(int64(v)))
  512. case uint8:
  513. p.Data.Write(encodeInteger(int64(v)))
  514. default:
  515. // TODO : add support for big.Int ?
  516. panic(fmt.Sprintf("Invalid type %T, expected {u|}int{64|32|16|8}", v))
  517. }
  518. return p
  519. }
  520. func NewString(classType Class, tagType Type, tag Tag, value, description string) *Packet {
  521. p := Encode(classType, tagType, tag, nil, description)
  522. p.Value = value
  523. p.Data.Write([]byte(value))
  524. return p
  525. }
  526. func NewGeneralizedTime(classType Class, tagType Type, tag Tag, value time.Time, description string) *Packet {
  527. p := Encode(classType, tagType, tag, nil, description)
  528. var s string
  529. if value.Nanosecond() != 0 {
  530. s = value.Format(`20060102150405.000000000Z`)
  531. } else {
  532. s = value.Format(`20060102150405Z`)
  533. }
  534. p.Value = s
  535. p.Data.Write([]byte(s))
  536. return p
  537. }
  538. func NewReal(classType Class, tagType Type, tag Tag, value interface{}, description string) *Packet {
  539. p := Encode(classType, tagType, tag, nil, description)
  540. switch v := value.(type) {
  541. case float64:
  542. p.Data.Write(encodeFloat(v))
  543. case float32:
  544. p.Data.Write(encodeFloat(float64(v)))
  545. default:
  546. panic(fmt.Sprintf("Invalid type %T, expected float{64|32}", v))
  547. }
  548. return p
  549. }
  550. func NewOID(classType Class, tagType Type, tag Tag, value interface{}, description string) *Packet {
  551. p := Encode(classType, tagType, tag, nil, description)
  552. switch v := value.(type) {
  553. case string:
  554. encoded, err := encodeOID(v)
  555. if err != nil {
  556. fmt.Printf("failed writing %v", err)
  557. return nil
  558. }
  559. p.Value = v
  560. p.Data.Write(encoded)
  561. // TODO: support []int already ?
  562. default:
  563. panic(fmt.Sprintf("Invalid type %T, expected float{64|32}", v))
  564. }
  565. return p
  566. }
  567. func NewRelativeOID(classType Class, tagType Type, tag Tag, value interface{}, description string) *Packet {
  568. p := Encode(classType, tagType, tag, nil, description)
  569. switch v := value.(type) {
  570. case string:
  571. encoded, err := encodeRelativeOID(v)
  572. if err != nil {
  573. fmt.Printf("failed writing %v", err)
  574. return nil
  575. }
  576. p.Value = v
  577. p.Data.Write(encoded)
  578. // TODO: support []int already ?
  579. default:
  580. panic(fmt.Sprintf("Invalid type %T, expected float{64|32}", v))
  581. }
  582. return p
  583. }
  584. // encodeOID takes a string representation of an OID and returns its DER-encoded byte slice along with any error.
  585. func encodeOID(oidString string) ([]byte, error) {
  586. // Convert the string representation to an asn1.ObjectIdentifier
  587. parts := strings.Split(oidString, ".")
  588. oid := make([]int, len(parts))
  589. for i, part := range parts {
  590. var val int
  591. if _, err := fmt.Sscanf(part, "%d", &val); err != nil {
  592. return nil, fmt.Errorf("invalid OID part '%s': %w", part, err)
  593. }
  594. oid[i] = val
  595. }
  596. if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
  597. panic(fmt.Sprintf("invalid object identifier % d", oid)) // TODO: not elegant
  598. }
  599. encoded := make([]byte, 0)
  600. encoded = appendBase128Int(encoded[:0], int64(oid[0]*40+oid[1]))
  601. for i := 2; i < len(oid); i++ {
  602. encoded = appendBase128Int(encoded, int64(oid[i]))
  603. }
  604. return encoded, nil
  605. }
  606. func encodeRelativeOID(oidString string) ([]byte, error) {
  607. parts := strings.Split(oidString, ".")
  608. oid := make([]int, len(parts))
  609. for i, part := range parts {
  610. var val int
  611. if _, err := fmt.Sscanf(part, "%d", &val); err != nil {
  612. return nil, fmt.Errorf("invalid RELATIVE OID part '%s': %w", part, err)
  613. }
  614. oid[i] = val
  615. }
  616. encoded := make([]byte, 0)
  617. for i := 0; i < len(oid); i++ {
  618. encoded = appendBase128Int(encoded, int64(oid[i]))
  619. }
  620. return encoded, nil
  621. }
  622. func appendBase128Int(dst []byte, n int64) []byte {
  623. l := base128IntLength(n)
  624. for i := l - 1; i >= 0; i-- {
  625. o := byte(n >> uint(i*7))
  626. o &= 0x7f
  627. if i != 0 {
  628. o |= 0x80
  629. }
  630. dst = append(dst, o)
  631. }
  632. return dst
  633. }
  634. func base128IntLength(n int64) int {
  635. if n == 0 {
  636. return 1
  637. }
  638. l := 0
  639. for i := n; i > 0; i >>= 7 {
  640. l++
  641. }
  642. return l
  643. }
  644. func OIDToString(oi []int) string {
  645. var s strings.Builder
  646. s.Grow(32)
  647. buf := make([]byte, 0, 19)
  648. for i, v := range oi {
  649. if i > 0 {
  650. s.WriteByte('.')
  651. }
  652. s.Write(strconv.AppendInt(buf, int64(v), 10))
  653. }
  654. return s.String()
  655. }
  656. // parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and
  657. // returns it. An object identifier is a sequence of variable length integers
  658. // that are assigned in a hierarchy.
  659. func parseObjectIdentifier(bytes []byte) (s []int, err error) {
  660. if len(bytes) == 0 {
  661. err = fmt.Errorf("zero length OBJECT IDENTIFIER")
  662. return
  663. }
  664. // In the worst case, we get two elements from the first byte (which is
  665. // encoded differently) and then every varint is a single byte long.
  666. s = make([]int, len(bytes)+1)
  667. // The first varint is 40*value1 + value2:
  668. // According to this packing, value1 can take the values 0, 1 and 2 only.
  669. // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2,
  670. // then there are no restrictions on value2.
  671. v, offset, err := parseBase128Int(bytes, 0)
  672. if err != nil {
  673. return
  674. }
  675. if v < 80 {
  676. s[0] = v / 40
  677. s[1] = v % 40
  678. } else {
  679. s[0] = 2
  680. s[1] = v - 80
  681. }
  682. i := 2
  683. for ; offset < len(bytes); i++ {
  684. v, offset, err = parseBase128Int(bytes, offset)
  685. if err != nil {
  686. return
  687. }
  688. s[i] = v
  689. }
  690. s = s[0:i]
  691. return
  692. }
  693. func parseRelativeObjectIdentifier(bytes []byte) (s []int, err error) {
  694. if len(bytes) == 0 {
  695. err = fmt.Errorf("zero length RELATIVE OBJECT IDENTIFIER")
  696. return
  697. }
  698. s = make([]int, len(bytes)+1)
  699. var v, offset int
  700. i := 0
  701. for ; offset < len(bytes); i++ {
  702. v, offset, err = parseBase128Int(bytes, offset)
  703. if err != nil {
  704. return
  705. }
  706. s[i] = v
  707. }
  708. s = s[0:i]
  709. return
  710. }
  711. // parseBase128Int parses a base-128 encoded int from the given offset in the
  712. // given byte slice. It returns the value and the new offset.
  713. func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) {
  714. offset = initOffset
  715. var ret64 int64
  716. for shifted := 0; offset < len(bytes); shifted++ {
  717. // 5 * 7 bits per byte == 35 bits of data
  718. // Thus the representation is either non-minimal or too large for an int32
  719. if shifted == 5 {
  720. err = fmt.Errorf("base 128 integer too large")
  721. return
  722. }
  723. ret64 <<= 7
  724. b := bytes[offset]
  725. // integers should be minimally encoded, so the leading octet should
  726. // never be 0x80
  727. if shifted == 0 && b == 0x80 {
  728. err = fmt.Errorf("integer is not minimally encoded")
  729. return
  730. }
  731. ret64 |= int64(b & 0x7f)
  732. offset++
  733. if b&0x80 == 0 {
  734. ret = int(ret64)
  735. // Ensure that the returned value fits in an int on all platforms
  736. if ret64 > math.MaxInt32 {
  737. err = fmt.Errorf("base 128 integer too large")
  738. }
  739. return
  740. }
  741. }
  742. err = fmt.Errorf("truncated base 128 integer")
  743. return
  744. }