@@ -3,84 +3,42 @@ package srtp
3
3
import (
4
4
"crypto/aes"
5
5
"encoding/binary"
6
+ "errors"
6
7
)
7
8
8
- // All of these key derivation functions are AES-CM specific
9
- // in the future we have multiple implementations of each of these functions
9
+ func aesCmKeyDerivation (label byte , masterKey , masterSalt []byte , indexOverKdr int , outLen int ) ([]byte , error ) {
10
+ if indexOverKdr != 0 {
11
+ // 24-bit "index DIV kdr" must be xored to prf input.
12
+ return nil , errors .New ("indexOverKdr > 0 is not supported yet" )
13
+ }
10
14
11
- func generateSessionKey (label byte , masterKey , masterSalt []byte ) ([]byte , error ) {
12
15
// https://tools.ietf.org/html/rfc3711#appendix-B.3
13
16
// The input block for AES-CM is generated by exclusive-oring the master salt with the
14
17
// concatenation of the encryption key label 0x00 with (index DIV kdr),
15
18
// - index is 'rollover count' and DIV is 'divided by'
16
- sessionKey := make ([]byte , len (masterSalt ))
17
- copy (sessionKey , masterSalt )
18
-
19
- labelAndIndexOverKdr := []byte {label , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 }
20
- for i , j := len (labelAndIndexOverKdr )- 1 , len (sessionKey )- 1 ; i >= 0 ; i , j = i - 1 , j - 1 {
21
- sessionKey [j ] = sessionKey [j ] ^ labelAndIndexOverKdr [i ]
22
- }
23
19
24
- // then padding on the right with two null octets (which implements the multiply-by-2^16 operation, see Section 4.3.3).
25
- sessionKey = append ( sessionKey , [] byte { 0x00 , 0x00 } ... )
20
+ nMasterKey := len ( masterKey )
21
+ nMasterSalt := len ( masterSalt )
26
22
27
- //The resulting value is then AES-CM- encrypted using the master key to get the cipher key.
28
- block , err := aes .NewCipher (masterKey )
29
- if err != nil {
30
- return nil , err
31
- }
32
-
33
- block .Encrypt (sessionKey , sessionKey )
34
- return sessionKey , nil
35
- }
36
-
37
- func generateSessionSalt (label byte , masterKey , masterSalt []byte ) ([]byte , error ) {
38
- // https://tools.ietf.org/html/rfc3711#appendix-B.3
39
- // The input block for AES-CM is generated by exclusive-oring the master salt with
40
- // the concatenation of the encryption salt label
41
- sessionSalt := make ([]byte , len (masterSalt ))
42
- copy (sessionSalt , masterSalt )
23
+ prfIn := make ([]byte , nMasterKey )
24
+ copy (prfIn [:nMasterSalt ], masterSalt )
43
25
44
- labelAndIndexOverKdr := []byte {label , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 }
45
- for i , j := len (labelAndIndexOverKdr )- 1 , len (sessionSalt )- 1 ; i >= 0 ; i , j = i - 1 , j - 1 {
46
- sessionSalt [j ] = sessionSalt [j ] ^ labelAndIndexOverKdr [i ]
47
- }
26
+ prfIn [7 ] ^= label
48
27
49
- // That value is padded and encrypted as above.
50
- sessionSalt = append (sessionSalt , []byte {0x00 , 0x00 }... )
28
+ //The resulting value is then AES encrypted using the master key to get the cipher key.
51
29
block , err := aes .NewCipher (masterKey )
52
30
if err != nil {
53
31
return nil , err
54
32
}
55
33
56
- block .Encrypt (sessionSalt , sessionSalt )
57
- return sessionSalt [0 :len (masterSalt )], nil
58
- }
59
-
60
- func generateSessionAuthTag (label byte , masterKey , masterSalt []byte ) ([]byte , error ) {
61
- // https://tools.ietf.org/html/rfc3711#appendix-B.3
62
- // We now show how the auth key is generated. The input block for AES-
63
- // CM is generated as above, but using the authentication key label.
64
- sessionAuthTag := make ([]byte , len (masterSalt ))
65
- copy (sessionAuthTag , masterSalt )
66
-
67
- labelAndIndexOverKdr := []byte {label , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 }
68
- for i , j := len (labelAndIndexOverKdr )- 1 , len (sessionAuthTag )- 1 ; i >= 0 ; i , j = i - 1 , j - 1 {
69
- sessionAuthTag [j ] = sessionAuthTag [j ] ^ labelAndIndexOverKdr [i ]
34
+ out := make ([]byte , ((outLen + nMasterKey )/ nMasterKey )* nMasterKey )
35
+ var i uint16
36
+ for n := 0 ; n < outLen ; n += nMasterKey {
37
+ binary .BigEndian .PutUint16 (prfIn [nMasterKey - 2 :], i )
38
+ block .Encrypt (out [n :n + nMasterKey ], prfIn )
39
+ i ++
70
40
}
71
-
72
- // That value is padded and encrypted as above.
73
- // - We need to do multiple runs at key size (20) is larger then source
74
- firstRun := append (sessionAuthTag , []byte {0x00 , 0x00 }... )
75
- secondRun := append (sessionAuthTag , []byte {0x00 , 0x01 }... )
76
- block , err := aes .NewCipher (masterKey )
77
- if err != nil {
78
- return nil , err
79
- }
80
-
81
- block .Encrypt (firstRun , firstRun )
82
- block .Encrypt (secondRun , secondRun )
83
- return append (firstRun , secondRun [:4 ]... ), nil
41
+ return out [:outLen ], nil
84
42
}
85
43
86
44
// Generate IV https://tools.ietf.org/html/rfc3711#section-4.1.1
0 commit comments