diff options
Diffstat (limited to 'vendor/golang.org/x/crypto/openpgp/packet/opaque.go')
-rw-r--r-- | vendor/golang.org/x/crypto/openpgp/packet/opaque.go | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/opaque.go b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go new file mode 100644 index 0000000..456d807 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go | |||
@@ -0,0 +1,162 @@ | |||
1 | // Copyright 2012 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package packet | ||
6 | |||
7 | import ( | ||
8 | "bytes" | ||
9 | "io" | ||
10 | "io/ioutil" | ||
11 | |||
12 | "golang.org/x/crypto/openpgp/errors" | ||
13 | ) | ||
14 | |||
15 | // OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is | ||
16 | // useful for splitting and storing the original packet contents separately, | ||
17 | // handling unsupported packet types or accessing parts of the packet not yet | ||
18 | // implemented by this package. | ||
19 | type OpaquePacket struct { | ||
20 | // Packet type | ||
21 | Tag uint8 | ||
22 | // Reason why the packet was parsed opaquely | ||
23 | Reason error | ||
24 | // Binary contents of the packet data | ||
25 | Contents []byte | ||
26 | } | ||
27 | |||
28 | func (op *OpaquePacket) parse(r io.Reader) (err error) { | ||
29 | op.Contents, err = ioutil.ReadAll(r) | ||
30 | return | ||
31 | } | ||
32 | |||
33 | // Serialize marshals the packet to a writer in its original form, including | ||
34 | // the packet header. | ||
35 | func (op *OpaquePacket) Serialize(w io.Writer) (err error) { | ||
36 | err = serializeHeader(w, packetType(op.Tag), len(op.Contents)) | ||
37 | if err == nil { | ||
38 | _, err = w.Write(op.Contents) | ||
39 | } | ||
40 | return | ||
41 | } | ||
42 | |||
43 | // Parse attempts to parse the opaque contents into a structure supported by | ||
44 | // this package. If the packet is not known then the result will be another | ||
45 | // OpaquePacket. | ||
46 | func (op *OpaquePacket) Parse() (p Packet, err error) { | ||
47 | hdr := bytes.NewBuffer(nil) | ||
48 | err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents)) | ||
49 | if err != nil { | ||
50 | op.Reason = err | ||
51 | return op, err | ||
52 | } | ||
53 | p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents))) | ||
54 | if err != nil { | ||
55 | op.Reason = err | ||
56 | p = op | ||
57 | } | ||
58 | return | ||
59 | } | ||
60 | |||
61 | // OpaqueReader reads OpaquePackets from an io.Reader. | ||
62 | type OpaqueReader struct { | ||
63 | r io.Reader | ||
64 | } | ||
65 | |||
66 | func NewOpaqueReader(r io.Reader) *OpaqueReader { | ||
67 | return &OpaqueReader{r: r} | ||
68 | } | ||
69 | |||
70 | // Read the next OpaquePacket. | ||
71 | func (or *OpaqueReader) Next() (op *OpaquePacket, err error) { | ||
72 | tag, _, contents, err := readHeader(or.r) | ||
73 | if err != nil { | ||
74 | return | ||
75 | } | ||
76 | op = &OpaquePacket{Tag: uint8(tag), Reason: err} | ||
77 | err = op.parse(contents) | ||
78 | if err != nil { | ||
79 | consumeAll(contents) | ||
80 | } | ||
81 | return | ||
82 | } | ||
83 | |||
84 | // OpaqueSubpacket represents an unparsed OpenPGP subpacket, | ||
85 | // as found in signature and user attribute packets. | ||
86 | type OpaqueSubpacket struct { | ||
87 | SubType uint8 | ||
88 | Contents []byte | ||
89 | } | ||
90 | |||
91 | // OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from | ||
92 | // their byte representation. | ||
93 | func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) { | ||
94 | var ( | ||
95 | subHeaderLen int | ||
96 | subPacket *OpaqueSubpacket | ||
97 | ) | ||
98 | for len(contents) > 0 { | ||
99 | subHeaderLen, subPacket, err = nextSubpacket(contents) | ||
100 | if err != nil { | ||
101 | break | ||
102 | } | ||
103 | result = append(result, subPacket) | ||
104 | contents = contents[subHeaderLen+len(subPacket.Contents):] | ||
105 | } | ||
106 | return | ||
107 | } | ||
108 | |||
109 | func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) { | ||
110 | // RFC 4880, section 5.2.3.1 | ||
111 | var subLen uint32 | ||
112 | if len(contents) < 1 { | ||
113 | goto Truncated | ||
114 | } | ||
115 | subPacket = &OpaqueSubpacket{} | ||
116 | switch { | ||
117 | case contents[0] < 192: | ||
118 | subHeaderLen = 2 // 1 length byte, 1 subtype byte | ||
119 | if len(contents) < subHeaderLen { | ||
120 | goto Truncated | ||
121 | } | ||
122 | subLen = uint32(contents[0]) | ||
123 | contents = contents[1:] | ||
124 | case contents[0] < 255: | ||
125 | subHeaderLen = 3 // 2 length bytes, 1 subtype | ||
126 | if len(contents) < subHeaderLen { | ||
127 | goto Truncated | ||
128 | } | ||
129 | subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192 | ||
130 | contents = contents[2:] | ||
131 | default: | ||
132 | subHeaderLen = 6 // 5 length bytes, 1 subtype | ||
133 | if len(contents) < subHeaderLen { | ||
134 | goto Truncated | ||
135 | } | ||
136 | subLen = uint32(contents[1])<<24 | | ||
137 | uint32(contents[2])<<16 | | ||
138 | uint32(contents[3])<<8 | | ||
139 | uint32(contents[4]) | ||
140 | contents = contents[5:] | ||
141 | } | ||
142 | if subLen > uint32(len(contents)) || subLen == 0 { | ||
143 | goto Truncated | ||
144 | } | ||
145 | subPacket.SubType = contents[0] | ||
146 | subPacket.Contents = contents[1:subLen] | ||
147 | return | ||
148 | Truncated: | ||
149 | err = errors.StructuralError("subpacket truncated") | ||
150 | return | ||
151 | } | ||
152 | |||
153 | func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) { | ||
154 | buf := make([]byte, 6) | ||
155 | n := serializeSubpacketLength(buf, len(osp.Contents)+1) | ||
156 | buf[n] = osp.SubType | ||
157 | if _, err = w.Write(buf[:n+1]); err != nil { | ||
158 | return | ||
159 | } | ||
160 | _, err = w.Write(osp.Contents) | ||
161 | return | ||
162 | } | ||