aboutsummaryrefslogtreecommitdiff
path: root/plugins/crypto-vala
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/crypto-vala')
-rw-r--r--plugins/crypto-vala/CMakeLists.txt8
-rw-r--r--plugins/crypto-vala/src/error.vala4
-rw-r--r--plugins/crypto-vala/src/random.vala5
-rw-r--r--plugins/crypto-vala/src/srtp.vala122
-rw-r--r--plugins/crypto-vala/vapi/libsrtp2.vapi115
5 files changed, 251 insertions, 3 deletions
diff --git a/plugins/crypto-vala/CMakeLists.txt b/plugins/crypto-vala/CMakeLists.txt
index 2c9f790a..f615854c 100644
--- a/plugins/crypto-vala/CMakeLists.txt
+++ b/plugins/crypto-vala/CMakeLists.txt
@@ -1,4 +1,5 @@
find_package(GCrypt REQUIRED)
+find_package(Srtp2 REQUIRED)
find_packages(CRYPTO_VALA_PACKAGES REQUIRED
GLib
GObject
@@ -10,8 +11,11 @@ SOURCES
"src/cipher.vala"
"src/cipher_converter.vala"
"src/error.vala"
+ "src/random.vala"
+ "src/srtp.vala"
CUSTOM_VAPIS
"${CMAKE_CURRENT_SOURCE_DIR}/vapi/gcrypt.vapi"
+ "${CMAKE_CURRENT_SOURCE_DIR}/vapi/libsrtp2.vapi"
PACKAGES
${CRYPTO_VALA_PACKAGES}
GENERATE_VAPI
@@ -20,9 +24,9 @@ GENERATE_HEADER
crypto-vala
)
-set(CFLAGS ${VALA_CFLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/src)
+set(CFLAGS ${VALA_CFLAGS})
add_definitions(${CFLAGS})
add_library(crypto-vala STATIC ${CRYPTO_VALA_C})
-target_link_libraries(crypto-vala ${CRYPTO_VALA_PACKAGES} gcrypt)
+target_link_libraries(crypto-vala ${CRYPTO_VALA_PACKAGES} gcrypt libsrtp2)
set_property(TARGET crypto-vala PROPERTY POSITION_INDEPENDENT_CODE ON)
diff --git a/plugins/crypto-vala/src/error.vala b/plugins/crypto-vala/src/error.vala
index bae4ad08..5007d725 100644
--- a/plugins/crypto-vala/src/error.vala
+++ b/plugins/crypto-vala/src/error.vala
@@ -2,7 +2,9 @@ namespace Crypto {
public errordomain Error {
ILLEGAL_ARGUMENTS,
- GCRYPT
+ GCRYPT,
+ AUTHENTICATION_FAILED,
+ UNKNOWN
}
internal void may_throw_gcrypt_error(GCrypt.Error e) throws Error {
diff --git a/plugins/crypto-vala/src/random.vala b/plugins/crypto-vala/src/random.vala
new file mode 100644
index 00000000..3f5d3ba9
--- /dev/null
+++ b/plugins/crypto-vala/src/random.vala
@@ -0,0 +1,5 @@
+namespace Crypto {
+public static void randomize(uint8[] buffer) {
+ GCrypt.Random.randomize(buffer);
+}
+} \ No newline at end of file
diff --git a/plugins/crypto-vala/src/srtp.vala b/plugins/crypto-vala/src/srtp.vala
new file mode 100644
index 00000000..493afdb0
--- /dev/null
+++ b/plugins/crypto-vala/src/srtp.vala
@@ -0,0 +1,122 @@
+using Srtp;
+
+public class Crypto.Srtp {
+ public const string AES_CM_128_HMAC_SHA1_80 = "AES_CM_128_HMAC_SHA1_80";
+ public const string AES_CM_128_HMAC_SHA1_32 = "AES_CM_128_HMAC_SHA1_32";
+ public const string F8_128_HMAC_SHA1_80 = "F8_128_HMAC_SHA1_80";
+
+ public class Session {
+ public bool has_encrypt { get; private set; default = false; }
+ public bool has_decrypt { get; private set; default = false; }
+
+ private Context encrypt_context;
+ private Context decrypt_context;
+
+ static construct {
+ init();
+ install_log_handler(log);
+ }
+
+ private static void log(LogLevel level, string msg) {
+ print(@"SRTP[$level]: $msg\n");
+ }
+
+ public Session() {
+ Context.create(out encrypt_context, null);
+ Context.create(out decrypt_context, null);
+ }
+
+ public uint8[] encrypt_rtp(uint8[] data) throws Error {
+ uint8[] buf = new uint8[data.length + MAX_TRAILER_LEN];
+ Memory.copy(buf, data, data.length);
+ int buf_use = data.length;
+ ErrorStatus res = encrypt_context.protect(buf, ref buf_use);
+ if (res != ErrorStatus.ok) {
+ throw new Error.UNKNOWN(@"SRTP encrypt failed: $res");
+ }
+ uint8[] ret = new uint8[buf_use];
+ GLib.Memory.copy(ret, buf, buf_use);
+ return ret;
+ }
+
+ public uint8[] decrypt_rtp(uint8[] data) throws Error {
+ uint8[] buf = new uint8[data.length];
+ Memory.copy(buf, data, data.length);
+ int buf_use = data.length;
+ ErrorStatus res = decrypt_context.unprotect(buf, ref buf_use);
+ switch (res) {
+ case ErrorStatus.auth_fail:
+ throw new Error.AUTHENTICATION_FAILED("SRTP packet failed the message authentication check");
+ case ErrorStatus.ok:
+ break;
+ default:
+ throw new Error.UNKNOWN(@"SRTP decrypt failed: $res");
+ }
+ uint8[] ret = new uint8[buf_use];
+ GLib.Memory.copy(ret, buf, buf_use);
+ return ret;
+ }
+
+ public uint8[] encrypt_rtcp(uint8[] data) throws Error {
+ uint8[] buf = new uint8[data.length + MAX_TRAILER_LEN + 4];
+ Memory.copy(buf, data, data.length);
+ int buf_use = data.length;
+ ErrorStatus res = encrypt_context.protect_rtcp(buf, ref buf_use);
+ if (res != ErrorStatus.ok) {
+ throw new Error.UNKNOWN(@"SRTCP encrypt failed: $res");
+ }
+ uint8[] ret = new uint8[buf_use];
+ GLib.Memory.copy(ret, buf, buf_use);
+ return ret;
+ }
+
+ public uint8[] decrypt_rtcp(uint8[] data) throws Error {
+ uint8[] buf = new uint8[data.length];
+ Memory.copy(buf, data, data.length);
+ int buf_use = data.length;
+ ErrorStatus res = decrypt_context.unprotect_rtcp(buf, ref buf_use);
+ switch (res) {
+ case ErrorStatus.auth_fail:
+ throw new Error.AUTHENTICATION_FAILED("SRTCP packet failed the message authentication check");
+ case ErrorStatus.ok:
+ break;
+ default:
+ throw new Error.UNKNOWN(@"SRTP decrypt failed: $res");
+ }
+ uint8[] ret = new uint8[buf_use];
+ GLib.Memory.copy(ret, buf, buf_use);
+ return ret;
+ }
+
+ private Policy create_policy(string profile) {
+ Policy policy = Policy();
+ switch (profile) {
+ case AES_CM_128_HMAC_SHA1_80:
+ policy.rtp.set_aes_cm_128_hmac_sha1_80();
+ policy.rtcp.set_aes_cm_128_hmac_sha1_80();
+ break;
+ }
+ return policy;
+ }
+
+ public void set_encryption_key(string profile, uint8[] key, uint8[] salt) {
+ Policy policy = create_policy(profile);
+ policy.ssrc.type = SsrcType.any_outbound;
+ policy.key = new uint8[key.length + salt.length];
+ Memory.copy(policy.key, key, key.length);
+ Memory.copy(((uint8*)policy.key) + key.length, salt, salt.length);
+ encrypt_context.add_stream(ref policy);
+ has_encrypt = true;
+ }
+
+ public void set_decryption_key(string profile, uint8[] key, uint8[] salt) {
+ Policy policy = create_policy(profile);
+ policy.ssrc.type = SsrcType.any_inbound;
+ policy.key = new uint8[key.length + salt.length];
+ Memory.copy(policy.key, key, key.length);
+ Memory.copy(((uint8*)policy.key) + key.length, salt, salt.length);
+ decrypt_context.add_stream(ref policy);
+ has_decrypt = true;
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/crypto-vala/vapi/libsrtp2.vapi b/plugins/crypto-vala/vapi/libsrtp2.vapi
new file mode 100644
index 00000000..5ceedced
--- /dev/null
+++ b/plugins/crypto-vala/vapi/libsrtp2.vapi
@@ -0,0 +1,115 @@
+[CCode (cheader_filename = "srtp2/srtp.h")]
+namespace Srtp {
+public const uint MAX_TRAILER_LEN;
+
+public static ErrorStatus init();
+public static ErrorStatus shutdown();
+
+[Compact]
+[CCode (cname = "srtp_ctx_t", cprefix = "srtp_", free_function = "srtp_dealloc")]
+public class Context {
+ public static ErrorStatus create(out Context session, Policy? policy);
+
+ public ErrorStatus protect([CCode (type = "void*", array_length = false)] uint8[] rtp, ref int len);
+ public ErrorStatus unprotect([CCode (type = "void*", array_length = false)] uint8[] rtp, ref int len);
+
+ public ErrorStatus protect_rtcp([CCode (type = "void*", array_length = false)] uint8[] rtcp, ref int len);
+ public ErrorStatus unprotect_rtcp([CCode (type = "void*", array_length = false)] uint8[] rtcp, ref int len);
+
+ public ErrorStatus add_stream(ref Policy policy);
+ public ErrorStatus update_stream(ref Policy policy);
+ public ErrorStatus remove_stream(uint ssrc);
+ public ErrorStatus update(ref Policy policy);
+}
+
+[CCode (cname = "srtp_ssrc_t")]
+public struct Ssrc {
+ public SsrcType type;
+ public uint value;
+}
+
+[CCode (cname = "srtp_ssrc_type_t", cprefix = "ssrc_")]
+public enum SsrcType {
+ undefined, specific, any_inbound, any_outbound
+}
+
+[CCode (cname = "srtp_policy_t", destroy_function = "")]
+public struct Policy {
+ public Ssrc ssrc;
+ public CryptoPolicy rtp;
+ public CryptoPolicy rtcp;
+ [CCode (array_length = false)]
+ public uint8[] key;
+ public ulong num_master_keys;
+ public ulong window_size;
+ public int allow_repeat_tx;
+ [CCode (array_length_cname = "enc_xtn_hdr_count")]
+ public int[] enc_xtn_hdr;
+}
+
+[CCode (cname = "srtp_crypto_policy_t")]
+public struct CryptoPolicy {
+ public CipherType cipher_type;
+ public int cipher_key_len;
+ public AuthType auth_type;
+ public int auth_key_len;
+ public int auth_tag_len;
+ public SecurityServices sec_serv;
+
+ public void set_aes_cm_128_hmac_sha1_80();
+ public void set_aes_cm_128_hmac_sha1_32();
+ public void set_aes_cm_128_null_auth();
+ public void set_aes_cm_192_hmac_sha1_32();
+ public void set_aes_cm_192_hmac_sha1_80();
+ public void set_aes_cm_192_null_auth();
+ public void set_aes_cm_256_hmac_sha1_32();
+ public void set_aes_cm_256_hmac_sha1_80();
+ public void set_aes_cm_256_null_auth();
+ public void set_aes_gcm_128_16_auth();
+ public void set_aes_gcm_128_8_auth();
+ public void set_aes_gcm_128_8_only_auth();
+ public void set_aes_gcm_256_16_auth();
+ public void set_aes_gcm_256_8_auth();
+ public void set_aes_gcm_256_8_only_auth();
+ public void set_null_cipher_hmac_null();
+ public void set_null_cipher_hmac_sha1_80();
+
+ public void set_rtp_default();
+ public void set_rtcp_default();
+
+ public void set_from_profile_for_rtp(Profile profile);
+ public void set_from_profile_for_rtcp(Profile profile);
+}
+
+[CCode (cname = "srtp_profile_t", cprefix = "srtp_profile_")]
+public enum Profile {
+ reserved, aes128_cm_sha1_80, aes128_cm_sha1_32, null_sha1_80, null_sha1_32, aead_aes_128_gcm, aead_aes_256_gcm
+}
+
+[CCode (cname = "srtp_cipher_type_id_t")]
+public struct CipherType : uint32 {}
+
+[CCode (cname = "srtp_auth_type_id_t")]
+public struct AuthType : uint32 {}
+
+[CCode (cname = "srtp_sec_serv_t", cprefix = "sec_serv_")]
+public enum SecurityServices {
+ none, conf, auth, conf_and_auth;
+}
+
+[CCode (cname = "srtp_err_status_t", cprefix = "srtp_err_status_", has_type_id = false)]
+public enum ErrorStatus {
+ ok, fail, bad_param, alloc_fail, dealloc_fail, init_fail, terminus, auth_fail, cipher_fail, replay_fail, algo_fail, no_such_op, no_ctx, cant_check, key_expired, socket_err, signal_err, nonce_bad, encode_err, semaphore_err, pfkey_err, bad_mki, pkt_idx_old, pkt_idx_adv
+}
+
+[CCode (cname = "srtp_log_level_t", cprefix = "srtp_log_level_", has_type_id = false)]
+public enum LogLevel {
+ error, warning, info, debug
+}
+
+[CCode (cname = "srtp_log_handler_func_t")]
+public delegate void LogHandler(LogLevel level, string msg);
+
+public static ErrorStatus install_log_handler(LogHandler func);
+
+} \ No newline at end of file