Merge pull request #80 from coien/master
Thank you for the contribution.
diff --git a/Makefile.in b/Makefile.in
index bbbbab7..eb4ce65 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -157,12 +157,14 @@
$(testapp): libsrtp.a
-test/rtpw$(EXE): test/rtpw.c test/rtp.c test/getopt_s.c
- $(COMPILE) $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
+test/rtpw$(EXE): test/rtpw.c test/rtp.c test/getopt_s.c \
+ crypto/math/datatypes.c
+ $(COMPILE) -DTESTAPP_SOURCE=1 $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
ifeq (1, $(HAVE_PCAP))
-test/rtp_decoder$(EXE): test/rtp_decoder.c test/rtp.c test/getopt_s.c
- $(COMPILE) $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
+test/rtp_decoder$(EXE): test/rtp_decoder.c test/rtp.c test/getopt_s.c \
+ crypto/math/datatypes.c
+ $(COMPILE) -DTESTAPP_SOURCE=1 $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
endif
test/srtp_driver$(EXE): test/srtp_driver.c test/getopt_s.c
diff --git a/README b/README
index 97f382c..b3ee608 100644
--- a/README
+++ b/README
@@ -78,7 +78,7 @@
Manual srtp keying uses the -k option; automated key management
using gdoi will be added later.
-usage: rtpw [-d <debug>]* [-k <key> [-a][-e <key size>][-g]] [-s | -r] dest_ip dest_port
+usage: rtpw [-d <debug>]* [-k|b <key> [-a][-e <key size>][-g]] [-s | -r] dest_ip dest_port
or rtpw -l
Either the -s (sender) or -r (receiver) option must be chosen.
@@ -96,6 +96,8 @@
key is a hexadecimal value (without the
leading "0x")
+ -b <key> same as -k but with base64 encoded key
+
-e <keysize> encrypt/decrypt (for data confidentiality)
(requires use of -k option as well)
(use 128, 192, or 256 for keysize)
diff --git a/crypto/include/datatypes.h b/crypto/include/datatypes.h
index a9bdd4c..b18435f 100644
--- a/crypto/include/datatypes.h
+++ b/crypto/include/datatypes.h
@@ -509,4 +509,8 @@
char *
bitvector_bit_string(bitvector_t *x, char* buf, int len);
+#ifdef TESTAPP_SOURCE
+int base64_string_to_octet_string(char *raw, int *pad, char *base64, int len);
+#endif
+
#endif /* _DATATYPES_H */
diff --git a/crypto/math/datatypes.c b/crypto/math/datatypes.c
index 1e219fe..c4af8d7 100644
--- a/crypto/math/datatypes.c
+++ b/crypto/math/datatypes.c
@@ -529,196 +529,41 @@
}
+#ifdef TESTAPP_SOURCE
-/*
- * From RFC 1521: The Base64 Alphabet
- *
- * Value Encoding Value Encoding Value Encoding Value Encoding
- * 0 A 17 R 34 i 51 z
- * 1 B 18 S 35 j 52 0
- * 2 C 19 T 36 k 53 1
- * 3 D 20 U 37 l 54 2
- * 4 E 21 V 38 m 55 3
- * 5 F 22 W 39 n 56 4
- * 6 G 23 X 40 o 57 5
- * 7 H 24 Y 41 p 58 6
- * 8 I 25 Z 42 q 59 7
- * 9 J 26 a 43 r 60 8
- * 10 K 27 b 44 s 61 9
- * 11 L 28 c 45 t 62 +
- * 12 M 29 d 46 u 63 /
- * 13 N 30 e 47 v
- * 14 O 31 f 48 w (pad) =
- * 15 P 32 g 49 x
- * 16 Q 33 h 50 y
- */
+static const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz0123456789+/";
-int
-base64_char_to_sextet(uint8_t c) {
- switch(c) {
- case 'A':
- return 0;
- case 'B':
- return 1;
- case 'C':
- return 2;
- case 'D':
- return 3;
- case 'E':
- return 4;
- case 'F':
- return 5;
- case 'G':
- return 6;
- case 'H':
- return 7;
- case 'I':
- return 8;
- case 'J':
- return 9;
- case 'K':
- return 10;
- case 'L':
- return 11;
- case 'M':
- return 12;
- case 'N':
- return 13;
- case 'O':
- return 14;
- case 'P':
- return 15;
- case 'Q':
- return 16;
- case 'R':
- return 17;
- case 'S':
- return 18;
- case 'T':
- return 19;
- case 'U':
- return 20;
- case 'V':
- return 21;
- case 'W':
- return 22;
- case 'X':
- return 23;
- case 'Y':
- return 24;
- case 'Z':
- return 25;
- case 'a':
- return 26;
- case 'b':
- return 27;
- case 'c':
- return 28;
- case 'd':
- return 29;
- case 'e':
- return 30;
- case 'f':
- return 31;
- case 'g':
- return 32;
- case 'h':
- return 33;
- case 'i':
- return 34;
- case 'j':
- return 35;
- case 'k':
- return 36;
- case 'l':
- return 37;
- case 'm':
- return 38;
- case 'n':
- return 39;
- case 'o':
- return 40;
- case 'p':
- return 41;
- case 'q':
- return 42;
- case 'r':
- return 43;
- case 's':
- return 44;
- case 't':
- return 45;
- case 'u':
- return 46;
- case 'v':
- return 47;
- case 'w':
- return 48;
- case 'x':
- return 49;
- case 'y':
- return 50;
- case 'z':
- return 51;
- case '0':
- return 52;
- case '1':
- return 53;
- case '2':
- return 54;
- case '3':
- return 55;
- case '4':
- return 56;
- case '5':
- return 57;
- case '6':
- return 58;
- case '7':
- return 59;
- case '8':
- return 60;
- case '9':
- return 61;
- case '+':
- return 62;
- case '/':
- return 63;
- case '=':
- return 64;
- default:
- break;
- }
- return -1;
-}
+static int base64_block_to_octet_triple(char *out, char *in) {
+ unsigned char sextets[4] = {};
+ int j = 0;
+ int i;
-#ifdef INCLUDE_DEAD_CODE
-/*
- * base64_string_to_octet_string converts a hexadecimal string
- * of length 2 * len to a raw octet string of length len
- */
-
-int
-base64_string_to_octet_string(char *raw, char *base64, int len) {
- uint8_t x;
- int tmp;
- int base64_len;
-
- base64_len = 0;
- while (base64_len < len) {
- tmp = base64_char_to_sextet(base64[0]);
- if (tmp == -1)
- return base64_len;
- x = (tmp << 6);
- base64_len++;
- tmp = base64_char_to_sextet(base64[1]);
- if (tmp == -1)
- return base64_len;
- x |= (tmp & 0xffff);
- base64_len++;
- *raw++ = x;
- base64 += 2;
+ for (i = 0; i < 4; i++) {
+ char *p = strchr(b64chars, in[i]);
+ if (p != NULL) sextets[i] = p - b64chars;
+ else j++;
}
- return base64_len;
+
+ out[0] = (sextets[0]<<2)|(sextets[1]>>4);
+ if (j < 2) out[1] = (sextets[1]<<4)|(sextets[2]>>2);
+ if (j < 1) out[2] = (sextets[2]<<6)|sextets[3];
+ return j;
}
+
+int base64_string_to_octet_string(char *out, int *pad, char *in, int len) {
+ int k = 0;
+ int i = 0;
+ int j = 0;
+ if (len % 4 != 0) return 0;
+
+ while (i < len && j == 0) {
+ j = base64_block_to_octet_triple(out + k, in + i);
+ k += 3;
+ i += 4;
+ }
+ *pad = j;
+ return i;
+}
+
#endif
diff --git a/test/rtp_decoder.c b/test/rtp_decoder.c
index ddc93d0..60b8d18 100644
--- a/test/rtp_decoder.c
+++ b/test/rtp_decoder.c
@@ -70,6 +70,7 @@
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] = "";
@@ -77,6 +78,7 @@
srtp_policy_t policy;
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());
@@ -96,10 +98,8 @@
}
switch (c) {
case 'b':
- fprintf(stderr, "Decoding\n");
- decode_sdes(optarg_s, input_key);
- fprintf(stderr, "Decoded\n");
- break;
+ b64_input = 1;
+ /* fall thru */
case 'k':
input_key = optarg_s;
break;
@@ -275,16 +275,26 @@
}
/*
- * read key from hexadecimal on command line into an octet string
+ * read key from hexadecimal or base64 on command line into an octet string
*/
- len = hex_string_to_octet_string(key, input_key, policy.rtp.cipher_key_len*2);
-
+ 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 < policy.rtp.cipher_key_len*2) {
+ if (len < expected_len) {
fprintf(stderr,
"error: too few digits in key/salt "
- "(should be %d hexadecimal digits, found %d)\n",
- policy.rtp.cipher_key_len*2, len);
+ "(should be %d digits, found %d)\n",
+ expected_len, len);
exit(1);
}
if (strlen(input_key) > policy.rtp.cipher_key_len*2) {
@@ -377,8 +387,8 @@
" -e <key size> use encryption (use 128 or 256 for key size)\n"
" -g Use AES-GCM mode (must be used with -e)\n"
" -t <tag size> Tag size to use in GCM mode (use 8 or 16)\n"
- " -k <key> sets the srtp master key\n"
- " -b <key> sets the srtp master key as base64\n"
+ " -k <key> sets the srtp master key given in hexadecimal\n"
+ " -b <key> sets the srtp master key given in base64\n"
" -l list debug modules\n"
" -d <debug> turn on debugging for module <debug>\n",
string, string);
@@ -386,42 +396,6 @@
}
-static const char b64chars[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-unsigned char shiftb64(unsigned char c) {
- char *p = strchr(b64chars, c);
- assert(p);
- return p-b64chars;
-}
-
-void decode_block(char *in, unsigned char *out) {
- unsigned char shifts[4];
- int i;
-
- for (i = 0; i < 4; i++) {
- shifts[i] = shiftb64(in[i]);
- }
-
- out[0] = (shifts[0]<<2)|(shifts[1]>>4);
- out[1] = (shifts[1]<<4)|(shifts[2]>>2);
- out[2] = (shifts[2]<<6)|shifts[3];
-}
-
-char *decode_sdes(char *in, char *out) {
- int i;
- size_t len = strlen((char *) in);
- assert(len == 40);
- unsigned char raw[30];
-
- for (i = 0; 4*i < len; i++) {
- decode_block(in+4*i, raw+3*i);
- }
-
- memcpy(out, octet_string_hex_string(raw, 30), 60);
- return out;
-}
-
rtp_decoder_t
rtp_decoder_alloc(void) {
return (rtp_decoder_t)malloc(sizeof(rtp_decoder_ctx_t));
diff --git a/test/rtp_decoder.h b/test/rtp_decoder.h
index 832443d..3a92d8a 100644
--- a/test/rtp_decoder.h
+++ b/test/rtp_decoder.h
@@ -51,6 +51,7 @@
#include "srtp_priv.h"
#include "rtp_priv.h"
#include "rtp.h"
+#include "datatypes.h"
#define DEFAULT_RTP_OFFSET 42
diff --git a/test/rtpw.c b/test/rtpw.c
index 48c6649..17f27f2 100644
--- a/test/rtpw.c
+++ b/test/rtpw.c
@@ -161,6 +161,7 @@
int tag_size = 8;
int gcm_on = 0;
char *input_key = NULL;
+ int b64_input = 0;
char *address = NULL;
char key[MAX_KEY_LEN];
unsigned short port = 0;
@@ -168,6 +169,7 @@
srtp_policy_t policy;
err_status_t status;
int len;
+ int expected_len;
int do_list_mods = 0;
uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */
#ifdef RTPW_USE_WINSOCK2
@@ -196,11 +198,14 @@
/* check args */
while (1) {
- c = getopt_s(argc, argv, "k:rsgt:ae:ld:");
+ c = getopt_s(argc, argv, "b:k:rsgt:ae:ld:");
if (c == -1) {
break;
}
switch (c) {
+ case 'b':
+ b64_input = 1;
+ /* fall thru */
case 'k':
input_key = optarg_s;
break;
@@ -443,16 +448,26 @@
}
/*
- * read key from hexadecimal on command line into an octet string
+ * read key from hexadecimal or base64 on command line into an octet string
*/
- len = hex_string_to_octet_string(key, input_key, policy.rtp.cipher_key_len*2);
-
+ 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 < policy.rtp.cipher_key_len*2) {
+ if (len < expected_len) {
fprintf(stderr,
"error: too few digits in key/salt "
- "(should be %d hexadecimal digits, found %d)\n",
- policy.rtp.cipher_key_len*2, len);
+ "(should be %d digits, found %d)\n",
+ expected_len, len);
exit(1);
}
if (strlen(input_key) > policy.rtp.cipher_key_len*2) {
@@ -630,7 +645,8 @@
" -e <key size> use encryption (use 128 or 256 for key size)\n"
" -g Use AES-GCM mode (must be used with -e)\n"
" -t <tag size> Tag size to use in GCM mode (use 8 or 16)\n"
- " -k <key> sets the srtp master key\n"
+ " -k <key> sets the srtp master key given in hexadecimal\n"
+ " -b <key> sets the srtp master key given in base64\n"
" -s act as rtp sender\n"
" -r act as rtp receiver\n"
" -l list debug modules\n"
diff --git a/test/rtpw_test.sh b/test/rtpw_test.sh
index c3c32ca..cd2aa6a 100755
--- a/test/rtpw_test.sh
+++ b/test/rtpw_test.sh
@@ -8,9 +8,9 @@
DEST_PORT=9999
DURATION=3
-key=2b2edc5034f61a72345ca5986d7bfd0189aa6dc2ecab32fd9af74df6dfc6
+key=Ky7cUDT2GnI0XKWYbXv9AYmqbcLsqzL9mvdN9t/G
-ARGS="-k $key -a -e 128"
+ARGS="-b $key -a -e 128"
# First, we run "killall" to get rid of all existing rtpw processes.
# This step also enables this script to clean up after itself; if this