Пример #1
0
// TestIntegrity performs the message integrity check (MIC), see LoRaWAN specification 1r0 4.4
func (d *PHYPayload) TestIntegrity(key []byte) (bool, error) {
	b0 := new(bytes.Buffer)
	b0.Write([]byte{0x49, 0x0, 0x0, 0x0, 0x0})
	b0.WriteByte(0x0)
	binary.Write(b0, binary.LittleEndian, d.DevAddr)
	binary.Write(b0, binary.LittleEndian, uint32(d.FCnt))
	b0.WriteByte(0x0)
	b0.WriteByte(byte(1 + len(d.MACPayload)))
	b0.WriteByte(d.MHDR)
	b0.Write(d.MACPayload)

	hash, err := cmac.New(key)
	if err != nil {
		log.Printf("Failed to initialize CMAC: %s", err.Error())
		return false, err
	}

	_, err = hash.Write(b0.Bytes())
	if err != nil {
		log.Printf("Failed to hash data: %s", err.Error())
		return false, err
	}

	calculatedMIC := hash.Sum([]byte{})[0:4]
	return bytes.Equal(calculatedMIC, d.MIC), nil
}
Пример #2
0
func (t *HashTest) SumDoesntAffectState() {
	// Grab a test case.
	cases := aes_testing.CmacCases()
	AssertGt(len(cases), 10)
	c := cases[10]

	// Create a hash and feed it some of the test case's data.
	h, err := cmac.New(c.Key)
	AssertEq(nil, err)

	AssertGt(len(c.Msg), 5)
	_, err = h.Write(c.Msg[0:5])
	AssertEq(nil, err)

	// Call Sum.
	AssertEq(16, len(h.Sum([]byte{})))

	// Feed the rest of the data and call Sum again. We should get the correct
	// result.
	_, err = h.Write(c.Msg[5:])
	AssertEq(nil, err)

	ExpectThat(h.Sum([]byte{}), DeepEquals(c.Mac))

	// Calling repeatedly should also work.
	ExpectThat(h.Sum([]byte{}), DeepEquals(c.Mac))
	ExpectThat(h.Sum([]byte{}), DeepEquals(c.Mac))
	ExpectThat(h.Sum([]byte{}), DeepEquals(c.Mac))
}
Пример #3
0
// calculateMIC calculates and returns the MIC.
func (p PHYPayload) calculateMIC(key AES128Key) ([]byte, error) {
	if p.MACPayload == nil {
		return []byte{}, errors.New("lorawan: MACPayload should not be empty")
	}

	macPayload, ok := p.MACPayload.(*MACPayload)
	if !ok {
		return []byte{}, errors.New("lorawan: MACPayload should be of type *MACPayload")
	}

	var b []byte
	var err error
	var micBytes []byte

	b, err = p.MHDR.MarshalBinary()
	if err != nil {
		return nil, err
	}
	micBytes = append(micBytes, b...)

	b, err = macPayload.MarshalBinary()
	if err != nil {
		return nil, err
	}
	micBytes = append(micBytes, b...)

	b0 := make([]byte, 16)
	b0[0] = 0x49
	if !p.isUplink() {
		b0[5] = 1
	}
	b, err = macPayload.FHDR.DevAddr.MarshalBinary()
	if err != nil {
		return nil, err
	}
	copy(b0[6:10], b)
	binary.LittleEndian.PutUint32(b0[10:14], macPayload.FHDR.FCnt)
	b0[15] = byte(len(micBytes))

	hash, err := cmac.New(key[:])
	if err != nil {
		return nil, err
	}

	if _, err = hash.Write(b0); err != nil {
		return nil, err
	}
	if _, err = hash.Write(micBytes); err != nil {
		return nil, err
	}

	hb := hash.Sum([]byte{})
	if len(hb) < 4 {
		return nil, errors.New("lorawan: the hash returned less than 4 bytes")
	}
	return hb[0:4], nil
}
Пример #4
0
func runCmac(key []byte, msg []byte) []byte {
	h, err := cmac.New(key)
	AssertEq(nil, err)

	_, err = h.Write(msg)
	AssertEq(nil, err)

	return h.Sum([]byte{})
}
Пример #5
0
func (t *HashTest) BlockSize() {
	var h hash.Hash
	var err error

	// AES-128
	h, err = cmac.New(make([]byte, 16))
	AssertEq(nil, err)
	ExpectEq(16, h.BlockSize())

	// AES-192
	h, err = cmac.New(make([]byte, 24))
	AssertEq(nil, err)
	ExpectEq(16, h.BlockSize())

	// AES-256
	h, err = cmac.New(make([]byte, 32))
	AssertEq(nil, err)
	ExpectEq(16, h.BlockSize())
}
Пример #6
0
// Run the S2V "string to vector" function of RFC 5297 using the input key and
// string vector, which must be non-empty. (RFC 5297 defines S2V to handle the
// empty vector case, but it is never used that way by higher-level functions.)
//
// If provided, the supplied scatch space will be used to avoid an allocation.
// It should be (but is not required to be) as large as the last element of
// strings.
//
// The result is guaranteed to be of length s2vSize.
func s2v(key []byte, strings [][]byte, scratch []byte) []byte {
	numStrings := len(strings)
	if numStrings == 0 {
		panic("strings vector must be non-empty.")
	}

	// Create a CMAC hash.
	h, err := cmac.New(key)
	if err != nil {
		panic(fmt.Sprintf("cmac.New: %v", err))
	}

	// Initialize.
	if _, err := h.Write(s2vZero); err != nil {
		panic(fmt.Sprintf("h.Write: %v", err))
	}

	d := h.Sum([]byte{})
	h.Reset()

	// Handle all strings but the last.
	for i := 0; i < numStrings-1; i++ {
		if _, err := h.Write(strings[i]); err != nil {
			panic(fmt.Sprintf("h.Write: %v", err))
		}

		common.Xor(d, dbl(d), h.Sum([]byte{}))
		h.Reset()
	}

	// Handle the last string.
	lastString := strings[numStrings-1]
	var t []byte
	if len(lastString) >= aes.BlockSize {
		// Make an output buffer the length of lastString.
		if cap(scratch) >= len(lastString) {
			t = scratch[:len(lastString)]
		} else {
			t = make([]byte, len(lastString))
		}

		// XOR d on the end of lastString.
		xorend(t, lastString, d)
	} else {
		t = make([]byte, aes.BlockSize)
		common.Xor(t, dbl(d), common.PadBlock(lastString))
	}

	if _, err := h.Write(t); err != nil {
		panic(fmt.Sprintf("h.Write: %v", err))
	}

	return h.Sum([]byte{})
}
Пример #7
0
func (t *HashTest) SumAppendsToSlice() {
	// Grab a test case.
	cases := aes_testing.CmacCases()
	AssertGt(len(cases), 10)
	c := cases[10]

	// Create a hash and feed it the test case's data.
	h, err := cmac.New(c.Key)
	AssertEq(nil, err)

	_, err = h.Write(c.Msg)
	AssertEq(nil, err)

	// Ask it to append to a non-empty slice.
	prefix := []byte{0xde, 0xad, 0xbe, 0xef}
	mac := h.Sum(prefix)

	AssertEq(20, len(mac))
	ExpectThat(mac[0:4], DeepEquals(prefix))
	ExpectThat(mac[4:], DeepEquals(c.Mac))
}
Пример #8
0
func (t *HashTest) Reset() {
	// Grab a test case.
	cases := aes_testing.CmacCases()
	AssertGt(len(cases), 10)
	c := cases[10]

	// Create a hash and feed it some data, then reset it.
	h, err := cmac.New(c.Key)
	AssertEq(nil, err)

	_, err = h.Write([]byte{0xde, 0xad})
	AssertEq(nil, err)

	h.Reset()

	// Feed the hash the test case's data and make sure the result is correct.
	_, err = h.Write(c.Msg)
	AssertEq(nil, err)

	ExpectThat(h.Sum([]byte{}), DeepEquals(c.Mac))
}
Пример #9
0
// calculateJoinAcceptMIC calculates and returns the join-accept MIC.
func (p PHYPayload) calculateJoinAcceptMIC(key AES128Key) ([]byte, error) {
	if p.MACPayload == nil {
		return []byte{}, errors.New("lorawan: MACPayload should not be empty")
	}
	jaPayload, ok := p.MACPayload.(*JoinAcceptPayload)
	if !ok {
		return []byte{}, errors.New("lorawan: MACPayload should be of type *JoinAcceptPayload")
	}

	micBytes := make([]byte, 0, 13)

	b, err := p.MHDR.MarshalBinary()
	if err != nil {
		return []byte{}, err
	}
	micBytes = append(micBytes, b...)

	b, err = jaPayload.MarshalBinary()
	if err != nil {
		return nil, err
	}
	micBytes = append(micBytes, b...)

	hash, err := cmac.New(key[:])
	if err != nil {
		return []byte{}, err
	}
	if _, err = hash.Write(micBytes); err != nil {
		return nil, err
	}
	hb := hash.Sum([]byte{})
	if len(hb) < 4 {
		return []byte{}, errors.New("lorawan: the hash returned less than 4 bytes")
	}
	return hb[0:4], nil
}
Пример #10
0
func (t *HashTest) LongKey() {
	_, err := cmac.New(make([]byte, 33))
	ExpectThat(err, Error(HasSubstr("16-")))
	ExpectThat(err, Error(HasSubstr("24-")))
	ExpectThat(err, Error(HasSubstr("32-")))
}
Пример #11
0
func (t *HashTest) NilKey() {
	_, err := cmac.New(nil)
	ExpectThat(err, Error(HasSubstr("16-")))
	ExpectThat(err, Error(HasSubstr("24-")))
	ExpectThat(err, Error(HasSubstr("32-")))
}
Пример #12
0
func (t *HashTest) Size() {
	h, err := cmac.New(make([]byte, 16))
	AssertEq(nil, err)
	ExpectEq(16, h.Size())
}