mikey: Add support for GCM (RFC 7714)

The MIKEY details can be found in RFC 7714 section "14.3. MIKEY"
This commit is contained in:
Ulf Olsson 2019-04-03 08:51:16 +02:00 committed by Sebastian Dröge
parent 4320a31bd9
commit 7806285a10
2 changed files with 109 additions and 33 deletions

View file

@ -2154,30 +2154,79 @@ parse_error:
#define HMAC_32_KEY_LEN 4 #define HMAC_32_KEY_LEN 4
#define HMAC_80_KEY_LEN 10 #define HMAC_80_KEY_LEN 10
static guint8 static gboolean
enc_key_length_from_cipher_name (const gchar * cipher) auth_alg_from_cipher_name (const gchar * cipher, guint8 * auth_alg)
{ {
if (g_strcmp0 (cipher, "aes-128-icm") == 0) if (g_strcmp0 (cipher, "aes-128-icm") == 0)
return AES_128_KEY_LEN; *auth_alg = GST_MIKEY_MAC_HMAC_SHA_1_160;
else if (g_strcmp0 (cipher, "aes-256-icm") == 0) else if (g_strcmp0 (cipher, "aes-256-icm") == 0)
return AES_256_KEY_LEN; *auth_alg = GST_MIKEY_MAC_HMAC_SHA_1_160;
else if (g_strcmp0 (cipher, "aes-128-gcm") == 0)
*auth_alg = GST_MIKEY_MAC_NULL;
else if (g_strcmp0 (cipher, "aes-256-gcm") == 0)
*auth_alg = GST_MIKEY_MAC_NULL;
else { else {
GST_ERROR ("encryption algorithm '%s' not supported", cipher); GST_ERROR ("encryption algorithm '%s' not supported", cipher);
return 0; return FALSE;
} }
return TRUE;
} }
static guint8 static gboolean
auth_key_length_from_auth_name (const gchar * auth) enc_alg_from_cipher_name (const gchar * cipher, guint8 * enc_alg)
{ {
if (g_strcmp0 (auth, "hmac-sha1-32") == 0) if (g_strcmp0 (cipher, "aes-128-icm") == 0)
return HMAC_32_KEY_LEN; *enc_alg = GST_MIKEY_ENC_AES_CM_128;
else if (g_strcmp0 (auth, "hmac-sha1-80") == 0) else if (g_strcmp0 (cipher, "aes-256-icm") == 0)
return HMAC_80_KEY_LEN; *enc_alg = GST_MIKEY_ENC_AES_CM_128;
else if (g_strcmp0 (cipher, "aes-128-gcm") == 0)
*enc_alg = GST_MIKEY_ENC_AES_GCM_128;
else if (g_strcmp0 (cipher, "aes-256-gcm") == 0)
*enc_alg = GST_MIKEY_ENC_AES_GCM_128;
else { else {
GST_ERROR ("authentication algorithm '%s' not supported", auth); GST_ERROR ("encryption algorithm '%s' not supported", cipher);
return 0; return FALSE;
} }
return TRUE;
}
static gboolean
enc_key_length_from_cipher_name (const gchar * cipher, guint8 * enc_key_length)
{
if (g_strcmp0 (cipher, "aes-128-icm") == 0)
*enc_key_length = AES_128_KEY_LEN;
else if (g_strcmp0 (cipher, "aes-256-icm") == 0)
*enc_key_length = AES_256_KEY_LEN;
else if (g_strcmp0 (cipher, "aes-128-gcm") == 0)
*enc_key_length = AES_128_KEY_LEN;
else if (g_strcmp0 (cipher, "aes-256-gcm") == 0)
*enc_key_length = AES_256_KEY_LEN;
else {
GST_ERROR ("encryption algorithm '%s' not supported", cipher);
return FALSE;
}
return TRUE;
}
static gboolean
auth_key_length_from_auth_cipher_name (const gchar * auth, const gchar * cipher,
guint8 * length)
{
if (g_strcmp0 (cipher, "aes-128-gcm") == 0
|| g_strcmp0 (cipher, "aes-256-gcm") == 0) {
*length = 0;
} else {
if (g_strcmp0 (auth, "hmac-sha1-32") == 0) {
*length = HMAC_32_KEY_LEN;
} else if (g_strcmp0 (auth, "hmac-sha1-80") == 0) {
*length = HMAC_80_KEY_LEN;
} else {
GST_ERROR ("authentication algorithm '%s' not supported", auth);
return FALSE;
}
}
return TRUE;
} }
/** /**
@ -2200,6 +2249,10 @@ gst_mikey_message_new_from_caps (GstCaps * caps)
GstMIKEYMessage *msg; GstMIKEYMessage *msg;
GstMIKEYPayload *payload, *pkd; GstMIKEYPayload *payload, *pkd;
guint8 byte; guint8 byte;
guint8 enc_alg;
guint8 auth_alg;
guint8 enc_key_length;
guint8 auth_key_length;
GstStructure *s; GstStructure *s;
GstMapInfo info; GstMapInfo info;
GstBuffer *srtpkey; GstBuffer *srtpkey;
@ -2242,6 +2295,14 @@ gst_mikey_message_new_from_caps (GstCaps * caps)
if (auth == NULL) if (auth == NULL)
auth = srtcpauth; auth = srtcpauth;
/* get cipher and auth values */
if (!enc_alg_from_cipher_name (cipher, &enc_alg) ||
!auth_alg_from_cipher_name (cipher, &auth_alg) ||
!enc_key_length_from_cipher_name (cipher, &enc_key_length) ||
!auth_key_length_from_auth_cipher_name (auth, cipher, &auth_key_length)) {
return NULL;
}
msg = gst_mikey_message_new (); msg = gst_mikey_message_new ();
/* unencrypted MIKEY message, we send this over TLS so this is allowed */ /* unencrypted MIKEY message, we send this over TLS so this is allowed */
gst_mikey_message_set_info (msg, GST_MIKEY_VERSION, GST_MIKEY_TYPE_PSK_INIT, gst_mikey_message_set_info (msg, GST_MIKEY_VERSION, GST_MIKEY_TYPE_PSK_INIT,
@ -2256,21 +2317,18 @@ gst_mikey_message_new_from_caps (GstCaps * caps)
payload = gst_mikey_payload_new (GST_MIKEY_PT_SP); payload = gst_mikey_payload_new (GST_MIKEY_PT_SP);
gst_mikey_payload_sp_set (payload, 0, GST_MIKEY_SEC_PROTO_SRTP); gst_mikey_payload_sp_set (payload, 0, GST_MIKEY_SEC_PROTO_SRTP);
/* only AES-CM is supported */ /* AES-CM or AES-GCM is supported */
byte = 1; gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_ENC_ALG, 1,
gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_ENC_ALG, 1, &byte); &enc_alg);
/* encryption key length */ /* encryption key length */
byte = enc_key_length_from_cipher_name (cipher);
gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_ENC_KEY_LEN, 1, gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_ENC_KEY_LEN, 1,
&byte); &enc_key_length);
/* only HMAC-SHA1 */ /* HMAC-SHA1 or NULL in case of GCM */
byte = 1;
gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_AUTH_ALG, 1, gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_AUTH_ALG, 1,
&byte); &auth_alg);
/* authentication key length */ /* authentication key length */
byte = auth_key_length_from_auth_name (auth);
gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_AUTH_KEY_LEN, 1, gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_AUTH_KEY_LEN, 1,
&byte); &auth_key_length);
/* we enable encryption on RTP and RTCP */ /* we enable encryption on RTP and RTCP */
byte = 1; byte = 1;
gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_SRTP_ENC, 1, gst_mikey_payload_sp_add_param (payload, GST_MIKEY_SP_SRTP_SRTP_ENC, 1,
@ -2330,6 +2388,7 @@ gst_mikey_message_to_caps (const GstMIKEYMessage * msg, GstCaps * caps)
if ((payload = gst_mikey_message_find_payload (msg, GST_MIKEY_PT_SP, 0))) { if ((payload = gst_mikey_message_find_payload (msg, GST_MIKEY_PT_SP, 0))) {
GstMIKEYPayloadSP *p = (GstMIKEYPayloadSP *) payload; GstMIKEYPayloadSP *p = (GstMIKEYPayloadSP *) payload;
guint len, i; guint len, i;
guint enc_alg = GST_MIKEY_ENC_NULL;
if (p->proto != GST_MIKEY_SEC_PROTO_SRTP) if (p->proto != GST_MIKEY_SEC_PROTO_SRTP)
goto done; goto done;
@ -2341,14 +2400,18 @@ gst_mikey_message_to_caps (const GstMIKEYMessage * msg, GstCaps * caps)
switch (param->type) { switch (param->type) {
case GST_MIKEY_SP_SRTP_ENC_ALG: case GST_MIKEY_SP_SRTP_ENC_ALG:
enc_alg = param->val[0];
switch (param->val[0]) { switch (param->val[0]) {
case 0: case GST_MIKEY_ENC_NULL:
srtp_cipher = "null"; srtp_cipher = "null";
break; break;
case 2: case GST_MIKEY_ENC_AES_CM_128:
case 1: case GST_MIKEY_ENC_AES_KW_128:
srtp_cipher = "aes-128-icm"; srtp_cipher = "aes-128-icm";
break; break;
case GST_MIKEY_ENC_AES_GCM_128:
srtp_cipher = "aes-128-gcm";
break;
default: default:
break; break;
} }
@ -2356,10 +2419,20 @@ gst_mikey_message_to_caps (const GstMIKEYMessage * msg, GstCaps * caps)
case GST_MIKEY_SP_SRTP_ENC_KEY_LEN: case GST_MIKEY_SP_SRTP_ENC_KEY_LEN:
switch (param->val[0]) { switch (param->val[0]) {
case AES_128_KEY_LEN: case AES_128_KEY_LEN:
srtp_cipher = "aes-128-icm"; if (enc_alg == GST_MIKEY_ENC_AES_CM_128 ||
enc_alg == GST_MIKEY_ENC_AES_KW_128) {
srtp_cipher = "aes-128-icm";
} else if (enc_alg == GST_MIKEY_ENC_AES_GCM_128) {
srtp_cipher = "aes-128-gcm";
}
break; break;
case AES_256_KEY_LEN: case AES_256_KEY_LEN:
srtp_cipher = "aes-256-icm"; if (enc_alg == GST_MIKEY_ENC_AES_CM_128 ||
enc_alg == GST_MIKEY_ENC_AES_KW_128) {
srtp_cipher = "aes-256-icm";
} else if (enc_alg == GST_MIKEY_ENC_AES_GCM_128) {
srtp_cipher = "aes-256-gcm";
}
break; break;
default: default:
break; break;
@ -2367,11 +2440,10 @@ gst_mikey_message_to_caps (const GstMIKEYMessage * msg, GstCaps * caps)
break; break;
case GST_MIKEY_SP_SRTP_AUTH_ALG: case GST_MIKEY_SP_SRTP_AUTH_ALG:
switch (param->val[0]) { switch (param->val[0]) {
case 0: case GST_MIKEY_MAC_NULL:
srtp_auth = "null"; srtp_auth = "null";
break; break;
case 2: case GST_MIKEY_MAC_HMAC_SHA_1_160:
case 1:
srtp_auth = "hmac-sha1-80"; srtp_auth = "hmac-sha1-80";
break; break;
default: default:

View file

@ -219,6 +219,7 @@ gst_mikey_payload_copy (const GstMIKEYPayload * payload)
* @GST_MIKEY_ENC_NULL: no encryption * @GST_MIKEY_ENC_NULL: no encryption
* @GST_MIKEY_ENC_AES_CM_128: AES-CM using a 128-bit key * @GST_MIKEY_ENC_AES_CM_128: AES-CM using a 128-bit key
* @GST_MIKEY_ENC_AES_KW_128: AES Key Wrap using a 128-bit key * @GST_MIKEY_ENC_AES_KW_128: AES Key Wrap using a 128-bit key
* @GST_MIKEY_ENC_AES_GCM_128: AES-GCM using a 128-bit key
* *
* The encryption algorithm used to encrypt the Encr data field * The encryption algorithm used to encrypt the Encr data field
*/ */
@ -226,7 +227,8 @@ typedef enum
{ {
GST_MIKEY_ENC_NULL = 0, GST_MIKEY_ENC_NULL = 0,
GST_MIKEY_ENC_AES_CM_128 = 1, GST_MIKEY_ENC_AES_CM_128 = 1,
GST_MIKEY_ENC_AES_KW_128 = 2 GST_MIKEY_ENC_AES_KW_128 = 2,
GST_MIKEY_ENC_AES_GCM_128 = 6
} GstMIKEYEncAlg; } GstMIKEYEncAlg;
/** /**
@ -393,6 +395,7 @@ typedef enum
* @GST_MIKEY_SP_SRTP_SRTP_AUTH: SRTP authentication off/on, 0 if off, 1 if on * @GST_MIKEY_SP_SRTP_SRTP_AUTH: SRTP authentication off/on, 0 if off, 1 if on
* @GST_MIKEY_SP_SRTP_AUTH_TAG_LEN: Authentication tag length * @GST_MIKEY_SP_SRTP_AUTH_TAG_LEN: Authentication tag length
* @GST_MIKEY_SP_SRTP_SRTP_PREFIX_LEN: SRTP prefix length * @GST_MIKEY_SP_SRTP_SRTP_PREFIX_LEN: SRTP prefix length
* @GST_MIKEY_SP_SRTP_AEAD_AUTH_TAG_LEN: AEAD authentication tag length
* *
* This policy specifies the parameters for SRTP and SRTCP * This policy specifies the parameters for SRTP and SRTCP
*/ */
@ -410,7 +413,8 @@ typedef enum
GST_MIKEY_SP_SRTP_FEC_ORDER = 9, GST_MIKEY_SP_SRTP_FEC_ORDER = 9,
GST_MIKEY_SP_SRTP_SRTP_AUTH = 10, GST_MIKEY_SP_SRTP_SRTP_AUTH = 10,
GST_MIKEY_SP_SRTP_AUTH_TAG_LEN = 11, GST_MIKEY_SP_SRTP_AUTH_TAG_LEN = 11,
GST_MIKEY_SP_SRTP_SRTP_PREFIX_LEN = 12 GST_MIKEY_SP_SRTP_SRTP_PREFIX_LEN = 12,
GST_MIKEY_SP_SRTP_AEAD_AUTH_TAG_LEN = 20
} GstMIKEYSecSRTP; } GstMIKEYSecSRTP;
/** /**