key_derivation.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package srtp
  2. import (
  3. "crypto/aes"
  4. "encoding/binary"
  5. )
  6. func aesCmKeyDerivation(label byte, masterKey, masterSalt []byte, indexOverKdr int, outLen int) ([]byte, error) {
  7. if indexOverKdr != 0 {
  8. // 24-bit "index DIV kdr" must be xored to prf input.
  9. return nil, errNonZeroKDRNotSupported
  10. }
  11. // https://tools.ietf.org/html/rfc3711#appendix-B.3
  12. // The input block for AES-CM is generated by exclusive-oring the master salt with the
  13. // concatenation of the encryption key label 0x00 with (index DIV kdr),
  14. // - index is 'rollover count' and DIV is 'divided by'
  15. nMasterKey := len(masterKey)
  16. nMasterSalt := len(masterSalt)
  17. prfIn := make([]byte, nMasterKey)
  18. copy(prfIn[:nMasterSalt], masterSalt)
  19. prfIn[7] ^= label
  20. // The resulting value is then AES encrypted using the master key to get the cipher key.
  21. block, err := aes.NewCipher(masterKey)
  22. if err != nil {
  23. return nil, err
  24. }
  25. out := make([]byte, ((outLen+nMasterKey)/nMasterKey)*nMasterKey)
  26. var i uint16
  27. for n := 0; n < outLen; n += nMasterKey {
  28. binary.BigEndian.PutUint16(prfIn[nMasterKey-2:], i)
  29. block.Encrypt(out[n:n+nMasterKey], prfIn)
  30. i++
  31. }
  32. return out[:outLen], nil
  33. }
  34. // Generate IV https://tools.ietf.org/html/rfc3711#section-4.1.1
  35. // where the 128-bit integer value IV SHALL be defined by the SSRC, the
  36. // SRTP packet index i, and the SRTP session salting key k_s, as below.
  37. // - ROC = a 32-bit unsigned rollover counter (ROC), which records how many
  38. // - times the 16-bit RTP sequence number has been reset to zero after
  39. // - passing through 65,535
  40. // i = 2^16 * ROC + SEQ
  41. // IV = (salt*2 ^ 16) | (ssrc*2 ^ 64) | (i*2 ^ 16)
  42. func generateCounter(sequenceNumber uint16, rolloverCounter uint32, ssrc uint32, sessionSalt []byte) (counter [16]byte) {
  43. copy(counter[:], sessionSalt)
  44. counter[4] ^= byte(ssrc >> 24)
  45. counter[5] ^= byte(ssrc >> 16)
  46. counter[6] ^= byte(ssrc >> 8)
  47. counter[7] ^= byte(ssrc)
  48. counter[8] ^= byte(rolloverCounter >> 24)
  49. counter[9] ^= byte(rolloverCounter >> 16)
  50. counter[10] ^= byte(rolloverCounter >> 8)
  51. counter[11] ^= byte(rolloverCounter)
  52. counter[12] ^= byte(sequenceNumber >> 8)
  53. counter[13] ^= byte(sequenceNumber)
  54. return counter
  55. }