-
Notifications
You must be signed in to change notification settings - Fork 58
/
tllv.go
189 lines (153 loc) · 5.48 KB
/
tllv.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package ksm
import (
"crypto/rand"
"encoding/binary"
"errors"
"fmt"
)
// TLLVBlock represents a TLLV block structure.
type TLLVBlock struct {
Tag uint64
BlockLength uint32
ValueLength uint32 //The number of bytes in the value field. This number may be any amount, including 0x0000
Value []byte
}
// NewTLLVBlock creates a new TLLVBlock object using the specified tag and value.
func NewTLLVBlock(tag uint64, value []byte) *TLLVBlock {
valueLen := uint32(len(value))
paddingSize := 32 - valueLen%16 // Extend to nearest 16 bytes + extra 16 bytes
blockLen := valueLen + paddingSize
return &TLLVBlock{
Tag: tag,
BlockLength: blockLen,
ValueLength: valueLen,
Value: value,
}
}
// Serialize returns serialize byte array.
func (t *TLLVBlock) Serialize() ([]byte, error) {
if err := t.check(); err != nil {
return nil, err
}
var out []byte
tagOut := make([]byte, 8)
blockLenOut := make([]byte, 4)
valueLenOut := make([]byte, 4)
valueLen := uint32(len(t.Value))
paddingLen := 32 - valueLen%16 // Extend to nearest 16 bytes + extra 16 bytes
blockLen := valueLen + paddingLen
paddingOut := make([]byte, paddingLen)
rand.Read(paddingOut)
binary.BigEndian.PutUint64(tagOut, t.Tag)
binary.BigEndian.PutUint32(blockLenOut, blockLen)
binary.BigEndian.PutUint32(valueLenOut, valueLen)
out = append(out, tagOut...)
out = append(out, blockLenOut...)
out = append(out, valueLenOut...)
out = append(out, t.Value...)
out = append(out, paddingOut...)
return out, nil
}
func (t *TLLVBlock) check() error {
if t.Tag == 0 {
return errors.New("tag not found")
}
if len(t.Value) == 0 {
fmt.Printf("tag: %x :value not found\n", t.Tag)
fmt.Printf("tag.ValueLength: %x \n", t.ValueLength)
//return fmt.Errorf("tag: %x :value not found", t.Tag)
}
return nil
}
// SKR1TLLVBlock represents a SKR1 TLLV block structure.
type SKR1TLLVBlock struct {
TLLVBlock
IV []byte
Payload []byte
}
// DecryptedSKR1Payload represents a decrypted SKR1 payload structure.
type DecryptedSKR1Payload struct {
SK []byte //Session key
HU []byte
R1 []byte
IntegrityBytes []byte
}
// CkcR1 represents a ckcR1 structure.
type CkcR1 struct {
R1 []byte
}
// CkcDataIv represents a ckc data iv structure.
type CkcDataIv struct {
IV []byte
}
//CkcEncryptedPayload represents a ckc encrypted payload structure.
type CkcEncryptedPayload struct {
Payload []byte
}
// CkcContentKeyDurationBlock represents a ckc content key duration block structure.
type CkcContentKeyDurationBlock struct {
*TLLVBlock
LeaseDuration uint32 // 16-19, The duration of the lease, if any, in seconds.
RentalDuration uint32 // 20-23, The duration of the rental, if any, in seconds.
KeyType uint32 // 24-27,The key type.
//Reserved uint32 // Reserved; set to a fixed value of 0x86d34a3a.
//Padding []byte // Random values to fill out the TLLV to a multiple of 16 bytes.
}
// NewCkcContentKeyDurationBlock creates a new a ckc content key duration block object using the specified lease duration and rental duration.
func NewCkcContentKeyDurationBlock(LeaseDuration, RentalDuration uint32) *CkcContentKeyDurationBlock {
var value []byte
LeaseDurationOut := make([]byte, 4)
binary.BigEndian.PutUint32(LeaseDurationOut, LeaseDuration)
rentalDurationOut := make([]byte, 4)
binary.BigEndian.PutUint32(rentalDurationOut, RentalDuration)
keyTypeOut := make([]byte, 4)
//binary.BigEndian.PutUint32(keyTypeOut, contentKeyValidForLease)
binary.BigEndian.PutUint32(keyTypeOut, contentKeyPersisted)
value = append(value, LeaseDurationOut...)
value = append(value, rentalDurationOut...)
value = append(value, keyTypeOut...)
value = append(value, []byte{0x86, 0xd3, 0x4a, 0x3a}...) //Reserved; set to a fixed value of 0x86d34a3a.
tllv := NewTLLVBlock(tagContentKeyDuration, value)
return &CkcContentKeyDurationBlock{
TLLVBlock: tllv,
LeaseDuration: LeaseDuration,
RentalDuration: RentalDuration,
KeyType: contentKeyValidForLease, //TODO: KeyType does not use
}
}
const (
tagSessionKeyR1 = 0x3d1a10b8bffac2ec
tagSessionKeyR1Integrity = 0xb349d4809e910687
tagAntiReplaySeed = 0x89c90f12204106b2
tagR2 = 0x71b5595ac1521133
tagReturnRequest = 0x19f9d4e5ab7609cb
tagAssetID = 0x1bf7f53f5d5d5a1f
tagTransactionID = 0x47aa7ad3440577de
tagProtocolVersionsSupported = 0x67b8fb79ecce1a13
tagProtocolVersionUsed = 0x5d81bcbcc7f61703
tagTreamingIndicator = 0xabb0256a31843974
tagMediaPlaybackState = 0xeb8efdf2b25ab3a0
playbackStateReadyToStart = 0xf4dee5a2
playbackStatePlayingOrPaused = 0xa5d6739e
playbackStatePlaying = 0x4f834330
playbackStateHalted = 0x5991bf20
)
const (
fieldTagLength = 8
fieldBlockLength = 4
fieldValueLength = 4
)
const (
tagEncryptedCk = 0x58b38165af0e3d5a
tagR1 = 0xea74c4645d5efee9
tagContentKeyDuration = 0x47acf6a418cd091a
tagHdcpEnforcement = 0x2e52f1530d8ddb4a
contentKeyValidForLease = 0x1a4bde7e //Content key valid for lease only
contentKeyValidForRental = 0x3dfe45a0 //Content key valid for rental only
contentKeyValidForBoth = 0x27b59bde //Content key valid for both lease and rental
)
const (
//Offline
contentKeyPersisted = 0x3df2d9fb //Content key can be persisted with unlimited validity duration
contentKeyPersistedWithlimited = 0x18f06048 //Content key can be persisted, and it’s validity duration is limited to the “Rental Duration” value
)