Skip to content

Commit

Permalink
Major refactor into single directory.
Browse files Browse the repository at this point in the history
  • Loading branch information
jimwert committed Nov 20, 2016
1 parent 2a733d1 commit 09aef84
Show file tree
Hide file tree
Showing 34 changed files with 615 additions and 711 deletions.
18 changes: 9 additions & 9 deletions common/reader.go → bytereader.go
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
package common
package dtls

import (
"bytes"
"encoding/binary"
"io"
)

type Reader struct {
type byteReader struct {
rdr io.Reader
}

func NewReader(data []byte) *Reader {
return &Reader{rdr: bytes.NewReader(data)}
func newByteReader(data []byte) *byteReader {
return &byteReader{rdr: bytes.NewReader(data)}
}

func (r *Reader) GetUint8() uint8 {
func (r *byteReader) GetUint8() uint8 {
raw := make([]byte, 1)
r.rdr.Read(raw)
return raw[0]
}

func (r *Reader) GetUint16() uint16 {
func (r *byteReader) GetUint16() uint16 {
raw := make([]byte, 2)
r.rdr.Read(raw)
return binary.BigEndian.Uint16(raw)
}

func (r *Reader) GetUint24() uint32 {
func (r *byteReader) GetUint24() uint32 {
raw := make([]byte, 3, 4)
r.rdr.Read(raw)
raw = append(raw, 0x00)
u24 := binary.BigEndian.Uint32(raw)
return u24 >> 8
}

func (r *Reader) GetUint32() uint32 {
func (r *byteReader) GetUint32() uint32 {
raw := make([]byte, 4)
r.rdr.Read(raw)
return binary.BigEndian.Uint32(raw)
}

func (r *Reader) GetBytes(l int) []byte {
func (r *byteReader) GetBytes(l int) []byte {
raw := make([]byte, l)
r.rdr.Read(raw)
return raw
Expand Down
26 changes: 13 additions & 13 deletions common/writer.go → bytewriter.go
Original file line number Diff line number Diff line change
@@ -1,64 +1,64 @@
package common
package dtls

import (
"bytes"
"encoding/binary"
)

type Writer struct {
type byteWriter struct {
buf *bytes.Buffer
}

func NewWriter() *Writer {
return &Writer{buf: new(bytes.Buffer)}
func newByteWriter() *byteWriter {
return &byteWriter{buf: new(bytes.Buffer)}
}

func (w *Writer) Bytes() []byte {
func (w *byteWriter) Bytes() []byte {
return w.buf.Bytes()
}

func (w *Writer) PadTo(l int) {
func (w *byteWriter) PadTo(l int) {
if w.buf.Len() < l {
buf := make([]byte, l-w.buf.Len())
w.PutBytes(buf)
}
}

func (w *Writer) PutUint8(value uint8) {
func (w *byteWriter) PutUint8(value uint8) {
binary.Write(w.buf, binary.BigEndian, value)
return
}

func (w *Writer) PutUint16(value uint16) {
func (w *byteWriter) PutUint16(value uint16) {
binary.Write(w.buf, binary.BigEndian, value)
return
}

func (w *Writer) PutUint24(value uint32) {
func (w *byteWriter) PutUint24(value uint32) {
buf := make([]byte, 4)
binary.BigEndian.PutUint32(buf, value)
w.buf.Write(buf[1:])
return
}

func (w *Writer) PutUint32(value uint32) {
func (w *byteWriter) PutUint32(value uint32) {
binary.Write(w.buf, binary.BigEndian, value)
return
}

func (w *Writer) PutUint48(value uint64) {
func (w *byteWriter) PutUint48(value uint64) {
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, value)
w.buf.Write(buf[2:])
return
}

func (w *Writer) PutString(value string) {
func (w *byteWriter) PutString(value string) {
binary.Write(w.buf, binary.BigEndian, value)
return
}

func (w *Writer) PutBytes(value []byte) {
func (w *byteWriter) PutBytes(value []byte) {
w.buf.Write(value)
return
}
File renamed without changes.
4 changes: 2 additions & 2 deletions common/common.go → common.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package common
package dtls

import (
"crypto/rand"
Expand All @@ -8,7 +8,7 @@ const (
DtlsVersion12 uint16 = 0xFEFD
)

func RandomBytes(length int) []byte {
func randomBytes(length int) []byte {
rbuf := make([]byte, length)
rand.Read(rbuf)
return rbuf
Expand Down
180 changes: 180 additions & 0 deletions crypto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package dtls

import (
"bytes"
"crypto/aes"
"crypto/hmac"
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"

"github.com/bocajim/dtls/ccm"
)

const (
AadAuthLen int = 13
)

func newNonce(iv []byte, epoch uint16, seq uint64) []byte {
nonce := new(bytes.Buffer)
nonce.Write(iv)
seq += uint64(epoch) << 48
binary.Write(nonce, binary.BigEndian, seq)
return nonce.Bytes()
}

func newAad(epoch uint16, seq uint64, msgType uint8, dataLen uint16) []byte {
w := newByteWriter()
w.PutUint16(epoch)
w.PutUint48(seq)
w.PutUint8(msgType)
w.PutUint16(DtlsVersion12)
w.PutUint16(dataLen)
return w.Bytes()
}

type keyBlock struct {
MasterSecret []byte
ClientWriteKey []byte
ServerWriteKey []byte
ClientIV []byte
ServerIV []byte
}

func (kb *keyBlock) Print() string {
return fmt.Sprintf("ClientWriteKey[%X], ServerWriteKey[%X], ClientIV[%X], ServerIV[%X]", kb.ClientWriteKey, kb.ServerWriteKey, kb.ClientIV, kb.ServerIV)
}

func newKeyBlock(identity []byte, psk, clientRandom, serverRandom []byte) (*keyBlock, error) {

//generate pre-master secret
preMasterSecret := generatePskPreMasterSecret(psk)

//generate master secret
masterSecret := generatePrf(preMasterSecret, clientRandom, serverRandom, "master secret", 48)

//generate key block
rawKeyBlock := generatePrf(masterSecret, serverRandom, clientRandom, "key expansion", 48)

keyBlock := &keyBlock{MasterSecret: masterSecret, ClientWriteKey: rawKeyBlock[0:16], ServerWriteKey: rawKeyBlock[16:32], ClientIV: rawKeyBlock[32:36], ServerIV: rawKeyBlock[36:40]}

return keyBlock, nil
}

//dtls_psk_pre_master_secret(unsigned char *key, size_t keylen,unsigned char *result, size_t result_len)
func generatePskPreMasterSecret(psk []byte) []byte {

zeroBuffer := make([]byte, len(psk))

w := newByteWriter()

w.PutUint16(uint16(len(psk)))
w.PutBytes(zeroBuffer)
w.PutUint16(uint16(len(psk)))
w.PutBytes(psk)

return w.Bytes()
}

func generatePrf(key, random1, random2 []byte, label string, keyLen int) []byte {

buf := make([]byte, 0, keyLen)

seed := hmac.New(sha256.New, key)
seed.Write([]byte(label))
seed.Write(random1)
seed.Write(random2)
seedHash := seed.Sum(nil)

hash := hmac.New(sha256.New, key)

for len(buf)+len(seedHash) < keyLen {

hash.Reset()
hash.Write(seedHash)
hash.Write([]byte(label))
hash.Write(random1)
hash.Write(random2)

tmp := hash.Sum(nil)

buf = append(buf, tmp...)

seed.Reset()
seed.Write(seedHash)
seedHash = seed.Sum(nil)
}

hash.Reset()
hash.Write(seedHash)
hash.Write([]byte(label))
hash.Write(random1)
hash.Write(random2)

tmp := hash.Sum(nil)

buf = append(buf, tmp...)

return buf[:keyLen]
}

func dataEncrypt(data []byte, nonce []byte, key []byte, aad []byte, peer string) ([]byte, error) {

cipher, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
ccmCipher, err := ccm.NewCCM(cipher, 8, 12)
if err != nil {
return nil, err
}

if len(peer) > 0 {
logDebug("dtls: [%s] encrypt nonce[%X] key[%X] aad[%X]", peer, nonce, key, aad)
logDebug("dtls: [%s] encrypt clearText[%X][%d]", peer, data, len(data))
}

cipherTextLen := (len(data) / 16) * 16
if len(data)%16 != 0 {
cipherTextLen += 16
}
cipherText := make([]byte, 0, cipherTextLen)

if len(nonce) != 12 {
return nil, errors.New("dtls: invalid nonce length")
}
cipherText = ccmCipher.Seal(cipherText, nonce, data, aad)
if len(peer) > 0 {
logDebug("dtls: [%s] encrypt cipherText[%X][%d]", peer, cipherText, len(cipherText))
}
return cipherText, nil
}

func dataDecrypt(data []byte, nonce []byte, key []byte, aad []byte, peer string) ([]byte, error) {

cipher, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
ccmCipher, err := ccm.NewCCM(cipher, 8, 12)
if err != nil {
return nil, err
}

if len(peer) > 0 {
logDebug("dtls: [%s] decrypt nonce[%X] key[%X] aad[%X]", peer, nonce, key, aad)
logDebug("stls: [%s] decrypt cipherText[%X][%d]", peer, data, len(data))
}

clearText := make([]byte, 0, len(data))

clearText, err = ccmCipher.Open(clearText, nonce, data, aad)
if err != nil {
return nil, err
}
if len(peer) > 0 {
logDebug("dtls: [%s] decrypt clearText[%X][%d]", peer, clearText, len(clearText))
}
return clearText, nil
}
Loading

0 comments on commit 09aef84

Please sign in to comment.