X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libs%2Fsrtp%2Fsrtp.c;h=ec49101494e104c0247ab6fb02d4117a22e7e964;hb=61f757bbca707b37caa6ed569486303fbc5eb6cf;hp=daf0e18d203db42b3e8f97f033bba23109063fa3;hpb=7bdd4ba5b1c58233b656c75e4abd9017f7ef02ee;p=vlc diff --git a/libs/srtp/srtp.c b/libs/srtp/srtp.c index daf0e18d20..ec49101494 100644 --- a/libs/srtp/srtp.c +++ b/libs/srtp/srtp.c @@ -90,13 +90,13 @@ static bool libgcrypt_usable = false; static void initonce_libgcrypt (void) { - if ((gcry_check_version ("1.1.94") == NULL) - || gcry_control (GCRYCTL_DISABLE_SECMEM, 0) - || gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0) #ifndef WIN32 - || gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread) + gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); #endif - ) + + if ((gcry_check_version ("1.1.94") == NULL) + || gcry_control (GCRYCTL_DISABLE_SECMEM, 0) + || gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0)) return; libgcrypt_usable = true; @@ -106,20 +106,17 @@ static int init_libgcrypt (void) { int retval; #ifndef WIN32 - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_once_t once = PTHREAD_ONCE_INIT; - pthread_mutex_lock (&mutex); pthread_once (&once, initonce_libgcrypt); - retval = -libgcrypt_usable; - pthread_mutex_unlock (&mutex); #else # warning FIXME: This is not thread-safe. if (!libgcrypt_usable) initonce_libgcrypt (); - retval = -libgcrypt_usable; #endif + retval = libgcrypt_usable ? 0 : -1; + return retval; } @@ -205,7 +202,7 @@ srtp_create (int encr, int auth, unsigned tag_len, int prf, unsigned flags) return NULL; } - if (tag_len > gcry_md_get_algo_dlen (auth)) + if (tag_len > gcry_md_get_algo_dlen (md)) return NULL; if (prf != SRTP_PRF_AES_CM) @@ -328,6 +325,7 @@ srtp_derive (srtp_session_t *s, const void *key, size_t keylen, || gcry_cipher_setkey (prf, key, keylen)) return -1; +#if 0 /* RTP key derivation */ if (s->kdr != 0) { @@ -341,6 +339,7 @@ srtp_derive (srtp_session_t *s, const void *key, size_t keylen, } } else +#endif memset (r, 0, sizeof (r)); if (proto_derive (&s->rtp, prf, salt, saltlen, r, 6, false)) @@ -373,6 +372,53 @@ srtp_setkey (srtp_session_t *s, const void *key, size_t keylen, return srtp_derive (s, key, keylen, salt, saltlen) ? EINVAL : 0; } +static int hexdigit (char c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + if ((c >= 'A') && (c <= 'F')) + return c - 'A' + 0xA; + if ((c >= 'a') && (c <= 'f')) + return c - 'a' + 0xa; + return -1; +} + +static ssize_t hexstring (const char *in, uint8_t *out, size_t outlen) +{ + size_t inlen = strlen (in); + + if ((inlen > (2 * outlen)) || (inlen & 1)) + return -1; + + for (size_t i = 0; i < inlen; i += 2) + { + int a = hexdigit (in[i]), b = hexdigit (in[i + 1]); + if ((a == -1) || (b == -1)) + return -1; + out[i / 2] = (a << 4) | b; + } + return inlen / 2; +} + +/** + * Sets (or resets) the master key and master salt for a SRTP session + * from hexadecimal strings. See also srtp_setkey(). + * + * @return 0 on success, in case of error: + * EINVAL invalid or unsupported key/salt sizes combination + */ +int +srtp_setkeystring (srtp_session_t *s, const char *key, const char *salt) +{ + uint8_t bkey[16]; /* TODO/NOTE: hard-coded for AES */ + uint8_t bsalt[14]; /* TODO/NOTE: hard-coded for the PRF-AES-CM */ + ssize_t bkeylen = hexstring (key, bkey, sizeof (bkey)); + ssize_t bsaltlen = hexstring (salt, bsalt, sizeof (bsalt)); + + if ((bkeylen == -1) || (bsaltlen == -1)) + return EINVAL; + return srtp_setkey (s, bkey, bkeylen, bsalt, bsaltlen) ? EINVAL : 0; +} /** * Sets Roll-over-Counter Carry (RCC) rate for the SRTP session. If not @@ -554,17 +600,21 @@ int srtp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize) { size_t len = *lenp; - int val = srtp_crypt (s, buf, len); - if (val) - return val; + size_t tag_len = s->tag_len; if (!(s->flags & SRTP_UNAUTHENTICATED)) { - size_t tag_len = s->tag_len; *lenp = len + tag_len; if (bufsize < (len + tag_len)) return ENOSPC; + } + + int val = srtp_crypt (s, buf, len); + if (val) + return val; + if (!(s->flags & SRTP_UNAUTHENTICATED)) + { uint32_t roc = srtp_compute_roc (s, rtp_seq (buf)); const uint8_t *tag = rtp_digest (s, buf, len, roc); if (rcc_mode (s)) @@ -646,7 +696,16 @@ srtp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp) rcc = roc; const uint8_t *tag = rtp_digest (s, buf, len, rcc); - if (memcmp (buf + len + roc_len, tag, s->tag_len)) +#if 0 + printf ("Computed: 0x"); + for (unsigned i = 0; i < tag_len; i++) + printf ("%02x", tag[i]); + printf ("\nReceived: 0x"); + for (unsigned i = 0; i < tag_len; i++) + printf ("%02x", buf[len + roc_len + i]); + puts (""); +#endif + if (memcmp (buf + len + roc_len, tag, tag_len)) return EACCES; if (roc_len)