Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e7f98c0
Fixed content truncation by looping through all packages and parsing …
Apr 14, 2016
35fe2c3
Removed unnecessary variable declaration
Apr 14, 2016
6221838
Bug fix and hack to allow unsigning certain files
Jul 30, 2016
b995b8d
Merge pull request #1 from tpjg/master
geoko86 Jul 30, 2016
43ffad5
Correctly marshal degenerate certificates (#7)
groob Jun 5, 2016
477c9f6
AES-128-GCM support in Encrypt() and Decrypt() (#8)
hryx Jul 19, 2016
bcb2b81
Fix signers without AuthenticatedAttributes
fullsailor Jul 24, 2016
6fc3400
Fix an unstaged git hunk.
fullsailor Jul 24, 2016
b1490d5
Add travis.yml
fullsailor Jul 25, 2016
544cda0
Update travis.yml release -> 1.6
fullsailor Jul 25, 2016
a5d962c
Add build status to README
fullsailor Jul 25, 2016
7041c07
add support for aes128-CBC
groob Nov 12, 2016
10edc64
Support S/MIME detached signatures, and improve tests
jvehent Dec 29, 2016
a2fc7ee
Fix indefinite form parsing to parse nested indefinite form correctly.
addie9000 Apr 11, 2017
fa02d36
Fix hardcoded signature algorithm for verifying signers
fullsailor Feb 22, 2018
d0374ff
Bump tested Go versions to include 1.9 & 1.10
fullsailor Feb 22, 2018
6a48d77
Fix verifying App Store receipts
fullsailor Feb 23, 2018
917222b
Don't use asn1.NullBytes, its unavailable in Go 1.8
fullsailor Feb 23, 2018
6569da0
Test in Go 1.10, not Go 1.1
fullsailor Feb 23, 2018
663621a
Don't use asn1.TagNull, it was also introduced in Go 1.9
fullsailor Feb 23, 2018
22bc924
Fix failure to parse enveloped data in Go 1.10
fullsailor Apr 22, 2018
720ab68
Fix detached data content type
fullsailor Apr 22, 2018
37e4b64
Add support for verifying SHA256 signer digest
ktezlaf Apr 23, 2018
aa41f78
Comment out all lines with encodeIndent variable
lchudinov Jan 30, 2019
38a5ffa
Merge pull request #2 from sggms/georg/ch6977/esb-race-condition-dete…
geoko86 Nov 27, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
language: go

go:
- 1.8
- 1.9
- "1.10"
- tip
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# pkcs7

[![GoDoc](https://godoc.org/github.com/fullsailor/pkcs7?status.svg)](https://godoc.org/github.com/fullsailor/pkcs7)
[![Build Status](https://travis-ci.org/fullsailor/pkcs7.svg?branch=master)](https://travis-ci.org/fullsailor/pkcs7)

pkcs7 implements parsing and creating signed and enveloped messages.

Expand Down
51 changes: 36 additions & 15 deletions ber.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"errors"
)

var encodeIndent = 0
// var encodeIndent = 0

type asn1Object interface {
EncodeTo(writer *bytes.Buffer) error
Expand All @@ -18,15 +18,15 @@ type asn1Structured struct {

func (s asn1Structured) EncodeTo(out *bytes.Buffer) error {
//fmt.Printf("%s--> tag: % X\n", strings.Repeat("| ", encodeIndent), s.tagBytes)
encodeIndent++
//encodeIndent++
inner := new(bytes.Buffer)
for _, obj := range s.content {
err := obj.EncodeTo(inner)
if err != nil {
return err
}
}
encodeIndent--
//encodeIndent--
out.Write(s.tagBytes)
encodeLength(out, inner.Len())
out.Write(inner.Bytes())
Expand Down Expand Up @@ -161,7 +161,7 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) {
var length int
l := ber[offset]
offset++
hack := 0
indefinite := false
if l > 0x80 {
numberOfBytes := (int)(l & 0x7F)
if numberOfBytes > 4 { // int is only guaranteed to be 32bit
Expand All @@ -180,14 +180,7 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) {
offset++
}
} else if l == 0x80 {
// find length by searching content
markerIndex := bytes.LastIndex(ber[offset:], []byte{0x0, 0x0})
if markerIndex == -1 {
return nil, 0, errors.New("ber2der: Invalid BER format")
}
length = markerIndex
hack = 2
//fmt.Printf("--> (compute length) marker found at offset: %d\n", markerIndex+offset)
indefinite = true
} else {
length = (int)(l)
}
Expand All @@ -201,6 +194,9 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) {
//fmt.Printf("--> content end : %d\n", contentEnd)
//fmt.Printf("--> content : % X\n", ber[offset:contentEnd])
var obj asn1Object
if indefinite && kind == 0 {
return nil, 0, errors.New("ber2der: Indefinite form tag must have constructed encoding")
}
if kind == 0 {
obj = asn1Primitive{
tagBytes: ber[tagStart:tagEnd],
Expand All @@ -209,20 +205,45 @@ func readObject(ber []byte, offset int) (asn1Object, int, error) {
}
} else {
var subObjects []asn1Object
for offset < contentEnd {
for (offset < contentEnd) || indefinite {
var subObj asn1Object
var err error
subObj, offset, err = readObject(ber[:contentEnd], offset)

subObj, offset, err = readObject(ber, offset)
if err != nil {
return nil, 0, err
}
subObjects = append(subObjects, subObj)

if indefinite {
terminated, err := isIndefiniteTermination(ber, offset)
if err != nil {
return nil, 0, err
}

if terminated {
break
}
}
}
obj = asn1Structured{
tagBytes: ber[tagStart:tagEnd],
content: subObjects,
}
}

return obj, contentEnd + hack, nil
// Apply indefinite form length with 0x0000 terminator.
if indefinite {
contentEnd = offset + 2
}

return obj, contentEnd, nil
}

func isIndefiniteTermination(ber []byte, offset int) (bool, error) {
if len(ber)-offset < 2 {
return false, errors.New("ber2der: Invalid BER format")
}

return bytes.Index(ber[offset:], []byte{0x0, 0x0}) == 0, nil
}
38 changes: 37 additions & 1 deletion ber_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestBer2Der_Negatives(t *testing.T) {
{[]byte{0x30, 0x85}, "length too long"},
{[]byte{0x30, 0x84, 0x80, 0x0, 0x0, 0x0}, "length is negative"},
{[]byte{0x30, 0x82, 0x0, 0x1}, "length has leading zero"},
{[]byte{0x30, 0x80, 0x1, 0x2}, "Invalid BER format"},
{[]byte{0x30, 0x80, 0x1, 0x2, 0x1, 0x2}, "Invalid BER format"},
{[]byte{0x30, 0x03, 0x01, 0x02}, "length is more than available data"},
}

Expand All @@ -59,3 +59,39 @@ func TestBer2Der_Negatives(t *testing.T) {
}
}
}

func TestBer2Der_NestedMultipleIndefinite(t *testing.T) {
// indefinite length fixture
ber := []byte{0x30, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x00, 0x00, 0x30, 0x80, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00}
expected := []byte{0x30, 0x0A, 0x30, 0x03, 0x02, 0x01, 0x01, 0x30, 0x03, 0x02, 0x01, 0x02}

der, err := ber2der(ber)
if err != nil {
t.Fatalf("ber2der failed with error: %v", err)
}
if bytes.Compare(der, expected) != 0 {
t.Errorf("ber2der result did not match.\n\tExpected: % X\n\tActual: % X", expected, der)
}

if der2, err := ber2der(der); err != nil {
t.Errorf("ber2der on DER bytes failed with error: %v", err)
} else {
if !bytes.Equal(der, der2) {
t.Error("ber2der is not idempotent")
}
}
var thing struct {
Nest1 struct {
Number int
}
Nest2 struct {
Number int
}
}
rest, err := asn1.Unmarshal(der, &thing)
if err != nil {
t.Errorf("Cannot parse resulting DER because: %v", err)
} else if len(rest) > 0 {
t.Errorf("Resulting DER has trailing data: % X", rest)
}
}
Loading