]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added gnutls_srtp_get_keys().
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 1 Nov 2012 23:04:08 +0000 (00:04 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 1 Nov 2012 23:04:08 +0000 (00:04 +0100)
lib/ext/srtp.c
lib/includes/gnutls/gnutls.h.in
lib/libgnutls.map
tests/mini-dtls-srtp.c

index f0512cefb406e97b33b3ed6cd9672e6cffe61a9d..e9899112aa7d0c551b9bfe609243d7a4fb8306d1 100644 (file)
@@ -55,31 +55,49 @@ typedef struct
 {
   const char *name;
   gnutls_srtp_profile_t id;
+  unsigned int key_length;
+  unsigned int salt_length;
 } srtp_profile_st;
 
 static const srtp_profile_st profile_names[] = {
   {
     "SRTP_AES128_CM_SHA1_80",
     GNUTLS_SRTP_AES128_CM_SHA1_80,
+    16,14
   },
   {
     "SRTP_AES128_CM_SHA1_32",
     GNUTLS_SRTP_AES128_CM_SHA1_32,
+    16,14
   },
   {
     "SRTP_NULL_SHA1_80",
     GNUTLS_SRTP_NULL_SHA1_80,
+    16,14
   },
   {
     "SRTP_NULL_SHA1_32",
     GNUTLS_SRTP_NULL_SHA1_32,
+    16,14
   },
   {
     NULL,
-    0
+    0,0,0
   }
 };
 
+static const srtp_profile_st *get_profile (gnutls_srtp_profile_t profile)
+{
+  const srtp_profile_st *p = profile_names;
+  while (p->name != NULL)
+    {
+      if (p->id == profile)
+        return p;
+      p++;
+    }
+  return NULL;
+}
+
 static gnutls_srtp_profile_t find_profile (const char *str, const char *end)
 {
   const srtp_profile_st *prof = profile_names;
@@ -141,13 +159,11 @@ int gnutls_srtp_get_profile_id (const char *name,
  **/
 const char *gnutls_srtp_get_profile_name (gnutls_srtp_profile_t profile)
 {
-  const srtp_profile_st *p = profile_names;
-  while (p->name != NULL)
-    {
-      if (p->id == profile)
-        return p->name;
-      p++;
-    }
+  const srtp_profile_st *p = get_profile(profile);
+  
+  if (p != NULL)
+    return p->name;
+  
   return NULL;
 }
 
@@ -419,6 +435,89 @@ gnutls_srtp_set_profile_direct (gnutls_session_t session,
   return 0;
 }
 
+/**
+ * gnutls_srtp_get_keys:
+ * @session: is a #gnutls_session_t structure.
+ * @key_material: Space to hold the generated key material
+ * @key_material_size: The maximum size of the key material
+ * @client_key: The master client write key, pointing inside the key material
+ * @server_key: The master server write key, pointing inside the key material
+ * @client_salt: The master client write salt, pointing inside the key material
+ * @server_salt: The master server write salt, pointing inside the key material
+ *
+ * This is a helper function to generate the keying material for SRTP.
+ * It requires the space of the key material to be pre-allocated (should be at least
+ * 2x the maximum key size and salt size). The @client_key, @client_salt, @server_key
+ * and @server_salt are convenience datums that point inside the key material. The may
+ * be %NULL.
+ *
+ * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not sufficient, 
+ * %GNUTLS_E_SUCCESS on success, or an error code.
+ *
+ * Since 3.1.4
+ **/
+int
+gnutls_srtp_get_keys (gnutls_session_t session, 
+                      void *key_material,
+                      unsigned int key_material_size,
+                      gnutls_datum_t *client_key, 
+                      gnutls_datum_t *client_salt,
+                      gnutls_datum_t *server_key, 
+                      gnutls_datum_t *server_salt)
+{  
+int ret;
+const srtp_profile_st *p;
+gnutls_srtp_profile_t profile;
+unsigned int msize;
+uint8_t *km = key_material;
+
+  ret = gnutls_srtp_get_selected_profile (session, &profile);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  p = get_profile(profile);
+  if (p == NULL)
+    return gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM);
+  
+  msize = 2*(p->key_length+p->salt_length);
+  if (msize > key_material_size)
+    return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+    
+  if (msize == 0)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+  ret = gnutls_prf(session, sizeof("EXTRACTOR-dtls_srtp")-1, "EXTRACTOR-dtls_srtp", 0, 0, 
+                   NULL, msize, key_material);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  if (client_key)
+    {
+      client_key->data = km;
+      client_key->size = p->key_length;
+    }
+
+  if (server_key)
+    {
+      server_key->data = km + p->key_length;
+      server_key->size = p->key_length;
+    }
+
+  if (client_salt)
+    {
+      client_salt->data = km + 2*p->key_length;
+      client_salt->size = p->salt_length;
+    }
+  
+  if (server_salt)
+    {
+      server_salt->data = km + 2*p->key_length + p->salt_length;
+      server_salt->size = p->salt_length;
+    }
+
+  return 0;
+}
+
 static void
 _gnutls_srtp_deinit_data (extension_priv_data_t priv)
 {
index 60726d0d1b4d876021c21a66e098828da5ebfcdb..a64db31fe3af388d24940095f80a5e1ad7c33772 100644 (file)
@@ -992,6 +992,13 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session);
   const char *gnutls_srtp_get_profile_name (gnutls_srtp_profile_t profile);
   int gnutls_srtp_get_profile_id (const char *name,
                                   gnutls_srtp_profile_t *profile);
+  int gnutls_srtp_get_keys (gnutls_session_t session, 
+                      void *key_material,
+                      unsigned int key_material_size,
+                      gnutls_datum_t *client_key, 
+                      gnutls_datum_t *client_salt,
+                      gnutls_datum_t *server_key, 
+                      gnutls_datum_t *server_salt);
 
   int gnutls_key_generate (gnutls_datum_t * key, unsigned int key_size);
 
index 635e58a181508e4e25a4b4e8c45633c8b83c8109..2843f26cd3f9ccf684da3c84f1f2717427e3e1da 100644 (file)
@@ -866,6 +866,7 @@ GNUTLS_3_1_0 {
        gnutls_srtp_get_selected_profile;
        gnutls_srtp_set_profile;
        gnutls_srtp_set_profile_direct;
+       gnutls_srtp_get_keys;
 } GNUTLS_3_0_0;
 
 GNUTLS_PRIVATE {
index 8f41d619e4443a591b7305d25fab577674e99e85..76edfdf558b16577ccca0abc41ff327a9226011b 100644 (file)
@@ -69,7 +69,8 @@ client_log_func (int level, const char *str)
 /* These are global */
 static pid_t child;
 
-/* A very basic DTLS client, with anonymous authentication, that exchanges heartbeats.
+#define MAX_KEY_MATERIAL 64*4
+/* A very basic DTLS client, with anonymous authentication, that negotiates SRTP
  */
 
 static void
@@ -78,6 +79,9 @@ client (int fd, int profile)
     gnutls_session_t session;
     int ret;
     gnutls_anon_client_credentials_t anoncred;
+    uint8_t km[MAX_KEY_MATERIAL];
+    char buf[2*MAX_KEY_MATERIAL];
+    gnutls_datum_t cli_key, cli_salt, server_key, server_salt;
     /* Need to enable anonymous KX specifically. */
 
     gnutls_global_init ();
@@ -144,14 +148,33 @@ client (int fd, int profile)
                  gnutls_protocol_get_name (gnutls_protocol_get_version
                                            (session)));
 
-/*
-    ret = gnutls_prf(session, sizeof("EXTRACTOR-dtls_srtp")-1, "EXTRACTOR-dtls_srtp", 0, ctx_len, ctx, 32, out);
+    ret = gnutls_srtp_get_keys (session, km, sizeof(km), &cli_key, &cli_salt, &server_key, &server_salt);
     if (ret < 0)
       {
         gnutls_perror(ret);
         exit(1);
       }
-*/
+
+    if (debug)
+      {
+        size_t size = sizeof(buf);
+        gnutls_hex_encode(&cli_key, buf, &size);
+        success ("Client key: %s\n", buf);
+
+        size = sizeof(buf);
+        gnutls_hex_encode(&cli_salt, buf, &size);
+        success ("Client salt: %s\n", buf);
+
+        size = sizeof(buf);
+        gnutls_hex_encode(&server_key, buf, &size);
+        success ("Server key: %s\n", buf);
+
+        size = sizeof(buf);
+        gnutls_hex_encode(&server_salt, buf, &size);
+        success ("Server salt: %s\n", buf);
+      }
+
+
     gnutls_bye (session, GNUTLS_SHUT_WR);
 
     close (fd);
@@ -179,6 +202,10 @@ server (int fd, int profile)
     int ret;
     gnutls_session_t session;
     gnutls_anon_server_credentials_t anoncred;
+    uint8_t km[MAX_KEY_MATERIAL];
+    char buf[2*MAX_KEY_MATERIAL];
+    gnutls_datum_t cli_key, cli_salt, server_key, server_salt;
+
     /* this must be called once in the program
      */
     gnutls_global_init ();
@@ -239,14 +266,31 @@ server (int fd, int profile)
                  gnutls_protocol_get_name (gnutls_protocol_get_version
                                            (session)));
 
-/*
-    ret = gnutls_prf(session, sizeof("EXTRACTOR-dtls_srtp")-1, "EXTRACTOR-dtls_srtp", 0, ctx_len, ctx, 32, out);
+    ret = gnutls_srtp_get_keys (session, km, sizeof(km), &cli_key, &cli_salt, &server_key, &server_salt);
     if (ret < 0)
       {
         gnutls_perror(ret);
         exit(1);
       }
-*/
+    
+    if (debug)
+      {
+        size_t size = sizeof(buf);
+        gnutls_hex_encode(&cli_key, buf, &size);
+        success ("Client key: %s\n", buf);
+
+        size = sizeof(buf);
+        gnutls_hex_encode(&cli_salt, buf, &size);
+        success ("Client salt: %s\n", buf);
+
+        size = sizeof(buf);
+        gnutls_hex_encode(&server_key, buf, &size);
+        success ("Server key: %s\n", buf);
+
+        size = sizeof(buf);
+        gnutls_hex_encode(&server_salt, buf, &size);
+        success ("Server salt: %s\n", buf);
+      }
 
     /* do not wait for the peer to close the connection.
      */