Index: pjproject/trunk/third_party/srtp/crypto/cipher/cipher.c
===================================================================
--- pjproject/trunk/third_party/srtp/crypto/cipher/cipher.c	(revision 2660)
+++ pjproject/trunk/third_party/srtp/crypto/cipher/cipher.c	(revision 5261)
@@ -11,5 +11,5 @@
 /*
  *	
- * Copyright (c) 2001-2006, Cisco Systems, Inc.
+ * Copyright (c) 2001-2006,2013 Cisco Systems, Inc.
  * All rights reserved.
  * 
@@ -45,5 +45,10 @@
  */
 
+#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()  */
@@ -72,6 +77,6 @@
 
 /* 
- * 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
  */
@@ -82,10 +87,11 @@
 
 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;
@@ -106,7 +112,6 @@
    */  
   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;
@@ -118,5 +123,5 @@
     
     /* initialize cipher */
-    status = cipher_init(c, test_case->key, direction_encrypt);
+    status = cipher_init(c, test_case->key);
     if (status) {
       cipher_dealloc(c);
@@ -137,5 +142,5 @@
 
     /* 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);
@@ -143,4 +148,22 @@
     } 
     
+    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;
@@ -151,4 +174,16 @@
     }
     
+    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,
@@ -185,5 +220,5 @@
 
     /* 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);
@@ -204,5 +239,5 @@
 
     /* 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);
@@ -210,4 +245,19 @@
     } 
     
+    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;
@@ -261,6 +311,6 @@
 
   /* 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;
@@ -270,5 +320,5 @@
   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];
@@ -298,5 +348,5 @@
         
     /* initialize cipher */
-    status = cipher_init(c, key, direction_encrypt);
+    status = cipher_init(c, key);
     if (status) {
       cipher_dealloc(c);
@@ -305,9 +355,24 @@
 
     /* 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 */
@@ -317,4 +382,15 @@
       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",
@@ -325,14 +401,28 @@
      * decrypt the ciphertext
      */
-    status = cipher_init(c, key, direction_decrypt);
-    if (status) {
-      cipher_dealloc(c);
-      return status;
-    }
-    status = cipher_set_iv(c, test_case->idx);
+    status = cipher_init(c, key);
+    if (status) {
+      cipher_dealloc(c);
+      return status;
+    }
+    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) {
@@ -345,6 +435,7 @@
 
     /* 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++)
@@ -361,9 +452,21 @@
   }
 
-  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);
+}
 
 /*
@@ -394,5 +497,5 @@
   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);
   }
