Squashed 'third_party/rawrtc/re/' content from commit f3163ce8b

Change-Id: I6a235e6ac0f03269d951026f9d195da05c40fdab
git-subtree-dir: third_party/rawrtc/re
git-subtree-split: f3163ce8b526a13b35ef71ce4dd6f43585064d8a
diff --git a/src/srtp/misc.c b/src/srtp/misc.c
new file mode 100644
index 0000000..8b4d5c3
--- /dev/null
+++ b/src/srtp/misc.c
@@ -0,0 +1,120 @@
+/**
+ * @file srtp/misc.c  SRTP functions
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <string.h>
+#include <re_types.h>
+#include <re_mem.h>
+#include <re_mbuf.h>
+#include <re_list.h>
+#include <re_aes.h>
+#include <re_sa.h>
+#include <re_srtp.h>
+#include "srtp.h"
+
+
+/*
+ * Appendix A: Pseudocode for Index Determination
+ *
+ * In the following, signed arithmetic is assumed.
+ */
+uint64_t srtp_get_index(uint32_t roc, uint16_t s_l, uint16_t seq)
+{
+	int v;
+
+	if (s_l < 32768) {
+
+		if ((int)seq - (int)s_l > 32768)
+			v = (roc-1) & 0xffffffffu;
+		else
+			v = roc;
+	}
+	else {
+		if ((int)s_l - 32768 > seq)
+			v = (roc+1) & 0xffffffffu;
+		else
+			v = roc;
+	}
+
+	return seq + v*65536;
+}
+
+
+int srtp_derive(uint8_t *out, size_t out_len, uint8_t label,
+		const uint8_t *master_key, size_t key_bytes,
+		const uint8_t *master_salt, size_t salt_bytes)
+{
+	uint8_t x[AES_BLOCK_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+	static const uint8_t null[AES_BLOCK_SIZE * 2];
+	struct aes *aes;
+	int err;
+
+	if (!out || !master_key || !master_salt)
+		return EINVAL;
+
+	if (out_len > sizeof(null) || salt_bytes > sizeof(x))
+		return EINVAL;
+
+	memcpy(x, master_salt, salt_bytes);
+	x[7] ^= label;
+
+	/* NOTE: Counter Mode is used for both CTR and GCM */
+	err = aes_alloc(&aes, AES_MODE_CTR, master_key, key_bytes*8, x);
+	if (err)
+		return err;
+
+	err = aes_encr(aes, out, null, out_len);
+
+	mem_deref(aes);
+
+	return err;
+
+}
+
+
+void srtp_iv_calc(union vect128 *iv, const union vect128 *k_s,
+		  uint32_t ssrc, uint64_t ix)
+{
+	if (!iv || !k_s)
+		return;
+
+	iv->u32[0] = k_s->u32[0];
+	iv->u32[1] = k_s->u32[1] ^ htonl(ssrc);
+	iv->u32[2] = k_s->u32[2] ^ htonl((uint32_t)(ix>>16));
+	iv->u16[6] = k_s->u16[6] ^ htons((uint16_t)ix);
+	iv->u16[7] = 0;
+}
+
+
+/*
+ * NOTE: The IV for AES-GCM is 12 bytes
+ */
+void srtp_iv_calc_gcm(union vect128 *iv, const union vect128 *k_s,
+		      uint32_t ssrc, uint64_t ix)
+{
+	if (!iv || !k_s)
+		return;
+
+	iv->u16[0] = k_s->u16[0];
+	iv->u16[1] = k_s->u16[1] ^ htons(ssrc >> 16);
+	iv->u16[2] = k_s->u16[2] ^ htons(ssrc & 0xffff);
+	iv->u16[3] = k_s->u16[3] ^ htons((ix >> 32) & 0xffff);
+	iv->u16[4] = k_s->u16[4] ^ htons((ix >> 16) & 0xffff);
+	iv->u16[5] = k_s->u16[5] ^ htons(ix & 0xffff);
+}
+
+
+const char *srtp_suite_name(enum srtp_suite suite)
+{
+	switch (suite) {
+
+	case SRTP_AES_CM_128_HMAC_SHA1_32:  return "AES_CM_128_HMAC_SHA1_32";
+	case SRTP_AES_CM_128_HMAC_SHA1_80:  return "AES_CM_128_HMAC_SHA1_80";
+	case SRTP_AES_256_CM_HMAC_SHA1_32:  return "AES_256_CM_HMAC_SHA1_32";
+	case SRTP_AES_256_CM_HMAC_SHA1_80:  return "AES_256_CM_HMAC_SHA1_80";
+	case SRTP_AES_128_GCM:              return "AEAD_AES_128_GCM";
+	case SRTP_AES_256_GCM:              return "AEAD_AES_256_GCM";
+	default:                            return "?";
+	}
+}