diff options
Diffstat (limited to 'third_party/srtp/crypto')
60 files changed, 4097 insertions, 1605 deletions
diff --git a/third_party/srtp/crypto/Makefile b/third_party/srtp/crypto/Makefile deleted file mode 100644 index d7ac61fb..00000000 --- a/third_party/srtp/crypto/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -# Makefile for libcryptomodule.a -# -# David A. McGrew -# Cisco Systems, Inc. - -srcdir = . -top_srcdir = .. -top_builddir = ../ - - -CC = gcc -INCDIR = -Iinclude -I$(srcdir)/include -DEFS = -DHAVE_CONFIG_H -CPPFLAGS= -CFLAGS = -Wall -O4 -fexpensive-optimizations -funroll-loops -LIBS = -LDFLAGS = -L. -COMPILE = $(CC) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CFLAGS) -CRYPTOLIB = -lcryptomodule - -RANLIB = ranlib - -# EXE defines the suffix on executables - it's .exe for cygwin, and -# null on linux, bsd, and OS X and other OSes. we define this so that -# `make clean` will work on the cygwin platform -EXE = -# Random source. -RNG_OBJS = rand_source.o - -ifdef ARCH - DEFS += -D$(ARCH)=1 -endif - -ifdef sysname - DEFS += -D$(sysname)=1 -endif - -.PHONY: dummy all runtest clean superclean - -dummy : all runtest - -# test applications - -testapp = test/cipher_driver$(EXE) test/datatypes_driver$(EXE) \ - test/stat_driver$(EXE) test/sha1_driver$(EXE) \ - test/kernel_driver$(EXE) test/aes_calc$(EXE) test/rand_gen$(EXE) \ - test/env$(EXE) - -# data values used to test the aes_calc application - -k=000102030405060708090a0b0c0d0e0f -p=00112233445566778899aabbccddeeff -c=69c4e0d86a7b0430d8cdb78070b4c55a - -runtest: libcryptomodule.a $(testapp) - test/env$(EXE) # print out information on the build environment - @echo "running libcryptomodule test applications..." - test `test/aes_calc $k $p` = $c - test/cipher_driver$(EXE) -v >/dev/null - test/datatypes_driver$(EXE) -v >/dev/null - test/stat_driver$(EXE) >/dev/null - test/sha1_driver$(EXE) -v >/dev/null - test/kernel_driver$(EXE) -v >/dev/null - test/rand_gen$(EXE) -n 256 >/dev/null - @echo "libcryptomodule test applications passed." - -# libcryptomodule.a (the crypto engine) - -ciphers = cipher/cipher.o cipher/null_cipher.o \ - cipher/aes.o cipher/aes_icm.o \ - cipher/aes_cbc.o - -hashes = hash/null_auth.o hash/sha1.o \ - hash/hmac.o hash/auth.o - -math = math/datatypes.o math/stat.o - -rng = rng/$(RNG_OBJS) rng/rand_source.o rng/prng.o rng/ctr_prng.o - -err = kernel/err.o - -kernel = kernel/crypto_kernel.o kernel/alloc.o \ - kernel/key.o $(rng) $(err) - -xfm = ae_xfm/xfm.o - -cryptobj = $(ciphers) $(hashes) $(math) $(stat) $(kernel) $(xfm) - -# the rule for making object files and test apps - -%.o: %.c - $(COMPILE) -c $< -o $@ - -%$(EXE): %.c libcryptomodule.a - $(COMPILE) $(LDFLAGS) $< -o $@ $(CRYPTOLIB) $(LIBS) - -ifndef AR - AR=ar -endif - -# and the crypto module library itself - -libcryptomodule.a: $(cryptobj) - $(AR) cr libcryptomodule.a $(cryptobj) - $(RANLIB) libcryptomodule.a - -all: libcryptomodule.a $(testapp) - -# housekeeping functions - -clean: - rm -f libcryptomodule.a - rm -f $(testapp) *.o */*.o - for a in * .* */*; do if [ -f "$$a~" ] ; then rm $$a~; fi; done; - rm -f `find . -name "*.[ch]~*~"` - rm -rf latex - -superclean: clean - rm -f *core TAGS ktrace.out - - -# the target 'package' builds a compressed tar archive of the source code - -distname = crypto-$(shell cat VERSION) - -package: superclean - cd ..; tar cvzf $(distname).tgz crypto/ - - -# EOF diff --git a/third_party/srtp/crypto/Makefile.in b/third_party/srtp/crypto/Makefile.in index c14dba50..49384376 100644 --- a/third_party/srtp/crypto/Makefile.in +++ b/third_party/srtp/crypto/Makefile.in @@ -9,14 +9,14 @@ top_builddir = @top_builddir@ VPATH = @srcdir@ CC = @CC@ -INCDIR = -Iinclude -I$(srcdir)/include +INCDIR = -Iinclude -I$(srcdir)/include -I$(top_srcdir)/include DEFS = @DEFS@ CPPFLAGS= @CPPFLAGS@ CFLAGS = @CFLAGS@ LIBS = @LIBS@ -LDFLAGS = @LDFLAGS@ -L. +LDFLAGS = @LDFLAGS@ -L. -L.. COMPILE = $(CC) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CFLAGS) -CRYPTOLIB = -lcryptomodule +CRYPTOLIB = -lsrtp RANLIB = @RANLIB@ @@ -25,7 +25,7 @@ RANLIB = @RANLIB@ # `make clean` will work on the cygwin platform EXE = @EXE@ # Random source. -RNG_OBJS = @RNG_OBJS@ +USE_OPENSSL = @USE_OPENSSL@ ifdef ARCH DEFS += -D$(ARCH)=1 @@ -40,71 +40,52 @@ endif dummy : all runtest # test applications +ifneq (1, $(USE_OPENSSL)) +AES_CALC = test/aes_calc$(EXE) +endif testapp = test/cipher_driver$(EXE) test/datatypes_driver$(EXE) \ test/stat_driver$(EXE) test/sha1_driver$(EXE) \ - test/kernel_driver$(EXE) test/aes_calc$(EXE) test/rand_gen$(EXE) \ + test/kernel_driver$(EXE) $(AES_CALC) test/rand_gen$(EXE) \ test/env$(EXE) -# data values used to test the aes_calc application +# data values used to test the aes_calc application for AES-128 +k128=000102030405060708090a0b0c0d0e0f +p128=00112233445566778899aabbccddeeff +c128=69c4e0d86a7b0430d8cdb78070b4c55a + -k=000102030405060708090a0b0c0d0e0f -p=00112233445566778899aabbccddeeff -c=69c4e0d86a7b0430d8cdb78070b4c55a +# data values used to test the aes_calc application for AES-256 +k256=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +p256=00112233445566778899aabbccddeeff +c256=8ea2b7ca516745bfeafc49904b496089 -runtest: libcryptomodule.a $(testapp) + +runtest: $(testapp) test/env$(EXE) # print out information on the build environment - @echo "running libcryptomodule test applications..." - test `test/aes_calc $k $p` = $c + @echo "running crypto test applications..." +ifneq (1, $(USE_OPENSSL)) + test `test/aes_calc $(k128) $(p128)` = $(c128) + test `test/aes_calc $(k256) $(p256)` = $(c256) +endif test/cipher_driver$(EXE) -v >/dev/null test/datatypes_driver$(EXE) -v >/dev/null test/stat_driver$(EXE) >/dev/null test/sha1_driver$(EXE) -v >/dev/null test/kernel_driver$(EXE) -v >/dev/null test/rand_gen$(EXE) -n 256 >/dev/null - @echo "libcryptomodule test applications passed." - -# libcryptomodule.a (the crypto engine) - -ciphers = cipher/cipher.o cipher/null_cipher.o \ - cipher/aes.o cipher/aes_icm.o \ - cipher/aes_cbc.o - -hashes = hash/null_auth.o hash/sha1.o \ - hash/hmac.o hash/auth.o - -math = math/datatypes.o math/stat.o + @echo "crypto test applications passed." -rng = rng/$(RNG_OBJS) rng/rand_source.o rng/prng.o rng/ctr_prng.o - -err = kernel/err.o - -kernel = kernel/crypto_kernel.o kernel/alloc.o \ - kernel/key.o $(rng) $(err) - -xfm = ae_xfm/xfm.o - -cryptobj = $(ciphers) $(hashes) $(math) $(stat) $(kernel) $(xfm) # the rule for making object files and test apps %.o: %.c $(COMPILE) -c $< -o $@ -%$(EXE): %.c libcryptomodule.a - $(COMPILE) $(LDFLAGS) $< -o $@ $(CRYPTOLIB) $(LIBS) - -ifndef AR - AR=ar -endif - -# and the crypto module library itself - -libcryptomodule.a: $(cryptobj) - $(AR) cr libcryptomodule.a $(cryptobj) - $(RANLIB) libcryptomodule.a +%$(EXE): %.c ../test/getopt_s.c + $(COMPILE) $(LDFLAGS) $< ../test/getopt_s.c -o $@ $(CRYPTOLIB) $(LIBS) -all: libcryptomodule.a $(testapp) +all: $(testapp) # housekeeping functions diff --git a/third_party/srtp/crypto/ae_xfm/xfm.c b/third_party/srtp/crypto/ae_xfm/xfm.c deleted file mode 100644 index 0655aca4..00000000 --- a/third_party/srtp/crypto/ae_xfm/xfm.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * xfm.c - * - * Crypto transform implementation - * - * David A. McGrew - * Cisco Systems, Inc. - */ - -#include "cryptoalg.h" -#include "aes_cbc.h" -#include "hmac.h" -#include "crypto_kernel.h" /* for crypto_get_random() */ - -#define KEY_LEN 16 -#define ENC_KEY_LEN 16 -#define MAC_KEY_LEN 16 -#define IV_LEN 16 -#define TAG_LEN 12 -#define MAX_EXPAND 27 - -err_status_t -aes_128_cbc_hmac_sha1_96_func(void *key, - void *clear, - unsigned clear_len, - void *iv, - void *opaque, - unsigned *opaque_len, - void *auth_tag) { - aes_cbc_ctx_t aes_ctx; - hmac_ctx_t hmac_ctx; - unsigned char enc_key[ENC_KEY_LEN]; - unsigned char mac_key[MAC_KEY_LEN]; - err_status_t status; - - /* check if we're doing authentication only */ - if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { - - /* perform authentication only */ - - } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { - - /* - * bad parameter - we expect either all three pointers to be NULL, - * or none of those pointers to be NULL - */ - return err_status_fail; - - } else { - - /* derive encryption and authentication keys from the input key */ - status = hmac_init(&hmac_ctx, key, KEY_LEN); - if (status) return status; - status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key); - if (status) return status; - - status = hmac_init(&hmac_ctx, key, KEY_LEN); - if (status) return status; - status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key); - if (status) return status; - - - /* perform encryption and authentication */ - - /* set aes key */ - status = aes_cbc_context_init(&aes_ctx, key, direction_encrypt); - if (status) return status; - - /* set iv */ - status = crypto_get_random(iv, IV_LEN); - if (status) return status; - status = aes_cbc_set_iv(&aes_ctx, iv); - - /* encrypt the opaque data */ - status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len); - if (status) return status; - - /* authenticate clear and opaque data */ - status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN); - if (status) return status; - - status = hmac_start(&hmac_ctx); - if (status) return status; - - status = hmac_update(&hmac_ctx, clear, clear_len); - if (status) return status; - - status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag); - if (status) return status; - - } - - return err_status_ok; -} - -err_status_t -aes_128_cbc_hmac_sha1_96_inv(void *key, - void *clear, - unsigned clear_len, - void *iv, - void *opaque, - unsigned *opaque_len, - void *auth_tag) { - aes_cbc_ctx_t aes_ctx; - hmac_ctx_t hmac_ctx; - unsigned char enc_key[ENC_KEY_LEN]; - unsigned char mac_key[MAC_KEY_LEN]; - unsigned char tmp_tag[TAG_LEN]; - unsigned char *tag = auth_tag; - err_status_t status; - int i; - - /* check if we're doing authentication only */ - if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { - - /* perform authentication only */ - - } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { - - /* - * bad parameter - we expect either all three pointers to be NULL, - * or none of those pointers to be NULL - */ - return err_status_fail; - - } else { - - /* derive encryption and authentication keys from the input key */ - status = hmac_init(&hmac_ctx, key, KEY_LEN); - if (status) return status; - status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key); - if (status) return status; - - status = hmac_init(&hmac_ctx, key, KEY_LEN); - if (status) return status; - status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key); - if (status) return status; - - /* perform encryption and authentication */ - - /* set aes key */ - status = aes_cbc_context_init(&aes_ctx, key, direction_decrypt); - if (status) return status; - - /* set iv */ - status = rand_source_get_octet_string(iv, IV_LEN); - if (status) return status; - status = aes_cbc_set_iv(&aes_ctx, iv); - - /* encrypt the opaque data */ - status = aes_cbc_nist_decrypt(&aes_ctx, opaque, opaque_len); - if (status) return status; - - /* authenticate clear and opaque data */ - status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN); - if (status) return status; - - status = hmac_start(&hmac_ctx); - if (status) return status; - - status = hmac_update(&hmac_ctx, clear, clear_len); - if (status) return status; - - status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, tmp_tag); - if (status) return status; - - /* compare the computed tag with the one provided as input */ - for (i=0; i < TAG_LEN; i++) - if (tmp_tag[i] != tag[i]) - return err_status_auth_fail; - - } - - return err_status_ok; -} - - -#define ENC 1 -
-// eVC4 declares DEBUG
-#undef DEBUG
- -#define DEBUG 0 - -err_status_t -aes_128_cbc_hmac_sha1_96_enc(void *key, - const void *clear, - unsigned clear_len, - void *iv, - void *opaque, - unsigned *opaque_len) { - aes_cbc_ctx_t aes_ctx; - hmac_ctx_t hmac_ctx; - unsigned char enc_key[ENC_KEY_LEN]; - unsigned char mac_key[MAC_KEY_LEN]; - unsigned char *auth_tag; - err_status_t status; - - /* check if we're doing authentication only */ - if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { - - /* perform authentication only */ - - } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { - - /* - * bad parameter - we expect either all three pointers to be NULL, - * or none of those pointers to be NULL - */ - return err_status_fail; - - } else { - -#if DEBUG - printf("ENC using key %s\n", octet_string_hex_string(key, KEY_LEN)); -#endif - - /* derive encryption and authentication keys from the input key */ - status = hmac_init(&hmac_ctx, key, KEY_LEN); - if (status) return status; - status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key); - if (status) return status; - - status = hmac_init(&hmac_ctx, key, KEY_LEN); - if (status) return status; - status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key); - if (status) return status; - - - /* perform encryption and authentication */ - - /* set aes key */ - status = aes_cbc_context_init(&aes_ctx, key, direction_encrypt); - if (status) return status; - - /* set iv */ - status = rand_source_get_octet_string(iv, IV_LEN); - if (status) return status; - status = aes_cbc_set_iv(&aes_ctx, iv); - if (status) return status; - -#if DEBUG - printf("plaintext len: %d\n", *opaque_len); - printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN)); - printf("plaintext: %s\n", octet_string_hex_string(opaque, *opaque_len)); -#endif - -#if ENC - /* encrypt the opaque data */ - status = aes_cbc_nist_encrypt(&aes_ctx, opaque, opaque_len); - if (status) return status; -#endif - -#if DEBUG - printf("ciphertext len: %d\n", *opaque_len); - printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len)); -#endif - - /* - * authenticate clear and opaque data, then write the - * authentication tag to the location immediately following the - * ciphertext - */ - status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN); - if (status) return status; - - status = hmac_start(&hmac_ctx); - if (status) return status; - - status = hmac_update(&hmac_ctx, clear, clear_len); - if (status) return status; -#if DEBUG - printf("hmac input: %s\n", - octet_string_hex_string(clear, clear_len)); -#endif - auth_tag = (unsigned char *)opaque; - auth_tag += *opaque_len; - status = hmac_compute(&hmac_ctx, opaque, *opaque_len, TAG_LEN, auth_tag); - if (status) return status; -#if DEBUG - printf("hmac input: %s\n", - octet_string_hex_string(opaque, *opaque_len)); -#endif - /* bump up the opaque_len to reflect the authentication tag */ - *opaque_len += TAG_LEN; - -#if DEBUG - printf("prot data len: %d\n", *opaque_len); - printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len)); -#endif - } - - return err_status_ok; -} - -err_status_t -aes_128_cbc_hmac_sha1_96_dec(void *key, - const void *clear, - unsigned clear_len, - void *iv, - void *opaque, - unsigned *opaque_len) { - aes_cbc_ctx_t aes_ctx; - hmac_ctx_t hmac_ctx; - unsigned char enc_key[ENC_KEY_LEN]; - unsigned char mac_key[MAC_KEY_LEN]; - unsigned char tmp_tag[TAG_LEN]; - unsigned char *auth_tag; - unsigned ciphertext_len; - err_status_t status; - int i; - - /* check if we're doing authentication only */ - if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { - - /* perform authentication only */ - - } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { - - /* - * bad parameter - we expect either all three pointers to be NULL, - * or none of those pointers to be NULL - */ - return err_status_fail; - - } else { -#if DEBUG - printf("DEC using key %s\n", octet_string_hex_string(key, KEY_LEN)); -#endif - - /* derive encryption and authentication keys from the input key */ - status = hmac_init(&hmac_ctx, key, KEY_LEN); - if (status) return status; - status = hmac_compute(&hmac_ctx, "ENC", 3, ENC_KEY_LEN, enc_key); - if (status) return status; - - status = hmac_init(&hmac_ctx, key, KEY_LEN); - if (status) return status; - status = hmac_compute(&hmac_ctx, "MAC", 3, MAC_KEY_LEN, mac_key); - if (status) return status; - -#if DEBUG - printf("prot data len: %d\n", *opaque_len); - printf("prot data: %s\n", octet_string_hex_string(opaque, *opaque_len)); -#endif - - /* - * set the protected data length to that of the ciphertext, by - * subtracting out the length of the authentication tag - */ - ciphertext_len = *opaque_len - TAG_LEN; - -#if DEBUG - printf("ciphertext len: %d\n", ciphertext_len); -#endif - /* verify the authentication tag */ - - /* - * compute the authentication tag for the clear and opaque data, - * and write it to a temporary location - */ - status = hmac_init(&hmac_ctx, mac_key, MAC_KEY_LEN); - if (status) return status; - - status = hmac_start(&hmac_ctx); - if (status) return status; - - status = hmac_update(&hmac_ctx, clear, clear_len); - if (status) return status; - -#if DEBUG - printf("hmac input: %s\n", - octet_string_hex_string(clear, clear_len)); -#endif - - status = hmac_compute(&hmac_ctx, opaque, ciphertext_len, TAG_LEN, tmp_tag); - if (status) return status; - -#if DEBUG - printf("hmac input: %s\n", - octet_string_hex_string(opaque, ciphertext_len)); -#endif - - /* - * compare the computed tag with the one provided as input (which - * immediately follows the ciphertext) - */ - auth_tag = (unsigned char *)opaque; - auth_tag += ciphertext_len; -#if DEBUG - printf("auth_tag: %s\n", octet_string_hex_string(auth_tag, TAG_LEN)); - printf("tmp_tag: %s\n", octet_string_hex_string(tmp_tag, TAG_LEN)); -#endif - for (i=0; i < TAG_LEN; i++) { - if (tmp_tag[i] != auth_tag[i]) - return err_status_auth_fail; - } - - /* bump down the opaque_len to reflect the authentication tag */ - *opaque_len -= TAG_LEN; - - /* decrypt the confidential data */ - status = aes_cbc_context_init(&aes_ctx, key, direction_decrypt); - if (status) return status; - status = aes_cbc_set_iv(&aes_ctx, iv); - if (status) return status; - -#if DEBUG - printf("ciphertext: %s\n", octet_string_hex_string(opaque, *opaque_len)); - printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN)); -#endif - -#if ENC - status = aes_cbc_nist_decrypt(&aes_ctx, opaque, &ciphertext_len); - if (status) return status; -#endif - -#if DEBUG - printf("plaintext len: %d\n", ciphertext_len); - printf("plaintext: %s\n", - octet_string_hex_string(opaque, ciphertext_len)); -#endif - - /* indicate the length of the plaintext */ - *opaque_len = ciphertext_len; - } - - return err_status_ok; -} - -cryptoalg_ctx_t cryptoalg_ctx = { - aes_128_cbc_hmac_sha1_96_enc, - aes_128_cbc_hmac_sha1_96_dec, - KEY_LEN, - IV_LEN, - TAG_LEN, - MAX_EXPAND, -}; - -cryptoalg_t cryptoalg = &cryptoalg_ctx; - -#define NULL_TAG_LEN 12 - -err_status_t -null_enc(void *key, - const void *clear, - unsigned clear_len, - void *iv, - void *opaque, - unsigned *opaque_len) { - int i; - unsigned char *auth_tag; - unsigned char *init_vec = iv; - - /* check if we're doing authentication only */ - if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { - - /* perform authentication only */ - - } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { - - /* - * bad parameter - we expect either all three pointers to be NULL, - * or none of those pointers to be NULL - */ - return err_status_fail; - - } else { - -#if DEBUG - printf("NULL ENC using key %s\n", octet_string_hex_string(key, KEY_LEN)); - printf("NULL_TAG_LEN: %d\n", NULL_TAG_LEN); - printf("plaintext len: %d\n", *opaque_len); -#endif - for (i=0; i < IV_LEN; i++) - init_vec[i] = i + (i * 16); -#if DEBUG - printf("iv: %s\n", - octet_string_hex_string(iv, IV_LEN)); - printf("plaintext: %s\n", - octet_string_hex_string(opaque, *opaque_len)); -#endif - auth_tag = opaque; - auth_tag += *opaque_len; - for (i=0; i < NULL_TAG_LEN; i++) - auth_tag[i] = i + (i * 16); - *opaque_len += NULL_TAG_LEN; -#if DEBUG - printf("protected data len: %d\n", *opaque_len); - printf("protected data: %s\n", - octet_string_hex_string(opaque, *opaque_len)); -#endif - - } - - return err_status_ok; -} - -err_status_t -null_dec(void *key, - const void *clear, - unsigned clear_len, - void *iv, - void *opaque, - unsigned *opaque_len) { - unsigned char *auth_tag; - - /* check if we're doing authentication only */ - if ((iv == NULL) && (opaque == NULL) && (opaque_len == NULL)) { - - /* perform authentication only */ - - } else if ((iv == NULL) || (opaque == NULL) || (opaque_len == NULL)) { - - /* - * bad parameter - we expect either all three pointers to be NULL, - * or none of those pointers to be NULL - */ - return err_status_fail; - - } else { - -#if DEBUG - printf("NULL DEC using key %s\n", octet_string_hex_string(key, KEY_LEN)); - - printf("protected data len: %d\n", *opaque_len); - printf("protected data: %s\n", - octet_string_hex_string(opaque, *opaque_len)); -#endif - auth_tag = opaque; - auth_tag += (*opaque_len - NULL_TAG_LEN); -#if DEBUG - printf("iv: %s\n", octet_string_hex_string(iv, IV_LEN)); -#endif - *opaque_len -= NULL_TAG_LEN; -#if DEBUG - printf("plaintext len: %d\n", *opaque_len); - printf("plaintext: %s\n", - octet_string_hex_string(opaque, *opaque_len)); -#endif - } - - return err_status_ok; -} - -cryptoalg_ctx_t null_cryptoalg_ctx = { - null_enc, - null_dec, - KEY_LEN, - IV_LEN, - NULL_TAG_LEN, - MAX_EXPAND, -}; - -cryptoalg_t null_cryptoalg = &null_cryptoalg_ctx; - -int -cryptoalg_get_id(cryptoalg_t c) { - if (c == cryptoalg) - return 1; - return 0; -} - -cryptoalg_t -cryptoalg_find_by_id(int id) { - switch(id) { - case 1: - return cryptoalg; - default: - break; - } - return 0; -} diff --git a/third_party/srtp/crypto/cipher/aes.c b/third_party/srtp/crypto/cipher/aes.c index f1286c36..e91e5254 100644 --- a/third_party/srtp/crypto/cipher/aes.c +++ b/third_party/srtp/crypto/cipher/aes.c @@ -43,6 +43,9 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif #include "aes.h" #include "err.h" @@ -1358,51 +1361,50 @@ static uint32_t U4[256] = { extern debug_module_t mod_aes_icm; -void -aes_expand_encryption_key(const v128_t *key, - aes_expanded_key_t expanded_key) { +static void +aes_128_expand_encryption_key(const uint8_t *key, + aes_expanded_key_t *expanded_key) { int i; gf2_8 rc; /* initialize round constant */ rc = 1; - expanded_key[0].v32[0] = key->v32[0]; - expanded_key[0].v32[1] = key->v32[1]; - expanded_key[0].v32[2] = key->v32[2]; - expanded_key[0].v32[3] = key->v32[3]; + expanded_key->num_rounds = 10; + + v128_copy_octet_string(&expanded_key->round[0], key); #if 0 debug_print(mod_aes_icm, - "expanded key[0]: %s", v128_hex_string(&expanded_key[0])); + "expanded key[0]: %s", v128_hex_string(&expanded_key->round[0])); #endif /* loop over round keys */ for (i=1; i < 11; i++) { /* munge first word of round key */ - expanded_key[i].v8[0] = aes_sbox[expanded_key[i-1].v8[13]] ^ rc; - expanded_key[i].v8[1] = aes_sbox[expanded_key[i-1].v8[14]]; - expanded_key[i].v8[2] = aes_sbox[expanded_key[i-1].v8[15]]; - expanded_key[i].v8[3] = aes_sbox[expanded_key[i-1].v8[12]]; + expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[13]] ^ rc; + expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[14]]; + expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[15]]; + expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i-1].v8[12]]; - expanded_key[i].v32[0] ^= expanded_key[i-1].v32[0]; + expanded_key->round[i].v32[0] ^= expanded_key->round[i-1].v32[0]; /* set remaining 32 bit words to the exor of the one previous with * the one four words previous */ - expanded_key[i].v32[1] = - expanded_key[i].v32[0] ^ expanded_key[i-1].v32[1]; + expanded_key->round[i].v32[1] = + expanded_key->round[i].v32[0] ^ expanded_key->round[i-1].v32[1]; - expanded_key[i].v32[2] = - expanded_key[i].v32[1] ^ expanded_key[i-1].v32[2]; + expanded_key->round[i].v32[2] = + expanded_key->round[i].v32[1] ^ expanded_key->round[i-1].v32[2]; - expanded_key[i].v32[3] = - expanded_key[i].v32[2] ^ expanded_key[i-1].v32[3]; + expanded_key->round[i].v32[3] = + expanded_key->round[i].v32[2] ^ expanded_key->round[i-1].v32[3]; #if 0 debug_print2(mod_aes_icm, - "expanded key[%d]: %s", i,v128_hex_string(&expanded_key[i])); + "expanded key[%d]: %s", i,v128_hex_string(&expanded_key->round[i])); #endif /* modify round constant */ @@ -1411,19 +1413,107 @@ aes_expand_encryption_key(const v128_t *key, } } -void -aes_expand_decryption_key(const v128_t *key, - aes_expanded_key_t expanded_key) { +static void +aes_256_expand_encryption_key(const unsigned char *key, + aes_expanded_key_t *expanded_key) { + int i; + gf2_8 rc; + + /* initialize round constant */ + rc = 1; + + expanded_key->num_rounds = 14; + + v128_copy_octet_string(&expanded_key->round[0], key); + v128_copy_octet_string(&expanded_key->round[1], key+16); + +#if 0 + debug_print(mod_aes_icm, + "expanded key[0]: %s", v128_hex_string(&expanded_key->round[0])); + debug_print(mod_aes_icm, + "expanded key[1]: %s", v128_hex_string(&expanded_key->round[1])); +#endif + + /* loop over rest of round keys */ + for (i=2; i < 15; i++) { + + /* munge first word of round key */ + if ((i & 1) == 0) { + expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[13]] ^ rc; + expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[14]]; + expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[15]]; + expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i-1].v8[12]]; + + /* modify round constant */ + rc = gf2_8_shift(rc); + } + else { + expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i-1].v8[12]]; + expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i-1].v8[13]]; + expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i-1].v8[14]]; + expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i-1].v8[15]]; + } + + expanded_key->round[i].v32[0] ^= expanded_key->round[i-2].v32[0]; + + /* set remaining 32 bit words to the exor of the one previous with + * the one eight words previous */ + + expanded_key->round[i].v32[1] = + expanded_key->round[i].v32[0] ^ expanded_key->round[i-2].v32[1]; + + expanded_key->round[i].v32[2] = + expanded_key->round[i].v32[1] ^ expanded_key->round[i-2].v32[2]; + + expanded_key->round[i].v32[3] = + expanded_key->round[i].v32[2] ^ expanded_key->round[i-2].v32[3]; + +#if 0 + debug_print2(mod_aes_icm, + "expanded key[%d]: %s", i,v128_hex_string(&expanded_key->round[i])); +#endif + + } +} + +err_status_t +aes_expand_encryption_key(const uint8_t *key, + int key_len, + aes_expanded_key_t *expanded_key) { + if (key_len == 16) { + aes_128_expand_encryption_key(key, expanded_key); + return err_status_ok; + } + else if (key_len == 24) { + /* AES-192 not yet supported */ + return err_status_bad_param; + } + else if (key_len == 32) { + aes_256_expand_encryption_key(key, expanded_key); + return err_status_ok; + } + else + return err_status_bad_param; +} + +err_status_t +aes_expand_decryption_key(const uint8_t *key, + int key_len, + aes_expanded_key_t *expanded_key) { int i; + err_status_t status; + int num_rounds = expanded_key->num_rounds; - aes_expand_encryption_key(key, expanded_key); + status = aes_expand_encryption_key(key, key_len, expanded_key); + if (status) + return status; /* invert the order of the round keys */ - for (i=0; i < 5; i++) { + for (i=0; i < num_rounds/2; i++) { v128_t tmp; - v128_copy(&tmp, &expanded_key[10-i]); - v128_copy(&expanded_key[10-i], &expanded_key[i]); - v128_copy(&expanded_key[i], &tmp); + v128_copy(&tmp, &expanded_key->round[num_rounds-i]); + v128_copy(&expanded_key->round[num_rounds-i], &expanded_key->round[i]); + v128_copy(&expanded_key->round[i], &tmp); } /* @@ -1434,68 +1524,101 @@ aes_expand_decryption_key(const v128_t *key, * followed by the T4 table (which cancels out the use of the sbox * in the U-tables) */ - for (i=1; i < 10; i++) { + for (i=1; i < num_rounds; i++) { #ifdef CPU_RISC uint32_t tmp; - tmp = expanded_key[i].v32[0]; - expanded_key[i].v32[0] = +#ifdef WORDS_BIGENDIAN + tmp = expanded_key->round[i].v32[0]; + expanded_key->round[i].v32[0] = U0[T4[(tmp >> 24) ] & 0xff] ^ U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ U2[T4[(tmp >> 8) & 0xff] & 0xff] ^ U3[T4[(tmp) & 0xff] & 0xff]; - tmp = expanded_key[i].v32[1]; - expanded_key[i].v32[1] = + tmp = expanded_key->round[i].v32[1]; + expanded_key->round[i].v32[1] = U0[T4[(tmp >> 24) ] & 0xff] ^ U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ U2[T4[(tmp >> 8) & 0xff] & 0xff] ^ U3[T4[(tmp) & 0xff] & 0xff]; - tmp = expanded_key[i].v32[2]; - expanded_key[i].v32[2] = + tmp = expanded_key->round[i].v32[2]; + expanded_key->round[i].v32[2] = U0[T4[(tmp >> 24) ] & 0xff] ^ U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ U2[T4[(tmp >> 8) & 0xff] & 0xff] ^ U3[T4[(tmp) & 0xff] & 0xff]; - tmp = expanded_key[i].v32[3]; - expanded_key[i].v32[3] = + tmp = expanded_key->round[i].v32[3]; + expanded_key->round[i].v32[3] = U0[T4[(tmp >> 24) ] & 0xff] ^ U1[T4[(tmp >> 16) & 0xff] & 0xff] ^ U2[T4[(tmp >> 8) & 0xff] & 0xff] ^ U3[T4[(tmp) & 0xff] & 0xff]; +#else + tmp = expanded_key->round[i].v32[0]; + expanded_key->round[i].v32[0] = + U3[T4[(tmp >> 24) ] & 0xff] ^ + U2[T4[(tmp >> 16) & 0xff] & 0xff] ^ + U1[T4[(tmp >> 8) & 0xff] & 0xff] ^ + U0[T4[(tmp) & 0xff] & 0xff]; + + tmp = expanded_key->round[i].v32[1]; + expanded_key->round[i].v32[1] = + U3[T4[(tmp >> 24) ] & 0xff] ^ + U2[T4[(tmp >> 16) & 0xff] & 0xff] ^ + U1[T4[(tmp >> 8) & 0xff] & 0xff] ^ + U0[T4[(tmp) & 0xff] & 0xff]; + + tmp = expanded_key->round[i].v32[2]; + expanded_key->round[i].v32[2] = + U3[T4[(tmp >> 24) ] & 0xff] ^ + U2[T4[(tmp >> 16) & 0xff] & 0xff] ^ + U1[T4[(tmp >> 8) & 0xff] & 0xff] ^ + U0[T4[(tmp) & 0xff] & 0xff]; + + tmp = expanded_key->round[i].v32[3]; + expanded_key->round[i].v32[3] = + U3[T4[(tmp >> 24) ] & 0xff] ^ + U2[T4[(tmp >> 16) & 0xff] & 0xff] ^ + U1[T4[(tmp >> 8) & 0xff] & 0xff] ^ + U0[T4[(tmp) & 0xff] & 0xff]; +#endif /* WORDS_BIGENDIAN */ + #else /* assume CPU_CISC */ uint32_t c0, c1, c2, c3; - c0 = U0[aes_sbox[expanded_key[i].v8[0]]] - ^ U1[aes_sbox[expanded_key[i].v8[1]]] - ^ U2[aes_sbox[expanded_key[i].v8[2]]] - ^ U3[aes_sbox[expanded_key[i].v8[3]]]; + c0 = U0[aes_sbox[expanded_key->round[i].v8[0]]] + ^ U1[aes_sbox[expanded_key->round[i].v8[1]]] + ^ U2[aes_sbox[expanded_key->round[i].v8[2]]] + ^ U3[aes_sbox[expanded_key->round[i].v8[3]]]; - c1 = U0[aes_sbox[expanded_key[i].v8[4]]] - ^ U1[aes_sbox[expanded_key[i].v8[5]]] - ^ U2[aes_sbox[expanded_key[i].v8[6]]] - ^ U3[aes_sbox[expanded_key[i].v8[7]]]; + c1 = U0[aes_sbox[expanded_key->round[i].v8[4]]] + ^ U1[aes_sbox[expanded_key->round[i].v8[5]]] + ^ U2[aes_sbox[expanded_key->round[i].v8[6]]] + ^ U3[aes_sbox[expanded_key->round[i].v8[7]]]; - c2 = U0[aes_sbox[expanded_key[i].v8[8]]] - ^ U1[aes_sbox[expanded_key[i].v8[9]]] - ^ U2[aes_sbox[expanded_key[i].v8[10]]] - ^ U3[aes_sbox[expanded_key[i].v8[11]]]; + c2 = U0[aes_sbox[expanded_key->round[i].v8[8]]] + ^ U1[aes_sbox[expanded_key->round[i].v8[9]]] + ^ U2[aes_sbox[expanded_key->round[i].v8[10]]] + ^ U3[aes_sbox[expanded_key->round[i].v8[11]]]; - c3 = U0[aes_sbox[expanded_key[i].v8[12]]] - ^ U1[aes_sbox[expanded_key[i].v8[13]]] - ^ U2[aes_sbox[expanded_key[i].v8[14]]] - ^ U3[aes_sbox[expanded_key[i].v8[15]]]; + c3 = U0[aes_sbox[expanded_key->round[i].v8[12]]] + ^ U1[aes_sbox[expanded_key->round[i].v8[13]]] + ^ U2[aes_sbox[expanded_key->round[i].v8[14]]] + ^ U3[aes_sbox[expanded_key->round[i].v8[15]]]; - expanded_key[i].v32[0] = c0; - expanded_key[i].v32[1] = c1; - expanded_key[i].v32[2] = c2; - expanded_key[i].v32[3] = c3; + expanded_key->round[i].v32[0] = c0; + expanded_key->round[i].v32[1] = c1; + expanded_key->round[i].v32[2] = c2; + expanded_key->round[i].v32[3] = c3; #endif } + + return err_status_ok; } #ifdef CPU_CISC @@ -1676,7 +1799,6 @@ aes_inv_round(v128_t *state, const v128_t *round_key) { of state, using the tables U0, U1, U2, U3 */ #ifdef WORDS_BIGENDIAN - /* FIX! WRong indexes */ column0 = U0[state->v32[0] >> 24] ^ U1[(state->v32[3] >> 16) & 0xff] ^ U2[(state->v32[2] >> 8) & 0xff] ^ U3[state->v32[1] & 0xff]; @@ -1689,17 +1811,17 @@ aes_inv_round(v128_t *state, const v128_t *round_key) { column3 = U0[state->v32[3] >> 24] ^ U1[(state->v32[2] >> 16) & 0xff] ^ U2[(state->v32[1] >> 8) & 0xff] ^ U3[state->v32[0] & 0xff]; #else - column0 = U0[state->v32[0] & 0xff] ^ U1[(state->v32[1] >> 8) & 0xff] - ^ U2[(state->v32[2] >> 16) & 0xff] ^ U3[state->v32[3] >> 24]; + column0 = U0[state->v32[0] & 0xff] ^ U1[(state->v32[3] >> 8) & 0xff] + ^ U2[(state->v32[2] >> 16) & 0xff] ^ U3[(state->v32[1] >> 24) & 0xff]; - column1 = U0[state->v32[1] & 0xff] ^ U1[(state->v32[2] >> 8) & 0xff] - ^ U2[(state->v32[3] >> 16) & 0xff] ^ U3[state->v32[0] >> 24]; + column1 = U0[state->v32[1] & 0xff] ^ U1[(state->v32[0] >> 8) & 0xff] + ^ U2[(state->v32[3] >> 16) & 0xff] ^ U3[(state->v32[2] >> 24) & 0xff]; - column2 = U0[state->v32[2] & 0xff] ^ U1[(state->v32[3] >> 8) & 0xff] - ^ U2[(state->v32[0] >> 16) & 0xff] ^ U3[state->v32[1] >> 24]; + column2 = U0[state->v32[2] & 0xff] ^ U1[(state->v32[1] >> 8) & 0xff] + ^ U2[(state->v32[0] >> 16) & 0xff] ^ U3[(state->v32[3] >> 24) & 0xff]; - column3 = U0[state->v32[3] & 0xff] ^ U1[(state->v32[0] >> 8) & 0xff] - ^ U2[(state->v32[1] >> 16) & 0xff] ^ U3[state->v32[2] >> 24]; + column3 = U0[state->v32[3] & 0xff] ^ U1[(state->v32[2] >> 8) & 0xff] + ^ U2[(state->v32[1] >> 16) & 0xff] ^ U3[(state->v32[0] >> 24) & 0xff]; #endif /* WORDS_BIGENDIAN */ state->v32[0] = column0 ^ round_key->v32[0]; @@ -1713,6 +1835,7 @@ static inline void aes_final_round(v128_t *state, const v128_t *round_key) { uint32_t tmp0, tmp1, tmp2, tmp3; +#ifdef WORDS_BIGENDIAN tmp0 = (T4[(state->v32[0] >> 24)] & 0xff000000) ^ (T4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000) ^ (T4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) @@ -1736,6 +1859,31 @@ aes_final_round(v128_t *state, const v128_t *round_key) { ^ (T4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) ^ (T4[(state->v32[2] ) & 0xff] & 0x000000ff) ^ round_key->v32[3]; +#else + tmp0 = (T4[(state->v32[3] >> 24)] & 0xff000000) + ^ (T4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000) + ^ (T4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) + ^ (T4[(state->v32[0] ) & 0xff] & 0x000000ff) + ^ round_key->v32[0]; + + tmp1 = (T4[(state->v32[0] >> 24)] & 0xff000000) + ^ (T4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000) + ^ (T4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) + ^ (T4[(state->v32[1] ) & 0xff] & 0x000000ff) + ^ round_key->v32[1]; + + tmp2 = (T4[(state->v32[1] >> 24)] & 0xff000000) + ^ (T4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000) + ^ (T4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00) + ^ (T4[(state->v32[2] ) & 0xff] & 0x000000ff) + ^ round_key->v32[2]; + + tmp3 = (T4[(state->v32[2] >> 24)] & 0xff000000) + ^ (T4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000) + ^ (T4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00) + ^ (T4[(state->v32[3] ) & 0xff] & 0x000000ff) + ^ round_key->v32[3]; +#endif /* WORDS_BIGENDIAN */ state->v32[0] = tmp0; state->v32[1] = tmp1; @@ -1748,6 +1896,7 @@ static inline void aes_inv_final_round(v128_t *state, const v128_t *round_key) { uint32_t tmp0, tmp1, tmp2, tmp3; +#ifdef WORDS_BIGENDIAN tmp0 = (U4[(state->v32[0] >> 24)] & 0xff000000) ^ (U4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000) ^ (U4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) @@ -1771,6 +1920,31 @@ aes_inv_final_round(v128_t *state, const v128_t *round_key) { ^ (U4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) ^ (U4[(state->v32[0] ) & 0xff] & 0x000000ff) ^ round_key->v32[3]; +#else + tmp0 = (U4[(state->v32[1] >> 24)] & 0xff000000) + ^ (U4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000) + ^ (U4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00) + ^ (U4[(state->v32[0] ) & 0xff] & 0x000000ff) + ^ round_key->v32[0]; + + tmp1 = (U4[(state->v32[2] >> 24)] & 0xff000000) + ^ (U4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000) + ^ (U4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00) + ^ (U4[(state->v32[1] ) & 0xff] & 0x000000ff) + ^ round_key->v32[1]; + + tmp2 = (U4[(state->v32[3] >> 24)] & 0xff000000) + ^ (U4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000) + ^ (U4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) + ^ (U4[(state->v32[2] ) & 0xff] & 0x000000ff) + ^ round_key->v32[2]; + + tmp3 = (U4[(state->v32[0] >> 24)] & 0xff000000) + ^ (U4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000) + ^ (U4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) + ^ (U4[(state->v32[3] ) & 0xff] & 0x000000ff) + ^ round_key->v32[3]; +#endif /* WORDS_BIGENDIAN */ state->v32[0] = tmp0; state->v32[1] = tmp1; @@ -1910,42 +2084,67 @@ aes_inv_final_round(v128_t *state, const v128_t *round_key) { void -aes_encrypt(v128_t *plaintext, const aes_expanded_key_t exp_key) { +aes_encrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key) { /* add in the subkey */ - v128_xor_eq(plaintext, exp_key + 0); - - /* now do nine rounds */ - aes_round(plaintext, exp_key + 1); - aes_round(plaintext, exp_key + 2); - aes_round(plaintext, exp_key + 3); - aes_round(plaintext, exp_key + 4); - aes_round(plaintext, exp_key + 5); - aes_round(plaintext, exp_key + 6); - aes_round(plaintext, exp_key + 7); - aes_round(plaintext, exp_key + 8); - aes_round(plaintext, exp_key + 9); - /* the last round is different */ - - aes_final_round(plaintext, exp_key + 10); + v128_xor_eq(plaintext, &exp_key->round[0]); + + /* now do the rounds */ + aes_round(plaintext, &exp_key->round[1]); + aes_round(plaintext, &exp_key->round[2]); + aes_round(plaintext, &exp_key->round[3]); + aes_round(plaintext, &exp_key->round[4]); + aes_round(plaintext, &exp_key->round[5]); + aes_round(plaintext, &exp_key->round[6]); + aes_round(plaintext, &exp_key->round[7]); + aes_round(plaintext, &exp_key->round[8]); + aes_round(plaintext, &exp_key->round[9]); + if (exp_key->num_rounds == 10) { + aes_final_round(plaintext, &exp_key->round[10]); + } + else if (exp_key->num_rounds == 12) { + aes_round(plaintext, &exp_key->round[10]); + aes_round(plaintext, &exp_key->round[11]); + aes_final_round(plaintext, &exp_key->round[12]); + } + else if (exp_key->num_rounds == 14) { + aes_round(plaintext, &exp_key->round[10]); + aes_round(plaintext, &exp_key->round[11]); + aes_round(plaintext, &exp_key->round[12]); + aes_round(plaintext, &exp_key->round[13]); + aes_final_round(plaintext, &exp_key->round[14]); + } } void -aes_decrypt(v128_t *plaintext, const aes_expanded_key_t exp_key) { +aes_decrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key) { /* add in the subkey */ - v128_xor_eq(plaintext, exp_key + 0); - - /* now do nine rounds */ - aes_inv_round(plaintext, exp_key + 1); - aes_inv_round(plaintext, exp_key + 2); - aes_inv_round(plaintext, exp_key + 3); - aes_inv_round(plaintext, exp_key + 4); - aes_inv_round(plaintext, exp_key + 5); - aes_inv_round(plaintext, exp_key + 6); - aes_inv_round(plaintext, exp_key + 7); - aes_inv_round(plaintext, exp_key + 8); - aes_inv_round(plaintext, exp_key + 9); - /* the last round is different */ - aes_inv_final_round(plaintext, exp_key + 10); + v128_xor_eq(plaintext, &exp_key->round[0]); + + /* now do the rounds */ + aes_inv_round(plaintext, &exp_key->round[1]); + aes_inv_round(plaintext, &exp_key->round[2]); + aes_inv_round(plaintext, &exp_key->round[3]); + aes_inv_round(plaintext, &exp_key->round[4]); + aes_inv_round(plaintext, &exp_key->round[5]); + aes_inv_round(plaintext, &exp_key->round[6]); + aes_inv_round(plaintext, &exp_key->round[7]); + aes_inv_round(plaintext, &exp_key->round[8]); + aes_inv_round(plaintext, &exp_key->round[9]); + if (exp_key->num_rounds == 10) { + aes_inv_final_round(plaintext, &exp_key->round[10]); + } + else if (exp_key->num_rounds == 12) { + aes_inv_round(plaintext, &exp_key->round[10]); + aes_inv_round(plaintext, &exp_key->round[11]); + aes_inv_final_round(plaintext, &exp_key->round[12]); + } + else if (exp_key->num_rounds == 14) { + aes_inv_round(plaintext, &exp_key->round[10]); + aes_inv_round(plaintext, &exp_key->round[11]); + aes_inv_round(plaintext, &exp_key->round[12]); + aes_inv_round(plaintext, &exp_key->round[13]); + aes_inv_final_round(plaintext, &exp_key->round[14]); + } } diff --git a/third_party/srtp/crypto/cipher/aes_cbc.c b/third_party/srtp/crypto/cipher/aes_cbc.c index 8fc6a327..11953bf2 100644 --- a/third_party/srtp/crypto/cipher/aes_cbc.c +++ b/third_party/srtp/crypto/cipher/aes_cbc.c @@ -43,6 +43,9 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif #include "aes_cbc.h" #include "alloc.h" @@ -55,7 +58,7 @@ debug_module_t mod_aes_cbc = { err_status_t -aes_cbc_alloc(cipher_t **c, int key_len) { +aes_cbc_alloc(cipher_t **c, int key_len, int tlen) { extern cipher_type_t aes_cbc; uint8_t *pointer; int tmp; @@ -63,10 +66,10 @@ aes_cbc_alloc(cipher_t **c, int key_len) { debug_print(mod_aes_cbc, "allocating cipher with key length %d", key_len); - if (key_len != 16) + if (key_len != 16 && key_len != 24 && key_len != 32) return err_status_bad_param; - /* allocate memory a cipher of type aes_icm */ + /* allocate memory a cipher of type aes_cbc */ tmp = (sizeof(aes_cbc_ctx_t) + sizeof(cipher_t)); pointer = (uint8_t*)crypto_alloc(tmp); if (pointer == NULL) @@ -74,6 +77,7 @@ aes_cbc_alloc(cipher_t **c, int key_len) { /* set pointers */ *c = (cipher_t *)pointer; + (*c)->algorithm = AES_CBC; (*c)->type = &aes_cbc; (*c)->state = pointer + sizeof(cipher_t); @@ -104,35 +108,25 @@ aes_cbc_dealloc(cipher_t *c) { } err_status_t -aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, - cipher_direction_t dir) { - v128_t tmp_key; - - /* set tmp_key (for alignment) */ - v128_copy_octet_string(&tmp_key, key); +aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, int key_len) { debug_print(mod_aes_cbc, - "key: %s", v128_hex_string(&tmp_key)); - - /* expand key for the appropriate direction */ - switch (dir) { - case (direction_encrypt): - aes_expand_encryption_key(&tmp_key, c->expanded_key); - break; - case (direction_decrypt): - aes_expand_decryption_key(&tmp_key, c->expanded_key); - break; - default: - return err_status_bad_param; - } + "key: %s", octet_string_hex_string(key, key_len)); + /* + * Save the key until we have the IV later. We don't + * know the direction until the IV is set. + */ + c->key_len = (key_len <= 32 ? key_len : 32); + memcpy(c->key, key, c->key_len); return err_status_ok; } err_status_t -aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv) { +aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv, int direction) { + err_status_t status; int i; /* v128_t *input = iv; */ uint8_t *input = (uint8_t*) iv; @@ -143,6 +137,24 @@ aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv) { debug_print(mod_aes_cbc, "setting iv: %s", v128_hex_string(&c->state)); + /* expand key for the appropriate direction */ + switch (direction) { + case (direction_encrypt): + status = aes_expand_encryption_key(c->key, c->key_len, &c->expanded_key); + memset(c->key, 0, 32); + if (status) + return status; + break; + case (direction_decrypt): + status = aes_expand_decryption_key(c->key, c->key_len, &c->expanded_key); + memset(c->key, 0, 32); + if (status) + return status; + break; + default: + return err_status_bad_param; + } + return err_status_ok; } @@ -181,7 +193,7 @@ aes_cbc_encrypt(aes_cbc_ctx_t *c, debug_print(mod_aes_cbc, "inblock: %s", v128_hex_string(&c->state)); - aes_encrypt(&c->state, c->expanded_key); + aes_encrypt(&c->state, &c->expanded_key); debug_print(mod_aes_cbc, "outblock: %s", v128_hex_string(&c->state)); @@ -236,7 +248,7 @@ aes_cbc_decrypt(aes_cbc_ctx_t *c, v128_hex_string(&state)); /* decrypt state */ - aes_decrypt(&state, c->expanded_key); + aes_decrypt(&state, &c->expanded_key); debug_print(mod_aes_cbc, "outblock: %s", v128_hex_string(&state)); @@ -332,7 +344,7 @@ char aes_cbc_description[] = "aes cipher block chaining (cbc) mode"; /* - * Test case 0 is derived from FIPS 197 Appendix A; it uses an + * Test case 0 is derived from FIPS 197 Appendix C; it uses an * all-zero IV, so that the first block encryption matches the test * case in that appendix. This property provides a check of the base * AES encryption and decryption algorithms; if CBC fails on some @@ -374,6 +386,9 @@ cipher_test_case_t aes_cbc_test_case_0 = { aes_cbc_test_case_0_plaintext, /* plaintext */ 32, /* octets in ciphertext */ aes_cbc_test_case_0_ciphertext, /* ciphertext */ + 0, + NULL, + 0, NULL /* pointer to next testcase */ }; @@ -425,20 +440,126 @@ cipher_test_case_t aes_cbc_test_case_1 = { aes_cbc_test_case_1_plaintext, /* plaintext */ 80, /* octets in ciphertext */ aes_cbc_test_case_1_ciphertext, /* ciphertext */ + 0, + NULL, + 0, &aes_cbc_test_case_0 /* pointer to next testcase */ }; +/* + * Test case 2 is like test case 0, but for 256-bit keys. (FIPS 197 + * appendix C.3). + */ + + +uint8_t aes_cbc_test_case_2_key[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f +}; + +uint8_t aes_cbc_test_case_2_plaintext[64] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff +}; + +uint8_t aes_cbc_test_case_2_ciphertext[80] = { + 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89, + 0x72, 0x72, 0x6e, 0xe7, 0x71, 0x39, 0xbf, 0x11, + 0xe5, 0x40, 0xe2, 0x7c, 0x54, 0x65, 0x1d, 0xee +}; + +uint8_t aes_cbc_test_case_2_iv[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +cipher_test_case_t aes_cbc_test_case_2 = { + 32, /* octets in key */ + aes_cbc_test_case_2_key, /* key */ + aes_cbc_test_case_2_iv, /* initialization vector */ + 16, /* octets in plaintext */ + aes_cbc_test_case_2_plaintext, /* plaintext */ + 32, /* octets in ciphertext */ + aes_cbc_test_case_2_ciphertext, /* ciphertext */ + 0, + NULL, + 0, + &aes_cbc_test_case_1 /* pointer to next testcase */ +}; + + +/* + * this test case is taken directly from Appendix F.2 of NIST Special + * Publication SP 800-38A + */ + +uint8_t aes_cbc_test_case_3_key[32] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; + +uint8_t aes_cbc_test_case_3_plaintext[64] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 +}; + +uint8_t aes_cbc_test_case_3_ciphertext[80] = { + 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, + 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, + 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, + 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d, + 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, + 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61, + 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, + 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b, + 0xfb, 0x98, 0x20, 0x2c, 0x45, 0xb2, 0xe4, 0xa0, + 0x63, 0xc4, 0x68, 0xba, 0x84, 0x39, 0x16, 0x5a +}; + +uint8_t aes_cbc_test_case_3_iv[16] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; + +cipher_test_case_t aes_cbc_test_case_3 = { + 32, /* octets in key */ + aes_cbc_test_case_3_key, /* key */ + aes_cbc_test_case_3_iv, /* initialization vector */ + 64, /* octets in plaintext */ + aes_cbc_test_case_3_plaintext, /* plaintext */ + 80, /* octets in ciphertext */ + aes_cbc_test_case_3_ciphertext, /* ciphertext */ + 0, + NULL, + 0, + &aes_cbc_test_case_2 /* pointer to next testcase */ +}; + cipher_type_t aes_cbc = { (cipher_alloc_func_t) aes_cbc_alloc, (cipher_dealloc_func_t) aes_cbc_dealloc, (cipher_init_func_t) aes_cbc_context_init, + (cipher_set_aad_func_t) 0, (cipher_encrypt_func_t) aes_cbc_nist_encrypt, (cipher_decrypt_func_t) aes_cbc_nist_decrypt, (cipher_set_iv_func_t) aes_cbc_set_iv, + (cipher_get_tag_func_t) 0, (char *) aes_cbc_description, (int) 0, /* instance count */ - (cipher_test_case_t *) &aes_cbc_test_case_0, - (debug_module_t *) &mod_aes_cbc + (cipher_test_case_t *) &aes_cbc_test_case_3, + (debug_module_t *) &mod_aes_cbc, + (cipher_type_id_t) AES_CBC }; diff --git a/third_party/srtp/crypto/cipher/aes_gcm_ossl.c b/third_party/srtp/crypto/cipher/aes_gcm_ossl.c new file mode 100644 index 00000000..dce2a337 --- /dev/null +++ b/third_party/srtp/crypto/cipher/aes_gcm_ossl.c @@ -0,0 +1,570 @@ +/* + * aes_gcm_ossl.c + * + * AES Galois Counter Mode + * + * John A. Foley + * Cisco Systems, Inc. + * + */ + +/* + * + * Copyright (c) 2013, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include <openssl/evp.h> +#include "aes_icm_ossl.h" +#include "aes_gcm_ossl.h" +#include "alloc.h" +#include "crypto_types.h" + + +debug_module_t mod_aes_gcm = { + 0, /* debugging is off by default */ + "aes gcm" /* printable module name */ +}; + +/* + * The following are the global singleton instances for the + * 128-bit and 256-bit GCM ciphers. + */ +extern cipher_type_t aes_gcm_128_openssl; +extern cipher_type_t aes_gcm_256_openssl; + +/* + * For now we only support 8 and 16 octet tags. The spec allows for + * optional 12 byte tag, which may be supported in the future. + */ +#define GCM_AUTH_TAG_LEN 16 +#define GCM_AUTH_TAG_LEN_8 8 + + +/* + * This function allocates a new instance of this crypto engine. + * The key_len parameter should be one of 28 or 44 for + * AES-128-GCM or AES-256-GCM respectively. Note that the + * key length includes the 14 byte salt value that is used when + * initializing the KDF. + */ +err_status_t aes_gcm_openssl_alloc (cipher_t **c, int key_len, int tlen) +{ + aes_gcm_ctx_t *gcm; + int tmp; + uint8_t *allptr; + + debug_print(mod_aes_gcm, "allocating cipher with key length %d", key_len); + debug_print(mod_aes_gcm, "allocating cipher with tag length %d", tlen); + + /* + * Verify the key_len is valid for one of: AES-128/256 + */ + if (key_len != AES_128_GCM_KEYSIZE_WSALT && + key_len != AES_256_GCM_KEYSIZE_WSALT) { + return (err_status_bad_param); + } + + if (tlen != GCM_AUTH_TAG_LEN && + tlen != GCM_AUTH_TAG_LEN_8) { + return (err_status_bad_param); + } + + /* allocate memory a cipher of type aes_gcm */ + tmp = sizeof(cipher_t) + sizeof(aes_gcm_ctx_t); + allptr = crypto_alloc(tmp); + if (allptr == NULL) { + return (err_status_alloc_fail); + } + + /* set pointers */ + *c = (cipher_t*)allptr; + (*c)->state = allptr + sizeof(cipher_t); + gcm = (aes_gcm_ctx_t *)(*c)->state; + + /* increment ref_count */ + switch (key_len) { + case AES_128_GCM_KEYSIZE_WSALT: + (*c)->type = &aes_gcm_128_openssl; + (*c)->algorithm = AES_128_GCM; + aes_gcm_128_openssl.ref_count++; + ((aes_gcm_ctx_t*)(*c)->state)->key_size = AES_128_KEYSIZE; + ((aes_gcm_ctx_t*)(*c)->state)->tag_len = tlen; + break; + case AES_256_GCM_KEYSIZE_WSALT: + (*c)->type = &aes_gcm_256_openssl; + (*c)->algorithm = AES_256_GCM; + aes_gcm_256_openssl.ref_count++; + ((aes_gcm_ctx_t*)(*c)->state)->key_size = AES_256_KEYSIZE; + ((aes_gcm_ctx_t*)(*c)->state)->tag_len = tlen; + break; + } + + /* set key size */ + (*c)->key_len = key_len; + EVP_CIPHER_CTX_init(&gcm->ctx); + + return (err_status_ok); +} + + +/* + * This function deallocates a GCM session + */ +err_status_t aes_gcm_openssl_dealloc (cipher_t *c) +{ + aes_gcm_ctx_t *ctx; + + ctx = (aes_gcm_ctx_t*)c->state; + if (ctx) { + EVP_CIPHER_CTX_cleanup(&ctx->ctx); + /* decrement ref_count for the appropriate engine */ + switch (ctx->key_size) { + case AES_256_KEYSIZE: + aes_gcm_256_openssl.ref_count--; + break; + case AES_128_KEYSIZE: + aes_gcm_128_openssl.ref_count--; + break; + default: + return (err_status_dealloc_fail); + break; + } + } + + /* zeroize entire state*/ + octet_string_set_to_zero((uint8_t*)c, sizeof(cipher_t) + sizeof(aes_gcm_ctx_t)); + + /* free memory */ + crypto_free(c); + + return (err_status_ok); +} + +/* + * aes_gcm_openssl_context_init(...) initializes the aes_gcm_context + * using the value in key[]. + * + * the key is the secret key + */ +err_status_t aes_gcm_openssl_context_init (aes_gcm_ctx_t *c, const uint8_t *key) +{ + c->dir = direction_any; + + /* copy key to be used later when CiscoSSL crypto context is created */ + v128_copy_octet_string((v128_t*)&c->key, key); + + if (c->key_size == AES_256_KEYSIZE) { + debug_print(mod_aes_gcm, "Copying last 16 bytes of key: %s", + v128_hex_string((v128_t*)(key + AES_128_KEYSIZE))); + v128_copy_octet_string(((v128_t*)(&c->key.v8)) + 1, + key + AES_128_KEYSIZE); + } + + debug_print(mod_aes_gcm, "key: %s", v128_hex_string((v128_t*)&c->key)); + + EVP_CIPHER_CTX_cleanup(&c->ctx); + + return (err_status_ok); +} + + +/* + * aes_gcm_openssl_set_iv(c, iv) sets the counter value to the exor of iv with + * the offset + */ +err_status_t aes_gcm_openssl_set_iv (aes_gcm_ctx_t *c, void *iv, + int direction) +{ + const EVP_CIPHER *evp; + + if (direction != direction_encrypt && direction != direction_decrypt) { + return (err_status_bad_param); + } + c->dir = direction; + + debug_print(mod_aes_gcm, "setting iv: %s", v128_hex_string(iv)); + + switch (c->key_size) { + case AES_256_KEYSIZE: + evp = EVP_aes_256_gcm(); + break; + case AES_128_KEYSIZE: + evp = EVP_aes_128_gcm(); + break; + default: + return (err_status_bad_param); + break; + } + + if (!EVP_CipherInit_ex(&c->ctx, evp, NULL, (const unsigned char*)&c->key.v8, + NULL, (c->dir == direction_encrypt ? 1 : 0))) { + return (err_status_init_fail); + } + + /* set IV len and the IV value, the followiong 3 calls are required */ + if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) { + return (err_status_init_fail); + } + if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_IV_FIXED, -1, iv)) { + return (err_status_init_fail); + } + if (!EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_IV_GEN, 0, iv)) { + return (err_status_init_fail); + } + + return (err_status_ok); +} + +/* + * This function processes the AAD + * + * Parameters: + * c Crypto context + * aad Additional data to process for AEAD cipher suites + * aad_len length of aad buffer + */ +err_status_t aes_gcm_openssl_set_aad (aes_gcm_ctx_t *c, unsigned char *aad, + unsigned int aad_len) +{ + int rv; + + /* + * Set dummy tag, OpenSSL requires the Tag to be set before + * processing AAD + */ + EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len, aad); + + rv = EVP_Cipher(&c->ctx, NULL, aad, aad_len); + if (rv != aad_len) { + return (err_status_algo_fail); + } else { + return (err_status_ok); + } +} + +/* + * This function encrypts a buffer using AES GCM mode + * + * Parameters: + * c Crypto context + * buf data to encrypt + * enc_len length of encrypt buffer + */ +err_status_t aes_gcm_openssl_encrypt (aes_gcm_ctx_t *c, unsigned char *buf, + unsigned int *enc_len) +{ + if (c->dir != direction_encrypt && c->dir != direction_decrypt) { + return (err_status_bad_param); + } + + /* + * Encrypt the data + */ + EVP_Cipher(&c->ctx, buf, buf, *enc_len); + + return (err_status_ok); +} + +/* + * This function calculates and returns the GCM tag for a given context. + * This should be called after encrypting the data. The *len value + * is increased by the tag size. The caller must ensure that *buf has + * enough room to accept the appended tag. + * + * Parameters: + * c Crypto context + * buf data to encrypt + * len length of encrypt buffer + */ +err_status_t aes_gcm_openssl_get_tag (aes_gcm_ctx_t *c, unsigned char *buf, + int *len) +{ + /* + * Calculate the tag + */ + EVP_Cipher(&c->ctx, NULL, NULL, 0); + + /* + * Retreive the tag + */ + EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_GET_TAG, c->tag_len, buf); + + /* + * Increase encryption length by desired tag size + */ + *len = c->tag_len; + + return (err_status_ok); +} + + +/* + * This function decrypts a buffer using AES GCM mode + * + * Parameters: + * c Crypto context + * buf data to encrypt + * enc_len length of encrypt buffer + */ +err_status_t aes_gcm_openssl_decrypt (aes_gcm_ctx_t *c, unsigned char *buf, + unsigned int *enc_len) +{ + if (c->dir != direction_encrypt && c->dir != direction_decrypt) { + return (err_status_bad_param); + } + + /* + * Set the tag before decrypting + */ + EVP_CIPHER_CTX_ctrl(&c->ctx, EVP_CTRL_GCM_SET_TAG, c->tag_len, + buf + (*enc_len - c->tag_len)); + EVP_Cipher(&c->ctx, buf, buf, *enc_len - c->tag_len); + + /* + * Check the tag + */ + if (EVP_Cipher(&c->ctx, NULL, NULL, 0)) { + return (err_status_auth_fail); + } + + /* + * Reduce the buffer size by the tag length since the tag + * is not part of the original payload + */ + *enc_len -= c->tag_len; + + return (err_status_ok); +} + + + +/* + * Name of this crypto engine + */ +char aes_gcm_128_openssl_description[] = "AES-128 GCM using openssl"; +char aes_gcm_256_openssl_description[] = "AES-256 GCM using openssl"; + + +/* + * KAT values for AES self-test. These + * values we're derived from independent test code + * using OpenSSL. + */ +uint8_t aes_gcm_test_case_0_key[AES_128_GCM_KEYSIZE_WSALT] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, +}; + +uint8_t aes_gcm_test_case_0_iv[12] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 +}; + +uint8_t aes_gcm_test_case_0_plaintext[60] = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39 +}; + +uint8_t aes_gcm_test_case_0_aad[20] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 +}; + +uint8_t aes_gcm_test_case_0_ciphertext[76] = { + 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, + /* the last 16 bytes are the tag */ + 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47, +}; + +cipher_test_case_t aes_gcm_test_case_0a = { + AES_128_GCM_KEYSIZE_WSALT, /* octets in key */ + aes_gcm_test_case_0_key, /* key */ + aes_gcm_test_case_0_iv, /* packet index */ + 60, /* octets in plaintext */ + aes_gcm_test_case_0_plaintext, /* plaintext */ + 68, /* octets in ciphertext */ + aes_gcm_test_case_0_ciphertext, /* ciphertext + tag */ + 20, /* octets in AAD */ + aes_gcm_test_case_0_aad, /* AAD */ + GCM_AUTH_TAG_LEN_8, + NULL /* pointer to next testcase */ +}; + +cipher_test_case_t aes_gcm_test_case_0 = { + AES_128_GCM_KEYSIZE_WSALT, /* octets in key */ + aes_gcm_test_case_0_key, /* key */ + aes_gcm_test_case_0_iv, /* packet index */ + 60, /* octets in plaintext */ + aes_gcm_test_case_0_plaintext, /* plaintext */ + 76, /* octets in ciphertext */ + aes_gcm_test_case_0_ciphertext, /* ciphertext + tag */ + 20, /* octets in AAD */ + aes_gcm_test_case_0_aad, /* AAD */ + GCM_AUTH_TAG_LEN, + &aes_gcm_test_case_0a /* pointer to next testcase */ +}; + +uint8_t aes_gcm_test_case_1_key[AES_256_GCM_KEYSIZE_WSALT] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0xa5, 0x59, 0x09, 0xc5, 0x54, 0x66, 0x93, 0x1c, + 0xaf, 0xf5, 0x26, 0x9a, 0x21, 0xd5, 0x14, 0xb2, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, + +}; + +uint8_t aes_gcm_test_case_1_iv[12] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 +}; + +uint8_t aes_gcm_test_case_1_plaintext[60] = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39 +}; + +uint8_t aes_gcm_test_case_1_aad[20] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 +}; + +uint8_t aes_gcm_test_case_1_ciphertext[76] = { + 0x0b, 0x11, 0xcf, 0xaf, 0x68, 0x4d, 0xae, 0x46, + 0xc7, 0x90, 0xb8, 0x8e, 0xb7, 0x6a, 0x76, 0x2a, + 0x94, 0x82, 0xca, 0xab, 0x3e, 0x39, 0xd7, 0x86, + 0x1b, 0xc7, 0x93, 0xed, 0x75, 0x7f, 0x23, 0x5a, + 0xda, 0xfd, 0xd3, 0xe2, 0x0e, 0x80, 0x87, 0xa9, + 0x6d, 0xd7, 0xe2, 0x6a, 0x7d, 0x5f, 0xb4, 0x80, + 0xef, 0xef, 0xc5, 0x29, 0x12, 0xd1, 0xaa, 0x10, + 0x09, 0xc9, 0x86, 0xc1, + /* the last 16 bytes are the tag */ + 0x45, 0xbc, 0x03, 0xe6, 0xe1, 0xac, 0x0a, 0x9f, + 0x81, 0xcb, 0x8e, 0x5b, 0x46, 0x65, 0x63, 0x1d, +}; + +cipher_test_case_t aes_gcm_test_case_1a = { + AES_256_GCM_KEYSIZE_WSALT, /* octets in key */ + aes_gcm_test_case_1_key, /* key */ + aes_gcm_test_case_1_iv, /* packet index */ + 60, /* octets in plaintext */ + aes_gcm_test_case_1_plaintext, /* plaintext */ + 68, /* octets in ciphertext */ + aes_gcm_test_case_1_ciphertext, /* ciphertext + tag */ + 20, /* octets in AAD */ + aes_gcm_test_case_1_aad, /* AAD */ + GCM_AUTH_TAG_LEN_8, + NULL /* pointer to next testcase */ +}; + +cipher_test_case_t aes_gcm_test_case_1 = { + AES_256_GCM_KEYSIZE_WSALT, /* octets in key */ + aes_gcm_test_case_1_key, /* key */ + aes_gcm_test_case_1_iv, /* packet index */ + 60, /* octets in plaintext */ + aes_gcm_test_case_1_plaintext, /* plaintext */ + 76, /* octets in ciphertext */ + aes_gcm_test_case_1_ciphertext, /* ciphertext + tag */ + 20, /* octets in AAD */ + aes_gcm_test_case_1_aad, /* AAD */ + GCM_AUTH_TAG_LEN, + &aes_gcm_test_case_1a /* pointer to next testcase */ +}; + +/* + * This is the vector function table for this crypto engine. + */ +cipher_type_t aes_gcm_128_openssl = { + (cipher_alloc_func_t) aes_gcm_openssl_alloc, + (cipher_dealloc_func_t) aes_gcm_openssl_dealloc, + (cipher_init_func_t) aes_gcm_openssl_context_init, + (cipher_set_aad_func_t) aes_gcm_openssl_set_aad, + (cipher_encrypt_func_t) aes_gcm_openssl_encrypt, + (cipher_decrypt_func_t) aes_gcm_openssl_decrypt, + (cipher_set_iv_func_t) aes_gcm_openssl_set_iv, + (cipher_get_tag_func_t) aes_gcm_openssl_get_tag, + (char*) aes_gcm_128_openssl_description, + (int) 0, /* instance count */ + (cipher_test_case_t*) &aes_gcm_test_case_0, + (debug_module_t*) &mod_aes_gcm, + (cipher_type_id_t) AES_128_GCM +}; + +/* + * This is the vector function table for this crypto engine. + */ +cipher_type_t aes_gcm_256_openssl = { + (cipher_alloc_func_t) aes_gcm_openssl_alloc, + (cipher_dealloc_func_t) aes_gcm_openssl_dealloc, + (cipher_init_func_t) aes_gcm_openssl_context_init, + (cipher_set_aad_func_t) aes_gcm_openssl_set_aad, + (cipher_encrypt_func_t) aes_gcm_openssl_encrypt, + (cipher_decrypt_func_t) aes_gcm_openssl_decrypt, + (cipher_set_iv_func_t) aes_gcm_openssl_set_iv, + (cipher_get_tag_func_t) aes_gcm_openssl_get_tag, + (char*) aes_gcm_256_openssl_description, + (int) 0, /* instance count */ + (cipher_test_case_t*) &aes_gcm_test_case_1, + (debug_module_t*) &mod_aes_gcm, + (cipher_type_id_t) AES_256_GCM +}; + diff --git a/third_party/srtp/crypto/cipher/aes_icm.c b/third_party/srtp/crypto/cipher/aes_icm.c index e7e8c599..3d97e2ba 100644 --- a/third_party/srtp/crypto/cipher/aes_icm.c +++ b/third_party/srtp/crypto/cipher/aes_icm.c @@ -9,7 +9,7 @@ /* * - * Copyright (c) 2001-2006, Cisco Systems, Inc. + * Copyright (c) 2001-2006,2013 Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,6 +43,9 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif #define ALIGN_32 0 @@ -101,12 +104,13 @@ aes_icm_alloc_ismacryp(cipher_t **c, int key_len, int forIsmacryp) { /* * Ismacryp, for example, uses 16 byte key + 8 byte * salt so this function is called with key_len = 24. - * The check for key_len = 30 does not apply. Our usage + * The check for key_len = 30/38/46 does not apply. Our usage * of aes functions with key_len = values other than 30 * has not broken anything. Don't know what would be the * effect of skipping this check for srtp in general. */ - if (!forIsmacryp && key_len != 30) + if (!(forIsmacryp && key_len > 16 && key_len < 30) && + key_len != 30 && key_len != 38 && key_len != 46) return err_status_bad_param; /* allocate memory a cipher of type aes_icm */ @@ -117,6 +121,17 @@ aes_icm_alloc_ismacryp(cipher_t **c, int key_len, int forIsmacryp) { /* set pointers */ *c = (cipher_t *)pointer; + switch (key_len) { + case 46: + (*c)->algorithm = AES_256_ICM; + break; + case 38: + (*c)->algorithm = AES_192_ICM; + break; + default: + (*c)->algorithm = AES_128_ICM; + break; + } (*c)->type = &aes_icm; (*c)->state = pointer + sizeof(cipher_t); @@ -162,30 +177,44 @@ aes_icm_dealloc(cipher_t *c) { */ err_status_t -aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key) { - v128_t tmp_key; - - /* set counter and initial values to 'offset' value */ - /* FIX!!! this assumes the salt is at key + 16, and thus that the */ - /* FIX!!! cipher key length is 16! Also note this copies past the - end of the 'key' array by 2 bytes! */ - v128_copy_octet_string(&c->counter, key + 16); - v128_copy_octet_string(&c->offset, key + 16); - - /* force last two octets of the offset to zero (for srtp compatibility) */ - c->offset.v8[14] = c->offset.v8[15] = 0; - c->counter.v8[14] = c->counter.v8[15] = 0; - - /* set tmp_key (for alignment) */ - v128_copy_octet_string(&tmp_key, key); +aes_icm_context_init(aes_icm_ctx_t *c, const uint8_t *key, int key_len) { + err_status_t status; + int base_key_len, copy_len; + + if (key_len > 16 && key_len < 30) /* Ismacryp */ + base_key_len = 16; + else if (key_len == 30 || key_len == 38 || key_len == 46) + base_key_len = key_len - 14; + else + return err_status_bad_param; + + /* + * set counter and initial values to 'offset' value, being careful not to + * go past the end of the key buffer + */ + v128_set_to_zero(&c->counter); + v128_set_to_zero(&c->offset); + + copy_len = key_len - base_key_len; + /* force last two octets of the offset to be left zero (for srtp compatibility) */ + if (copy_len > 14) + copy_len = 14; + + memcpy(&c->counter, key + base_key_len, copy_len); + memcpy(&c->offset, key + base_key_len, copy_len); debug_print(mod_aes_icm, - "key: %s", v128_hex_string(&tmp_key)); + "key: %s", octet_string_hex_string(key, base_key_len)); debug_print(mod_aes_icm, "offset: %s", v128_hex_string(&c->offset)); /* expand key */ - aes_expand_encryption_key(&tmp_key, c->expanded_key); + status = aes_expand_encryption_key(key, base_key_len, &c->expanded_key); + if (status) { + v128_set_to_zero(&c->counter); + v128_set_to_zero(&c->offset); + return status; + } /* indicate that the keystream_buffer is empty */ c->bytes_in_buffer = 0; @@ -210,7 +239,7 @@ aes_icm_set_octet(aes_icm_ctx_t *c, ((high32(octet_num) & 0x0f)<<(32-4)) | (low32(octet_num) >> 4)); #else - int tail_num = octet_num % 16; + int tail_num = (int)(octet_num % 16); uint64_t block_num = octet_num / 16; #endif @@ -231,7 +260,7 @@ aes_icm_set_octet(aes_icm_ctx_t *c, /* fill keystream buffer, if needed */ if (tail_num) { v128_copy(&c->keystream_buffer, &c->counter); - aes_encrypt(&c->keystream_buffer, c->expanded_key); + aes_encrypt(&c->keystream_buffer, &c->expanded_key); c->bytes_in_buffer = sizeof(v128_t); debug_print(mod_aes_icm, "counter: %s", @@ -257,13 +286,16 @@ aes_icm_set_octet(aes_icm_ctx_t *c, */ err_status_t -aes_icm_set_iv(aes_icm_ctx_t *c, void *iv) { - v128_t *nonce = (v128_t *) iv; +aes_icm_set_iv(aes_icm_ctx_t *c, void *iv, int direction) { + v128_t nonce; + + /* set nonce (for alignment) */ + v128_copy_octet_string(&nonce, iv); debug_print(mod_aes_icm, - "setting iv: %s", v128_hex_string(nonce)); + "setting iv: %s", v128_hex_string(&nonce)); - v128_xor(&c->counter, &c->offset, nonce); + v128_xor(&c->counter, &c->offset, &nonce); debug_print(mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter)); @@ -287,7 +319,7 @@ static inline void aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) { /* fill buffer with new keystream */ v128_copy(&c->keystream_buffer, &c->counter); - aes_encrypt(&c->keystream_buffer, c->expanded_key); + aes_encrypt(&c->keystream_buffer, &c->expanded_key); c->bytes_in_buffer = sizeof(v128_t); debug_print(mod_aes_icm, "counter: %s", @@ -301,18 +333,14 @@ aes_icm_advance_ismacryp(aes_icm_ctx_t *c, uint8_t forIsmacryp) { uint32_t temp; //alex's clock counter forward temp = ntohl(c->counter.v32[3]); - c->counter.v32[3] = htonl(++temp); + ++temp; + c->counter.v32[3] = htonl(temp); } else { if (!++(c->counter.v8[15])) ++(c->counter.v8[14]); } } -inline void aes_icm_advance(aes_icm_ctx_t *c) { - aes_icm_advance_ismacryp(c, 0); -} - - /*e * icm_encrypt deals with the following cases: * @@ -440,7 +468,7 @@ aes_icm_encrypt(aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len) { } err_status_t -aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output) { +aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, unsigned int num_octets_to_output) { unsigned int len = num_octets_to_output; /* zeroize the buffer */ @@ -450,6 +478,10 @@ aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output) { return aes_icm_encrypt(c, buffer, &len); } +uint16_t +aes_icm_bytes_encrypted(aes_icm_ctx_t *c) { + return htons(c->counter.v16[7]); +} char aes_icm_description[] = "aes integer counter mode"; @@ -488,9 +520,55 @@ cipher_test_case_t aes_icm_test_case_0 = { aes_icm_test_case_0_plaintext, /* plaintext */ 32, /* octets in ciphertext */ aes_icm_test_case_0_ciphertext, /* ciphertext */ + 0, + NULL, + 0, NULL /* pointer to next testcase */ }; +uint8_t aes_icm_test_case_1_key[46] = { + 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70, + 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92, + 0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82, + 0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd +}; + +uint8_t aes_icm_test_case_1_nonce[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +uint8_t aes_icm_test_case_1_plaintext[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +uint8_t aes_icm_test_case_1_ciphertext[32] = { + 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25, + 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4, + 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6, + 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac +}; + +cipher_test_case_t aes_icm_test_case_1 = { + 46, /* octets in key */ + aes_icm_test_case_1_key, /* key */ + aes_icm_test_case_1_nonce, /* packet index */ + 32, /* octets in plaintext */ + aes_icm_test_case_1_plaintext, /* plaintext */ + 32, /* octets in ciphertext */ + aes_icm_test_case_1_ciphertext, /* ciphertext */ + 0, + NULL, + 0, + &aes_icm_test_case_0 /* pointer to next testcase */ +}; + + /* * note: the encrypt function is identical to the decrypt function @@ -500,12 +578,15 @@ cipher_type_t aes_icm = { (cipher_alloc_func_t) aes_icm_alloc, (cipher_dealloc_func_t) aes_icm_dealloc, (cipher_init_func_t) aes_icm_context_init, + (cipher_set_aad_func_t) 0, (cipher_encrypt_func_t) aes_icm_encrypt, (cipher_decrypt_func_t) aes_icm_encrypt, (cipher_set_iv_func_t) aes_icm_set_iv, + (cipher_get_tag_func_t) 0, (char *) aes_icm_description, (int) 0, /* instance count */ - (cipher_test_case_t *) &aes_icm_test_case_0, - (debug_module_t *) &mod_aes_icm + (cipher_test_case_t *) &aes_icm_test_case_1, + (debug_module_t *) &mod_aes_icm, + (cipher_type_id_t) AES_ICM }; diff --git a/third_party/srtp/crypto/cipher/aes_icm_ossl.c b/third_party/srtp/crypto/cipher/aes_icm_ossl.c new file mode 100644 index 00000000..eb585391 --- /dev/null +++ b/third_party/srtp/crypto/cipher/aes_icm_ossl.c @@ -0,0 +1,563 @@ +/* + * aes_icm_ossl.c + * + * AES Integer Counter Mode + * + * John A. Foley + * Cisco Systems, Inc. + * + * 2/24/2012: This module was modified to use CiscoSSL for AES counter + * mode. Eddy Lem contributed the code to allow this. + * + * 12/20/2012: Added support for AES-192 and AES-256. + */ + +/* + * + * Copyright (c) 2013, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include <openssl/evp.h> +#include "aes_icm_ossl.h" +#include "crypto_types.h" +#include "alloc.h" +#include "crypto_types.h" + + +debug_module_t mod_aes_icm = { + 0, /* debugging is off by default */ + "aes icm ossl" /* printable module name */ +}; +extern cipher_test_case_t aes_icm_test_case_0; +extern cipher_type_t aes_icm; +#ifndef SRTP_NO_AES192 +extern cipher_type_t aes_icm_192; +#endif +extern cipher_type_t aes_icm_256; + +/* + * integer counter mode works as follows: + * + * 16 bits + * <-----> + * +------+------+------+------+------+------+------+------+ + * | nonce | packet index | ctr |---+ + * +------+------+------+------+------+------+------+------+ | + * | + * +------+------+------+------+------+------+------+------+ v + * | salt |000000|->(+) + * +------+------+------+------+------+------+------+------+ | + * | + * +---------+ + * | encrypt | + * +---------+ + * | + * +------+------+------+------+------+------+------+------+ | + * | keystream block |<--+ + * +------+------+------+------+------+------+------+------+ + * + * All fields are big-endian + * + * ctr is the block counter, which increments from zero for + * each packet (16 bits wide) + * + * packet index is distinct for each packet (48 bits wide) + * + * nonce can be distinct across many uses of the same key, or + * can be a fixed value per key, or can be per-packet randomness + * (64 bits) + * + */ + +/* + * This function allocates a new instance of this crypto engine. + * The key_len parameter should be one of 30, 38, or 46 for + * AES-128, AES-192, and AES-256 respectively. Note, this key_len + * value is inflated, as it also accounts for the 112 bit salt + * value. The tlen argument is for the AEAD tag length, which + * isn't used in counter mode. + */ +err_status_t aes_icm_openssl_alloc (cipher_t **c, int key_len, int tlen) +{ + aes_icm_ctx_t *icm; + int tmp; + uint8_t *allptr; + + debug_print(mod_aes_icm, "allocating cipher with key length %d", key_len); + + /* + * Verify the key_len is valid for one of: AES-128/192/256 + */ + if (key_len != AES_128_KEYSIZE_WSALT && +#ifndef SRTP_NO_AES192 + key_len != AES_192_KEYSIZE_WSALT && +#endif + key_len != AES_256_KEYSIZE_WSALT) { + return err_status_bad_param; + } + + /* allocate memory a cipher of type aes_icm */ + tmp = sizeof(cipher_t) + sizeof(aes_icm_ctx_t); + allptr = (uint8_t*)crypto_alloc(tmp); + if (allptr == NULL) { + return err_status_alloc_fail; + } + + /* set pointers */ + *c = (cipher_t*)allptr; + (*c)->state = allptr + sizeof(cipher_t); + icm = (aes_icm_ctx_t*)(*c)->state; + + /* increment ref_count */ + switch (key_len) { + case AES_128_KEYSIZE_WSALT: + (*c)->algorithm = AES_128_ICM; + (*c)->type = &aes_icm; + aes_icm.ref_count++; + ((aes_icm_ctx_t*)(*c)->state)->key_size = AES_128_KEYSIZE; + break; +#ifndef SRTP_NO_AES192 + case AES_192_KEYSIZE_WSALT: + (*c)->algorithm = AES_192_ICM; + (*c)->type = &aes_icm_192; + aes_icm_192.ref_count++; + ((aes_icm_ctx_t*)(*c)->state)->key_size = AES_192_KEYSIZE; + break; +#endif + case AES_256_KEYSIZE_WSALT: + (*c)->algorithm = AES_256_ICM; + (*c)->type = &aes_icm_256; + aes_icm_256.ref_count++; + ((aes_icm_ctx_t*)(*c)->state)->key_size = AES_256_KEYSIZE; + break; + } + + /* set key size */ + (*c)->key_len = key_len; + EVP_CIPHER_CTX_init(&icm->ctx); + + return err_status_ok; +} + + +/* + * This function deallocates an instance of this engine + */ +err_status_t aes_icm_openssl_dealloc (cipher_t *c) +{ + aes_icm_ctx_t *ctx; + + if (c == NULL) { + return err_status_bad_param; + } + + /* + * Free the EVP context + */ + ctx = (aes_icm_ctx_t*)c->state; + if (ctx != NULL) { + EVP_CIPHER_CTX_cleanup(&ctx->ctx); + /* decrement ref_count for the appropriate engine */ + switch (ctx->key_size) { + case AES_256_KEYSIZE: + aes_icm_256.ref_count--; + break; +#ifndef SRTP_NO_AES192 + case AES_192_KEYSIZE: + aes_icm_192.ref_count--; + break; +#endif + case AES_128_KEYSIZE: + aes_icm.ref_count--; + break; + default: + return err_status_dealloc_fail; + break; + } + } + + /* zeroize entire state*/ + octet_string_set_to_zero((uint8_t*)c, + sizeof(cipher_t) + sizeof(aes_icm_ctx_t)); + + /* free memory */ + crypto_free(c); + + return err_status_ok; +} + +/* + * aes_icm_openssl_context_init(...) initializes the aes_icm_context + * using the value in key[]. + * + * the key is the secret key + * + * the salt is unpredictable (but not necessarily secret) data which + * randomizes the starting point in the keystream + */ +err_status_t aes_icm_openssl_context_init (aes_icm_ctx_t *c, const uint8_t *key, int len) +{ + /* + * set counter and initial values to 'offset' value, being careful not to + * go past the end of the key buffer + */ + + if (c->key_size + SALT_SIZE != len) + return err_status_bad_param; + + v128_set_to_zero(&c->counter); + v128_set_to_zero(&c->offset); + memcpy(&c->counter, key + c->key_size, SALT_SIZE); + memcpy(&c->offset, key + c->key_size, SALT_SIZE); + + /* force last two octets of the offset to zero (for srtp compatibility) */ + c->offset.v8[SALT_SIZE] = c->offset.v8[SALT_SIZE + 1] = 0; + c->counter.v8[SALT_SIZE] = c->counter.v8[SALT_SIZE + 1] = 0; + + /* copy key to be used later when CiscoSSL crypto context is created */ + v128_copy_octet_string((v128_t*)&c->key, key); + + /* if the key is greater than 16 bytes, copy the second + * half. Note, we treat AES-192 and AES-256 the same here + * for simplicity. The storage location receiving the + * key is statically allocated to handle a full 32 byte key + * regardless of the cipher in use. + */ + if (c->key_size == AES_256_KEYSIZE +#ifndef SRTP_NO_AES192 + || c->key_size == AES_192_KEYSIZE +#endif + ) { + debug_print(mod_aes_icm, "Copying last 16 bytes of key: %s", + v128_hex_string((v128_t*)(key + AES_128_KEYSIZE))); + v128_copy_octet_string(((v128_t*)(&c->key.v8)) + 1, key + AES_128_KEYSIZE); + } + + debug_print(mod_aes_icm, "key: %s", v128_hex_string((v128_t*)&c->key)); + debug_print(mod_aes_icm, "offset: %s", v128_hex_string(&c->offset)); + + EVP_CIPHER_CTX_cleanup(&c->ctx); + + return err_status_ok; +} + + +/* + * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with + * the offset + */ +err_status_t aes_icm_openssl_set_iv (aes_icm_ctx_t *c, void *iv, int dir) +{ + const EVP_CIPHER *evp; + v128_t nonce; + + /* set nonce (for alignment) */ + v128_copy_octet_string(&nonce, iv); + + debug_print(mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce)); + + v128_xor(&c->counter, &c->offset, &nonce); + + debug_print(mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter)); + + switch (c->key_size) { + case AES_256_KEYSIZE: + evp = EVP_aes_256_ctr(); + break; +#ifndef SRTP_NO_AES192 + case AES_192_KEYSIZE: + evp = EVP_aes_192_ctr(); + break; +#endif + case AES_128_KEYSIZE: + evp = EVP_aes_128_ctr(); + break; + default: + return err_status_bad_param; + break; + } + + if (!EVP_EncryptInit_ex(&c->ctx, evp, + NULL, c->key.v8, c->counter.v8)) { + return err_status_fail; + } else { + return err_status_ok; + } +} + +/* + * This function encrypts a buffer using AES CTR mode + * + * Parameters: + * c Crypto context + * buf data to encrypt + * enc_len length of encrypt buffer + */ +err_status_t aes_icm_openssl_encrypt (aes_icm_ctx_t *c, unsigned char *buf, unsigned int *enc_len) +{ + int len = 0; + + debug_print(mod_aes_icm, "rs0: %s", v128_hex_string(&c->counter)); + + if (!EVP_EncryptUpdate(&c->ctx, buf, &len, buf, *enc_len)) { + return err_status_cipher_fail; + } + *enc_len = len; + + if (!EVP_EncryptFinal_ex(&c->ctx, buf, &len)) { + return err_status_cipher_fail; + } + *enc_len += len; + + return err_status_ok; +} + +uint16_t aes_icm_bytes_encrypted(aes_icm_ctx_t *c) +{ + return htons(c->counter.v16[7]); +} + +/* + * Name of this crypto engine + */ +char aes_icm_openssl_description[] = "AES-128 counter mode using openssl"; +#ifndef SRTP_NO_AES192 +char aes_icm_192_openssl_description[] = "AES-192 counter mode using openssl"; +#endif +char aes_icm_256_openssl_description[] = "AES-256 counter mode using openssl"; + + +/* + * KAT values for AES self-test. These + * values came from the legacy libsrtp code. + */ +uint8_t aes_icm_test_case_0_key[AES_128_KEYSIZE_WSALT] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd +}; + +uint8_t aes_icm_test_case_0_nonce[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +uint8_t aes_icm_test_case_0_plaintext[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +uint8_t aes_icm_test_case_0_ciphertext[32] = { + 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80, + 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4, + 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7, + 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab +}; + +cipher_test_case_t aes_icm_test_case_0 = { + AES_128_KEYSIZE_WSALT, /* octets in key */ + aes_icm_test_case_0_key, /* key */ + aes_icm_test_case_0_nonce, /* packet index */ + 32, /* octets in plaintext */ + aes_icm_test_case_0_plaintext, /* plaintext */ + 32, /* octets in ciphertext */ + aes_icm_test_case_0_ciphertext, /* ciphertext */ + 0, + NULL, + 0, + NULL /* pointer to next testcase */ +}; + +#ifndef SRTP_NO_AES192 +/* + * KAT values for AES-192-CTR self-test. These + * values came from section 7 of RFC 6188. + */ +uint8_t aes_icm_192_test_case_1_key[AES_192_KEYSIZE_WSALT] = { + 0xea, 0xb2, 0x34, 0x76, 0x4e, 0x51, 0x7b, 0x2d, + 0x3d, 0x16, 0x0d, 0x58, 0x7d, 0x8c, 0x86, 0x21, + 0x97, 0x40, 0xf6, 0x5f, 0x99, 0xb6, 0xbc, 0xf7, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd +}; + +uint8_t aes_icm_192_test_case_1_nonce[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +uint8_t aes_icm_192_test_case_1_plaintext[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +uint8_t aes_icm_192_test_case_1_ciphertext[32] = { + 0x35, 0x09, 0x6c, 0xba, 0x46, 0x10, 0x02, 0x8d, + 0xc1, 0xb5, 0x75, 0x03, 0x80, 0x4c, 0xe3, 0x7c, + 0x5d, 0xe9, 0x86, 0x29, 0x1d, 0xcc, 0xe1, 0x61, + 0xd5, 0x16, 0x5e, 0xc4, 0x56, 0x8f, 0x5c, 0x9a +}; + +cipher_test_case_t aes_icm_192_test_case_1 = { + AES_192_KEYSIZE_WSALT, /* octets in key */ + aes_icm_192_test_case_1_key, /* key */ + aes_icm_192_test_case_1_nonce, /* packet index */ + 32, /* octets in plaintext */ + aes_icm_192_test_case_1_plaintext, /* plaintext */ + 32, /* octets in ciphertext */ + aes_icm_192_test_case_1_ciphertext, /* ciphertext */ + 0, + NULL, + 0, + NULL /* pointer to next testcase */ +}; +#endif + +/* + * KAT values for AES-256-CTR self-test. These + * values came from section 7 of RFC 6188. + */ +uint8_t aes_icm_256_test_case_2_key[AES_256_KEYSIZE_WSALT] = { + 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70, + 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92, + 0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82, + 0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd +}; + +uint8_t aes_icm_256_test_case_2_nonce[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +uint8_t aes_icm_256_test_case_2_plaintext[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +uint8_t aes_icm_256_test_case_2_ciphertext[32] = { + 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25, + 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4, + 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6, + 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac +}; + +cipher_test_case_t aes_icm_256_test_case_2 = { + AES_256_KEYSIZE_WSALT, /* octets in key */ + aes_icm_256_test_case_2_key, /* key */ + aes_icm_256_test_case_2_nonce, /* packet index */ + 32, /* octets in plaintext */ + aes_icm_256_test_case_2_plaintext, /* plaintext */ + 32, /* octets in ciphertext */ + aes_icm_256_test_case_2_ciphertext, /* ciphertext */ + 0, + NULL, + 0, + NULL /* pointer to next testcase */ +}; + +/* + * This is the function table for this crypto engine. + * note: the encrypt function is identical to the decrypt function + */ +cipher_type_t aes_icm = { + (cipher_alloc_func_t) aes_icm_openssl_alloc, + (cipher_dealloc_func_t) aes_icm_openssl_dealloc, + (cipher_init_func_t) aes_icm_openssl_context_init, + (cipher_set_aad_func_t) 0, + (cipher_encrypt_func_t) aes_icm_openssl_encrypt, + (cipher_decrypt_func_t) aes_icm_openssl_encrypt, + (cipher_set_iv_func_t) aes_icm_openssl_set_iv, + (cipher_get_tag_func_t) 0, + (char*) aes_icm_openssl_description, + (int) 0, /* instance count */ + (cipher_test_case_t*) &aes_icm_test_case_0, + (debug_module_t*) &mod_aes_icm, + (cipher_type_id_t) AES_ICM +}; + +#ifndef SRTP_NO_AES192 +/* + * This is the function table for this crypto engine. + * note: the encrypt function is identical to the decrypt function + */ +cipher_type_t aes_icm_192 = { + (cipher_alloc_func_t) aes_icm_openssl_alloc, + (cipher_dealloc_func_t) aes_icm_openssl_dealloc, + (cipher_init_func_t) aes_icm_openssl_context_init, + (cipher_set_aad_func_t) 0, + (cipher_encrypt_func_t) aes_icm_openssl_encrypt, + (cipher_decrypt_func_t) aes_icm_openssl_encrypt, + (cipher_set_iv_func_t) aes_icm_openssl_set_iv, + (cipher_get_tag_func_t) 0, + (char*) aes_icm_192_openssl_description, + (int) 0, /* instance count */ + (cipher_test_case_t*) &aes_icm_192_test_case_1, + (debug_module_t*) &mod_aes_icm, + (cipher_type_id_t) AES_192_ICM +}; +#endif + +/* + * This is the function table for this crypto engine. + * note: the encrypt function is identical to the decrypt function + */ +cipher_type_t aes_icm_256 = { + (cipher_alloc_func_t) aes_icm_openssl_alloc, + (cipher_dealloc_func_t) aes_icm_openssl_dealloc, + (cipher_init_func_t) aes_icm_openssl_context_init, + (cipher_set_aad_func_t) 0, + (cipher_encrypt_func_t) aes_icm_openssl_encrypt, + (cipher_decrypt_func_t) aes_icm_openssl_encrypt, + (cipher_set_iv_func_t) aes_icm_openssl_set_iv, + (cipher_get_tag_func_t) 0, + (char*) aes_icm_256_openssl_description, + (int) 0, /* instance count */ + (cipher_test_case_t*) &aes_icm_256_test_case_2, + (debug_module_t*) &mod_aes_icm, + (cipher_type_id_t) AES_256_ICM +}; + diff --git a/third_party/srtp/crypto/cipher/cipher.c b/third_party/srtp/crypto/cipher/cipher.c index 489a52d9..15b9088f 100644 --- a/third_party/srtp/crypto/cipher/cipher.c +++ b/third_party/srtp/crypto/cipher/cipher.c @@ -10,7 +10,7 @@ /* * - * Copyright (c) 2001-2006, Cisco Systems, Inc. + * Copyright (c) 2001-2006,2013 Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,12 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "cipher.h" +#include "crypto_types.h" #include "rand_source.h" /* used in invertibiltiy tests */ #include "alloc.h" /* for crypto_alloc(), crypto_free() */ @@ -71,8 +76,8 @@ cipher_get_key_length(const cipher_t *c) { } /* - * cipher_type_self_test(ct) tests a cipher of type ct against test cases - * provided in an array of values of key, salt, xtd_seq_num_t, + * cipher_type_test(ct, test_data) tests a cipher of type ct against + * test cases provided in a list test_data of values of key, salt, iv, * plaintext, and ciphertext that is known to be good */ @@ -81,12 +86,13 @@ cipher_get_key_length(const cipher_t *c) { #define MAX_KEY_LEN 64 err_status_t -cipher_type_self_test(const cipher_type_t *ct) { - const cipher_test_case_t *test_case = ct->test_data; +cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) { + const cipher_test_case_t *test_case = test_data; cipher_t *c; err_status_t status; uint8_t buffer[SELF_TEST_BUF_OCTETS]; uint8_t buffer2[SELF_TEST_BUF_OCTETS]; + int tag_len; unsigned int len; int i, j, case_num = 0; @@ -105,9 +111,8 @@ cipher_type_self_test(const cipher_type_t *ct) { * encryption and decryption functions */ while (test_case != NULL) { - /* allocate cipher */ - status = cipher_type_alloc(ct, &c, test_case->key_length_octets); + status = cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets); if (status) return status; @@ -117,7 +122,7 @@ cipher_type_self_test(const cipher_type_t *ct) { debug_print(mod_cipher, "testing encryption", NULL); /* initialize cipher */ - status = cipher_init(c, test_case->key, direction_encrypt); + status = cipher_init(c, test_case->key); if (status) { cipher_dealloc(c); return status; @@ -136,12 +141,30 @@ cipher_type_self_test(const cipher_type_t *ct) { test_case->plaintext_length_octets)); /* set the initialization vector */ - status = cipher_set_iv(c, test_case->idx); + status = cipher_set_iv(c, test_case->idx, direction_encrypt); if (status) { cipher_dealloc(c); return status; } + if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) { + debug_print(mod_cipher, "IV: %s", + octet_string_hex_string(test_case->idx, 12)); + + /* + * Set the AAD + */ + status = cipher_set_aad(c, test_case->aad, + test_case->aad_length_octets); + if (status) { + cipher_dealloc(c); + return status; + } + debug_print(mod_cipher, "AAD: %s", + octet_string_hex_string(test_case->aad, + test_case->aad_length_octets)); + } + /* encrypt */ len = test_case->plaintext_length_octets; status = cipher_encrypt(c, buffer, &len); @@ -150,6 +173,18 @@ cipher_type_self_test(const cipher_type_t *ct) { return status; } + if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) { + /* + * Get the GCM tag + */ + status = cipher_get_tag(c, buffer + len, &tag_len); + if (status) { + cipher_dealloc(c); + return status; + } + len += tag_len; + } + debug_print(mod_cipher, "ciphertext: %s", octet_string_hex_string(buffer, test_case->ciphertext_length_octets)); @@ -184,7 +219,7 @@ cipher_type_self_test(const cipher_type_t *ct) { debug_print(mod_cipher, "testing decryption", NULL); /* re-initialize cipher for decryption */ - status = cipher_init(c, test_case->key, direction_decrypt); + status = cipher_init(c, test_case->key); if (status) { cipher_dealloc(c); return status; @@ -203,12 +238,27 @@ cipher_type_self_test(const cipher_type_t *ct) { test_case->plaintext_length_octets)); /* set the initialization vector */ - status = cipher_set_iv(c, test_case->idx); + status = cipher_set_iv(c, test_case->idx, direction_decrypt); if (status) { cipher_dealloc(c); return status; } + if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) { + /* + * Set the AAD + */ + status = cipher_set_aad(c, test_case->aad, + test_case->aad_length_octets); + if (status) { + cipher_dealloc(c); + return status; + } + debug_print(mod_cipher, "AAD: %s", + octet_string_hex_string(test_case->aad, + test_case->aad_length_octets)); + } + /* decrypt */ len = test_case->ciphertext_length_octets; status = cipher_decrypt(c, buffer, &len); @@ -260,8 +310,8 @@ cipher_type_self_test(const cipher_type_t *ct) { /* now run some random invertibility tests */ /* allocate cipher, using paramaters from the first test case */ - test_case = ct->test_data; - status = cipher_type_alloc(ct, &c, test_case->key_length_octets); + test_case = test_data; + status = cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets); if (status) return status; @@ -269,7 +319,7 @@ cipher_type_self_test(const cipher_type_t *ct) { for (j=0; j < NUM_RAND_TESTS; j++) { unsigned length; - unsigned plaintext_len; + int plaintext_len; uint8_t key[MAX_KEY_LEN]; uint8_t iv[MAX_KEY_LEN]; @@ -297,19 +347,34 @@ cipher_type_self_test(const cipher_type_t *ct) { if (status) return status; /* initialize cipher */ - status = cipher_init(c, key, direction_encrypt); + status = cipher_init(c, key); if (status) { cipher_dealloc(c); return status; } /* set initialization vector */ - status = cipher_set_iv(c, test_case->idx); + status = cipher_set_iv(c, test_case->idx, direction_encrypt); if (status) { cipher_dealloc(c); return status; } + if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) { + /* + * Set the AAD + */ + status = cipher_set_aad(c, test_case->aad, + test_case->aad_length_octets); + if (status) { + cipher_dealloc(c); + return status; + } + debug_print(mod_cipher, "AAD: %s", + octet_string_hex_string(test_case->aad, + test_case->aad_length_octets)); + } + /* encrypt buffer with cipher */ plaintext_len = length; status = cipher_encrypt(c, buffer, &length); @@ -317,6 +382,17 @@ cipher_type_self_test(const cipher_type_t *ct) { cipher_dealloc(c); return status; } + if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) { + /* + * Get the GCM tag + */ + status = cipher_get_tag(c, buffer + length, &tag_len); + if (status) { + cipher_dealloc(c); + return status; + } + length += tag_len; + } debug_print(mod_cipher, "ciphertext: %s", octet_string_hex_string(buffer, length)); @@ -324,16 +400,30 @@ cipher_type_self_test(const cipher_type_t *ct) { * re-initialize cipher for decryption, re-set the iv, then * decrypt the ciphertext */ - status = cipher_init(c, key, direction_decrypt); + status = cipher_init(c, key); if (status) { cipher_dealloc(c); return status; } - status = cipher_set_iv(c, test_case->idx); + status = cipher_set_iv(c, test_case->idx, direction_decrypt); if (status) { cipher_dealloc(c); return status; } + if (c->algorithm == AES_128_GCM || c->algorithm == AES_256_GCM) { + /* + * Set the AAD + */ + status = cipher_set_aad(c, test_case->aad, + test_case->aad_length_octets); + if (status) { + cipher_dealloc(c); + return status; + } + debug_print(mod_cipher, "AAD: %s", + octet_string_hex_string(test_case->aad, + test_case->aad_length_octets)); + } status = cipher_decrypt(c, buffer, &length); if (status) { cipher_dealloc(c); @@ -344,8 +434,9 @@ cipher_type_self_test(const cipher_type_t *ct) { octet_string_hex_string(buffer, length)); /* compare the resulting plaintext with the original one */ - if (length != plaintext_len) + if (length != plaintext_len) { return err_status_algo_fail; + } status = err_status_ok; for (i=0; i < plaintext_len; i++) if (buffer[i] != buffer2[i]) { @@ -359,13 +450,25 @@ cipher_type_self_test(const cipher_type_t *ct) { } } -
- cipher_dealloc(c);
+ + status = cipher_dealloc(c); + if (status) + return status; return err_status_ok; } +/* + * cipher_type_self_test(ct) performs cipher_type_test on ct's internal + * list of test data. + */ + +err_status_t +cipher_type_self_test(const cipher_type_t *ct) { + return cipher_type_test(ct, ct->test_data); +} + /* * cipher_bits_per_second(c, l, t) computes (an estimate of) the * number of bits that a cipher implementation can encrypt in a second @@ -393,7 +496,7 @@ cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_trials) { v128_set_to_zero(&nonce); timer = clock(); for(i=0; i < num_trials; i++, nonce.v32[3] = i) { - cipher_set_iv(c, &nonce); + cipher_set_iv(c, &nonce, direction_encrypt); cipher_encrypt(c, enc_buf, &len); } timer = clock() - timer; diff --git a/third_party/srtp/crypto/cipher/null_cipher.c b/third_party/srtp/crypto/cipher/null_cipher.c index 721f50cf..3cd49fb9 100644 --- a/third_party/srtp/crypto/cipher/null_cipher.c +++ b/third_party/srtp/crypto/cipher/null_cipher.c @@ -10,7 +10,7 @@ /* * - * Copyright (c) 2001-2006, Cisco Systems, Inc. + * Copyright (c) 2001-2006,2013 Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,10 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "datatypes.h" #include "null_cipher.h" #include "alloc.h" @@ -53,7 +57,7 @@ extern debug_module_t mod_cipher; err_status_t -null_cipher_alloc(cipher_t **c, int key_len) { +null_cipher_alloc(cipher_t **c, int key_len, int tlen) { extern cipher_type_t null_cipher; uint8_t *pointer; @@ -67,6 +71,7 @@ null_cipher_alloc(cipher_t **c, int key_len) { /* set pointers */ *c = (cipher_t *)pointer; + (*c)->algorithm = NULL_CIPHER; (*c)->type = &null_cipher; (*c)->state = pointer + sizeof(cipher_t); @@ -99,7 +104,7 @@ null_cipher_dealloc(cipher_t *c) { } err_status_t -null_cipher_init(null_cipher_ctx_t *ctx, const uint8_t *key) { +null_cipher_init(null_cipher_ctx_t *ctx, const uint8_t *key, int key_len) { debug_print(mod_cipher, "initializing null cipher", NULL); @@ -129,6 +134,9 @@ null_cipher_test_0 = { NULL, /* plaintext */ 0, /* octets in plaintext */ NULL, /* ciphertext */ + 0, + NULL, + 0, NULL /* pointer to next testcase */ }; @@ -141,12 +149,15 @@ cipher_type_t null_cipher = { (cipher_alloc_func_t) null_cipher_alloc, (cipher_dealloc_func_t) null_cipher_dealloc, (cipher_init_func_t) null_cipher_init, + (cipher_set_aad_func_t) 0, (cipher_encrypt_func_t) null_cipher_encrypt, (cipher_decrypt_func_t) null_cipher_encrypt, (cipher_set_iv_func_t) null_cipher_set_iv, + (cipher_get_tag_func_t) 0, (char *) null_cipher_description, (int) 0, (cipher_test_case_t *) &null_cipher_test_0, - (debug_module_t *) NULL + (debug_module_t *) NULL, + (cipher_type_id_t) NULL_CIPHER }; diff --git a/third_party/srtp/crypto/hash/auth.c b/third_party/srtp/crypto/hash/auth.c index 8eb722d0..4ca0f03e 100644 --- a/third_party/srtp/crypto/hash/auth.c +++ b/third_party/srtp/crypto/hash/auth.c @@ -43,6 +43,10 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "auth.h" /* the debug module for authentiation */ @@ -74,8 +78,8 @@ auth_type_get_ref_count(const auth_type_t *at) { } /* - * auth_type_self_test() tests an auth function of type ct against - * test cases provided in an array of values of key, data, and tag + * auth_type_test() tests an auth function of type ct against + * test cases provided in a list test_data of values of key, data, and tag * that is known to be good */ @@ -83,8 +87,8 @@ auth_type_get_ref_count(const auth_type_t *at) { #define SELF_TEST_TAG_BUF_OCTETS 32 err_status_t -auth_type_self_test(const auth_type_t *at) { - auth_test_case_t *test_case = at->test_data; +auth_type_test(const auth_type_t *at, const auth_test_case_t *test_data) { + const auth_test_case_t *test_case = test_data; auth_t *a; err_status_t status; uint8_t tag[SELF_TEST_TAG_BUF_OCTETS]; @@ -171,3 +175,13 @@ auth_type_self_test(const auth_type_t *at) { } +/* + * auth_type_self_test(at) performs auth_type_test on at's internal + * list of test data. + */ + +err_status_t +auth_type_self_test(const auth_type_t *at) { + return auth_type_test(at, at->test_data); +} + diff --git a/third_party/srtp/crypto/hash/hmac.c b/third_party/srtp/crypto/hash/hmac.c index 4336cf0a..ddb75ea3 100644 --- a/third_party/srtp/crypto/hash/hmac.c +++ b/third_party/srtp/crypto/hash/hmac.c @@ -42,6 +42,10 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "hmac.h" #include "alloc.h" @@ -262,6 +266,7 @@ hmac = { (char *) hmac_description, (int) 0, /* instance count */ (auth_test_case_t *) &hmac_test_case_0, - (debug_module_t *) &mod_hmac + (debug_module_t *) &mod_hmac, + (auth_type_id_t) HMAC_SHA1 }; diff --git a/third_party/srtp/crypto/hash/hmac_ossl.c b/third_party/srtp/crypto/hash/hmac_ossl.c new file mode 100644 index 00000000..f62ce570 --- /dev/null +++ b/third_party/srtp/crypto/hash/hmac_ossl.c @@ -0,0 +1,302 @@ +/* + * hmac_ossl.c + * + * Implementation of hmac auth_type_t that leverages OpenSSL + * + * John A. Foley + * Cisco Systems, Inc. + */ +/* + * + * Copyright(c) 2013, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include "hmac.h" +#include "alloc.h" +#include <openssl/evp.h> + +#define HMAC_KEYLEN_MAX 20 + +/* the debug module for authentiation */ + +debug_module_t mod_hmac = { + 0, /* debugging is off by default */ + "hmac sha-1 openssl" /* printable name for module */ +}; + + +err_status_t +hmac_alloc (auth_t **a, int key_len, int out_len) +{ + extern auth_type_t hmac; + uint8_t *pointer; + hmac_ctx_t *new_hmac_ctx; + + debug_print(mod_hmac, "allocating auth func with key length %d", key_len); + debug_print(mod_hmac, " tag length %d", out_len); + + /* + * check key length - note that we don't support keys larger + * than 20 bytes yet + */ + if (key_len > HMAC_KEYLEN_MAX) { + return err_status_bad_param; + } + + /* check output length - should be less than 20 bytes */ + if (out_len > HMAC_KEYLEN_MAX) { + return err_status_bad_param; + } + + /* allocate memory for auth and hmac_ctx_t structures */ + pointer = (uint8_t*)crypto_alloc(sizeof(hmac_ctx_t) + sizeof(auth_t)); + if (pointer == NULL) { + return err_status_alloc_fail; + } + + /* set pointers */ + *a = (auth_t*)pointer; + (*a)->type = &hmac; + (*a)->state = pointer + sizeof(auth_t); + (*a)->out_len = out_len; + (*a)->key_len = key_len; + (*a)->prefix_len = 0; + new_hmac_ctx = (hmac_ctx_t*)((*a)->state); + memset(new_hmac_ctx, 0, sizeof(hmac_ctx_t)); + + /* increment global count of all hmac uses */ + hmac.ref_count++; + + return err_status_ok; +} + +err_status_t +hmac_dealloc (auth_t *a) +{ + extern auth_type_t hmac; + hmac_ctx_t *hmac_ctx; + + hmac_ctx = (hmac_ctx_t*)a->state; + if (hmac_ctx->ctx_initialized) { + EVP_MD_CTX_cleanup(&hmac_ctx->ctx); + } + if (hmac_ctx->init_ctx_initialized) { + EVP_MD_CTX_cleanup(&hmac_ctx->init_ctx); + } + + /* zeroize entire state*/ + octet_string_set_to_zero((uint8_t*)a, + sizeof(hmac_ctx_t) + sizeof(auth_t)); + + /* free memory */ + crypto_free(a); + + /* decrement global count of all hmac uses */ + hmac.ref_count--; + + return err_status_ok; +} + +err_status_t +hmac_init (hmac_ctx_t *state, const uint8_t *key, int key_len) +{ + int i; + uint8_t ipad[64]; + + /* + * check key length - note that we don't support keys larger + * than 20 bytes yet + */ + if (key_len > HMAC_KEYLEN_MAX) { + return err_status_bad_param; + } + + /* + * set values of ipad and opad by exoring the key into the + * appropriate constant values + */ + for (i = 0; i < key_len; i++) { + ipad[i] = key[i] ^ 0x36; + state->opad[i] = key[i] ^ 0x5c; + } + /* set the rest of ipad, opad to constant values */ + for (; i < sizeof(ipad); i++) { + ipad[i] = 0x36; + ((uint8_t*)state->opad)[i] = 0x5c; + } + + debug_print(mod_hmac, "ipad: %s", octet_string_hex_string(ipad, sizeof(ipad))); + + /* initialize sha1 context */ + sha1_init(&state->init_ctx); + state->init_ctx_initialized = 1; + + /* hash ipad ^ key */ + sha1_update(&state->init_ctx, ipad, sizeof(ipad)); + return (hmac_start(state)); +} + +err_status_t +hmac_start (hmac_ctx_t *state) +{ + if (state->ctx_initialized) { + EVP_MD_CTX_cleanup(&state->ctx); + } + if (!EVP_MD_CTX_copy(&state->ctx, &state->init_ctx)) { + return err_status_auth_fail; + } else { + state->ctx_initialized = 1; + return err_status_ok; + } +} + +err_status_t +hmac_update (hmac_ctx_t *state, const uint8_t *message, int msg_octets) +{ + debug_print(mod_hmac, "input: %s", + octet_string_hex_string(message, msg_octets)); + + /* hash message into sha1 context */ + sha1_update(&state->ctx, message, msg_octets); + + return err_status_ok; +} + +err_status_t +hmac_compute (hmac_ctx_t *state, const void *message, + int msg_octets, int tag_len, uint8_t *result) +{ + uint32_t hash_value[5]; + uint32_t H[5]; + int i; + + /* check tag length, return error if we can't provide the value expected */ + if (tag_len > HMAC_KEYLEN_MAX) { + return err_status_bad_param; + } + + /* hash message, copy output into H */ + sha1_update(&state->ctx, message, msg_octets); + sha1_final(&state->ctx, H); + + /* + * note that we don't need to debug_print() the input, since the + * function hmac_update() already did that for us + */ + debug_print(mod_hmac, "intermediate state: %s", + octet_string_hex_string((uint8_t*)H, sizeof(H))); + + /* re-initialize hash context */ + sha1_init(&state->ctx); + + /* hash opad ^ key */ + sha1_update(&state->ctx, (uint8_t*)state->opad, sizeof(state->opad)); + + /* hash the result of the inner hash */ + sha1_update(&state->ctx, (uint8_t*)H, sizeof(H)); + + /* the result is returned in the array hash_value[] */ + sha1_final(&state->ctx, hash_value); + + /* copy hash_value to *result */ + for (i = 0; i < tag_len; i++) { + result[i] = ((uint8_t*)hash_value)[i]; + } + + debug_print(mod_hmac, "output: %s", + octet_string_hex_string((uint8_t*)hash_value, tag_len)); + + return err_status_ok; +} + + +/* begin test case 0 */ + +uint8_t + hmac_test_case_0_key[HMAC_KEYLEN_MAX] = { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b +}; + +uint8_t + hmac_test_case_0_data[8] = { + 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 /* "Hi There" */ +}; + +uint8_t + hmac_test_case_0_tag[HMAC_KEYLEN_MAX] = { + 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, + 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, + 0xf1, 0x46, 0xbe, 0x00 +}; + +auth_test_case_t + hmac_test_case_0 = { + sizeof(hmac_test_case_0_key), /* octets in key */ + hmac_test_case_0_key, /* key */ + sizeof(hmac_test_case_0_data), /* octets in data */ + hmac_test_case_0_data, /* data */ + sizeof(hmac_test_case_0_tag), /* octets in tag */ + hmac_test_case_0_tag, /* tag */ + NULL /* pointer to next testcase */ +}; + +/* end test case 0 */ + +char hmac_description[] = "hmac sha-1 authentication function"; + +/* + * auth_type_t hmac is the hmac metaobject + */ + +auth_type_t + hmac = { + (auth_alloc_func) hmac_alloc, + (auth_dealloc_func) hmac_dealloc, + (auth_init_func) hmac_init, + (auth_compute_func) hmac_compute, + (auth_update_func) hmac_update, + (auth_start_func) hmac_start, + (char*) hmac_description, + (int) 0, /* instance count */ + (auth_test_case_t*) &hmac_test_case_0, + (debug_module_t*) &mod_hmac, + (auth_type_id_t) HMAC_SHA1 +}; + diff --git a/third_party/srtp/crypto/hash/null_auth.c b/third_party/srtp/crypto/hash/null_auth.c index 301348b6..73fd9187 100644 --- a/third_party/srtp/crypto/hash/null_auth.c +++ b/third_party/srtp/crypto/hash/null_auth.c @@ -44,6 +44,9 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif #include "null_auth.h" #include "alloc.h" @@ -155,6 +158,8 @@ null_auth = { (auth_start_func) null_auth_start, (char *) null_auth_description, (int) 0, /* instance count */ - (auth_test_case_t *) &null_auth_test_case_0 + (auth_test_case_t *) &null_auth_test_case_0, + (debug_module_t *) NULL, + (auth_type_id_t) NULL_AUTH }; diff --git a/third_party/srtp/crypto/hash/sha1.c b/third_party/srtp/crypto/hash/sha1.c index 566672de..c200437b 100644 --- a/third_party/srtp/crypto/hash/sha1.c +++ b/third_party/srtp/crypto/hash/sha1.c @@ -44,6 +44,9 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif #include "sha1.h" @@ -114,7 +117,7 @@ sha1_core(const uint32_t M[16], uint32_t hash_value[5]) { H4 = hash_value[4]; /* copy/xor message into array */ - + W[0] = be32_to_cpu(M[0]); W[1] = be32_to_cpu(M[1]); W[2] = be32_to_cpu(M[2]); @@ -184,7 +187,7 @@ sha1_core(const uint32_t M[16], uint32_t hash_value[5]) { void sha1_init(sha1_ctx_t *ctx) { - + /* initialize state vector */ ctx->H[0] = 0x67452301; ctx->H[1] = 0xefcdab89; @@ -210,7 +213,7 @@ sha1_update(sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_msg) { /* loop over 16-word blocks of M */ while (octets_in_msg > 0) { - + if (octets_in_msg + ctx->octets_in_buffer >= 64) { /* @@ -260,7 +263,7 @@ sha1_final(sha1_ctx_t *ctx, uint32_t *output) { */ { int tail = ctx->octets_in_buffer % 4; - + /* copy/xor message into array */ for (i=0; i < (ctx->octets_in_buffer+3)/4; i++) W[i] = be32_to_cpu(ctx->M[i]); @@ -283,7 +286,7 @@ sha1_final(sha1_ctx_t *ctx, uint32_t *output) { W[i] = 0x80000000; break; } - + /* zeroize remaining words */ for (i++ ; i < 15; i++) W[i] = 0x0; @@ -299,7 +302,8 @@ sha1_final(sha1_ctx_t *ctx, uint32_t *output) { else if (ctx->octets_in_buffer < 60) W[15] = 0x0; - /* process the word array */ for (t=16; t < 80; t++) { + /* process the word array */ + for (t=16; t < 80; t++) { TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]; W[t] = S1(TEMP); } diff --git a/third_party/srtp/crypto/include/aes.h b/third_party/srtp/crypto/include/aes.h index 20d28047..d88ce403 100644 --- a/third_party/srtp/crypto/include/aes.h +++ b/third_party/srtp/crypto/include/aes.h @@ -46,28 +46,32 @@ #ifndef _AES_H #define _AES_H -#include "srtp_config.h" - #include "datatypes.h" #include "gf2_8.h" +#include "err.h" /* aes internals */ -typedef v128_t aes_expanded_key_t[11]; +typedef struct { + v128_t round[15]; + int num_rounds; +} aes_expanded_key_t; -void -aes_expand_encryption_key(const v128_t *key, - aes_expanded_key_t expanded_key); +err_status_t +aes_expand_encryption_key(const uint8_t *key, + int key_len, + aes_expanded_key_t *expanded_key); -void -aes_expand_decryption_key(const v128_t *key, - aes_expanded_key_t expanded_key); +err_status_t +aes_expand_decryption_key(const uint8_t *key, + int key_len, + aes_expanded_key_t *expanded_key); void -aes_encrypt(v128_t *plaintext, const aes_expanded_key_t exp_key); +aes_encrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key); void -aes_decrypt(v128_t *plaintext, const aes_expanded_key_t exp_key); +aes_decrypt(v128_t *plaintext, const aes_expanded_key_t *exp_key); #if 0 /* diff --git a/third_party/srtp/crypto/include/aes_cbc.h b/third_party/srtp/crypto/include/aes_cbc.h index 9fb6682b..4fda3903 100644 --- a/third_party/srtp/crypto/include/aes_cbc.h +++ b/third_party/srtp/crypto/include/aes_cbc.h @@ -8,6 +8,42 @@ * */ +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + #ifndef AES_CBC_H #define AES_CBC_H @@ -17,6 +53,8 @@ typedef struct { v128_t state; /* cipher chaining state */ v128_t previous; /* previous ciphertext block */ + uint8_t key[32]; + int key_len; aes_expanded_key_t expanded_key; /* the cipher key */ } aes_cbc_ctx_t; @@ -31,10 +69,10 @@ aes_cbc_encrypt(aes_cbc_ctx_t *c, err_status_t aes_cbc_context_init(aes_cbc_ctx_t *c, const uint8_t *key, - cipher_direction_t dir); + int key_len); err_status_t -aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv); +aes_cbc_set_iv(aes_cbc_ctx_t *c, void *iv, int direction); err_status_t aes_cbc_nist_encrypt(aes_cbc_ctx_t *c, diff --git a/third_party/srtp/crypto/include/aes_gcm_ossl.h b/third_party/srtp/crypto/include/aes_gcm_ossl.h new file mode 100644 index 00000000..8e7711dc --- /dev/null +++ b/third_party/srtp/crypto/include/aes_gcm_ossl.h @@ -0,0 +1,63 @@ +/* + * aes_gcm_ossl.h + * + * Header for AES Galois Counter Mode. + * + * John A. Foley + * Cisco Systems, Inc. + * + */ +/* + * + * Copyright (c) 2013, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef AES_GCM_OSSL_H +#define AES_GCM_OSSL_H + +#include "cipher.h" +#include "srtp.h" +#include <openssl/evp.h> +#include <openssl/aes.h> + +typedef struct { + v256_t key; + int key_size; + int tag_len; + EVP_CIPHER_CTX ctx; + cipher_direction_t dir; +} aes_gcm_ctx_t; + +#endif /* AES_GCM_OSSL_H */ + diff --git a/third_party/srtp/crypto/include/aes_icm.h b/third_party/srtp/crypto/include/aes_icm.h index 17a1ddba..1a2fd82c 100644 --- a/third_party/srtp/crypto/include/aes_icm.h +++ b/third_party/srtp/crypto/include/aes_icm.h @@ -8,6 +8,42 @@ * */ +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + #ifndef AES_ICM_H #define AES_ICM_H @@ -25,10 +61,11 @@ typedef struct { err_status_t aes_icm_context_init(aes_icm_ctx_t *c, - const unsigned char *key); + const unsigned char *key, + int key_len); err_status_t -aes_icm_set_iv(aes_icm_ctx_t *c, void *iv); +aes_icm_set_iv(aes_icm_ctx_t *c, void *iv, int direction); err_status_t aes_icm_encrypt(aes_icm_ctx_t *c, @@ -36,7 +73,7 @@ aes_icm_encrypt(aes_icm_ctx_t *c, err_status_t aes_icm_output(aes_icm_ctx_t *c, - unsigned char *buf, int bytes_to_output); + unsigned char *buf, unsigned int bytes_to_output); err_status_t aes_icm_dealloc(cipher_t *c); @@ -52,5 +89,8 @@ aes_icm_alloc_ismacryp(cipher_t **c, int key_len, int forIsmacryp); +uint16_t +aes_icm_bytes_encrypted(aes_icm_ctx_t *c); + #endif /* AES_ICM_H */ diff --git a/third_party/srtp/crypto/include/aes_icm_ossl.h b/third_party/srtp/crypto/include/aes_icm_ossl.h new file mode 100644 index 00000000..b4ec40a4 --- /dev/null +++ b/third_party/srtp/crypto/include/aes_icm_ossl.h @@ -0,0 +1,85 @@ +/* + * aes_icm.h + * + * Header for AES Integer Counter Mode. + * + * David A. McGrew + * Cisco Systems, Inc. + * + */ +/* + * + * Copyright (c) 2001-2005,2012, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef AES_ICM_H +#define AES_ICM_H + +#include "cipher.h" +#include <openssl/evp.h> +#include <openssl/aes.h> + +#ifdef OPENSSL_IS_BORINGSSL +// BoringSSL doesn't support AES-192, cipher will be disabled +#define SRTP_NO_AES192 +#endif + +#define SALT_SIZE 14 +#define AES_128_KEYSIZE AES_BLOCK_SIZE +#ifndef SRTP_NO_AES192 +#define AES_192_KEYSIZE AES_BLOCK_SIZE + AES_BLOCK_SIZE / 2 +#endif +#define AES_256_KEYSIZE AES_BLOCK_SIZE * 2 +#define AES_128_KEYSIZE_WSALT AES_128_KEYSIZE + SALT_SIZE +#ifndef SRTP_NO_AES192 +#define AES_192_KEYSIZE_WSALT AES_192_KEYSIZE + SALT_SIZE +#endif +#define AES_256_KEYSIZE_WSALT AES_256_KEYSIZE + SALT_SIZE + +typedef struct { + v128_t counter; /* holds the counter value */ + v128_t offset; /* initial offset value */ + v256_t key; + int key_size; + EVP_CIPHER_CTX ctx; +} aes_icm_ctx_t; + +err_status_t aes_icm_openssl_set_iv(aes_icm_ctx_t *c, void *iv, int dir); +err_status_t aes_icm_openssl_context_init(aes_icm_ctx_t *c, const uint8_t *key, int len); +err_status_t aes_icm_output(aes_icm_ctx_t *c, uint8_t *buffer, int num_octets_to_output); +uint16_t aes_icm_bytes_encrypted(aes_icm_ctx_t *c); + + +#endif /* AES_ICM_H */ + diff --git a/third_party/srtp/crypto/include/auth.h b/third_party/srtp/crypto/include/auth.h index 295b5f6f..5b5e4b21 100644 --- a/third_party/srtp/crypto/include/auth.h +++ b/third_party/srtp/crypto/include/auth.h @@ -48,6 +48,8 @@ #include "datatypes.h" #include "err.h" /* error codes */ +#include "crypto.h" /* for auth_type_id_t */ +#include "crypto_types.h" /* for values of auth_type_id_t */ typedef struct auth_type_t *auth_type_pointer; typedef struct auth_t *auth_pointer_t; @@ -129,6 +131,7 @@ typedef struct auth_type_t { int ref_count; auth_test_case_t *test_data; debug_module_t *debug; + auth_type_id_t id; } auth_type_t; typedef struct auth_t { @@ -148,6 +151,15 @@ typedef struct auth_t { err_status_t auth_type_self_test(const auth_type_t *at); +/* + * auth_type_test() tests an auth_type against external test cases + * provided in an array of values of key/message/tag that is known to + * be good + */ + +err_status_t +auth_type_test(const auth_type_t *at, const auth_test_case_t *test_data); + /* * auth_type_get_ref_count(at) returns the reference count (the number * of instantiations) of the auth_type_t at diff --git a/third_party/srtp/crypto/include/cipher.h b/third_party/srtp/crypto/include/cipher.h index f485660c..d0d6b57f 100644 --- a/third_party/srtp/crypto/include/cipher.h +++ b/third_party/srtp/crypto/include/cipher.h @@ -8,7 +8,7 @@ */ /* * - * Copyright (c) 2001-2006, Cisco Systems, Inc. + * Copyright (c) 2001-2006,2013 Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,6 +49,8 @@ #include "datatypes.h" #include "rdbx.h" /* for xtd_seq_num_t */ #include "err.h" /* for error codes */ +#include "crypto.h" /* for cipher_type_id_t */ +#include "crypto_types.h" /* for values of cipher_type_id_t */ /** @@ -78,15 +80,14 @@ typedef struct cipher_t *cipher_pointer_t; */ typedef err_status_t (*cipher_alloc_func_t) - (cipher_pointer_t *cp, int key_len); + (cipher_pointer_t *cp, int key_len, int tag_len); /* * a cipher_init_func_t [re-]initializes a cipher_t with a given key - * and direction (i.e., encrypt or decrypt) */ typedef err_status_t (*cipher_init_func_t) - (void *state, const uint8_t *key, cipher_direction_t dir); +(void *state, const uint8_t *key, int key_len); /* a cipher_dealloc_func_t de-allocates a cipher_t */ @@ -97,6 +98,13 @@ typedef err_status_t (*cipher_dealloc_func_t)(cipher_pointer_t cp); typedef err_status_t (*cipher_set_segment_func_t) (void *state, xtd_seq_num_t idx); +/* + * a cipher_set_aad_func_t processes the AAD data for AEAD ciphers + */ +typedef err_status_t (*cipher_set_aad_func_t) + (void *state, uint8_t *aad, unsigned int aad_len); + + /* a cipher_encrypt_func_t encrypts data in-place */ typedef err_status_t (*cipher_encrypt_func_t) @@ -108,12 +116,19 @@ typedef err_status_t (*cipher_decrypt_func_t) (void *state, uint8_t *buffer, unsigned int *octets_to_decrypt); /* - * a cipher_set_nonce_seq_func_t function sets both the nonce - * and the extended sequence number + * a cipher_set_iv_func_t function sets the current initialization vector */ typedef err_status_t (*cipher_set_iv_func_t) - (cipher_pointer_t cp, void *iv); + (cipher_pointer_t cp, void *iv, cipher_direction_t direction); + +/* + * a cipher_get_tag_funct_t function is used to get the authentication + * tag that was calculated by an AEAD cipher. + */ +typedef err_status_t (*cipher_get_tag_func_t) + (void *state, void *tag, int *len); + /* * cipher_test_case_t is a (list of) key, salt, xtd_seq_num_t, @@ -127,10 +142,13 @@ typedef struct cipher_test_case_t { int key_length_octets; /* octets in key */ uint8_t *key; /* key */ uint8_t *idx; /* packet index */ - unsigned int plaintext_length_octets; /* octets in plaintext */ + int plaintext_length_octets; /* octets in plaintext */ uint8_t *plaintext; /* plaintext */ - unsigned int ciphertext_length_octets; /* octets in plaintext */ + int ciphertext_length_octets; /* octets in plaintext */ uint8_t *ciphertext; /* ciphertext */ + int aad_length_octets; /* octets in AAD */ + uint8_t *aad; /* AAD */ + int tag_length_octets; /* Length of AEAD tag */ struct cipher_test_case_t *next_test_case; /* pointer to next testcase */ } cipher_test_case_t; @@ -140,13 +158,16 @@ typedef struct cipher_type_t { cipher_alloc_func_t alloc; cipher_dealloc_func_t dealloc; cipher_init_func_t init; + cipher_set_aad_func_t set_aad; cipher_encrypt_func_t encrypt; cipher_encrypt_func_t decrypt; cipher_set_iv_func_t set_iv; + cipher_get_tag_func_t get_tag; char *description; int ref_count; cipher_test_case_t *test_data; debug_module_t *debug; + cipher_type_id_t id; } cipher_type_t; /* @@ -158,27 +179,32 @@ typedef struct cipher_t { cipher_type_t *type; void *state; int key_len; -#ifdef FORCE_64BIT_ALIGN - int pad; -#endif + int algorithm; } cipher_t; /* some syntactic sugar on these function types */ -#define cipher_type_alloc(ct, c, klen) ((ct)->alloc((c), (klen))) +#define cipher_type_alloc(ct, c, klen, tlen) ((ct)->alloc((c), (klen), (tlen))) #define cipher_dealloc(c) (((c)->type)->dealloc(c)) -#define cipher_init(c, k, dir) (((c)->type)->init(((c)->state), (k), (dir))) +#define cipher_init(c, k) (((c)->type)->init(((c)->state), (k), ((c)->key_len))) #define cipher_encrypt(c, buf, len) \ (((c)->type)->encrypt(((c)->state), (buf), (len))) +#define cipher_get_tag(c, buf, len) \ + (((c)->type)->get_tag(((c)->state), (buf), (len))) + #define cipher_decrypt(c, buf, len) \ (((c)->type)->decrypt(((c)->state), (buf), (len))) -#define cipher_set_iv(c, n) \ - ((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)->state), (n))) : \ +#define cipher_set_iv(c, n, dir) \ + ((c) ? (((c)->type)->set_iv(((cipher_pointer_t)(c)->state), (n), (dir))) : \ + err_status_no_such_op) +#define cipher_set_aad(c, a, l) \ + (((c) && (((c)->type)->set_aad)) ? \ + (((c)->type)->set_aad(((c)->state), (a), (l))) : \ err_status_no_such_op) err_status_t @@ -201,6 +227,16 @@ err_status_t cipher_type_self_test(const cipher_type_t *ct); +/* + * cipher_type_test() tests a cipher against external test cases provided in + * an array of values of key/xtd_seq_num_t/plaintext/ciphertext + * that is known to be good + */ + +err_status_t +cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data); + + /* * cipher_bits_per_second(c, l, t) computes (and estimate of) the * number of bits that a cipher implementation can encrypt in a second diff --git a/third_party/srtp/crypto/include/crypto.h b/third_party/srtp/crypto/include/crypto.h index 0e9667da..ab6f6bef 100644 --- a/third_party/srtp/crypto/include/crypto.h +++ b/third_party/srtp/crypto/include/crypto.h @@ -7,6 +7,42 @@ * Cisco Systems, Inc. */ +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + #ifndef CRYPTO_H #define CRYPTO_H diff --git a/third_party/srtp/crypto/include/crypto_kernel.h b/third_party/srtp/crypto/include/crypto_kernel.h index b8cd9be1..caccfa03 100644 --- a/third_party/srtp/crypto/include/crypto_kernel.h +++ b/third_party/srtp/crypto/include/crypto_kernel.h @@ -182,6 +182,28 @@ crypto_kernel_load_cipher_type(cipher_type_t *ct, cipher_type_id_t id); err_status_t crypto_kernel_load_auth_type(auth_type_t *ct, auth_type_id_t id); +/* + * crypto_kernel_replace_cipher_type(ct, id) + * + * replaces the crypto kernel's existing cipher for the cipher_type id + * with a new one passed in externally. The new cipher must pass all the + * existing cipher_type's self tests as well as its own. + */ +err_status_t +crypto_kernel_replace_cipher_type(cipher_type_t *ct, cipher_type_id_t id); + + +/* + * crypto_kernel_replace_auth_type(ct, id) + * + * replaces the crypto kernel's existing cipher for the auth_type id + * with a new one passed in externally. The new auth type must pass all the + * existing auth_type's self tests as well as its own. + */ +err_status_t +crypto_kernel_replace_auth_type(auth_type_t *ct, auth_type_id_t id); + + err_status_t crypto_kernel_load_debug_module(debug_module_t *new_dm); @@ -199,7 +221,8 @@ crypto_kernel_load_debug_module(debug_module_t *new_dm); err_status_t crypto_kernel_alloc_cipher(cipher_type_id_t id, cipher_pointer_t *cp, - int key_len); + int key_len, + int tag_len); /* * crypto_kernel_alloc_auth(id, ap, key_len, tag_len); diff --git a/third_party/srtp/crypto/include/crypto_math.h b/third_party/srtp/crypto/include/crypto_math.h index c3e7b76b..52f08372 100644 --- a/third_party/srtp/crypto/include/crypto_math.h +++ b/third_party/srtp/crypto/include/crypto_math.h @@ -233,40 +233,6 @@ void octet_string_set_to_zero(uint8_t *s, int len); -/* - * functions manipulating bit_vector_t - * - * A bitvector_t consists of an array of words and an integer - * representing the number of significant bits stored in the array. - * The bits are packed as follows: the least significant bit is that - * of word[0], while the most significant bit is the nth most - * significant bit of word[m], where length = bits_per_word * m + n. - * - */ - -#define bits_per_word 32 -#define bytes_per_word 4 - -typedef struct { - uint32_t length; - uint32_t *word; -} bitvector_t; - -int -bitvector_alloc(bitvector_t *v, unsigned long length); - -void -bitvector_set_bit(bitvector_t *v, int bit_index); - -int -bitvector_get_bit(const bitvector_t *v, int bit_index); - -int -bitvector_print_hex(const bitvector_t *v, FILE *stream); - -int -bitvector_set_from_hex(bitvector_t *v, char *string); - #endif /* MATH_H */ diff --git a/third_party/srtp/crypto/include/crypto_types.h b/third_party/srtp/crypto/include/crypto_types.h index 0ce50f4b..dbb50c37 100644 --- a/third_party/srtp/crypto/include/crypto_types.h +++ b/third_party/srtp/crypto/include/crypto_types.h @@ -8,7 +8,7 @@ */ /* * - * Copyright(c) 2001-2006 Cisco Systems, Inc. + * Copyright(c) 2001-2006,2013 Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -97,12 +97,19 @@ #define NULL_CIPHER 0 /** - * @brief AES-128 Integer Counter Mode (AES ICM) + * @brief AES Integer Counter Mode (AES ICM) * - * AES-128 ICM is the variant of counter mode that is used by Secure RTP. - * This cipher uses a 16-octet key and a 30-octet offset (or salt) value. + * AES ICM is the variant of counter mode that is used by Secure RTP. + * This cipher uses a 16-, 24-, or 32-octet key concatenated with a + * 14-octet offset (or salt) value. + */ +#define AES_ICM 1 + +/** + * @brief AES-128 Integer Counter Mode (AES ICM) + * AES-128 ICM is a deprecated alternate name for AES ICM. */ -#define AES_128_ICM 1 +#define AES_128_ICM AES_ICM /** * @brief SEAL 3.0 @@ -113,19 +120,54 @@ #define SEAL 2 /** - * @brief AES-128 Integer Counter Mode (AES ICM) + * @brief AES Cipher Block Chaining mode (AES CBC) * - * AES-128 ICM is the variant of counter mode that is used by Secure RTP. - * This cipher uses a 16-octet key and a 30-octet offset (or salt) value. + * AES CBC is the AES Cipher Block Chaining mode. + * This cipher uses a 16-, 24-, or 32-octet key. */ -#define AES_128_CBC 3 +#define AES_CBC 3 + +/** + * @brief AES-128 Cipher Block Chaining mode (AES CBC) + * + * AES-128 CBC is a deprecated alternate name for AES CBC. + */ +#define AES_128_CBC AES_CBC /** * @brief Strongest available cipher. * * This identifier resolves to the strongest cipher type available. */ -#define STRONGHOLD_CIPHER AES_128_ICM +#define STRONGHOLD_CIPHER AES_ICM + +/** + * @brief AES-192 Integer Counter Mode (AES ICM) + * AES-192 ICM is a deprecated alternate name for AES ICM. + */ +#define AES_192_ICM 4 + +/** + * @brief AES-256 Integer Counter Mode (AES ICM) + * AES-256 ICM is a deprecated alternate name for AES ICM. + */ +#define AES_256_ICM 5 + +/** + * @brief AES-128_GCM Galois Counter Mode (AES GCM) + * + * AES-128 GCM is the variant of galois counter mode that is used by + * Secure RTP. This cipher uses a 16-octet key. + */ +#define AES_128_GCM 6 + +/** + * @brief AES-256_GCM Galois Counter Mode (AES GCM) + * + * AES-256 GCM is the variant of galois counter mode that is used by + * Secure RTP. This cipher uses a 32-octet key. + */ +#define AES_256_GCM 7 /** * @} diff --git a/third_party/srtp/crypto/include/datatypes.h b/third_party/srtp/crypto/include/datatypes.h index 4f86b556..b18435f0 100644 --- a/third_party/srtp/crypto/include/datatypes.h +++ b/third_party/srtp/crypto/include/datatypes.h @@ -92,6 +92,12 @@ typedef union { uint64_t v64[2]; } v128_t; +typedef union { + uint8_t v8[32]; + uint16_t v16[16]; + uint32_t v32[8]; + uint64_t v64[4]; +} v256_t; /* some useful and simple math functions */ @@ -155,10 +161,10 @@ void v128_copy_octet_string(v128_t *x, const uint8_t s[16]); void -v128_left_shift(v128_t *x, int index); +v128_left_shift(v128_t *x, int shift_index); void -v128_right_shift(v128_t *x, int index); +v128_right_shift(v128_t *x, int shift_index); /* * the following macros define the data manipulation functions @@ -377,7 +383,7 @@ void octet_string_set_to_zero(uint8_t *s, int len); -#ifndef SRTP_KERNEL_LINUX +#if !defined(SRTP_KERNEL_LINUX) && defined(HAVE_CONFIG_H) /* * Convert big endian integers to CPU byte order. @@ -424,4 +430,87 @@ static inline uint64_t be64_to_cpu(uint64_t v) { #endif /* WORDS_BIGENDIAN */ +/* + * functions manipulating bitvector_t + * + * A bitvector_t consists of an array of words and an integer + * representing the number of significant bits stored in the array. + * The bits are packed as follows: the least significant bit is that + * of word[0], while the most significant bit is the nth most + * significant bit of word[m], where length = bits_per_word * m + n. + * + */ + +#define bits_per_word 32 +#define bytes_per_word 4 + +typedef struct { + uint32_t length; + uint32_t *word; +} bitvector_t; + + +#define _bitvector_get_bit(v, bit_index) \ +( \ + ((((v)->word[((bit_index) >> 5)]) >> ((bit_index) & 31)) & 1) \ +) + + +#define _bitvector_set_bit(v, bit_index) \ +( \ + (((v)->word[((bit_index) >> 5)] |= ((uint32_t)1 << ((bit_index) & 31)))) \ +) + +#define _bitvector_clear_bit(v, bit_index) \ +( \ + (((v)->word[((bit_index) >> 5)] &= ~((uint32_t)1 << ((bit_index) & 31)))) \ +) + +#define _bitvector_get_length(v) \ +( \ + ((v)->length) \ +) + +#ifdef DATATYPES_USE_MACROS /* little functions are really macros */ + +#define bitvector_get_bit(v, bit_index) _bitvector_get_bit(v, bit_index) +#define bitvector_set_bit(v, bit_index) _bitvector_set_bit(v, bit_index) +#define bitvector_clear_bit(v, bit_index) _bitvector_clear_bit(v, bit_index) +#define bitvector_get_length(v) _bitvector_get_length(v) + +#else + +int +bitvector_get_bit(const bitvector_t *v, int bit_index); + +void +bitvector_set_bit(bitvector_t *v, int bit_index); + +void +bitvector_clear_bit(bitvector_t *v, int bit_index); + +unsigned long +bitvector_get_length(const bitvector_t *v); + +#endif + +int +bitvector_alloc(bitvector_t *v, unsigned long length); + +void +bitvector_dealloc(bitvector_t *v); + +void +bitvector_set_to_zero(bitvector_t *x); + +void +bitvector_left_shift(bitvector_t *x, int index); + +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/third_party/srtp/crypto/include/err.h b/third_party/srtp/crypto/include/err.h index 1a6e1701..4f401a6d 100644 --- a/third_party/srtp/crypto/include/err.h +++ b/third_party/srtp/crypto/include/err.h @@ -46,7 +46,8 @@ #ifndef ERR_H #define ERR_H -#include "datatypes.h" +#include <stdio.h> +#include <stdarg.h> /** * @defgroup Error Error Codes @@ -87,7 +88,7 @@ typedef enum { err_status_nonce_bad = 18, /**< nonce check failed */ err_status_read_fail = 19, /**< couldn't read data */ err_status_write_fail = 20, /**< couldn't write data */ - err_status_parse_err = 21, /**< error pasring data */ + err_status_parse_err = 21, /**< error parsing data */ err_status_encode_err = 22, /**< error encoding data */ err_status_semaphore_err = 23,/**< error while using semaphores */ err_status_pfkey_err = 24 /**< error while using pfkey */ @@ -118,7 +119,7 @@ typedef enum { */ err_status_t -err_reporting_init(char *ident); +err_reporting_init(const char *ident); #ifdef SRTP_KERNEL_LINUX extern err_reporting_level_t err_level; @@ -135,7 +136,7 @@ extern err_reporting_level_t err_level; */ void -err_report(int priority, char *format, ...); +err_report(int priority, const char *format, ...); #endif /* ! SRTP_KERNEL_LINUX */ @@ -145,7 +146,7 @@ err_report(int priority, char *format, ...); typedef struct { int on; /* 1 if debugging is on, 0 if it is off */ - char *name; /* printable name for debug module */ + const char *name; /* printable name for debug module */ } debug_module_t; #ifdef ENABLE_DEBUGGING diff --git a/third_party/srtp/crypto/include/hmac.h b/third_party/srtp/crypto/include/hmac.h index 262c0e2d..875f45c6 100644 --- a/third_party/srtp/crypto/include/hmac.h +++ b/third_party/srtp/crypto/include/hmac.h @@ -9,7 +9,7 @@ */ /* * - * Copyright (c) 2001-2006, Cisco Systems, Inc. + * Copyright (c) 2001-2006,2013, Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,6 +53,10 @@ typedef struct { uint8_t opad[64]; sha1_ctx_t ctx; sha1_ctx_t init_ctx; +#ifdef OPENSSL + int ctx_initialized; + int init_ctx_initialized; +#endif } hmac_ctx_t; err_status_t diff --git a/third_party/srtp/crypto/include/integers.h b/third_party/srtp/crypto/include/integers.h index 138ea9c5..179ec39f 100644 --- a/third_party/srtp/crypto/include/integers.h +++ b/third_party/srtp/crypto/include/integers.h @@ -47,7 +47,7 @@ #ifndef INTEGERS_H #define INTEGERS_H -#include "srtp_config.h" /* configuration file, using autoconf */ +#include "config.h" #ifdef SRTP_KERNEL @@ -76,7 +76,7 @@ #endif /* Can we do 64 bit integers? */ -#ifndef HAVE_UINT64_T +#if !defined(HAVE_UINT64_T) # if SIZEOF_UNSIGNED_LONG == 8 typedef unsigned long uint64_t; # elif SIZEOF_UNSIGNED_LONG_LONG == 8 @@ -99,7 +99,7 @@ typedef unsigned int uint32_t; #endif -#ifdef NO_64BIT_MATH +#if defined(NO_64BIT_MATH) && defined(HAVE_CONFIG_H) typedef double uint64_t; /* assert that sizeof(double) == 8 */ extern uint64_t make64(uint32_t high, uint32_t low); diff --git a/third_party/srtp/crypto/include/null_cipher.h b/third_party/srtp/crypto/include/null_cipher.h index 7d6bbdd6..39da59a8 100644 --- a/third_party/srtp/crypto/include/null_cipher.h +++ b/third_party/srtp/crypto/include/null_cipher.h @@ -62,11 +62,11 @@ typedef struct { */ err_status_t -null_cipher_init(null_cipher_ctx_t *c, const uint8_t *key); +null_cipher_init(null_cipher_ctx_t *c, const uint8_t *key, int key_len); err_status_t null_cipher_set_segment(null_cipher_ctx_t *c, - unsigned long index); + unsigned long segment_index); err_status_t null_cipher_encrypt(null_cipher_ctx_t *c, diff --git a/third_party/srtp/crypto/include/prng.h b/third_party/srtp/crypto/include/prng.h index fb96b5eb..c5ec2306 100644 --- a/third_party/srtp/crypto/include/prng.h +++ b/third_party/srtp/crypto/include/prng.h @@ -7,12 +7,53 @@ * Cisco Systems, Inc. */ +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + #ifndef PRNG_H #define PRNG_H #include "rand_source.h" /* for rand_source_func_t definition */ #include "aes.h" /* for aes */ +//FIXME: this is temporary until we pull in the code to use OpenSSL for RNG +#ifdef OPENSSL +#include "aes_icm_ossl.h" /* for aes ctr */ +#else #include "aes_icm.h" /* for aes ctr */ +#endif #define MAX_PRNG_OUT_LEN 0xffffffffU diff --git a/third_party/srtp/crypto/include/rdb.h b/third_party/srtp/crypto/include/rdb.h index 5a26c5e3..300c569f 100644 --- a/third_party/srtp/crypto/include/rdb.h +++ b/third_party/srtp/crypto/include/rdb.h @@ -8,6 +8,42 @@ */ +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + #ifndef REPLAY_DB_H #define REPLAY_DB_H @@ -49,7 +85,7 @@ rdb_init(rdb_t *rdb); */ err_status_t -rdb_check(const rdb_t *rdb, uint32_t index); +rdb_check(const rdb_t *rdb, uint32_t rdb_index); /* * rdb_add_index @@ -61,7 +97,7 @@ rdb_check(const rdb_t *rdb, uint32_t index); */ err_status_t -rdb_add_index(rdb_t *rdb, uint32_t index); +rdb_add_index(rdb_t *rdb, uint32_t rdb_index); /* * the functions rdb_increment() and rdb_get_value() are for use by diff --git a/third_party/srtp/crypto/include/rdbx.h b/third_party/srtp/crypto/include/rdbx.h index ce9ecf6f..4b8dd229 100644 --- a/third_party/srtp/crypto/include/rdbx.h +++ b/third_party/srtp/crypto/include/rdbx.h @@ -8,6 +8,42 @@ * */ +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + #ifndef RDBX_H #define RDBX_H @@ -46,19 +82,29 @@ typedef uint64_t xtd_seq_num_t; typedef struct { xtd_seq_num_t index; - v128_t bitmask; + bitvector_t bitmask; } rdbx_t; /* - * rdbx_init(rdbx_ptr) + * rdbx_init(rdbx_ptr, ws) * - * initializes the rdbx pointed to by its argument, setting the - * rollover counter and sequence number to zero + * initializes the rdbx pointed to by its argument with the window size ws, + * setting the rollover counter and sequence number to zero */ err_status_t -rdbx_init(rdbx_t *rdbx); +rdbx_init(rdbx_t *rdbx, unsigned long ws); + + +/* + * rdbx_dealloc(rdbx_ptr) + * + * frees memory associated with the rdbx + */ + +err_status_t +rdbx_dealloc(rdbx_t *rdbx); /* @@ -100,12 +146,42 @@ rdbx_check(const rdbx_t *rdbx, int difference); err_status_t rdbx_add_index(rdbx_t *rdbx, int delta); + +/* + * rdbx_set_roc(rdbx, roc) initalizes the rdbx_t at the location rdbx + * to have the rollover counter value roc. If that value is less than + * the current rollover counter value, then the function returns + * err_status_replay_old; otherwise, err_status_ok is returned. + * + */ + +err_status_t +rdbx_set_roc(rdbx_t *rdbx, uint32_t roc); + +/* + * rdbx_get_roc(rdbx) returns the value of the rollover counter for + * the rdbx_t pointed to by rdbx + * + */ + +xtd_seq_num_t +rdbx_get_packet_index(const rdbx_t *rdbx); + /* * xtd_seq_num_t functions - these are *internal* functions of rdbx, and * shouldn't be used to manipulate rdbx internal values. use the rdbx * api instead! */ +/* + * rdbx_get_ws(rdbx_ptr) + * + * gets the window size which was used to initialize the rdbx + */ + +unsigned long +rdbx_get_window_size(const rdbx_t *rdbx); + /* index_init(&pi) initializes a packet index pi (sets it to zero) */ diff --git a/third_party/srtp/crypto/include/sha1.h b/third_party/srtp/crypto/include/sha1.h index e3af4d4b..f1744ced 100644 --- a/third_party/srtp/crypto/include/sha1.h +++ b/third_party/srtp/crypto/include/sha1.h @@ -47,7 +47,49 @@ #ifndef SHA1_H #define SHA1_H +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "err.h" +#ifdef OPENSSL +#include <openssl/evp.h> +#include <stdint.h> + +typedef EVP_MD_CTX sha1_ctx_t; + +/* + * sha1_init(&ctx) initializes the SHA1 context ctx + * + * sha1_update(&ctx, msg, len) hashes the len octets starting at msg + * into the SHA1 context + * + * sha1_final(&ctx, output) performs the final processing of the SHA1 + * context and writes the result to the 20 octets at output + * + * Return values are ignored on the EVP functions since all three + * of these functions return void. + * + */ + +static inline void sha1_init (sha1_ctx_t *ctx) +{ + EVP_MD_CTX_init(ctx); + EVP_DigestInit(ctx, EVP_sha1()); +} + +static inline void sha1_update (sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg) +{ + EVP_DigestUpdate(ctx, M, octets_in_msg); +} + +static inline void sha1_final (sha1_ctx_t *ctx, uint32_t *output) +{ + unsigned int len = 0; + + EVP_DigestFinal(ctx, (unsigned char*)output, &len); +} +#else #include "datatypes.h" typedef struct { @@ -104,5 +146,7 @@ sha1_final(sha1_ctx_t *ctx, uint32_t output[5]); void sha1_core(const uint32_t M[16], uint32_t hash_value[5]); + +#endif /* else OPENSSL */ #endif /* SHA1_H */ diff --git a/third_party/srtp/crypto/include/xfm.h b/third_party/srtp/crypto/include/xfm.h index 5837149b..80774f96 100644 --- a/third_party/srtp/crypto/include/xfm.h +++ b/third_party/srtp/crypto/include/xfm.h @@ -7,6 +7,42 @@ * Cisco Systems, Inc. */ +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + #ifndef XFM_H #define XFM_H diff --git a/third_party/srtp/crypto/kernel/alloc.c b/third_party/srtp/crypto/kernel/alloc.c index 5dd09474..e728798c 100644 --- a/third_party/srtp/crypto/kernel/alloc.c +++ b/third_party/srtp/crypto/kernel/alloc.c @@ -42,6 +42,10 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "alloc.h" #include "crypto_kernel.h" @@ -73,8 +77,9 @@ crypto_alloc(size_t size) { if (ptr) { debug_print(mod_alloc, "(location: %p) allocated", ptr); - } else + } else { debug_print(mod_alloc, "allocation failed (asked for %d bytes)\n", size); + } return ptr; } @@ -98,9 +103,10 @@ crypto_alloc(size_t size) { if (ptr) { debug_print(mod_alloc, "(location: %p) allocated", ptr); - } else + } else { debug_print(mod_alloc, "allocation failed (asked for %d bytes)\n", size); - + } + return ptr; } diff --git a/third_party/srtp/crypto/kernel/crypto_kernel.c b/third_party/srtp/crypto/kernel/crypto_kernel.c index 230dda62..f01a72a5 100644 --- a/third_party/srtp/crypto/kernel/crypto_kernel.c +++ b/third_party/srtp/crypto/kernel/crypto_kernel.c @@ -8,7 +8,7 @@ */ /* * - * Copyright(c) 2001-2006 Cisco Systems, Inc. + * Copyright(c) 2001-2006,2013 Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,6 +43,10 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "alloc.h" #include "crypto_kernel.h" @@ -69,7 +73,12 @@ extern debug_module_t mod_alloc; extern cipher_type_t null_cipher; extern cipher_type_t aes_icm; +#ifndef OPENSSL extern cipher_type_t aes_cbc; +#else +extern cipher_type_t aes_gcm_128_openssl; +extern cipher_type_t aes_gcm_256_openssl; +#endif /* @@ -137,6 +146,7 @@ crypto_kernel_init() { if (status) return status; +#ifndef OPENSSL /* initialize pseudorandom number generator */ status = ctr_prng_init(rand_source_get_octet_string); if (status) @@ -146,17 +156,29 @@ crypto_kernel_init() { status = stat_test_rand_source_with_repetition(ctr_prng_get_octet_string, MAX_RNG_TRIALS); if (status) return status; +#endif /* load cipher types */ status = crypto_kernel_load_cipher_type(&null_cipher, NULL_CIPHER); if (status) return status; - status = crypto_kernel_load_cipher_type(&aes_icm, AES_128_ICM); + status = crypto_kernel_load_cipher_type(&aes_icm, AES_ICM); if (status) return status; - status = crypto_kernel_load_cipher_type(&aes_cbc, AES_128_CBC); +#ifndef OPENSSL + status = crypto_kernel_load_cipher_type(&aes_cbc, AES_CBC); if (status) return status; +#else + status = crypto_kernel_load_cipher_type(&aes_gcm_128_openssl, AES_128_GCM); + if (status) { + return status; + } + status = crypto_kernel_load_cipher_type(&aes_gcm_256_openssl, AES_256_GCM); + if (status) { + return status; + } +#endif /* load auth func types */ status = crypto_kernel_load_auth_type(&null_auth, NULL_AUTH); @@ -297,8 +319,9 @@ crypto_kernel_shutdown() { return err_status_ok; } -err_status_t -crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { +static inline err_status_t +crypto_kernel_do_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id, + int replace) { kernel_cipher_type_t *ctype, *new_ctype; err_status_t status; @@ -306,6 +329,9 @@ crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { if (new_ct == NULL) return err_status_bad_param; + if (new_ct->id != id) + return err_status_bad_param; + /* check cipher type by running self-test */ status = cipher_type_self_test(new_ct); if (status) { @@ -315,24 +341,35 @@ crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { /* walk down list, checking if this type is in the list already */ ctype = crypto_kernel.cipher_type_list; while (ctype != NULL) { - if ((new_ct == ctype->cipher_type) || (id == ctype->id)) + if (id == ctype->id) { + if (!replace) + return err_status_bad_param; + status = cipher_type_test(new_ct, ctype->cipher_type->test_data); + if (status) + return status; + new_ctype = ctype; + break; + } + else if (new_ct == ctype->cipher_type) return err_status_bad_param; ctype = ctype->next; } - /* put new_ct at the head of the list */ + /* if not found, put new_ct at the head of the list */ + if (ctype == NULL) { /* allocate memory */ - new_ctype = (kernel_cipher_type_t *) crypto_alloc(sizeof(kernel_cipher_type_t)); - if (new_ctype == NULL) - return err_status_alloc_fail; + new_ctype = (kernel_cipher_type_t *) crypto_alloc(sizeof(kernel_cipher_type_t)); + if (new_ctype == NULL) + return err_status_alloc_fail; + new_ctype->next = crypto_kernel.cipher_type_list; + + /* set head of list to new cipher type */ + crypto_kernel.cipher_type_list = new_ctype; + } /* set fields */ new_ctype->cipher_type = new_ct; new_ctype->id = id; - new_ctype->next = crypto_kernel.cipher_type_list; - - /* set head of list to new cipher type */ - crypto_kernel.cipher_type_list = new_ctype; /* load debug module, if there is one present */ if (new_ct->debug != NULL) @@ -343,7 +380,18 @@ crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { } err_status_t -crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) { +crypto_kernel_load_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { + return crypto_kernel_do_load_cipher_type(new_ct, id, 0); +} + +err_status_t +crypto_kernel_replace_cipher_type(cipher_type_t *new_ct, cipher_type_id_t id) { + return crypto_kernel_do_load_cipher_type(new_ct, id, 1); +} + +err_status_t +crypto_kernel_do_load_auth_type(auth_type_t *new_at, auth_type_id_t id, + int replace) { kernel_auth_type_t *atype, *new_atype; err_status_t status; @@ -351,6 +399,9 @@ crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) { if (new_at == NULL) return err_status_bad_param; + if (new_at->id != id) + return err_status_bad_param; + /* check auth type by running self-test */ status = auth_type_self_test(new_at); if (status) { @@ -360,24 +411,35 @@ crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) { /* walk down list, checking if this type is in the list already */ atype = crypto_kernel.auth_type_list; while (atype != NULL) { - if ((new_at == atype->auth_type) || (id == atype->id)) + if (id == atype->id) { + if (!replace) + return err_status_bad_param; + status = auth_type_test(new_at, atype->auth_type->test_data); + if (status) + return status; + new_atype = atype; + break; + } + else if (new_at == atype->auth_type) return err_status_bad_param; atype = atype->next; } - /* put new_at at the head of the list */ - /* allocate memory */ - new_atype = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t)); - if (new_atype == NULL) - return err_status_alloc_fail; + /* if not found, put new_at at the head of the list */ + if (atype == NULL) { + /* allocate memory */ + new_atype = (kernel_auth_type_t *)crypto_alloc(sizeof(kernel_auth_type_t)); + if (new_atype == NULL) + return err_status_alloc_fail; + + new_atype->next = crypto_kernel.auth_type_list; + /* set head of list to new auth type */ + crypto_kernel.auth_type_list = new_atype; + } /* set fields */ new_atype->auth_type = new_at; new_atype->id = id; - new_atype->next = crypto_kernel.auth_type_list; - - /* set head of list to new auth type */ - crypto_kernel.auth_type_list = new_atype; /* load debug module, if there is one present */ if (new_at->debug != NULL) @@ -388,6 +450,16 @@ crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) { } +err_status_t +crypto_kernel_load_auth_type(auth_type_t *new_at, auth_type_id_t id) { + return crypto_kernel_do_load_auth_type(new_at, id, 0); +} + +err_status_t +crypto_kernel_replace_auth_type(auth_type_t *new_at, auth_type_id_t id) { + return crypto_kernel_do_load_auth_type(new_at, id, 1); +} + cipher_type_t * crypto_kernel_get_cipher_type(cipher_type_id_t id) { @@ -409,7 +481,8 @@ crypto_kernel_get_cipher_type(cipher_type_id_t id) { err_status_t crypto_kernel_alloc_cipher(cipher_type_id_t id, cipher_pointer_t *cp, - int key_len) { + int key_len, + int tag_len) { cipher_type_t *ct; /* @@ -423,7 +496,7 @@ crypto_kernel_alloc_cipher(cipher_type_id_t id, if (!ct) return err_status_fail; - return ((ct)->alloc(cp, key_len)); + return ((ct)->alloc(cp, key_len, tag_len)); } @@ -517,7 +590,11 @@ crypto_kernel_set_debug_module(char *name, int on) { err_status_t crypto_get_random(unsigned char *buffer, unsigned int length) { if (crypto_kernel.state == crypto_kernel_state_secure) +#ifdef OPENSSL + return rand_source_get_octet_string(buffer, length); +#else return ctr_prng_get_octet_string(buffer, length); +#endif else return err_status_fail; } diff --git a/third_party/srtp/crypto/kernel/err.c b/third_party/srtp/crypto/kernel/err.c index 4a3a8589..fcd90784 100644 --- a/third_party/srtp/crypto/kernel/err.c +++ b/third_party/srtp/crypto/kernel/err.c @@ -42,6 +42,10 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "err.h" #ifdef ERR_REPORTING_SYSLOG @@ -57,7 +61,7 @@ err_reporting_level_t err_level = err_level_none; #ifdef SRTP_KERNEL_LINUX err_status_t -err_reporting_init(char *ident) { +err_reporting_init(const char *ident) { return err_status_ok; } @@ -69,7 +73,7 @@ err_reporting_init(char *ident) { static FILE *err_file = NULL; err_status_t -err_reporting_init(char *ident) { +err_reporting_init(const char *ident) { #ifdef ERR_REPORTING_SYSLOG openlog(ident, LOG_PID, LOG_AUTHPRIV); #endif @@ -92,7 +96,7 @@ err_reporting_init(char *ident) { } void -err_report(int priority, char *format, ...) { +err_report(int priority, const char *format, ...) { va_list args; if (priority <= err_level) { diff --git a/third_party/srtp/crypto/kernel/key.c b/third_party/srtp/crypto/kernel/key.c index 9f63b22c..3521e2f8 100644 --- a/third_party/srtp/crypto/kernel/key.c +++ b/third_party/srtp/crypto/kernel/key.c @@ -42,6 +42,10 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "key.h" #define soft_limit 0x10000 diff --git a/third_party/srtp/crypto/math/datatypes.c b/third_party/srtp/crypto/math/datatypes.c index c8f44a52..a30873ee 100644 --- a/third_party/srtp/crypto/math/datatypes.c +++ b/third_party/srtp/crypto/math/datatypes.c @@ -43,6 +43,10 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "datatypes.h" int @@ -113,8 +117,8 @@ octet_string_hex_string(const void *s, int length) { length *= 2; /* truncate string if it would be too long */ - if (length >= MAX_PRINT_STRING_LEN-1) - length = MAX_PRINT_STRING_LEN-2; + if (length > MAX_PRINT_STRING_LEN) + length = MAX_PRINT_STRING_LEN-1; for (i=0; i < length; i+=2) { bit_string[i] = nibble_to_hex_char(*str >> 4); @@ -149,9 +153,10 @@ hex_char_to_nibble(uint8_t c) { case ('E'): return 0xe; case ('f'): return 0xf; case ('F'): return 0xf; - default: break; /* this flags an error */ + default: return -1; /* this flags an error */ } - return -1; + /* NOTREACHED */ + return -1; /* this keeps compilers from complaining */ } int @@ -206,16 +211,16 @@ v128_hex_string(v128_t *x) { char * v128_bit_string(v128_t *x) { - int j, index; + int j, i; uint32_t mask; - for (j=index=0; j < 4; j++) { + for (j=i=0; j < 4; j++) { for (mask=0x80000000; mask > 0; mask >>= 1) { if (x->v32[j] & mask) - bit_string[index] = '1'; + bit_string[i] = '1'; else - bit_string[index] = '0'; - ++index; + bit_string[i] = '0'; + ++i; } } bit_string[128] = 0; /* null terminate string */ @@ -322,13 +327,13 @@ v128_set_bit_to(v128_t *x, int i, int y){ #endif /* DATATYPES_USE_MACROS */ void -v128_right_shift(v128_t *x, int index) { - const int base_index = index >> 5; - const int bit_index = index & 31; +v128_right_shift(v128_t *x, int shift) { + const int base_index = shift >> 5; + const int bit_index = shift & 31; int i, from; uint32_t b; - if (index > 127) { + if (shift > 127) { v128_set_to_zero(x); return; } @@ -360,12 +365,12 @@ v128_right_shift(v128_t *x, int index) { } void -v128_left_shift(v128_t *x, int index) { +v128_left_shift(v128_t *x, int shift) { int i; - const int base_index = index >> 5; - const int bit_index = index & 31; + const int base_index = shift >> 5; + const int bit_index = shift & 31; - if (index > 127) { + if (shift > 127) { v128_set_to_zero(x); return; } @@ -386,6 +391,124 @@ v128_left_shift(v128_t *x, int index) { } +/* functions manipulating bitvector_t */ + +#ifndef DATATYPES_USE_MACROS /* little functions are not macros */ + +int +bitvector_get_bit(const bitvector_t *v, int bit_index) +{ + return _bitvector_get_bit(v, bit_index); +} + +void +bitvector_set_bit(bitvector_t *v, int bit_index) +{ + _bitvector_set_bit(v, bit_index); +} + +void +bitvector_clear_bit(bitvector_t *v, int bit_index) +{ + _bitvector_clear_bit(v, bit_index); +} + + +#endif /* DATATYPES_USE_MACROS */ + +int +bitvector_alloc(bitvector_t *v, unsigned long length) { + unsigned long l; + + /* Round length up to a multiple of bits_per_word */ + length = (length + bits_per_word - 1) & ~(unsigned long)((bits_per_word - 1)); + + l = length / bits_per_word * bytes_per_word; + + /* allocate memory, then set parameters */ + if (l == 0) + v->word = NULL; + else { + v->word = (uint32_t*)crypto_alloc(l); + if (v->word == NULL) { + v->word = NULL; + v->length = 0; + return -1; + } + } + v->length = length; + + /* initialize bitvector to zero */ + bitvector_set_to_zero(v); + + return 0; +} + + +void +bitvector_dealloc(bitvector_t *v) { + if (v->word != NULL) + crypto_free(v->word); + v->word = NULL; + v->length = 0; +} + +void +bitvector_set_to_zero(bitvector_t *x) +{ + /* C99 guarantees that memset(0) will set the value 0 for uint32_t */ + memset(x->word, 0, x->length >> 3); +} + +char * +bitvector_bit_string(bitvector_t *x, char* buf, int len) { + int j, i; + uint32_t mask; + + for (j=i=0; j < (int)(x->length>>5) && i < len-1; j++) { + for (mask=0x80000000; mask > 0; mask >>= 1) { + if (x->word[j] & mask) + buf[i] = '1'; + else + buf[i] = '0'; + ++i; + if (i >= len-1) + break; + } + } + buf[i] = 0; /* null terminate string */ + + return buf; +} + +void +bitvector_left_shift(bitvector_t *x, int shift) { + int i; + const int base_index = shift >> 5; + const int bit_index = shift & 31; + const int word_length = x->length >> 5; + + if (shift >= (int)x->length) { + bitvector_set_to_zero(x); + return; + } + + if (bit_index == 0) { + for (i=0; i < word_length - base_index; i++) + x->word[i] = x->word[i+base_index]; + } else { + for (i=0; i < word_length - base_index - 1; i++) + x->word[i] = (x->word[i+base_index] >> bit_index) ^ + (x->word[i+base_index+1] << (32 - bit_index)); + x->word[word_length - base_index-1] = x->word[word_length-1] >> bit_index; + } + + /* now wrap up the final portion */ + for (i = word_length - base_index; i < word_length; i++) + x->word[i] = 0; + +} + int octet_string_is_eq(uint8_t *a, uint8_t *b, int len) { @@ -406,194 +529,41 @@ octet_string_set_to_zero(uint8_t *s, int len) { } +#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] = {0}; + int j = 0; + int i; -/* - * base64_string_to_octet_string converts a hexadecimal string - * of length 2 * len to a raw octet string of length len - */ + for (i = 0; i < 4; i++) { + char *p = strchr(b64chars, in[i]); + if (p != NULL) sextets[i] = p - b64chars; + else j++; + } -int -base64_string_to_octet_string(char *raw, char *base64, int len) { - uint8_t x; - int tmp; - int 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; +} - 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; +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; } - return base64_len; + *pad = j; + return i; } + +#endif diff --git a/third_party/srtp/crypto/math/gf2_8.c b/third_party/srtp/crypto/math/gf2_8.c index 8a112ba7..c57f8d23 100644 --- a/third_party/srtp/crypto/math/gf2_8.c +++ b/third_party/srtp/crypto/math/gf2_8.c @@ -45,12 +45,16 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "datatypes.h" #include "gf2_8.h" /* gf2_8_shift() moved to gf2_8.h as an inline function */ -inline gf2_8 +gf2_8 gf2_8_multiply(gf2_8 x, gf2_8 y) { gf2_8 z = 0; diff --git a/third_party/srtp/crypto/math/math.c b/third_party/srtp/crypto/math/math.c index 3e619979..7f0bcd2b 100644 --- a/third_party/srtp/crypto/math/math.c +++ b/third_party/srtp/crypto/math/math.c @@ -42,8 +42,11 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "crypto_math.h" -#include <stdlib.h> /* malloc() used in bitvector_alloc */ int octet_weight[256] = { @@ -173,7 +176,7 @@ v32_weight(v32_t a) { return wt; } -inline unsigned char +unsigned char v32_distance(v32_t x, v32_t y) { x.value ^= y.value; return v32_weight(x); @@ -524,13 +527,13 @@ A_times_x_plus_b(uint8_t A[8], uint8_t x, uint8_t b) { return b; } -inline void +void v16_copy_octet_string(v16_t *x, const uint8_t s[2]) { x->v8[0] = s[0]; x->v8[1] = s[1]; } -inline void +void v32_copy_octet_string(v32_t *x, const uint8_t s[4]) { x->v8[0] = s[0]; x->v8[1] = s[1]; @@ -538,7 +541,7 @@ v32_copy_octet_string(v32_t *x, const uint8_t s[4]) { x->v8[3] = s[3]; } -inline void +void v64_copy_octet_string(v64_t *x, const uint8_t s[8]) { x->v8[0] = s[0]; x->v8[1] = s[1]; @@ -632,7 +635,7 @@ v128_set_bit_to(v128_t *x, int i, int y){ #endif /* DATATYPES_USE_MACROS */ -inline void +static inline void v128_left_shift2(v128_t *x, int num_bits) { int i; int word_shift = num_bits >> 5; @@ -773,165 +776,6 @@ octet_string_set_to_zero(uint8_t *s, int len) { } -/* functions manipulating bit_vector_t */ - -#define BITVECTOR_MAX_WORDS 5 - -int -bitvector_alloc(bitvector_t *v, unsigned long length) { - unsigned long l = (length + bytes_per_word - 1) / bytes_per_word; - int i; - - /* allocate memory, then set parameters */ - if (l > BITVECTOR_MAX_WORDS) - return -1; - else - l = BITVECTOR_MAX_WORDS; - v->word = malloc(l); - if (v->word == NULL) - return -1; - v->length = length; - - /* initialize bitvector to zero */ - for (i=0; i < (length >> 5); i++) { - v->word = 0; - } - - return 0; -} - -void -bitvector_set_bit(bitvector_t *v, int bit_index) { - - v->word[(bit_index >> 5)] |= (1 << (bit_index & 31)); - -} - -int -bitvector_get_bit(const bitvector_t *v, int bit_index) { - - return ((v->word[(bit_index >> 5)]) >> (bit_index & 31)) & 1; - -} - -#include <stdio.h> - -int -bitvector_print_hex(const bitvector_t *v, FILE *stream) { - int i; - int m = v->length >> 5; - int n = v->length & 31; - char string[9]; - uint32_t tmp; - - /* if length isn't a multiple of four, we can't hex_print */ - if (n & 3) - return -1; - - /* if the length is zero, do nothing */ - if (v->length == 0) - return 0; - - /* - * loop over words from most significant to least significant - - */ - - for (i=m; i > 0; i++) { - char *str = string + 7; - tmp = v->word[i]; - - /* null terminate string */ - string[8] = 0; - - /* loop over nibbles */ - *str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4; - *str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4; - *str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4; - *str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4; - *str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4; - *str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4; - *str-- = nibble_to_hex_char(tmp & 0xf); tmp >>= 4; - *str-- = nibble_to_hex_char(tmp & 0xf); - - /* now print stream */ - fprintf(stream, string); - } - - return 0; - -} - - -int -hex_string_length(char *s) { - int count = 0; - - /* ignore leading zeros */ - while ((*s != 0) && *s == '0') - s++; - - /* count remaining characters */ - while (*s != 0) { - if (hex_char_to_nibble(*s++) == -1) - return -1; - count++; - } - - return count; -} - -int -bitvector_set_from_hex(bitvector_t *v, char *string) { - int num_hex_chars, m, n, i, j; - uint32_t tmp; - - num_hex_chars = hex_string_length(string); - if (num_hex_chars == -1) - return -1; - - /* set length */ - v->length = num_hex_chars * 4; - /* - * at this point, we should subtract away a bit if the high - * bit of the first character is zero, but we ignore that - * for now and assume that we're four-bit aligned - DAM - */ - - - m = num_hex_chars / 8; /* number of words */ - n = num_hex_chars % 8; /* number of nibbles in last word */ - - /* if the length is greater than the bitvector, return an error */ - if (m > BITVECTOR_MAX_WORDS) - return -1; - - /* - * loop over words from most significant - first word is a special - * case - */ - - if (n) { - tmp = 0; - for (i=0; i < n; i++) { - tmp = hex_char_to_nibble(*string++); - tmp <<= 4; - } - v->word[m] = tmp; - } - - /* now loop over the rest of the words */ - for (i=m-1; i >= 0; i--) { - tmp = 0; - for (j=0; j < 8; j++) { - tmp = hex_char_to_nibble(*string++); - tmp <<= 4; - } - v->word[i] = tmp; - } - - return 0; -} - /* functions below not yet tested! */ diff --git a/third_party/srtp/crypto/math/stat.c b/third_party/srtp/crypto/math/stat.c index 5e46c209..aaff3c4f 100644 --- a/third_party/srtp/crypto/math/stat.c +++ b/third_party/srtp/crypto/math/stat.c @@ -7,6 +7,46 @@ * Cisco Systems, Inc. */ +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "stat.h" debug_module_t mod_stat = { diff --git a/third_party/srtp/crypto/replay/rdb.c b/third_party/srtp/crypto/replay/rdb.c index c826912a..c84222fd 100644 --- a/third_party/srtp/crypto/replay/rdb.c +++ b/third_party/srtp/crypto/replay/rdb.c @@ -44,6 +44,10 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "rdb.h" @@ -70,18 +74,18 @@ rdb_init(rdb_t *rdb) { */ err_status_t -rdb_check(const rdb_t *rdb, uint32_t index) { +rdb_check(const rdb_t *rdb, uint32_t p_index) { /* if the index appears after (or at very end of) the window, its good */ - if (index >= rdb->window_start + rdb_bits_in_bitmask) + if (p_index >= rdb->window_start + rdb_bits_in_bitmask) return err_status_ok; /* if the index appears before the window, its bad */ - if (index < rdb->window_start) + if (p_index < rdb->window_start) return err_status_replay_old; /* otherwise, the index appears within the window, so check the bitmask */ - if (v128_get_bit(&rdb->bitmask, (index - rdb->window_start)) == 1) + if (v128_get_bit(&rdb->bitmask, (p_index - rdb->window_start)) == 1) return err_status_replay_fail; /* otherwise, the index is okay */ @@ -98,15 +102,15 @@ rdb_check(const rdb_t *rdb, uint32_t index) { */ err_status_t -rdb_add_index(rdb_t *rdb, uint32_t index) { +rdb_add_index(rdb_t *rdb, uint32_t p_index) { int delta; - /* here we *assume* that index > rdb->window_start */ + /* here we *assume* that p_index > rdb->window_start */ - delta = (index - rdb->window_start); + delta = (p_index - rdb->window_start); if (delta < rdb_bits_in_bitmask) { - /* if the index is within the window, set the appropriate bit */ + /* if the p_index is within the window, set the appropriate bit */ v128_set_bit(&rdb->bitmask, delta); } else { diff --git a/third_party/srtp/crypto/replay/rdbx.c b/third_party/srtp/crypto/replay/rdbx.c index 12e4e8f8..153676f3 100644 --- a/third_party/srtp/crypto/replay/rdbx.c +++ b/third_party/srtp/crypto/replay/rdbx.c @@ -43,20 +43,23 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "rdbx.h" -#define rdbx_high_bit_in_bitmask 127 /* - * from draft-ietf-avt-srtp-00.txt: + * from RFC 3711: * * A receiver reconstructs the index i of a packet with sequence - * number s using the estimate + * number SEQ using the estimate * - * i = 65,536 * t + s, + * i = 2^16 * v + SEQ, * - * where t is chosen from the set { r-1, r, r+1 } such that i is - * closest to the value 65,536 * r + s_l. If the value r+1 is used, + * where v is chosen from the set { ROC-1, ROC, ROC+1 } such that i is + * closest to the value 2^16 * ROC + s_l. If the value r+1 is used, * then the rollover counter r in the cryptographic context is * incremented by one (if the packet containing s is authentic). */ @@ -146,18 +149,18 @@ index_guess(const xtd_seq_num_t *local, if (local_seq < seq_num_median) { if (s - local_seq > seq_num_median) { guess_roc = local_roc - 1; - difference = seq_num_max - s + local_seq; + difference = s - local_seq - seq_num_max; } else { guess_roc = local_roc; difference = s - local_seq; } } else { if (local_seq - seq_num_median > s) { - guess_roc = local_roc+1; - difference = seq_num_max - local_seq + s; + guess_roc = local_roc + 1; + difference = s - local_seq + seq_num_max; } else { - difference = s - local_seq; guess_roc = local_roc; + difference = s - local_seq; } } guess_seq = s; @@ -180,17 +183,81 @@ index_guess(const xtd_seq_num_t *local, /* - * rdbx_init(&r) initalizes the rdbx_t pointed to by r + * rdbx_init(&r, ws) initializes the rdbx_t pointed to by r with window size ws */ err_status_t -rdbx_init(rdbx_t *rdbx) { - v128_set_to_zero(&rdbx->bitmask); +rdbx_init(rdbx_t *rdbx, unsigned long ws) { + if (ws == 0) + return err_status_bad_param; + + if (bitvector_alloc(&rdbx->bitmask, ws) != 0) + return err_status_alloc_fail; + index_init(&rdbx->index); return err_status_ok; } +/* + * rdbx_dealloc(&r) frees memory for the rdbx_t pointed to by r + */ + +err_status_t +rdbx_dealloc(rdbx_t *rdbx) { + bitvector_dealloc(&rdbx->bitmask); + + return err_status_ok; +} + +/* + * rdbx_set_roc(rdbx, roc) initalizes the rdbx_t at the location rdbx + * to have the rollover counter value roc. If that value is less than + * the current rollover counter value, then the function returns + * err_status_replay_old; otherwise, err_status_ok is returned. + * + */ + +err_status_t +rdbx_set_roc(rdbx_t *rdbx, uint32_t roc) { + bitvector_set_to_zero(&rdbx->bitmask); + +#ifdef NO_64BIT_MATH + #error not yet implemented +#else + + /* make sure that we're not moving backwards */ + if (roc < (rdbx->index >> 16)) + return err_status_replay_old; + + rdbx->index &= 0xffff; /* retain lowest 16 bits */ + rdbx->index |= ((uint64_t)roc) << 16; /* set ROC */ +#endif + + return err_status_ok; +} + +/* + * rdbx_get_packet_index(rdbx) returns the value of the packet index + * for the rdbx_t pointed to by rdbx + * + */ + +xtd_seq_num_t +rdbx_get_packet_index(const rdbx_t *rdbx) { + return rdbx->index; +} + +/* + * rdbx_get_window_size(rdbx) returns the value of the window size + * for the rdbx_t pointed to by rdbx + * + */ + +unsigned long +rdbx_get_window_size(const rdbx_t *rdbx) { + return bitvector_get_length(&rdbx->bitmask); +} /* * rdbx_check(&r, delta) checks to see if the xtd_seq_num_t @@ -202,11 +269,11 @@ rdbx_check(const rdbx_t *rdbx, int delta) { if (delta > 0) { /* if delta is positive, it's good */ return err_status_ok; - } else if (rdbx_high_bit_in_bitmask + delta < 0) { + } else if ((int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta < 0) { /* if delta is lower than the bitmask, it's bad */ return err_status_replay_old; - } else if (v128_get_bit(&rdbx->bitmask, - rdbx_high_bit_in_bitmask + delta) == 1) { + } else if (bitvector_get_bit(&rdbx->bitmask, + (int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta) == 1) { /* delta is within the window, so check the bitmask */ return err_status_replay_fail; } @@ -230,11 +297,11 @@ rdbx_add_index(rdbx_t *rdbx, int delta) { if (delta > 0) { /* shift forward by delta */ index_advance(&rdbx->index, delta); - v128_left_shift(&rdbx->bitmask, delta); - v128_set_bit(&rdbx->bitmask, 127); + bitvector_left_shift(&rdbx->bitmask, delta); + bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) - 1); } else { - /* delta is in window, so flip bit in bitmask */ - v128_set_bit(&rdbx->bitmask, -delta); + /* delta is in window */ + bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) -1 + delta); } /* note that we need not consider the case that delta == 0 */ diff --git a/third_party/srtp/crypto/replay/ut_sim.c b/third_party/srtp/crypto/replay/ut_sim.c index 43c411e4..5a1c37c7 100644 --- a/third_party/srtp/crypto/replay/ut_sim.c +++ b/third_party/srtp/crypto/replay/ut_sim.c @@ -45,6 +45,10 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "ut_sim.h" diff --git a/third_party/srtp/crypto/rng/ctr_prng.c b/third_party/srtp/crypto/rng/ctr_prng.c index ab76df36..e24b0aba 100644 --- a/third_party/srtp/crypto/rng/ctr_prng.c +++ b/third_party/srtp/crypto/rng/ctr_prng.c @@ -43,6 +43,10 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "prng.h" /* single, global prng structure */ @@ -66,7 +70,11 @@ ctr_prng_init(rand_source_func_t random_source) { return status; /* initialize aes ctr context with random key */ - status = aes_icm_context_init(&ctr_prng.state, tmp_key); +#ifdef OPENSSL + status = aes_icm_openssl_context_init(&ctr_prng.state, tmp_key, 30); +#else + status = aes_icm_context_init(&ctr_prng.state, tmp_key, 30); +#endif if (status) return status; @@ -79,10 +87,8 @@ ctr_prng_get_octet_string(void *dest, uint32_t len) { /* * if we need to re-initialize the prng, do so now - * - * avoid 32-bit overflows by subtracting instead of adding */ - if (ctr_prng.octet_count > MAX_PRNG_OUT_LEN - len) { + if ((aes_icm_bytes_encrypted(&ctr_prng.state) + len) > 0xffff) { status = ctr_prng_init(ctr_prng.rand); if (status) return status; diff --git a/third_party/srtp/crypto/rng/prng.c b/third_party/srtp/crypto/rng/prng.c index 69350a48..208e2680 100644 --- a/third_party/srtp/crypto/rng/prng.c +++ b/third_party/srtp/crypto/rng/prng.c @@ -43,6 +43,10 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "prng.h" /* single, global prng structure */ @@ -51,7 +55,7 @@ x917_prng_t x917_prng; err_status_t x917_prng_init(rand_source_func_t random_source) { - v128_t tmp_key; + uint8_t tmp_key[16]; err_status_t status; /* initialize output count to zero */ @@ -61,12 +65,12 @@ x917_prng_init(rand_source_func_t random_source) { x917_prng.rand = random_source; /* initialize secret key from random source */ - status = random_source((uint8_t *)&tmp_key, 16); + status = random_source(tmp_key, 16); if (status) return status; /* expand aes key */ - aes_expand_encryption_key(&tmp_key, x917_prng.key); + aes_expand_encryption_key(tmp_key, 16, &x917_prng.key); /* initialize prng state from random source */ status = x917_prng.rand((uint8_t *)&x917_prng.state, 16); @@ -108,7 +112,7 @@ x917_prng_get_octet_string(uint8_t *dest, uint32_t len) { v128_copy(&buffer, &x917_prng.state); /* apply aes to buffer */ - aes_encrypt(&buffer, x917_prng.key); + aes_encrypt(&buffer, &x917_prng.key); /* write data to output */ *dest++ = buffer.v8[0]; @@ -132,7 +136,7 @@ x917_prng_get_octet_string(uint8_t *dest, uint32_t len) { buffer.v32[0] ^= t; /* encrypt buffer */ - aes_encrypt(&buffer, x917_prng.key); + aes_encrypt(&buffer, &x917_prng.key); /* copy buffer into state */ v128_copy(&x917_prng.state, &buffer); @@ -150,7 +154,7 @@ x917_prng_get_octet_string(uint8_t *dest, uint32_t len) { v128_copy(&buffer, &x917_prng.state); /* apply aes to buffer */ - aes_encrypt(&buffer, x917_prng.key); + aes_encrypt(&buffer, &x917_prng.key); /* write data to output */ for (i=0; i < tail_len; i++) { @@ -163,7 +167,7 @@ x917_prng_get_octet_string(uint8_t *dest, uint32_t len) { buffer.v32[0] ^= t; /* encrypt buffer */ - aes_encrypt(&buffer, x917_prng.key); + aes_encrypt(&buffer, &x917_prng.key); /* copy buffer into state */ v128_copy(&x917_prng.state, &buffer); diff --git a/third_party/srtp/crypto/rng/rand_source.c b/third_party/srtp/crypto/rng/rand_source.c index 3d01d25a..1eb6fbb0 100644 --- a/third_party/srtp/crypto/rng/rand_source.c +++ b/third_party/srtp/crypto/rng/rand_source.c @@ -42,15 +42,14 @@ * */ -#include "srtp_config.h" +#include "config.h" -#if defined(DEV_URANDOM) || defined(PJ_DEV_URANDOM) +#ifdef DEV_URANDOM # include <fcntl.h> /* for open() */ # include <unistd.h> /* for close() */ -#elif (_MSC_VER >= 1400) -#define _CRT_RAND_S +#elif defined(HAVE_RAND_S) +# define _CRT_RAND_S # include <stdlib.h> -# include <stdio.h> #else # include <stdio.h> #endif @@ -87,18 +86,11 @@ rand_source_init(void) { dev_random_fdes = open(DEV_URANDOM, O_RDONLY); if (dev_random_fdes < 0) return err_status_init_fail; -#elif defined(PJ_DEV_URANDOM) - /* open random source for reading */ - dev_random_fdes = open(PJ_DEV_URANDOM, O_RDONLY); - if (dev_random_fdes < 0) { - err_report(3,"Ugh: /dev/urandom not present, using rand() instead"); - return err_status_ok; /* it's ok, it'll fallback to using rand() */ - } -#elif (_MSC_VER >= 1400) +#elif defined(HAVE_RAND_S) dev_random_fdes = RAND_SOURCE_READY; #else - /* no random source available; let the user know */
- err_report(err_level_info, "WARNING: no real random source present!\n"); + /* no random source available; let the user know */ + fprintf(stderr, "WARNING: no real random source present!\n"); dev_random_fdes = RAND_SOURCE_READY; #endif return err_status_ok; @@ -113,35 +105,32 @@ rand_source_get_octet_string(void *dest, uint32_t len) { * written */ #ifdef DEV_URANDOM - if (read(dev_random_fdes, dest, len) != len) - return err_status_fail; -#elif 0 && (_MSC_VER >= 1400) /* disabled rand_s, causing assertion 'rand_s not supported' in vs8 */ - unsigned int *dst = dest; + uint8_t *dst = (uint8_t *)dest; while (len) { - unsigned int val = 0; - errno_t err = rand_s(&val); - if (err != 0) - { - return err_status_fail; - } - - *dst++ = val; - len--; + ssize_t num_read = read(dev_random_fdes, dst, len); + if (num_read <= 0 || num_read > len) + return err_status_fail; + len -= num_read; + dst += num_read; } -#else +#elif defined(HAVE_RAND_S) uint8_t *dst = (uint8_t *)dest; -
-#ifdef PJ_DEV_URANDOM - /* First try with /dev/urandom, if it's opened */ - if (dev_random_fdes >= 0) { - if (read(dev_random_fdes, dest, len) == len) - return err_status_ok; /* success */ - }
-#endif + while (len) + { + unsigned int val; + errno_t err = rand_s(&val); + if (err != 0) + return err_status_fail; + + *dst++ = val & 0xff; + len--; + } +#else /* Generic C-library (rand()) version */ /* This is a random source of last resort */ + uint8_t *dst = (uint8_t *)dest; while (len) { int val = rand(); @@ -157,19 +146,13 @@ rand_source_get_octet_string(void *dest, uint32_t len) { err_status_t rand_source_deinit(void) { -#ifndef PJ_DEV_URANDOM if (dev_random_fdes < 0) return err_status_dealloc_fail; /* well, we haven't really failed, * * but there is something wrong */ +#ifdef DEV_URANDOM + close(dev_random_fdes); #endif -
-#if defined(DEV_URANDOM) || defined(PJ_DEV_URANDOM) - if (dev_random_fdes >= 0) - close(dev_random_fdes); - - dev_random_fdes = RAND_SOURCE_NOT_READY;
-#endif + dev_random_fdes = RAND_SOURCE_NOT_READY; return err_status_ok; } - diff --git a/third_party/srtp/crypto/rng/rand_source_ossl.c b/third_party/srtp/crypto/rng/rand_source_ossl.c new file mode 100644 index 00000000..4bca6ac8 --- /dev/null +++ b/third_party/srtp/crypto/rng/rand_source_ossl.c @@ -0,0 +1,70 @@ +/* + * rand_source_ossl.c + * + * implements a random source based on OpenSSL RAND_bytes() + * + * John A. Foley + * Cisco Systems, Inc. + */ +/* + * + * Copyright(c) 2013, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met:crypto/test/aes_calc.c + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include "rand_source.h" +#include <openssl/rand.h> + + +err_status_t rand_source_init (void) +{ + return err_status_ok; +} + +err_status_t rand_source_get_octet_string (void *dest, uint32_t len) +{ + if (RAND_bytes(dest, len) == 1) { + return err_status_ok; + } else { + return err_status_fail; + } +} + +err_status_t rand_source_deinit (void) +{ + return err_status_ok; +} diff --git a/third_party/srtp/crypto/test/aes_calc.c b/third_party/srtp/crypto/test/aes_calc.c index 2fac07ae..b40e3726 100644 --- a/third_party/srtp/crypto/test/aes_calc.c +++ b/third_party/srtp/crypto/test/aes_calc.c @@ -8,6 +8,42 @@ */ /* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* Example usage (with first NIST FIPS 197 test case): @@ -18,6 +54,10 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include "aes.h" #include <stdio.h> #include <string.h> @@ -28,14 +68,16 @@ usage(char *prog_name) { exit(255); } -#define AES_KEY_LEN 16 +#define AES_MAX_KEY_LEN 32 int main (int argc, char *argv[]) { - v128_t data, key; + v128_t data; + uint8_t key[AES_MAX_KEY_LEN]; aes_expanded_key_t exp_key; - int len; - int verbose; + int key_len, len; + int verbose = 0; + err_status_t status; if (argc == 3) { /* we're not in verbose mode */ @@ -54,22 +96,23 @@ main (int argc, char *argv[]) { } /* read in key, checking length */ - if (strlen(argv[1]) > AES_KEY_LEN*2) { + if (strlen(argv[1]) > AES_MAX_KEY_LEN*2) { fprintf(stderr, "error: too many digits in key " - "(should be %d hexadecimal digits, found %u)\n", - AES_KEY_LEN*2, (unsigned)strlen(argv[1])); + "(should be at most %d hexadecimal digits, found %u)\n", + AES_MAX_KEY_LEN*2, (unsigned)strlen(argv[1])); exit(1); } - len = hex_string_to_octet_string((char *)&key, argv[1], AES_KEY_LEN*2); + len = hex_string_to_octet_string((char*)key, argv[1], AES_MAX_KEY_LEN*2); /* check that hex string is the right length */ - if (len < AES_KEY_LEN*2) { + if (len != 32 && len != 48 && len != 64) { fprintf(stderr, - "error: too few digits in key " - "(should be %d hexadecimal digits, found %d)\n", - AES_KEY_LEN*2, len); + "error: bad number of digits in key " + "(should be 32/48/64 hexadecimal digits, found %d)\n", + len); exit(1); } + key_len = len/2; /* read in plaintext, checking length */ if (strlen(argv[2]) > 16*2) { @@ -95,13 +138,18 @@ main (int argc, char *argv[]) { } /* encrypt plaintext */ - aes_expand_encryption_key(&key, exp_key); + status = aes_expand_encryption_key(key, key_len, &exp_key); + if (status) { + fprintf(stderr, + "error: AES key expansion failed.\n"); + exit(1); + } - aes_encrypt(&data, exp_key); + aes_encrypt(&data, &exp_key); /* write ciphertext to output */ if (verbose) { - printf("key:\t\t%s\n", v128_hex_string(&key)); + printf("key:\t\t%s\n", octet_string_hex_string(key, key_len)); printf("ciphertext:\t"); } printf("%s\n", v128_hex_string(&data)); diff --git a/third_party/srtp/crypto/test/cipher_driver.c b/third_party/srtp/crypto/test/cipher_driver.c index 25ca90af..9c9c2203 100644 --- a/third_party/srtp/crypto/test/cipher_driver.c +++ b/third_party/srtp/crypto/test/cipher_driver.c @@ -9,7 +9,7 @@ /* * - * Copyright (c) 2001-2006, Cisco Systems, Inc. + * Copyright (c) 2001-2006,2013 Cisco Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,12 +43,21 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include <stdio.h> /* for printf() */ #include <stdlib.h> /* for rand() */ #include <string.h> /* for memset() */ -#include <unistd.h> /* for getopt() */ +#include "getopt_s.h" #include "cipher.h" +#ifdef OPENSSL +#include "aes_icm_ossl.h" +#include "aes_gcm_ossl.h" +#else #include "aes_icm.h" +#endif #include "null_cipher.h" #define PRINT_DEBUG 0 @@ -114,16 +123,28 @@ check_status(err_status_t s) { extern cipher_type_t null_cipher; extern cipher_type_t aes_icm; +#ifndef OPENSSL extern cipher_type_t aes_cbc; +#else +#ifndef SRTP_NO_AES192 +extern cipher_type_t aes_icm_192; +#endif +extern cipher_type_t aes_icm_256; +extern cipher_type_t aes_gcm_128_openssl; +extern cipher_type_t aes_gcm_256_openssl; +#endif int main(int argc, char *argv[]) { cipher_t *c = NULL; err_status_t status; - unsigned char test_key[20] = { + unsigned char test_key[48] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13 + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, }; int q; unsigned do_timing_test = 0; @@ -132,7 +153,7 @@ main(int argc, char *argv[]) { /* process input arguments */ while (1) { - q = getopt(argc, argv, "tva"); + q = getopt_s(argc, argv, "tva"); if (q == -1) break; switch (q) { @@ -168,22 +189,53 @@ main(int argc, char *argv[]) { for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) cipher_driver_test_array_throughput(&aes_icm, 30, num_cipher); +#ifndef OPENSSL + for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) + cipher_driver_test_array_throughput(&aes_icm, 46, num_cipher); + for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) cipher_driver_test_array_throughput(&aes_cbc, 16, num_cipher); + for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) + cipher_driver_test_array_throughput(&aes_cbc, 32, num_cipher); +#else +#ifndef SRTP_NO_AES192 + for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) + cipher_driver_test_array_throughput(&aes_icm_192, 38, num_cipher); +#endif + for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) + cipher_driver_test_array_throughput(&aes_icm_256, 46, num_cipher); + + for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) { + cipher_driver_test_array_throughput(&aes_gcm_128_openssl, AES_128_GCM_KEYSIZE_WSALT, num_cipher); + } + + for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) { + cipher_driver_test_array_throughput(&aes_gcm_256_openssl, AES_256_GCM_KEYSIZE_WSALT, num_cipher); + } +#endif } if (do_validation) { cipher_driver_self_test(&null_cipher); cipher_driver_self_test(&aes_icm); +#ifndef OPENSSL cipher_driver_self_test(&aes_cbc); +#else +#ifndef SRTP_NO_AES192 + cipher_driver_self_test(&aes_icm_192); +#endif + cipher_driver_self_test(&aes_icm_256); + cipher_driver_self_test(&aes_gcm_128_openssl); + cipher_driver_self_test(&aes_gcm_256_openssl); +#endif } /* do timing and/or buffer_test on null_cipher */ - status = cipher_type_alloc(&null_cipher, &c, 0); + status = cipher_type_alloc(&null_cipher, &c, 0, 0); check_status(status); - status = cipher_init(c, NULL, direction_encrypt); + status = cipher_init(c, NULL); check_status(status); if (do_timing_test) @@ -196,14 +248,14 @@ main(int argc, char *argv[]) { check_status(status); - /* run the throughput test on the aes_icm cipher */ - status = cipher_type_alloc(&aes_icm, &c, 30); + /* run the throughput test on the aes_icm cipher (128-bit key) */ + status = cipher_type_alloc(&aes_icm, &c, 30, 0); if (status) { fprintf(stderr, "error: can't allocate cipher\n"); exit(status); } - status = cipher_init(c, test_key, direction_encrypt); + status = cipher_init(c, test_key); check_status(status); if (do_timing_test) @@ -216,8 +268,73 @@ main(int argc, char *argv[]) { status = cipher_dealloc(c); check_status(status); - - return 0; + + /* repeat the tests with 256-bit keys */ +#ifndef OPENSSL + status = cipher_type_alloc(&aes_icm, &c, 46, 0); +#else + status = cipher_type_alloc(&aes_icm_256, &c, 46, 0); +#endif + if (status) { + fprintf(stderr, "error: can't allocate cipher\n"); + exit(status); + } + + status = cipher_init(c, test_key); + check_status(status); + + if (do_timing_test) + cipher_driver_test_throughput(c); + + if (do_validation) { + status = cipher_driver_test_buffering(c); + check_status(status); + } + + status = cipher_dealloc(c); + check_status(status); + +#ifdef OPENSSL + /* run the throughput test on the aes_gcm_128_openssl cipher */ + status = cipher_type_alloc(&aes_gcm_128_openssl, &c, AES_128_GCM_KEYSIZE_WSALT, 8); + if (status) { + fprintf(stderr, "error: can't allocate GCM 128 cipher\n"); + exit(status); + } + status = cipher_init(c, test_key); + check_status(status); + if (do_timing_test) { + cipher_driver_test_throughput(c); + } + + if (do_validation) { + status = cipher_driver_test_buffering(c); + check_status(status); + } + status = cipher_dealloc(c); + check_status(status); + + /* run the throughput test on the aes_gcm_256_openssl cipher */ + status = cipher_type_alloc(&aes_gcm_256_openssl, &c, AES_256_GCM_KEYSIZE_WSALT, 16); + if (status) { + fprintf(stderr, "error: can't allocate GCM 256 cipher\n"); + exit(status); + } + status = cipher_init(c, test_key); + check_status(status); + if (do_timing_test) { + cipher_driver_test_throughput(c); + } + + if (do_validation) { + status = cipher_driver_test_buffering(c); + check_status(status); + } + status = cipher_dealloc(c); + check_status(status); +#endif + + return 0; } void @@ -225,9 +342,9 @@ cipher_driver_test_throughput(cipher_t *c) { int i; int min_enc_len = 32; int max_enc_len = 2048; /* should be a power of two */ - int num_trials = 100000; + int num_trials = 1000000; - printf("timing %s throughput:\n", c->type->description); + printf("timing %s throughput, key length %d:\n", c->type->description, c->key_len); fflush(stdout); for (i=min_enc_len; i <= max_enc_len; i = i * 2) printf("msg len: %d\tgigabits per second: %f\n", @@ -256,11 +373,12 @@ cipher_driver_self_test(cipher_type_t *ct) { * calls */ +#define INITIAL_BUFLEN 1024 err_status_t cipher_driver_test_buffering(cipher_t *c) { int i, j, num_trials = 1000; - unsigned len, buflen = 1024; - uint8_t buffer0[buflen], buffer1[buflen], *current, *end; + unsigned len, buflen = INITIAL_BUFLEN; + uint8_t buffer0[INITIAL_BUFLEN], buffer1[INITIAL_BUFLEN], *current, *end; uint8_t idx[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34 @@ -273,11 +391,12 @@ cipher_driver_test_buffering(cipher_t *c) { for (i=0; i < num_trials; i++) { /* set buffers to zero */ - for (j=0; j < buflen; j++) + for (j=0; j < (int) buflen; j++) { buffer0[j] = buffer1[j] = 0; + } /* initialize cipher */ - status = cipher_set_iv(c, idx); + status = cipher_set_iv(c, idx, direction_encrypt); if (status) return status; @@ -287,7 +406,7 @@ cipher_driver_test_buffering(cipher_t *c) { return status; /* re-initialize cipher */ - status = cipher_set_iv(c, idx); + status = cipher_set_iv(c, idx, direction_encrypt); if (status) return status; @@ -316,7 +435,7 @@ cipher_driver_test_buffering(cipher_t *c) { } /* compare buffers */ - for (j=0; j < buflen; j++) + for (j=0; j < (int) buflen; j++) { if (buffer0[j] != buffer1[j]) { #if PRINT_DEBUG printf("test case %d failed at byte %d\n", i, j); @@ -325,6 +444,7 @@ cipher_driver_test_buffering(cipher_t *c) { #endif return err_status_algo_fail; } + } } printf("passed\n"); @@ -348,6 +468,9 @@ cipher_array_alloc_init(cipher_t ***ca, int num_ciphers, err_status_t status; uint8_t *key; cipher_t **cipher_array; + /* pad klen allocation, to handle aes_icm reading 16 bytes for the + 14-byte salt */ + int klen_pad = ((klen + 15) >> 4) << 4; /* allocate array of pointers to ciphers */ cipher_array = (cipher_t **) malloc(sizeof(cipher_t *) * num_ciphers); @@ -358,7 +481,7 @@ cipher_array_alloc_init(cipher_t ***ca, int num_ciphers, *ca = cipher_array; /* allocate key */ - key = crypto_alloc(klen); + key = crypto_alloc(klen_pad); if (key == NULL) { free(cipher_array); return err_status_alloc_fail; @@ -368,14 +491,16 @@ cipher_array_alloc_init(cipher_t ***ca, int num_ciphers, for (i=0; i < num_ciphers; i++) { /* allocate cipher */ - status = cipher_type_alloc(ctype, cipher_array, klen); + status = cipher_type_alloc(ctype, cipher_array, klen, 16); if (status) return status; /* generate random key and initialize cipher */ for (j=0; j < klen; j++) key[j] = (uint8_t) rand(); - status = cipher_init(*cipher_array, key, direction_encrypt); + for (; j < klen_pad; j++) + key[j] = 0; + status = cipher_init(*cipher_array, key); if (status) return status; @@ -387,6 +512,8 @@ cipher_array_alloc_init(cipher_t ***ca, int num_ciphers, cipher_array++; } + crypto_free(key); + return err_status_ok; } @@ -423,24 +550,28 @@ cipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher, v128_t nonce; clock_t timer; unsigned char *enc_buf; - int cipher_index = 0; + int cipher_index = rand() % num_cipher; - - enc_buf = crypto_alloc(octets_in_buffer); + /* Over-alloc, for NIST CBC padding */ + enc_buf = crypto_alloc(octets_in_buffer+17); if (enc_buf == NULL) return 0; /* indicate bad parameters by returning null */ + memset(enc_buf, 0, octets_in_buffer); /* time repeated trials */ v128_set_to_zero(&nonce); timer = clock(); for(i=0; i < num_trials; i++, nonce.v32[3] = i) { + /* length parameter to cipher_encrypt is in/out -- out is total, padded + * length -- so reset it each time. */ + unsigned octets_to_encrypt = octets_in_buffer; + + /* encrypt buffer with cipher */ + cipher_set_iv(cipher_array[cipher_index], &nonce, direction_encrypt); + cipher_encrypt(cipher_array[cipher_index], enc_buf, &octets_to_encrypt); /* choose a cipher at random from the array*/ cipher_index = (*((uint32_t *)enc_buf)) % num_cipher; - - /* encrypt buffer with cipher */ - cipher_set_iv(cipher_array[cipher_index], &nonce); - cipher_encrypt(cipher_array[cipher_index], enc_buf, &octets_in_buffer); } timer = clock() - timer; @@ -451,7 +582,7 @@ cipher_array_bits_per_second(cipher_t *cipher_array[], int num_cipher, return 0; } - return CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer; + return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer; } void @@ -459,10 +590,10 @@ cipher_array_test_throughput(cipher_t *ca[], int num_cipher) { int i; int min_enc_len = 16; int max_enc_len = 2048; /* should be a power of two */ - int num_trials = 10000; + int num_trials = 1000000; - printf("timing %s throughput with array size %d:\n", - (ca[0])->type->description, num_cipher); + printf("timing %s throughput with key length %d, array size %d:\n", + (ca[0])->type->description, (ca[0])->key_len, num_cipher); fflush(stdout); for (i=min_enc_len; i <= max_enc_len; i = i * 4) printf("msg len: %d\tgigabits per second: %f\n", i, diff --git a/third_party/srtp/crypto/test/datatypes_driver.c b/third_party/srtp/crypto/test/datatypes_driver.c index f1866524..4b5e46c7 100644 --- a/third_party/srtp/crypto/test/datatypes_driver.c +++ b/third_party/srtp/crypto/test/datatypes_driver.c @@ -44,6 +44,10 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include <stdio.h> /* for printf() */ #include <string.h> /* for strlen() */ #include "datatypes.h" @@ -205,7 +209,7 @@ test_hex_string_funcs(void) { void print_string(char *s) { - int i; + size_t i; printf("%s\n", s); printf("strlen(s) = %u\n", (unsigned)strlen(s)); printf("{ "); diff --git a/third_party/srtp/crypto/test/env.c b/third_party/srtp/crypto/test/env.c index 37a6e273..6cc0f958 100644 --- a/third_party/srtp/crypto/test/env.c +++ b/third_party/srtp/crypto/test/env.c @@ -49,7 +49,9 @@ int main(void) { int err_count = 0; +#ifndef OPENSSL char *str; +#endif #ifdef WORDS_BIGENDIAN printf("CPU set to big-endian\t\t\t(WORDS_BIGENDIAN == 1)\n"); @@ -80,6 +82,7 @@ main(void) { printf("using stdout for error reporting\t(ERR_REPORTING_STDOUT == 1)\n"); #endif +#ifndef OPENSSL #ifdef DEV_URANDOM str = DEV_URANDOM; #else @@ -90,6 +93,7 @@ main(void) { if (strcmp("", str) == 0) { err_count++; } +#endif if (err_count) printf("warning: configuration is probably in error " diff --git a/third_party/srtp/crypto/test/kernel_driver.c b/third_party/srtp/crypto/test/kernel_driver.c index 8ef8a5f4..188637cd 100644 --- a/third_party/srtp/crypto/test/kernel_driver.c +++ b/third_party/srtp/crypto/test/kernel_driver.c @@ -43,8 +43,12 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include <stdio.h> /* for printf() */ -#include <unistd.h> /* for getopt() */ +#include "getopt_s.h" #include "crypto_kernel.h" void @@ -55,7 +59,6 @@ usage(char *prog_name) { int main (int argc, char *argv[]) { - extern char *optarg; int q; int do_validation = 0; err_status_t status; @@ -73,7 +76,7 @@ main (int argc, char *argv[]) { /* process input arguments */ while (1) { - q = getopt(argc, argv, "vd:"); + q = getopt_s(argc, argv, "vd:"); if (q == -1) break; switch (q) { @@ -81,9 +84,9 @@ main (int argc, char *argv[]) { do_validation = 1; break; case 'd': - status = crypto_kernel_set_debug_module(optarg, 1); + status = crypto_kernel_set_debug_module(optarg_s, 1); if (status) { - printf("error: set debug module (%s) failed\n", optarg); + printf("error: set debug module (%s) failed\n", optarg_s); exit(1); } break; diff --git a/third_party/srtp/crypto/test/rand_gen.c b/third_party/srtp/crypto/test/rand_gen.c index ccea097f..b8051d5b 100644 --- a/third_party/srtp/crypto/test/rand_gen.c +++ b/third_party/srtp/crypto/test/rand_gen.c @@ -43,8 +43,12 @@ */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include <stdio.h> /* for printf() */ -#include <unistd.h> /* for getopt() */ +#include "getopt_s.h" #include "crypto_kernel.h" /* @@ -68,7 +72,6 @@ usage(char *prog_name) { int main (int argc, char *argv[]) { - extern char *optarg; int q; int num_octets = 0; unsigned do_list_mods = 0; @@ -86,14 +89,14 @@ main (int argc, char *argv[]) { /* process input arguments */ while (1) { - q = getopt(argc, argv, "ld:n:"); + q = getopt_s(argc, argv, "ld:n:"); if (q == -1) break; switch (q) { case 'd': - status = crypto_kernel_set_debug_module(optarg, 1); + status = crypto_kernel_set_debug_module(optarg_s, 1); if (status) { - printf("error: set debug module (%s) failed\n", optarg); + printf("error: set debug module (%s) failed\n", optarg_s); exit(1); } break; @@ -101,7 +104,7 @@ main (int argc, char *argv[]) { do_list_mods = 1; break; case 'n': - num_octets = atoi(optarg); + num_octets = atoi(optarg_s); if (num_octets < 0 || num_octets > BUF_LEN) usage(argv[0]); break; diff --git a/third_party/srtp/crypto/test/rand_gen_soak.c b/third_party/srtp/crypto/test/rand_gen_soak.c new file mode 100644 index 00000000..b0e67a73 --- /dev/null +++ b/third_party/srtp/crypto/test/rand_gen_soak.c @@ -0,0 +1,116 @@ +/* + * Soak test the RNG for exhaustion failures + */ + +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + +#include <stdio.h> /* for printf() */ +#include "getopt_s.h" +#include "crypto_kernel.h" + +#define BUF_LEN (MAX_PRINT_STRING_LEN/2) + +int main(int argc, char *argv[]) +{ + int q; + int num_octets = 0; + err_status_t status; + uint32_t iterations = 0; + int print_values = 0; + + if (argc == 1) { + exit(255); + } + + status = crypto_kernel_init(); + if (status) { + printf("error: crypto_kernel init failed\n"); + exit(1); + } + + while (1) { + q = getopt_s(argc, argv, "pvn:"); + if (q == -1) { + break; + } + switch (q) { + case 'p': + print_values = 1; + break; + case 'n': + num_octets = atoi(optarg_s); + if (num_octets < 0 || num_octets > BUF_LEN) { + exit(255); + } + break; + case 'v': + num_octets = 30; + print_values = 0; + break; + default: + exit(255); + } + } + + if (num_octets > 0) { + while (iterations < 300000) { + uint8_t buffer[BUF_LEN]; + + status = crypto_get_random(buffer, num_octets); + if (status) { + printf("iteration %d error: failure in random source\n", iterations); + exit(255); + } else if (print_values) { + printf("%s\n", octet_string_hex_string(buffer, num_octets)); + } + iterations++; + } + } + + status = crypto_kernel_shutdown(); + if (status) { + printf("error: crypto_kernel shutdown failed\n"); + exit(1); + } + + return 0; +} + diff --git a/third_party/srtp/crypto/test/sha1_driver.c b/third_party/srtp/crypto/test/sha1_driver.c index f7cb6ca2..6adfad17 100644 --- a/third_party/srtp/crypto/test/sha1_driver.c +++ b/third_party/srtp/crypto/test/sha1_driver.c @@ -43,8 +43,14 @@ * */ +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif + #include <stdio.h> +#include <string.h> #include "sha1.h" +#include "datatypes.h" #define SHA_PASS 0 #define SHA_FAIL 1 @@ -113,17 +119,17 @@ sha1_test_case_validate(const hash_test_case_t *test_case) { if (0 == memcmp(test_case->hash, hash_value, 20)) { #if VERBOSE printf("PASSED: reference value: %s\n", - octet_string_hex_string((uint8_t *)test_case->hash, 20)); + octet_string_hex_string((const uint8_t *)test_case->hash, 20)); printf("PASSED: computed value: %s\n", - octet_string_hex_string((uint8_t *)hash_value, 20)); + octet_string_hex_string((const uint8_t *)hash_value, 20)); #endif return err_status_ok; } printf("reference value: %s\n", - octet_string_hex_string((uint8_t *)test_case->hash, 20)); + octet_string_hex_string((const uint8_t *)test_case->hash, 20)); printf("computed value: %s\n", - octet_string_hex_string((uint8_t *)hash_value, 20)); + octet_string_hex_string((const uint8_t *)hash_value, 20)); return err_status_algo_fail; @@ -136,7 +142,7 @@ struct hex_sha1_test_case_t { }; err_status_t -sha1_add_test_cases() { +sha1_add_test_cases(void) { int i; err_status_t err; @@ -485,6 +491,21 @@ sha1_add_test_cases() { return err_status_ok; } +err_status_t +sha1_dealloc_test_cases(void) { + hash_test_case_t *t, *next; + + for (t = sha1_test_case_list; t != NULL; t = next) { + next = t->next_test_case; + free(t); + } + + sha1_test_case_list = NULL; + + return err_status_ok; +} + + err_status_t sha1_validate(void) { @@ -510,6 +531,8 @@ sha1_validate(void) { test_case = test_case->next_test_case; } + sha1_dealloc_test_cases(); + return err_status_ok; } diff --git a/third_party/srtp/crypto/test/stat_driver.c b/third_party/srtp/crypto/test/stat_driver.c index 09cc44a6..962f7484 100644 --- a/third_party/srtp/crypto/test/stat_driver.c +++ b/third_party/srtp/crypto/test/stat_driver.c @@ -7,11 +7,51 @@ * Cisco Systems, Inc. */ +/* + * + * Copyright (c) 2001-2006, Cisco Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef HAVE_CONFIG_H + #include <config.h> +#endif #include <stdio.h> /* for printf() */ #include "err.h" #include "stat.h" +#include "srtp.h" #include "cipher.h" @@ -32,12 +72,18 @@ err_check(err_status_t s) { int main (int argc, char *argv[]) { - uint8_t buffer[2500]; + uint8_t buffer[2532]; unsigned int buf_len = 2500; int i, j; extern cipher_type_t aes_icm; +#ifdef OPENSSL + extern cipher_type_t aes_gcm_128_openssl; + extern cipher_type_t aes_gcm_256_openssl; +#endif cipher_t *c; - uint8_t key[30] = { + uint8_t key[46] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, @@ -49,6 +95,7 @@ main (int argc, char *argv[]) { printf("statistical tests driver\n"); + v128_set_to_zero(&nonce); for (i=0; i < 2500; i++) buffer[i] = 0; @@ -69,9 +116,9 @@ main (int argc, char *argv[]) { /* set buffer to cipher output */ for (i=0; i < 2500; i++) buffer[i] = 0; - err_check(cipher_type_alloc(&aes_icm, &c, 30)); - err_check(cipher_init(c, key, direction_encrypt)); - err_check(cipher_set_iv(c, &nonce)); + err_check(cipher_type_alloc(&aes_icm, &c, 30, 0)); + err_check(cipher_init(c, key)); + err_check(cipher_set_iv(c, &nonce, direction_encrypt)); err_check(cipher_encrypt(c, buffer, &buf_len)); /* run tests on cipher outout */ printf("monobit %d\n", stat_test_monobit(buffer)); @@ -86,7 +133,7 @@ main (int argc, char *argv[]) { for (i=0; i < 2500; i++) buffer[i] = 0; nonce.v32[3] = i; - err_check(cipher_set_iv(c, &nonce)); + err_check(cipher_set_iv(c, &nonce, direction_encrypt)); err_check(cipher_encrypt(c, buffer, &buf_len)); if (stat_test_runs(buffer)) { num_fail++; @@ -97,5 +144,103 @@ main (int argc, char *argv[]) { printf("(nota bene: a small fraction of stat_test failures does not \n" "indicate that the random source is invalid)\n"); + err_check(cipher_dealloc(c)); + + printf("running stat_tests on AES-256-ICM, expecting success\n"); + /* set buffer to cipher output */ + for (i=0; i < 2500; i++) + buffer[i] = 0; + err_check(cipher_type_alloc(&aes_icm, &c, 46, 0)); + err_check(cipher_init(c, key)); + err_check(cipher_set_iv(c, &nonce, direction_encrypt)); + err_check(cipher_encrypt(c, buffer, &buf_len)); + /* run tests on cipher outout */ + printf("monobit %d\n", stat_test_monobit(buffer)); + printf("poker %d\n", stat_test_poker(buffer)); + printf("runs %d\n", stat_test_runs(buffer)); + + printf("runs test (please be patient): "); + fflush(stdout); + num_fail = 0; + v128_set_to_zero(&nonce); + for(j=0; j < num_trials; j++) { + for (i=0; i < 2500; i++) + buffer[i] = 0; + nonce.v32[3] = i; + err_check(cipher_set_iv(c, &nonce, direction_encrypt)); + err_check(cipher_encrypt(c, buffer, &buf_len)); + if (stat_test_runs(buffer)) { + num_fail++; + } + } + +#ifdef OPENSSL + { + printf("running stat_tests on AES-128-GCM, expecting success\n"); + /* set buffer to cipher output */ + for (i=0; i < 2500; i++) { + buffer[i] = 0; + } + err_check(cipher_type_alloc(&aes_gcm_128_openssl, &c, AES_128_GCM_KEYSIZE_WSALT, 8)); + err_check(cipher_init(c, key)); + err_check(cipher_set_iv(c, &nonce, direction_encrypt)); + err_check(cipher_encrypt(c, buffer, &buf_len)); + /* run tests on cipher outout */ + printf("monobit %d\n", stat_test_monobit(buffer)); + printf("poker %d\n", stat_test_poker(buffer)); + printf("runs %d\n", stat_test_runs(buffer)); + fflush(stdout); + num_fail = 0; + v128_set_to_zero(&nonce); + for(j=0; j < num_trials; j++) { + for (i=0; i < 2500; i++) { + buffer[i] = 0; + } + nonce.v32[3] = i; + err_check(cipher_set_iv(c, &nonce, direction_encrypt)); + err_check(cipher_encrypt(c, buffer, &buf_len)); + buf_len = 2500; + if (stat_test_runs(buffer)) { + num_fail++; + } + } + + printf("running stat_tests on AES-256-GCM, expecting success\n"); + /* set buffer to cipher output */ + for (i=0; i < 2500; i++) { + buffer[i] = 0; + } + err_check(cipher_type_alloc(&aes_gcm_256_openssl, &c, AES_256_GCM_KEYSIZE_WSALT, 16)); + err_check(cipher_init(c, key)); + err_check(cipher_set_iv(c, &nonce, direction_encrypt)); + err_check(cipher_encrypt(c, buffer, &buf_len)); + /* run tests on cipher outout */ + printf("monobit %d\n", stat_test_monobit(buffer)); + printf("poker %d\n", stat_test_poker(buffer)); + printf("runs %d\n", stat_test_runs(buffer)); + fflush(stdout); + num_fail = 0; + v128_set_to_zero(&nonce); + for(j=0; j < num_trials; j++) { + for (i=0; i < 2500; i++) { + buffer[i] = 0; + } + nonce.v32[3] = i; + err_check(cipher_set_iv(c, &nonce, direction_encrypt)); + err_check(cipher_encrypt(c, buffer, &buf_len)); + buf_len = 2500; + if (stat_test_runs(buffer)) { + num_fail++; + } + } + } +#endif + + printf("%d failures in %d tests\n", num_fail, num_trials); + printf("(nota bene: a small fraction of stat_test failures does not \n" + "indicate that the random source is invalid)\n"); + + err_check(cipher_dealloc(c)); + return 0; } |