Пример #1
0
// Given the supplied cipher, whose block size must be 16 bytes, return two
// subkeys that can be used in MAC generation. See section 5.3 of NIST SP
// 800-38B. Note that the other NIST-approved block size of 8 bytes is not
// supported by this function.
func generateSubkeys(ciph cipher.Block) (k1 []byte, k2 []byte) {
	if ciph.BlockSize() != blockSize {
		panic("generateSubkeys requires a cipher with a block size of 16 bytes.")
	}

	// Step 1
	l := make([]byte, blockSize)
	ciph.Encrypt(l, subkeyZero)

	// Step 2: Derive the first subkey.
	if common.Msb(l) == 0 {
		// TODO(jacobsa): Accept a destination buffer in ShiftLeft and then hoist
		// the allocation in the else branch below.
		k1 = common.ShiftLeft(l)
	} else {
		k1 = make([]byte, blockSize)
		common.Xor(k1, common.ShiftLeft(l), subkeyRb)
	}

	// Step 3: Derive the second subkey.
	if common.Msb(k1) == 0 {
		k2 = common.ShiftLeft(k1)
	} else {
		k2 = make([]byte, blockSize)
		common.Xor(k2, common.ShiftLeft(k1), subkeyRb)
	}

	return
}
Пример #2
0
func (h *cmacHash) Sum(b []byte) []byte {
	dataLen := len(h.data)

	// We should have at most one block left.
	if dataLen > blockSize {
		panic(fmt.Sprintf("Unexpected data: %x", h.data))
	}

	// Calculate M_last.
	mLast := make([]byte, blockSize)
	if dataLen == blockSize {
		common.Xor(mLast, h.data, h.k1)
	} else {
		// TODO(jacobsa): Accept a destination buffer in common.PadBlock and
		// simplify this code.
		common.Xor(mLast, common.PadBlock(h.data), h.k2)
	}

	y := make([]byte, blockSize)
	common.Xor(y, mLast, h.x)

	result := make([]byte, blockSize)
	h.ciph.Encrypt(result, y)

	b = append(b, result...)
	return b
}
Пример #3
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{})
}
Пример #4
0
// Given a 128-bit binary string, shift the string left by one bit and XOR the
// result with 0x00...87 if the bit shifted off was one. This is the dbl
// function of RFC 5297.
func dbl(b []byte) []byte {
	if len(b) != aes.BlockSize {
		panic("dbl requires a 16-byte buffer.")
	}

	shiftedOne := common.Msb(b) == 1
	b = common.ShiftLeft(b)
	if shiftedOne {
		tmp := make([]byte, aes.BlockSize)
		common.Xor(tmp, b, dblRb)
		b = tmp
	}

	return b
}
Пример #5
0
// The xorend operator of RFC 5297.
//
// Given strings A and B with len(A) >= len(B), let D be len(A) - len(B). Write
// A[:D] followed by xor(A[D:], B) into dst. In other words, xor B over the
// rightmost end of A and write the result into dst.
func xorend(dst, a, b []byte) {
	aLen := len(a)
	bLen := len(b)
	dstLen := len(dst)

	if dstLen < aLen || aLen < bLen {
		log.Panicf("Bad buffer lengths: %d, %d, %d", dstLen, aLen, bLen)
	}

	// Copy the left part.
	difference := aLen - bLen
	copy(dst, a[:difference])

	// XOR in the right part.
	common.Xor(dst[difference:difference+bLen], a[difference:], b)
}
Пример #6
0
func xorWithResult(a []byte, b []byte) (result []byte) {
	result = make([]byte, len(a))
	common.Xor(result, a, b)
	return
}