Skip to content

Commit

Permalink
fix: update to use rawContent instead of expectedLen
Browse files Browse the repository at this point in the history
Signed-off-by: Junjie Gao <[email protected]>
  • Loading branch information
JeyJeyGao committed Aug 3, 2023
1 parent 3c99402 commit b9c73bd
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 59 deletions.
95 changes: 40 additions & 55 deletions internal/encoding/asn1/asn1.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,31 +56,30 @@ func ConvertToDER(ber []byte) ([]byte, error) {
// decode decodes BER-encoded ASN.1 data structures.
func decode(r []byte) (value, error) {
var (
identifier []byte
contentLen int
berValueLen int
err error
identifier []byte
contentLen int
err error
)
// prepare the first value
identifier, contentLen, _, r, err = decodeMetadata(r)
identifier, contentLen, r, err = decodeMetadata(r)
if err != nil {
return nil, err
}
if contentLen != len(r) {
return nil, ErrTrailingData
}

// primitive value
if isPrimitive(identifier) {
if contentLen != len(r) {
return nil, ErrTrailingData
}
return primitiveValue{
identifier: identifier,
content: r[:contentLen],
}, nil
}
// constructed value
rootConstructed := constructedValue{
identifier: identifier,
expectedLen: contentLen,
identifier: identifier,
rawContent: r[:contentLen],
}

// start depth-first decoding with stack
Expand All @@ -90,52 +89,42 @@ func decode(r []byte) (value, error) {
// top
v := valueStack[stackLen-1]

if v.expectedLen < 0 {
return nil, ErrInvalidBERData
}

if v.expectedLen == 0 {
// calculate the length of the constructed value
// the constructed value has been docoded
if len(v.rawContent) == 0 {
for _, m := range v.members {
v.length += m.EncodedLen()
}

// pop the constructued value
// pop
valueStack = valueStack[:stackLen-1]
continue
}

for v.expectedLen > 0 {
identifier, contentLen, berValueLen, r, err = decodeMetadata(r)
if err != nil {
return nil, err
// decode the next member of the constructed value
identifier, contentLen, v.rawContent, err = decodeMetadata(v.rawContent)
if err != nil {
return nil, err
}
if contentLen > len(v.rawContent) {
return nil, ErrEarlyEOF
}
if isPrimitive(identifier) {
// primitive value
pv := primitiveValue{
identifier: identifier,
content: v.rawContent[:contentLen],
}
if isPrimitive(identifier) {
// primitive value
pv := primitiveValue{
identifier: identifier,
content: r[:contentLen],
}
r = r[contentLen:]
v.expectedLen -= berValueLen
v.members = append(v.members, &pv)
} else {
// constructed value
cv := constructedValue{
identifier: identifier,
expectedLen: contentLen,
}
v.expectedLen -= berValueLen
v.members = append(v.members, &cv)
valueStack = append(valueStack, &cv)
// break to start decoding the new constructed value in the next
// iteration
break
v.members = append(v.members, &pv)
} else {
// constructed value
cv := constructedValue{
identifier: identifier,
rawContent: v.rawContent[:contentLen],
}
v.members = append(v.members, &cv)
valueStack = append(valueStack, &cv)
}
}
if len(r) > 0 {
return nil, ErrTrailingData
v.rawContent = v.rawContent[contentLen:]
}
return rootConstructed, nil
}
Expand All @@ -145,26 +134,22 @@ func decode(r []byte) (value, error) {
// r is the input byte slice.
// The first return value is the identifier octets.
// The second return value is the content length.
// The third return value is the BER value length.
// The fourth return value is the subsequent value after the identifier and
// The third return value is the subsequent value after the identifier and
// length octets.
func decodeMetadata(r []byte) ([]byte, int, int, []byte, error) {
length := len(r)
func decodeMetadata(r []byte) ([]byte, int, []byte, error) {
identifier, r, err := decodeIdentifier(r)
if err != nil {
return nil, 0, 0, nil, err
return nil, 0, nil, err
}
contentLen, r, err := decodeLength(r)
if err != nil {
return nil, 0, 0, nil, err
return nil, 0, nil, err
}

if contentLen > len(r) {
return nil, 0, 0, nil, ErrEarlyEOF
return nil, 0, nil, ErrEarlyEOF
}
metadataLen := length - len(r)
berValueLen := metadataLen + contentLen
return identifier, contentLen, berValueLen, r, nil
return identifier, contentLen, r, nil
}

// decodeIdentifier decodes decodeIdentifier octets.
Expand Down
8 changes: 4 additions & 4 deletions internal/encoding/asn1/constructed.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import "bytes"

// constructedValue represents a value in constructed encoding.
type constructedValue struct {
identifier []byte
expectedLen int
length int
members []value
identifier []byte
length int
members []value
rawContent []byte // the raw content of BER.
}

// Encode encodes the constructed value to the value writer in DER.
Expand Down

0 comments on commit b9c73bd

Please sign in to comment.