int main(int argc, char *argv[]) { unsigned do_list_mods = 0; int q; srtp_err_status_t err; printf("dtls_srtp_driver\n"); /* initialize srtp library */ err = srtp_init(); if (err) { printf("error: srtp init failed with error code %d\n", err); exit(1); } /* process input arguments */ while (1) { q = getopt_s(argc, argv, "ld:"); if (q == -1) break; switch (q) { case 'l': do_list_mods = 1; break; case 'd': err = srtp_crypto_kernel_set_debug_module(optarg_s, 1); if (err) { printf("error: set debug module (%s) failed\n", optarg_s); exit(1); } break; default: usage(argv[0]); } } if (do_list_mods) { err = srtp_crypto_kernel_list_debug_modules(); if (err) { printf("error: list of debug modules failed\n"); exit(1); } } printf("testing dtls_srtp..."); err = test_dtls_srtp(); if (err) { printf("\nerror (code %d)\n", err); exit(1); } printf("passed\n"); /* shut down srtp library */ err = srtp_shutdown(); if (err) { printf("error: srtp shutdown failed with error code %d\n", err); exit(1); } return 0; }
int main (int argc, char *argv[]) { char errbuf[PCAP_ERRBUF_SIZE]; bpf_u_int32 pcap_net = 0; pcap_t *pcap_handle; #if BEW struct sockaddr_in local; #endif srtp_sec_serv_t sec_servs = sec_serv_none; int c; int key_size = 128; int tag_size = 8; int gcm_on = 0; char *input_key = NULL; int b64_input = 0; char key[MAX_KEY_LEN]; struct bpf_program fp; char filter_exp[MAX_FILTER] = ""; rtp_decoder_t dec; srtp_policy_t policy; srtp_err_status_t status; int len; int expected_len; int do_list_mods = 0; fprintf(stderr, "Using %s [0x%x]\n", srtp_get_version_string(), srtp_get_version()); /* initialize srtp library */ status = srtp_init(); if (status) { fprintf(stderr, "error: srtp initialization failed with error code %d\n", status); exit(1); } /* check args */ while (1) { c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:"); if (c == -1) { break; } switch (c) { case 'b': b64_input = 1; /* fall thru */ case 'k': input_key = optarg_s; break; case 'e': key_size = atoi(optarg_s); if (key_size != 128 && key_size != 256) { fprintf(stderr, "error: encryption key size must be 128 or 256 (%d)\n", key_size); exit(1); } input_key = malloc(key_size); sec_servs |= sec_serv_conf; break; case 't': tag_size = atoi(optarg_s); if (tag_size != 8 && tag_size != 16) { fprintf(stderr, "error: GCM tag size must be 8 or 16 (%d)\n", tag_size); //exit(1); } break; case 'a': sec_servs |= sec_serv_auth; break; case 'g': gcm_on = 1; sec_servs |= sec_serv_auth; break; case 'd': status = srtp_crypto_kernel_set_debug_module(optarg_s, 1); if (status) { fprintf(stderr, "error: set debug module (%s) failed\n", optarg_s); exit(1); } break; case 'f': if(strlen(optarg_s) > MAX_FILTER){ fprintf(stderr, "error: filter bigger than %d characters\n", MAX_FILTER); exit(1); } fprintf(stderr, "Setting filter as %s\n", optarg_s); strcpy(filter_exp, optarg_s); break; case 'l': do_list_mods = 1; break; default: usage(argv[0]); } } if (do_list_mods) { status = srtp_crypto_kernel_list_debug_modules(); if (status) { fprintf(stderr, "error: list of debug modules failed\n"); exit(1); } return 0; } if ((sec_servs && !input_key) || (!sec_servs && input_key)) { /* * a key must be provided if and only if security services have * been requested */ if(input_key == NULL){ fprintf(stderr, "key not provided\n"); } if(!sec_servs){ fprintf(stderr, "no secservs\n"); } fprintf(stderr, "provided\n"); usage(argv[0]); } /* report security services selected on the command line */ fprintf(stderr, "security services: "); if (sec_servs & sec_serv_conf) fprintf(stderr, "confidentiality "); if (sec_servs & sec_serv_auth) fprintf(stderr, "message authentication"); if (sec_servs == sec_serv_none) fprintf(stderr, "none"); fprintf(stderr, "\n"); /* set up the srtp policy and master key */ if (sec_servs) { /* * create policy structure, using the default mechanisms but * with only the security services requested on the command line, * using the right SSRC value */ switch (sec_servs) { case sec_serv_conf_and_auth: if (gcm_on) { #ifdef OPENSSL switch (key_size) { case 128: srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); break; case 256: srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp); srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp); break; } #else fprintf(stderr, "error: GCM mode only supported when using the OpenSSL crypto engine.\n"); return 0; #endif } else { switch (key_size) { case 128: srtp_crypto_policy_set_rtp_default(&policy.rtp); srtp_crypto_policy_set_rtcp_default(&policy.rtcp); break; case 256: srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp); srtp_crypto_policy_set_rtcp_default(&policy.rtcp); break; } } break; case sec_serv_conf: if (gcm_on) { fprintf(stderr, "error: GCM mode must always be used with auth enabled\n"); return -1; } else { switch (key_size) { case 128: srtp_crypto_policy_set_aes_cm_128_null_auth(&policy.rtp); srtp_crypto_policy_set_rtcp_default(&policy.rtcp); break; case 256: srtp_crypto_policy_set_aes_cm_256_null_auth(&policy.rtp); srtp_crypto_policy_set_rtcp_default(&policy.rtcp); break; } } break; case sec_serv_auth: if (gcm_on) { #ifdef OPENSSL switch (key_size) { case 128: srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp); srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtcp); break; case 256: srtp_crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp); srtp_crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtcp); break; } #else printf("error: GCM mode only supported when using the OpenSSL crypto engine.\n"); return 0; #endif } else { srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp); srtp_crypto_policy_set_rtcp_default(&policy.rtcp); } break; default: fprintf(stderr, "error: unknown security service requested\n"); return -1; } policy.key = (uint8_t *) key; policy.ekt = NULL; policy.next = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; policy.rtp.sec_serv = sec_servs; policy.rtcp.sec_serv = sec_servs; //sec_serv_none; /* we don't do RTCP anyway */ fprintf(stderr, "setting tag len %d\n", tag_size); policy.rtp.auth_tag_len = tag_size; if (gcm_on && tag_size != 8) { fprintf(stderr, "setted tag len %d\n", tag_size); policy.rtp.auth_tag_len = tag_size; } /* * read key from hexadecimal or base64 on command line into an octet string */ if (b64_input) { int pad; expected_len = policy.rtp.cipher_key_len*4/3; len = base64_string_to_octet_string(key, &pad, input_key, expected_len); if (pad != 0) { fprintf(stderr, "error: padding in base64 unexpected\n"); exit(1); } } else { expected_len = policy.rtp.cipher_key_len*2; len = hex_string_to_octet_string(key, input_key, expected_len); } /* check that hex string is the right length */ if (len < expected_len) { fprintf(stderr, "error: too few digits in key/salt " "(should be %d digits, found %d)\n", expected_len, len); exit(1); } if (strlen(input_key) > policy.rtp.cipher_key_len*2) { fprintf(stderr, "error: too many digits in key/salt " "(should be %d hexadecimal digits, found %u)\n", policy.rtp.cipher_key_len*2, (unsigned)strlen(input_key)); exit(1); } fprintf(stderr, "set master key/salt to %s/", octet_string_hex_string(key, 16)); fprintf(stderr, "%s\n", octet_string_hex_string(key+16, 14)); } else { fprintf(stderr, "error: neither encryption or authentication were selected"); exit(1); } pcap_handle = pcap_open_offline("-", errbuf); if (!pcap_handle) { fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf); exit(1); } assert(pcap_handle != NULL); if ((pcap_compile(pcap_handle, &fp, filter_exp, 1, pcap_net)) == -1){ fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(pcap_handle)); return (2); } if (pcap_setfilter(pcap_handle, &fp) == -1){ fprintf(stderr, "couldn't install filter %s: %s\n", filter_exp, pcap_geterr(pcap_handle)); return (2); } dec = rtp_decoder_alloc(); if (dec == NULL) { fprintf(stderr, "error: malloc() failed\n"); exit(1); } fprintf(stderr, "Starting decoder\n"); rtp_decoder_init(dec, policy); pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec); rtp_decoder_deinit_srtp(dec); rtp_decoder_dealloc(dec); status = srtp_shutdown(); if (status) { fprintf(stderr, "error: srtp shutdown failed with error code %d\n", status); exit(1); } return 0; }