Преглед изворни кода

security: make into a library

ambrop7 пре 15 година
родитељ
комит
9805b0929d

+ 1 - 0
CMakeLists.txt

@@ -82,6 +82,7 @@ add_subdirectory(predicate)
 add_subdirectory(nspr_support)
 add_subdirectory(server_connection)
 add_subdirectory(listener)
+add_subdirectory(security)
 
 # example programs
 add_subdirectory(examples)

+ 1 - 1
client/CMakeLists.txt

@@ -6,7 +6,7 @@ add_executable(badvpn-client
     DataProto.c
     PasswordSender.c
 )
-target_link_libraries(badvpn-client system flow tuntap server_conection listener ${LIBCRYPTO_LIBRARIES} ${NSPR_LIBRARIES} ${NSS_LIBRARIES})
+target_link_libraries(badvpn-client system flow tuntap server_conection listener security ${NSPR_LIBRARIES} ${NSS_LIBRARIES})
 
 install(
     TARGETS badvpn-client

+ 7 - 7
client/client.c

@@ -37,11 +37,11 @@
 #include <misc/ipv4_proto.h>
 #include <misc/igmp_proto.h>
 #include <misc/nsskey.h>
-#include <misc/brandom.h>
 #include <misc/loglevel.h>
 #include <misc/dead.h>
 #include <misc/loggers_string.h>
 #include <structure/LinkedList2.h>
+#include <security/BRandom.h>
 #include <nspr_support/DummyPRFileDesc.h>
 #include <nspr_support/BSocketPRFileDesc.h>
 #include <system/BLog.h>
@@ -574,7 +574,7 @@ int main (int argc, char *argv[])
     num_peers = 0;
     
     // init peers by ID hash table
-    brandom_randomize((uint8_t *)&peers_by_id_initval, sizeof(peers_by_id_initval));
+    BRandom_randomize((uint8_t *)&peers_by_id_initval, sizeof(peers_by_id_initval));
     if (!HashTable_Init(
         &peers_by_id,
         OFFSET_DIFF(struct peer_data, id, table_node),
@@ -587,7 +587,7 @@ int main (int argc, char *argv[])
     }
     
     // init MAC address table
-    brandom_randomize((uint8_t *)&mac_table_initval, sizeof(mac_table_initval));
+    BRandom_randomize((uint8_t *)&mac_table_initval, sizeof(mac_table_initval));
     if (!HashTable_Init(
         &mac_table,
         OFFSET_DIFF(struct mac_table_entry, mac, table_node),
@@ -600,7 +600,7 @@ int main (int argc, char *argv[])
     }
     
     // init multicast MAC address table
-    brandom_randomize((uint8_t *)&multicast_table_initval, sizeof(multicast_table_initval));
+    BRandom_randomize((uint8_t *)&multicast_table_initval, sizeof(multicast_table_initval));
     if (!HashTable_Init(
         &multicast_table,
         OFFSET_DIFF(struct multicast_table_entry, sig, table_node),
@@ -2712,7 +2712,7 @@ int peer_udp_bind (struct peer_data *peer, int addr_index)
     
     // generate and set encryption key
     if (SPPROTO_HAVE_ENCRYPTION(sp_params)) {
-        brandom_randomize(key, sizeof(key));
+        BRandom_randomize(key, sizeof(key));
         DatagramPeerIO_SetEncryptionKey(&peer->pio.udp.pio, key);
     }
     
@@ -2982,8 +2982,8 @@ int peer_udp_send_seed (struct peer_data *peer)
     
     // generate seed
     peer->pio.udp.sendseed_sent_id = peer->pio.udp.sendseed_nextid;
-    brandom_randomize(peer->pio.udp.sendseed_sent_key, key_len);
-    brandom_randomize(peer->pio.udp.sendseed_sent_iv, iv_len);
+    BRandom_randomize(peer->pio.udp.sendseed_sent_key, key_len);
+    BRandom_randomize(peer->pio.udp.sendseed_sent_iv, iv_len);
     
     // set as sent, increment next seed ID
     peer->pio.udp.sendseed_sent = 1;

+ 4 - 4
examples/CMakeLists.txt

@@ -13,13 +13,13 @@ add_executable(fairqueue_test fairqueue_test.c)
 target_link_libraries(fairqueue_test system flow)
 
 add_executable(fairqueue_test2 fairqueue_test2.c)
-target_link_libraries(fairqueue_test2 system flow ${LIBCRYPTO_LIBRARIES})
+target_link_libraries(fairqueue_test2 system flow security)
 
 add_executable(bheap_test bheap_test.c)
-target_link_libraries(bheap_test ${LIBCRYPTO_LIBRARIES})
+target_link_libraries(bheap_test security)
 
 add_executable(bavl_test bavl_test.c)
-target_link_libraries(bavl_test ${LIBCRYPTO_LIBRARIES})
+target_link_libraries(bavl_test security)
 
 add_executable(hashtable_bench hashtable_bench.c)
-target_link_libraries(hashtable_bench system ${LIBCRYPTO_LIBRARIES})
+target_link_libraries(hashtable_bench system security)

+ 2 - 2
examples/RandomPacketSink.h

@@ -25,7 +25,7 @@
 
 #include <stdio.h>
 
-#include <misc/brandom.h>
+#include <security/BRandom.h>
 #include <system/BReactor.h>
 #include <flow/PacketPassInterface.h>
 
@@ -41,7 +41,7 @@ static int _RandomPacketSink_input_handler_send (RandomPacketSink *s, uint8_t *d
     fwrite(data, data_len, 1, stdout);
     
     uint8_t r;
-    brandom_randomize(&r, sizeof(r));
+    BRandom_randomize(&r, sizeof(r));
     if (r&(uint8_t)1) {
         printf("' accepting\n");
         return 1;

+ 3 - 3
examples/bavl_test.c

@@ -23,9 +23,9 @@
 #include <stdlib.h>
 
 #include <misc/offset.h>
-#include <misc/brandom.h>
 #include <misc/debug.h>
 #include <structure/BAVL.h>
+#include <security/BRandom.h>
 
 struct mynode {
     int used;
@@ -106,7 +106,7 @@ int main (int argc, char **argv)
     */
     
     printf("Inserting random values...\n");
-    brandom_randomize((uint8_t *)values_ins, num_nodes * sizeof(int));
+    BRandom_randomize((uint8_t *)values_ins, num_nodes * sizeof(int));
     for (int i = 0; i < num_nodes; i++) {
         nodes[i].num = values_ins[i];
         if (BAVL_Insert(&avl, &nodes[i].avl_node, NULL)) {
@@ -119,7 +119,7 @@ int main (int argc, char **argv)
     
     printf("Removing random entries...\n");
     int removed = 0;
-    brandom_randomize((uint8_t *)values, num_random_delete * sizeof(int));
+    BRandom_randomize((uint8_t *)values, num_random_delete * sizeof(int));
     for (int i = 0; i < num_random_delete; i++) {
         int index = (((unsigned int *)values)[i] % num_nodes);
         struct mynode *node = nodes + index;

+ 2 - 2
examples/bheap_test.c

@@ -21,8 +21,8 @@
  */
 
 #include <misc/offset.h>
-#include <misc/brandom.h>
 #include <structure/BHeap.h>
+#include <security/BRandom.h>
 
 struct mynode {
     int used;
@@ -99,7 +99,7 @@ int main (int argc, char **argv)
     //print_heap(&heap);
     
     printf("Removing random entries...\n");
-    brandom_randomize((uint8_t *)values, num_random_delete * sizeof(int));
+    BRandom_randomize((uint8_t *)values, num_random_delete * sizeof(int));
     for (int i = 0; i < num_random_delete; i++) {
         int index = (((unsigned int *)values)[i] % num_nodes);
         struct mynode *node = nodes + index;

+ 3 - 3
examples/hashtable_bench.c

@@ -23,10 +23,10 @@
 #include <stdlib.h>
 
 #include <misc/offset.h>
-#include <misc/brandom.h>
 #include <misc/debug.h>
 #include <misc/jenkins_hash.h>
 #include <structure/HashTable.h>
+#include <security/BRandom.h>
 
 struct mynode {
     int used;
@@ -86,7 +86,7 @@ int main (int argc, char **argv)
     }
     
     printf("Inserting random values...\n");
-    brandom_randomize((uint8_t *)values_ins, num_nodes * sizeof(int));
+    BRandom_randomize((uint8_t *)values_ins, num_nodes * sizeof(int));
     for (int i = 0; i < num_nodes; i++) {
         nodes[i].num = values_ins[i];
         if (HashTable_Insert(&ht, &nodes[i].hash_node)) {
@@ -99,7 +99,7 @@ int main (int argc, char **argv)
     
     printf("Removing random entries...\n");
     int removed = 0;
-    brandom_randomize((uint8_t *)values, num_random_delete * sizeof(int));
+    BRandom_randomize((uint8_t *)values, num_random_delete * sizeof(int));
     for (int i = 0; i < num_random_delete; i++) {
         int index = (((unsigned int *)values)[i] % num_nodes);
         struct mynode *node = nodes + index;

+ 1 - 1
flooder/CMakeLists.txt

@@ -1,5 +1,5 @@
 add_executable(badvpn-flooder flooder.c)
-target_link_libraries(badvpn-flooder system flow server_conection ${LIBCRYPTO_LIBRARIES} ${NSPR_LIBRARIES} ${NSS_LIBRARIES})
+target_link_libraries(badvpn-flooder system flow server_conection ${NSPR_LIBRARIES} ${NSS_LIBRARIES})
 
 install(
     TARGETS badvpn-flooder

+ 1 - 1
flow/CMakeLists.txt

@@ -28,4 +28,4 @@ add_library(flow
     PacketProtoFlow.c
     SinglePacketSender.c
 )
-target_link_libraries(flow system)
+target_link_libraries(flow system security)

+ 1 - 1
flow/SPProtoDecoder.c

@@ -25,7 +25,7 @@
 #include <misc/debug.h>
 #include <misc/balign.h>
 #include <misc/byteorder.h>
-#include <security/bhash.h>
+#include <security/BHash.h>
 
 #include <flow/SPProtoDecoder.h>
 

+ 3 - 3
flow/SPProtoEncoder.c

@@ -25,9 +25,9 @@
 
 #include <misc/debug.h>
 #include <misc/balign.h>
-#include <misc/brandom.h>
 #include <misc/offset.h>
-#include <security/bhash.h>
+#include <security/BRandom.h>
+#include <security/BHash.h>
 
 #include <flow/SPProtoEncoder.h>
 
@@ -88,7 +88,7 @@ static int encode_packet (SPProtoEncoder *o)
             plaintext[i] = 0;
         }
         // generate IV
-        brandom_randomize(o->out, o->group->enc_block_size);
+        BRandom_randomize(o->out, o->group->enc_block_size);
         // copy IV because BEncryption_Encrypt changes the IV
         uint8_t iv[o->group->enc_block_size];
         memcpy(iv, o->out, o->group->enc_block_size);

+ 1 - 1
protocol/spproto.h

@@ -54,7 +54,7 @@
 
 #include <misc/debug.h>
 #include <misc/balign.h>
-#include <security/bhash.h>
+#include <security/BHash.h>
 #include <security/BEncryption.h>
 #include <security/OTPCalculator.h>
 

+ 227 - 0
security/BEncryption.c

@@ -0,0 +1,227 @@
+/**
+ * @file BEncryption.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <security/BEncryption.h>
+
+int BEncryption_cipher_valid (int cipher)
+{
+    switch (cipher) {
+        case BENCRYPTION_CIPHER_BLOWFISH:
+        case BENCRYPTION_CIPHER_AES:
+            return 1;
+        default:
+            return 0;
+    }
+}
+
+int BEncryption_cipher_block_size (int cipher)
+{
+    switch (cipher) {
+        case BENCRYPTION_CIPHER_BLOWFISH:
+            return BENCRYPTION_CIPHER_BLOWFISH_BLOCK_SIZE;
+        case BENCRYPTION_CIPHER_AES:
+            return BENCRYPTION_CIPHER_AES_BLOCK_SIZE;
+        default:
+            ASSERT(0)
+            return 0;
+    }
+}
+
+int BEncryption_cipher_key_size (int cipher)
+{
+    switch (cipher) {
+        case BENCRYPTION_CIPHER_BLOWFISH:
+            return BENCRYPTION_CIPHER_BLOWFISH_KEY_SIZE;
+        case BENCRYPTION_CIPHER_AES:
+            return BENCRYPTION_CIPHER_AES_KEY_SIZE;
+        default:
+            ASSERT(0)
+            return 0;
+    }
+}
+
+void BEncryption_Init (BEncryption *enc, int mode, int cipher, uint8_t *key)
+{
+    ASSERT(!(mode&~(BENCRYPTION_MODE_ENCRYPT|BENCRYPTION_MODE_DECRYPT)))
+    ASSERT((mode&BENCRYPTION_MODE_ENCRYPT) || (mode&BENCRYPTION_MODE_DECRYPT))
+    
+    enc->mode = mode;
+    enc->cipher = cipher;
+    
+    #ifdef BADVPN_USE_CRYPTODEV
+    
+    switch (enc->cipher) {
+        case BENCRYPTION_CIPHER_AES:
+            enc->cryptodev.cipher = CRYPTO_AES_CBC;
+            break;
+        default:
+            goto fail1;
+    }
+    
+    if ((enc->cryptodev.fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
+        DEBUG("failed to open /dev/crypto");
+        goto fail1;
+    }
+    
+    if (ioctl(enc->cryptodev.fd, CRIOGET, &enc->cryptodev.cfd)) {
+        DEBUG("failed ioctl(CRIOGET)");
+        goto fail2;
+    }
+    
+    struct session_op sess;
+    memset(&sess, 0, sizeof(sess));
+    sess.cipher = enc->cryptodev.cipher;
+    sess.keylen = BEncryption_cipher_key_size(enc->cipher);
+    sess.key = key;
+    if (ioctl(enc->cryptodev.cfd, CIOCGSESSION, &sess)) {
+        DEBUG("failed ioctl(CIOCGSESSION)");
+        goto fail3;
+    }
+    
+    enc->cryptodev.ses = sess.ses;
+    enc->use_cryptodev = 1;
+    
+    goto success;
+    
+fail3:
+    ASSERT_FORCE(close(enc->cryptodev.cfd) == 0)
+fail2:
+    ASSERT_FORCE(close(enc->cryptodev.fd) == 0)
+fail1:
+    
+    enc->use_cryptodev = 0;
+    
+    #endif
+    
+    int res;
+    
+    switch (enc->cipher) {
+        case BENCRYPTION_CIPHER_BLOWFISH:
+            BF_set_key(&enc->blowfish, BENCRYPTION_CIPHER_BLOWFISH_KEY_SIZE, key);
+            break;
+        case BENCRYPTION_CIPHER_AES:
+            if (enc->mode&BENCRYPTION_MODE_ENCRYPT) {
+                res = AES_set_encrypt_key(key, 128, &enc->aes.encrypt);
+                ASSERT(res >= 0)
+            }
+            if (enc->mode&BENCRYPTION_MODE_DECRYPT) {
+                res = AES_set_decrypt_key(key, 128, &enc->aes.decrypt);
+                ASSERT(res >= 0)
+            }
+            break;
+        default:
+            ASSERT(0)
+            ;
+    }
+    
+success:
+    // init debug object
+    DebugObject_Init(&enc->d_obj);
+}
+
+void BEncryption_Free (BEncryption *enc)
+{
+    // free debug object
+    DebugObject_Free(&enc->d_obj);
+    
+    #ifdef BADVPN_USE_CRYPTODEV
+    
+    if (enc->use_cryptodev) {
+        ASSERT_FORCE(ioctl(enc->cryptodev.cfd, CIOCFSESSION, &enc->cryptodev.ses) == 0)
+        ASSERT_FORCE(close(enc->cryptodev.cfd) == 0)
+        ASSERT_FORCE(close(enc->cryptodev.fd) == 0)
+    }
+    
+    #endif
+}
+
+void BEncryption_Encrypt (BEncryption *enc, uint8_t *in, uint8_t *out, int len, uint8_t *iv)
+{
+    ASSERT(enc->mode&BENCRYPTION_MODE_ENCRYPT)
+    ASSERT(len >= 0)
+    ASSERT(len % BEncryption_cipher_block_size(enc->cipher) == 0)
+    
+    #ifdef BADVPN_USE_CRYPTODEV
+    
+    if (enc->use_cryptodev) {
+        struct crypt_op cryp;
+        memset(&cryp, 0, sizeof(cryp));
+        cryp.ses = enc->cryptodev.ses;
+        cryp.len = len;
+        cryp.src = in;
+        cryp.dst = out;
+        cryp.iv = iv;
+        cryp.op = COP_ENCRYPT;
+        ASSERT_FORCE(ioctl(enc->cryptodev.cfd, CIOCCRYPT, &cryp) == 0)
+        
+        return;
+    }
+    
+    #endif
+    
+    switch (enc->cipher) {
+        case BENCRYPTION_CIPHER_BLOWFISH:
+            BF_cbc_encrypt(in, out, len, &enc->blowfish, iv, BF_ENCRYPT);
+            break;
+        case BENCRYPTION_CIPHER_AES:
+            AES_cbc_encrypt(in, out, len, &enc->aes.encrypt, iv, AES_ENCRYPT);
+            break;
+        default:
+            ASSERT(0);
+    }
+}
+
+void BEncryption_Decrypt (BEncryption *enc, uint8_t *in, uint8_t *out, int len, uint8_t *iv)
+{
+    ASSERT(enc->mode&BENCRYPTION_MODE_DECRYPT)
+    ASSERT(len >= 0)
+    ASSERT(len % BEncryption_cipher_block_size(enc->cipher) == 0)
+    
+    #ifdef BADVPN_USE_CRYPTODEV
+    
+    if (enc->use_cryptodev) {
+        struct crypt_op cryp;
+        memset(&cryp, 0, sizeof(cryp));
+        cryp.ses = enc->cryptodev.ses;
+        cryp.len = len;
+        cryp.src = in;
+        cryp.dst = out;
+        cryp.iv = iv;
+        cryp.op = COP_DECRYPT;
+        ASSERT_FORCE(ioctl(enc->cryptodev.cfd, CIOCCRYPT, &cryp) == 0)
+        
+        return;
+    }
+    
+    #endif
+    
+    switch (enc->cipher) {
+        case BENCRYPTION_CIPHER_BLOWFISH:
+            BF_cbc_encrypt(in, out, len, &enc->blowfish, iv, BF_DECRYPT);
+            break;
+        case BENCRYPTION_CIPHER_AES:
+            AES_cbc_encrypt(in, out, len, &enc->aes.decrypt, iv, AES_DECRYPT);
+            break;
+        default:
+            ASSERT(0);
+    }
+}

+ 7 - 211
security/BEncryption.h

@@ -91,7 +91,7 @@ typedef struct {
  * @param cipher cipher number
  * @return 1 if valid, 0 if not
  */
-static int BEncryption_cipher_valid (int cipher);
+int BEncryption_cipher_valid (int cipher);
 
 /**
  * Returns the block size of a cipher.
@@ -99,7 +99,7 @@ static int BEncryption_cipher_valid (int cipher);
  * @param cipher cipher number. Must be valid.
  * @return block size in bytes
  */
-static int BEncryption_cipher_block_size (int cipher);
+int BEncryption_cipher_block_size (int cipher);
 
 /**
  * Returns the key size of a cipher.
@@ -107,7 +107,7 @@ static int BEncryption_cipher_block_size (int cipher);
  * @param cipher cipher number. Must be valid.
  * @return key size in bytes
  */
-static int BEncryption_cipher_key_size (int cipher);
+int BEncryption_cipher_key_size (int cipher);
 
 /**
  * Initializes the object.
@@ -119,14 +119,14 @@ static int BEncryption_cipher_key_size (int cipher);
  * @param cipher cipher number. Must be valid.
  * @param key encryption key
  */
-static void BEncryption_Init (BEncryption *enc, int mode, int cipher, uint8_t *key);
+void BEncryption_Init (BEncryption *enc, int mode, int cipher, uint8_t *key);
 
 /**
  * Frees the object.
  * 
  * @param enc the object
  */
-static void BEncryption_Free (BEncryption *enc);
+void BEncryption_Free (BEncryption *enc);
 
 /**
  * Encrypts data.
@@ -141,7 +141,7 @@ static void BEncryption_Free (BEncryption *enc);
  * @param iv initialization vector. Updated such that continuing a previous encryption
  *           starting with the updated IV is equivalent to performing just one encryption.
  */
-static void BEncryption_Encrypt (BEncryption *enc, uint8_t *in, uint8_t *out, int len, uint8_t *iv);
+void BEncryption_Encrypt (BEncryption *enc, uint8_t *in, uint8_t *out, int len, uint8_t *iv);
 
 /**
  * Decrypts data.
@@ -156,210 +156,6 @@ static void BEncryption_Encrypt (BEncryption *enc, uint8_t *in, uint8_t *out, in
  * @param iv initialization vector. Updated such that continuing a previous decryption
  *           starting with the updated IV is equivalent to performing just one decryption.
  */
-static void BEncryption_Decrypt (BEncryption *enc, uint8_t *in, uint8_t *out, int len, uint8_t *iv);
-
-int BEncryption_cipher_valid (int cipher)
-{
-    switch (cipher) {
-        case BENCRYPTION_CIPHER_BLOWFISH:
-        case BENCRYPTION_CIPHER_AES:
-            return 1;
-        default:
-            return 0;
-    }
-}
-
-int BEncryption_cipher_block_size (int cipher)
-{
-    switch (cipher) {
-        case BENCRYPTION_CIPHER_BLOWFISH:
-            return BENCRYPTION_CIPHER_BLOWFISH_BLOCK_SIZE;
-        case BENCRYPTION_CIPHER_AES:
-            return BENCRYPTION_CIPHER_AES_BLOCK_SIZE;
-        default:
-            ASSERT(0)
-            return 0;
-    }
-}
-
-int BEncryption_cipher_key_size (int cipher)
-{
-    switch (cipher) {
-        case BENCRYPTION_CIPHER_BLOWFISH:
-            return BENCRYPTION_CIPHER_BLOWFISH_KEY_SIZE;
-        case BENCRYPTION_CIPHER_AES:
-            return BENCRYPTION_CIPHER_AES_KEY_SIZE;
-        default:
-            ASSERT(0)
-            return 0;
-    }
-}
-
-void BEncryption_Init (BEncryption *enc, int mode, int cipher, uint8_t *key)
-{
-    ASSERT(!(mode&~(BENCRYPTION_MODE_ENCRYPT|BENCRYPTION_MODE_DECRYPT)))
-    ASSERT((mode&BENCRYPTION_MODE_ENCRYPT) || (mode&BENCRYPTION_MODE_DECRYPT))
-    
-    enc->mode = mode;
-    enc->cipher = cipher;
-    
-    #ifdef BADVPN_USE_CRYPTODEV
-    
-    switch (enc->cipher) {
-        case BENCRYPTION_CIPHER_AES:
-            enc->cryptodev.cipher = CRYPTO_AES_CBC;
-            break;
-        default:
-            goto fail1;
-    }
-    
-    if ((enc->cryptodev.fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
-        DEBUG("failed to open /dev/crypto");
-        goto fail1;
-    }
-    
-    if (ioctl(enc->cryptodev.fd, CRIOGET, &enc->cryptodev.cfd)) {
-        DEBUG("failed ioctl(CRIOGET)");
-        goto fail2;
-    }
-    
-    struct session_op sess;
-    memset(&sess, 0, sizeof(sess));
-    sess.cipher = enc->cryptodev.cipher;
-    sess.keylen = BEncryption_cipher_key_size(enc->cipher);
-    sess.key = key;
-    if (ioctl(enc->cryptodev.cfd, CIOCGSESSION, &sess)) {
-        DEBUG("failed ioctl(CIOCGSESSION)");
-        goto fail3;
-    }
-    
-    enc->cryptodev.ses = sess.ses;
-    enc->use_cryptodev = 1;
-    
-    goto success;
-    
-fail3:
-    ASSERT_FORCE(close(enc->cryptodev.cfd) == 0)
-fail2:
-    ASSERT_FORCE(close(enc->cryptodev.fd) == 0)
-fail1:
-    
-    enc->use_cryptodev = 0;
-    
-    #endif
-    
-    int res;
-    
-    switch (enc->cipher) {
-        case BENCRYPTION_CIPHER_BLOWFISH:
-            BF_set_key(&enc->blowfish, BENCRYPTION_CIPHER_BLOWFISH_KEY_SIZE, key);
-            break;
-        case BENCRYPTION_CIPHER_AES:
-            if (enc->mode&BENCRYPTION_MODE_ENCRYPT) {
-                res = AES_set_encrypt_key(key, 128, &enc->aes.encrypt);
-                ASSERT(res >= 0)
-            }
-            if (enc->mode&BENCRYPTION_MODE_DECRYPT) {
-                res = AES_set_decrypt_key(key, 128, &enc->aes.decrypt);
-                ASSERT(res >= 0)
-            }
-            break;
-        default:
-            ASSERT(0)
-            ;
-    }
-    
-success:
-    // init debug object
-    DebugObject_Init(&enc->d_obj);
-}
-
-void BEncryption_Free (BEncryption *enc)
-{
-    // free debug object
-    DebugObject_Free(&enc->d_obj);
-    
-    #ifdef BADVPN_USE_CRYPTODEV
-    
-    if (enc->use_cryptodev) {
-        ASSERT_FORCE(ioctl(enc->cryptodev.cfd, CIOCFSESSION, &enc->cryptodev.ses) == 0)
-        ASSERT_FORCE(close(enc->cryptodev.cfd) == 0)
-        ASSERT_FORCE(close(enc->cryptodev.fd) == 0)
-    }
-    
-    #endif
-}
-
-void BEncryption_Encrypt (BEncryption *enc, uint8_t *in, uint8_t *out, int len, uint8_t *iv)
-{
-    ASSERT(enc->mode&BENCRYPTION_MODE_ENCRYPT)
-    ASSERT(len >= 0)
-    ASSERT(len % BEncryption_cipher_block_size(enc->cipher) == 0)
-    
-    #ifdef BADVPN_USE_CRYPTODEV
-    
-    if (enc->use_cryptodev) {
-        struct crypt_op cryp;
-        memset(&cryp, 0, sizeof(cryp));
-        cryp.ses = enc->cryptodev.ses;
-        cryp.len = len;
-        cryp.src = in;
-        cryp.dst = out;
-        cryp.iv = iv;
-        cryp.op = COP_ENCRYPT;
-        ASSERT_FORCE(ioctl(enc->cryptodev.cfd, CIOCCRYPT, &cryp) == 0)
-        
-        return;
-    }
-    
-    #endif
-    
-    switch (enc->cipher) {
-        case BENCRYPTION_CIPHER_BLOWFISH:
-            BF_cbc_encrypt(in, out, len, &enc->blowfish, iv, BF_ENCRYPT);
-            break;
-        case BENCRYPTION_CIPHER_AES:
-            AES_cbc_encrypt(in, out, len, &enc->aes.encrypt, iv, AES_ENCRYPT);
-            break;
-        default:
-            ASSERT(0);
-    }
-}
-
-void BEncryption_Decrypt (BEncryption *enc, uint8_t *in, uint8_t *out, int len, uint8_t *iv)
-{
-    ASSERT(enc->mode&BENCRYPTION_MODE_DECRYPT)
-    ASSERT(len >= 0)
-    ASSERT(len % BEncryption_cipher_block_size(enc->cipher) == 0)
-    
-    #ifdef BADVPN_USE_CRYPTODEV
-    
-    if (enc->use_cryptodev) {
-        struct crypt_op cryp;
-        memset(&cryp, 0, sizeof(cryp));
-        cryp.ses = enc->cryptodev.ses;
-        cryp.len = len;
-        cryp.src = in;
-        cryp.dst = out;
-        cryp.iv = iv;
-        cryp.op = COP_DECRYPT;
-        ASSERT_FORCE(ioctl(enc->cryptodev.cfd, CIOCCRYPT, &cryp) == 0)
-        
-        return;
-    }
-    
-    #endif
-    
-    switch (enc->cipher) {
-        case BENCRYPTION_CIPHER_BLOWFISH:
-            BF_cbc_encrypt(in, out, len, &enc->blowfish, iv, BF_DECRYPT);
-            break;
-        case BENCRYPTION_CIPHER_AES:
-            AES_cbc_encrypt(in, out, len, &enc->aes.decrypt, iv, AES_DECRYPT);
-            break;
-        default:
-            ASSERT(0);
-    }
-}
+void BEncryption_Decrypt (BEncryption *enc, uint8_t *in, uint8_t *out, int len, uint8_t *iv);
 
 #endif

+ 62 - 0
security/BHash.c

@@ -0,0 +1,62 @@
+/**
+ * @file BHash.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <security/BHash.h>
+
+int BHash_type_valid (int type)
+{
+    switch (type) {
+        case BHASH_TYPE_MD5:
+        case BHASH_TYPE_SHA1:
+            return 1;
+        default:
+            return 0;
+    }
+}
+
+int BHash_size (int type)
+{
+    switch (type) {
+        case BHASH_TYPE_MD5:
+            return BHASH_TYPE_MD5_SIZE;
+        case BHASH_TYPE_SHA1:
+            return BHASH_TYPE_SHA1_SIZE;
+        default:
+            ASSERT(0)
+            return 0;
+    }
+}
+
+void BHash_calculate (int type, uint8_t *data, int data_len, uint8_t *out)
+{
+    switch (type) {
+        case BHASH_TYPE_MD5:
+            MD5(data, data_len, out);
+            break;
+        case BHASH_TYPE_SHA1:
+            SHA1(data, data_len, out);
+            break;
+        default:
+            ASSERT(0)
+            ;
+    }
+}

+ 4 - 43
security/bhash.h → security/BHash.h

@@ -1,5 +1,5 @@
 /**
- * @file bhash.h
+ * @file BHash.h
  * @author Ambroz Bizjak <ambrop7@gmail.com>
  * 
  * @section LICENSE
@@ -46,7 +46,7 @@
  * @param type hash type number
  * @return 1 if valid, 0 if not
  */
-static int BHash_type_valid (int type);
+int BHash_type_valid (int type);
 
 /**
  * Returns the size of a hash.
@@ -54,7 +54,7 @@ static int BHash_type_valid (int type);
  * @param cipher hash type number. Must be valid.
  * @return hash size in bytes
  */
-static int BHash_size (int type);
+int BHash_size (int type);
 
 /**
  * Calculates a hash.
@@ -64,45 +64,6 @@ static int BHash_size (int type);
  * @param data_len length of data
  * @param out the hash will be written here. Must not overlap with data.
  */
-static void BHash_calculate (int type, uint8_t *data, int data_len, uint8_t *out);
-
-int BHash_type_valid (int type)
-{
-    switch (type) {
-        case BHASH_TYPE_MD5:
-        case BHASH_TYPE_SHA1:
-            return 1;
-        default:
-            return 0;
-    }
-}
-
-int BHash_size (int type)
-{
-    switch (type) {
-        case BHASH_TYPE_MD5:
-            return BHASH_TYPE_MD5_SIZE;
-        case BHASH_TYPE_SHA1:
-            return BHASH_TYPE_SHA1_SIZE;
-        default:
-            ASSERT(0)
-            return 0;
-    }
-}
-
-void BHash_calculate (int type, uint8_t *data, int data_len, uint8_t *out)
-{
-    switch (type) {
-        case BHASH_TYPE_MD5:
-            MD5(data, data_len, out);
-            break;
-        case BHASH_TYPE_SHA1:
-            SHA1(data, data_len, out);
-            break;
-        default:
-            ASSERT(0)
-            ;
-    }
-}
+void BHash_calculate (int type, uint8_t *data, int data_len, uint8_t *out);
 
 #endif

+ 35 - 0
security/BRandom.c

@@ -0,0 +1,35 @@
+/**
+ * @file BRandom.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <openssl/rand.h>
+
+#include <misc/debug.h>
+
+#include <security/BRandom.h>
+
+void BRandom_randomize (uint8_t *buf, int len)
+{
+    ASSERT(len >= 0)
+    
+    DEBUG_ZERO_MEMORY(buf, len)
+    ASSERT_FORCE(RAND_bytes(buf, len) == 1)
+}

+ 4 - 14
misc/brandom.h → security/BRandom.h

@@ -1,5 +1,5 @@
 /**
- * @file brandom.h
+ * @file BRandom.h
  * @author Ambroz Bizjak <ambrop7@gmail.com>
  * 
  * @section LICENSE
@@ -24,27 +24,17 @@
  * Random data generation function.
  */
 
-#ifndef BADVPN_MISC_BRANDOM_H
-#define BADVPN_MISC_BRANDOM_H
+#ifndef BADVPN_SECURITY_BRANDOM_H
+#define BADVPN_SECURITY_BRANDOM_H
 
 #include <stdint.h>
 
-#include <openssl/rand.h>
-
-#include <misc/debug.h>
-
 /**
  * Generates random data.
  * 
  * @param buf buffer to write data into
  * @param len number of bytes to generate. Must be >=0.
  */
-static void brandom_randomize (uint8_t *buf, int len)
-{
-    ASSERT(len >= 0)
-    
-    DEBUG_ZERO_MEMORY(buf, len)
-    ASSERT_FORCE(RAND_bytes(buf, len) == 1)
-}
+void BRandom_randomize (uint8_t *buf, int len);
 
 #endif

+ 9 - 0
security/CMakeLists.txt

@@ -0,0 +1,9 @@
+add_library(security
+    BEncryption.c
+    BHash.c
+    BRandom.c
+    OTPCalculator.c
+    OTPChecker.c
+    OTPGenerator.c
+)
+target_link_libraries(security system ${LIBCRYPTO_LIBRARIES})

+ 105 - 0
security/OTPCalculator.c

@@ -0,0 +1,105 @@
+/**
+ * @file OTPCalculator.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <security/OTPCalculator.h>
+
+int OTPCalculator_Init (OTPCalculator *calc, int num_otps, int cipher)
+{
+    ASSERT(num_otps >= 0)
+    ASSERT(BEncryption_cipher_valid(cipher))
+    
+    // init arguments
+    calc->num_otps = num_otps;
+    calc->cipher = cipher;
+    
+    // remember block size
+    calc->block_size = BEncryption_cipher_block_size(calc->cipher);
+    
+    // calculate number of blocks
+    calc->num_blocks = BDIVIDE_UP(calc->num_otps * sizeof(otp_t), calc->block_size);
+    
+    // allocate buffer
+    calc->data = malloc(calc->num_blocks * calc->block_size);
+    if (!calc->data) {
+        goto fail0;
+    }
+    
+    // init debug object
+    DebugObject_Init(&calc->d_obj);
+    
+    return 1;
+    
+fail0:
+    return 0;
+}
+
+void OTPCalculator_Free (OTPCalculator *calc)
+{
+    // free debug object
+    DebugObject_Free(&calc->d_obj);
+    
+    // free buffer
+    free(calc->data);
+}
+
+otp_t * OTPCalculator_Generate (OTPCalculator *calc, uint8_t *key, uint8_t *iv, int shuffle)
+{
+    ASSERT(shuffle == 0 || shuffle == 1)
+    
+    // copy IV so it can be updated
+    uint8_t iv_work[calc->block_size];
+    memcpy(iv_work, iv, calc->block_size);
+    
+    // create zero block
+    uint8_t zero[calc->block_size];
+    memset(zero, 0, calc->block_size);
+    
+    // init encryptor
+    BEncryption encryptor;
+    BEncryption_Init(&encryptor, BENCRYPTION_MODE_ENCRYPT, calc->cipher, key);
+    
+    // encrypt zero blocks
+    for (int i = 0; i < calc->num_blocks; i++) {
+        BEncryption_Encrypt(&encryptor, zero, (uint8_t *)calc->data + i * calc->block_size, calc->block_size, iv_work);
+    }
+    
+    // free encryptor
+    BEncryption_Free(&encryptor);
+    
+    // shuffle if requested
+    if (shuffle) {
+        int i = 0;
+        while (i < calc->num_otps) {
+            uint16_t ints[256];
+            BRandom_randomize((uint8_t *)ints, sizeof(ints));
+            for (int j = 0; j < 256 && i < calc->num_otps; j++) {
+                int newIndex = i + (ints[j] % (calc->num_otps - i));
+                otp_t temp = calc->data[i];
+                calc->data[i] = calc->data[newIndex];
+                calc->data[newIndex] = temp;
+                i++;
+            }
+        }
+    }
+    
+    return calc->data;
+}

+ 4 - 86
security/OTPCalculator.h

@@ -32,7 +32,7 @@
 
 #include <misc/balign.h>
 #include <misc/debug.h>
-#include <misc/brandom.h>
+#include <security/BRandom.h>
 #include <security/BEncryption.h>
 #include <system/DebugObject.h>
 
@@ -62,14 +62,14 @@ typedef struct {
  *               according to {@link BEncryption_cipher_valid}.
  * @return 1 on success, 0 on failure
  */
-static int OTPCalculator_Init (OTPCalculator *calc, int num_otps, int cipher) WARN_UNUSED;
+int OTPCalculator_Init (OTPCalculator *calc, int num_otps, int cipher) WARN_UNUSED;
 
 /**
  * Frees the calculator.
  *
  * @param calc the object
  */
-static void OTPCalculator_Free (OTPCalculator *calc);
+void OTPCalculator_Free (OTPCalculator *calc);
 
 /**
  * Generates OTPs from the given key and IV.
@@ -82,88 +82,6 @@ static void OTPCalculator_Free (OTPCalculator *calc);
  *         in {@link OTPCalculator_Init}. Valid until the next generation or
  *         until the object is freed.
  */
-static otp_t * OTPCalculator_Generate (OTPCalculator *calc, uint8_t *key, uint8_t *iv, int shuffle);
-
-int OTPCalculator_Init (OTPCalculator *calc, int num_otps, int cipher)
-{
-    ASSERT(num_otps >= 0)
-    ASSERT(BEncryption_cipher_valid(cipher))
-    
-    // init arguments
-    calc->num_otps = num_otps;
-    calc->cipher = cipher;
-    
-    // remember block size
-    calc->block_size = BEncryption_cipher_block_size(calc->cipher);
-    
-    // calculate number of blocks
-    calc->num_blocks = BDIVIDE_UP(calc->num_otps * sizeof(otp_t), calc->block_size);
-    
-    // allocate buffer
-    calc->data = malloc(calc->num_blocks * calc->block_size);
-    if (!calc->data) {
-        goto fail0;
-    }
-    
-    // init debug object
-    DebugObject_Init(&calc->d_obj);
-    
-    return 1;
-    
-fail0:
-    return 0;
-}
-
-void OTPCalculator_Free (OTPCalculator *calc)
-{
-    // free debug object
-    DebugObject_Free(&calc->d_obj);
-    
-    // free buffer
-    free(calc->data);
-}
-
-otp_t * OTPCalculator_Generate (OTPCalculator *calc, uint8_t *key, uint8_t *iv, int shuffle)
-{
-    ASSERT(shuffle == 0 || shuffle == 1)
-    
-    // copy IV so it can be updated
-    uint8_t iv_work[calc->block_size];
-    memcpy(iv_work, iv, calc->block_size);
-    
-    // create zero block
-    uint8_t zero[calc->block_size];
-    memset(zero, 0, calc->block_size);
-    
-    // init encryptor
-    BEncryption encryptor;
-    BEncryption_Init(&encryptor, BENCRYPTION_MODE_ENCRYPT, calc->cipher, key);
-    
-    // encrypt zero blocks
-    for (int i = 0; i < calc->num_blocks; i++) {
-        BEncryption_Encrypt(&encryptor, zero, (uint8_t *)calc->data + i * calc->block_size, calc->block_size, iv_work);
-    }
-    
-    // free encryptor
-    BEncryption_Free(&encryptor);
-    
-    // shuffle if requested
-    if (shuffle) {
-        int i = 0;
-        while (i < calc->num_otps) {
-            uint16_t ints[256];
-            brandom_randomize((uint8_t *)ints, sizeof(ints));
-            for (int j = 0; j < 256 && i < calc->num_otps; j++) {
-                int newIndex = i + (ints[j] % (calc->num_otps - i));
-                otp_t temp = calc->data[i];
-                calc->data[i] = calc->data[newIndex];
-                calc->data[newIndex] = temp;
-                i++;
-            }
-        }
-    }
-    
-    return calc->data;
-}
+otp_t * OTPCalculator_Generate (OTPCalculator *calc, uint8_t *key, uint8_t *iv, int shuffle);
 
 #endif

+ 202 - 0
security/OTPChecker.c

@@ -0,0 +1,202 @@
+/**
+ * @file OTPChecker.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <security/OTPChecker.h>
+
+static void OTPChecker_Table_Empty (OTPChecker *mc, oc_table *t);
+static void OTPChecker_Table_AddOTP (OTPChecker *mc, oc_table *t, otp_t otp);
+static void OTPChecker_Table_Generate (OTPChecker *mc, oc_table *t, OTPCalculator *calc, uint8_t *key, uint8_t *iv);
+static int OTPChecker_Table_CheckOTP (OTPChecker *mc, oc_table *t, otp_t otp);
+
+void OTPChecker_Table_Empty (OTPChecker *mc, oc_table *t)
+{
+    for (int i = 0; i < mc->num_entries; i++) {
+        oc_table_entries_at(&mc->tables_params.tables_params, t, i)->avail = -1;
+    }
+}
+
+void OTPChecker_Table_AddOTP (OTPChecker *mc, oc_table *t, otp_t otp)
+{
+    // calculate starting index
+    int start_index = otp % mc->num_entries;
+    
+    // try indexes starting with the base position
+    for (int i = 0; i < mc->num_entries; i++) {
+        int index = BMODADD(start_index, i, mc->num_entries);
+        struct OTPChecker_entry *entry = oc_table_entries_at(&mc->tables_params.tables_params, t, index);
+        
+        // if we find a free index, use it
+        if (entry->avail < 0) {
+            entry->otp = otp;
+            entry->avail = 1;
+            return;
+        }
+        
+        // if we find a used index with the same mac,
+        // use it by incrementing its count
+        if (entry->otp == otp) {
+            entry->avail++;
+            return;
+        }
+    }
+    
+    // will never add more macs than we can hold
+    ASSERT(0)
+}
+
+void OTPChecker_Table_Generate (OTPChecker *mc, oc_table *t, OTPCalculator *calc, uint8_t *key, uint8_t *iv)
+{
+    // calculate values
+    otp_t *otps = OTPCalculator_Generate(calc, key, iv, 0);
+    
+    // empty table
+    OTPChecker_Table_Empty(mc ,t);
+    
+    // add calculated values to table
+    for (int i = 0; i < mc->num_otps; i++) {
+        OTPChecker_Table_AddOTP(mc, t, otps[i]);
+    }
+}
+
+int OTPChecker_Table_CheckOTP (OTPChecker *mc, oc_table *t, otp_t otp)
+{
+    // calculate starting index
+    int start_index = otp % mc->num_entries;
+    
+    // try indexes starting with the base position
+    for (int i = 0; i < mc->num_entries; i++) {
+        int index = BMODADD(start_index, i, mc->num_entries);
+        struct OTPChecker_entry *entry = oc_table_entries_at(&mc->tables_params.tables_params, t, index);
+        
+        // if we find an empty entry, there is no such mac
+        if (entry->avail < 0) {
+            return 0;
+        }
+        
+        // if we find a matching entry, check its count
+        if (entry->otp == otp) {
+            if (entry->avail > 0) {
+                entry->avail--;
+                return 1;
+            }
+            return 0;
+        }
+    }
+    
+    // there are always empty slots
+    ASSERT(0)
+    return 0;
+}
+
+int OTPChecker_Init (OTPChecker *mc, int num_otps, int cipher, int num_tables)
+{
+    ASSERT(num_otps > 0)
+    ASSERT(BEncryption_cipher_valid(cipher))
+    ASSERT(num_tables > 0)
+    
+    // init arguments
+    mc->num_otps = num_otps;
+    mc->num_tables = num_tables;
+    
+    // set number of entries
+    mc->num_entries = 2 * mc->num_otps;
+    
+    // set no tables used
+    mc->tables_used = 0;
+    mc->next_table = 0;
+    
+    // initialize calculator
+    if (!OTPCalculator_Init(&mc->calc, mc->num_otps, cipher)) {
+        goto fail0;
+    }
+    
+    // allocate tables
+    oc_tablesParams_Init(&mc->tables_params, mc->num_tables, mc->num_entries);
+    if (!(mc->tables = malloc(mc->tables_params.len))) {
+        goto fail1;
+    }
+    
+    // initialize tables
+    for (int i = 0; i < mc->num_tables; i++) {
+        OTPChecker_Table_Empty(mc, oc_tables_tables_at(&mc->tables_params, mc->tables, i));
+    }
+    
+    // init debug object
+    DebugObject_Init(&mc->d_obj);
+    
+    return 1;
+    
+fail1:
+    OTPCalculator_Free(&mc->calc);
+fail0:
+    return 0;
+}
+
+void OTPChecker_Free (OTPChecker *mc)
+{
+    // free debug object
+    DebugObject_Free(&mc->d_obj);
+    
+    // free tables
+    free(mc->tables);
+    
+    // free calculator
+    OTPCalculator_Free(&mc->calc);
+}
+
+void OTPChecker_AddSeed (OTPChecker *mc, uint16_t seed_id, uint8_t *key, uint8_t *iv)
+{
+    ASSERT(mc->next_table >= 0)
+    ASSERT(mc->next_table < mc->num_tables)
+    
+    // initialize next table
+    oc_table *table = oc_tables_tables_at(&mc->tables_params, mc->tables, mc->next_table);
+    *oc_table_id(&mc->tables_params.tables_params, table) = seed_id;
+    OTPChecker_Table_Generate(mc, table, &mc->calc, key, iv);
+    
+    // update next table number
+    mc->next_table = BMODADD(mc->next_table, 1, mc->num_tables);
+    // update number of used tables if not all are used yet
+    if (mc->tables_used < mc->num_tables) {
+        mc->tables_used++;
+    }
+}
+
+void OTPChecker_RemoveSeeds (OTPChecker *mc)
+{
+    mc->tables_used = 0;
+    mc->next_table = 0;
+}
+
+int OTPChecker_CheckOTP (OTPChecker *mc, uint16_t seed_id, otp_t otp)
+{
+    // try tables in reverse order
+    for (int i = 1; i <= mc->tables_used; i++) {
+        int table_index = BMODADD(mc->next_table, mc->num_tables - i, mc->num_tables);
+        oc_table *table = oc_tables_tables_at(&mc->tables_params, mc->tables, table_index);
+        if (*oc_table_id(&mc->tables_params.tables_params, table) == seed_id) {
+            return OTPChecker_Table_CheckOTP(mc, table, otp);
+        }
+    }
+    
+    return 0;
+}

+ 5 - 184
security/OTPChecker.h

@@ -67,14 +67,14 @@ typedef struct {
  * @param num_tables number of tables to keep, each for one seed. Must be >0.
  * @return 1 on success, 0 on failure
  */
-static int OTPChecker_Init (OTPChecker *mc, int num_otps, int cipher, int num_tables) WARN_UNUSED;
+int OTPChecker_Init (OTPChecker *mc, int num_otps, int cipher, int num_tables) WARN_UNUSED;
 
 /**
  * Frees the checker.
  *
  * @param mc the object
  */
-static void OTPChecker_Free (OTPChecker *mc);
+void OTPChecker_Free (OTPChecker *mc);
 
 /**
  * Adds a seed whose OTPs should be recognized.
@@ -84,14 +84,14 @@ static void OTPChecker_Free (OTPChecker *mc);
  * @param key encryption key
  * @param iv initialization vector
  */
-static void OTPChecker_AddSeed (OTPChecker *mc, uint16_t seed_id, uint8_t *key, uint8_t *iv);
+void OTPChecker_AddSeed (OTPChecker *mc, uint16_t seed_id, uint8_t *key, uint8_t *iv);
 
 /**
  * Removes all active seeds.
  *
  * @param mc the object
  */
-static void OTPChecker_RemoveSeeds (OTPChecker *mc);
+void OTPChecker_RemoveSeeds (OTPChecker *mc);
 
 /**
  * Checks an OTP.
@@ -101,185 +101,6 @@ static void OTPChecker_RemoveSeeds (OTPChecker *mc);
  * @param otp OTP to check
  * @return 1 if the OTP is valid, 0 if not
  */
-static int OTPChecker_CheckOTP (OTPChecker *mc, uint16_t seed_id, otp_t otp);
-
-static void OTPChecker_Table_Empty (OTPChecker *mc, oc_table *t);
-static void OTPChecker_Table_AddOTP (OTPChecker *mc, oc_table *t, otp_t otp);
-static void OTPChecker_Table_Generate (OTPChecker *mc, oc_table *t, OTPCalculator *calc, uint8_t *key, uint8_t *iv);
-static int OTPChecker_Table_CheckOTP (OTPChecker *mc, oc_table *t, otp_t otp);
-
-void OTPChecker_Table_Empty (OTPChecker *mc, oc_table *t)
-{
-    for (int i = 0; i < mc->num_entries; i++) {
-        oc_table_entries_at(&mc->tables_params.tables_params, t, i)->avail = -1;
-    }
-}
-
-void OTPChecker_Table_AddOTP (OTPChecker *mc, oc_table *t, otp_t otp)
-{
-    // calculate starting index
-    int start_index = otp % mc->num_entries;
-    
-    // try indexes starting with the base position
-    for (int i = 0; i < mc->num_entries; i++) {
-        int index = BMODADD(start_index, i, mc->num_entries);
-        struct OTPChecker_entry *entry = oc_table_entries_at(&mc->tables_params.tables_params, t, index);
-        
-        // if we find a free index, use it
-        if (entry->avail < 0) {
-            entry->otp = otp;
-            entry->avail = 1;
-            return;
-        }
-        
-        // if we find a used index with the same mac,
-        // use it by incrementing its count
-        if (entry->otp == otp) {
-            entry->avail++;
-            return;
-        }
-    }
-    
-    // will never add more macs than we can hold
-    ASSERT(0)
-}
-
-void OTPChecker_Table_Generate (OTPChecker *mc, oc_table *t, OTPCalculator *calc, uint8_t *key, uint8_t *iv)
-{
-    // calculate values
-    otp_t *otps = OTPCalculator_Generate(calc, key, iv, 0);
-    
-    // empty table
-    OTPChecker_Table_Empty(mc ,t);
-    
-    // add calculated values to table
-    for (int i = 0; i < mc->num_otps; i++) {
-        OTPChecker_Table_AddOTP(mc, t, otps[i]);
-    }
-}
-
-int OTPChecker_Table_CheckOTP (OTPChecker *mc, oc_table *t, otp_t otp)
-{
-    // calculate starting index
-    int start_index = otp % mc->num_entries;
-    
-    // try indexes starting with the base position
-    for (int i = 0; i < mc->num_entries; i++) {
-        int index = BMODADD(start_index, i, mc->num_entries);
-        struct OTPChecker_entry *entry = oc_table_entries_at(&mc->tables_params.tables_params, t, index);
-        
-        // if we find an empty entry, there is no such mac
-        if (entry->avail < 0) {
-            return 0;
-        }
-        
-        // if we find a matching entry, check its count
-        if (entry->otp == otp) {
-            if (entry->avail > 0) {
-                entry->avail--;
-                return 1;
-            }
-            return 0;
-        }
-    }
-    
-    // there are always empty slots
-    ASSERT(0)
-    return 0;
-}
-
-int OTPChecker_Init (OTPChecker *mc, int num_otps, int cipher, int num_tables)
-{
-    ASSERT(num_otps > 0)
-    ASSERT(BEncryption_cipher_valid(cipher))
-    ASSERT(num_tables > 0)
-    
-    // init arguments
-    mc->num_otps = num_otps;
-    mc->num_tables = num_tables;
-    
-    // set number of entries
-    mc->num_entries = 2 * mc->num_otps;
-    
-    // set no tables used
-    mc->tables_used = 0;
-    mc->next_table = 0;
-    
-    // initialize calculator
-    if (!OTPCalculator_Init(&mc->calc, mc->num_otps, cipher)) {
-        goto fail0;
-    }
-    
-    // allocate tables
-    oc_tablesParams_Init(&mc->tables_params, mc->num_tables, mc->num_entries);
-    if (!(mc->tables = malloc(mc->tables_params.len))) {
-        goto fail1;
-    }
-    
-    // initialize tables
-    for (int i = 0; i < mc->num_tables; i++) {
-        OTPChecker_Table_Empty(mc, oc_tables_tables_at(&mc->tables_params, mc->tables, i));
-    }
-    
-    // init debug object
-    DebugObject_Init(&mc->d_obj);
-    
-    return 1;
-    
-fail1:
-    OTPCalculator_Free(&mc->calc);
-fail0:
-    return 0;
-}
-
-void OTPChecker_Free (OTPChecker *mc)
-{
-    // free debug object
-    DebugObject_Free(&mc->d_obj);
-    
-    // free tables
-    free(mc->tables);
-    
-    // free calculator
-    OTPCalculator_Free(&mc->calc);
-}
-
-void OTPChecker_AddSeed (OTPChecker *mc, uint16_t seed_id, uint8_t *key, uint8_t *iv)
-{
-    ASSERT(mc->next_table >= 0)
-    ASSERT(mc->next_table < mc->num_tables)
-    
-    // initialize next table
-    oc_table *table = oc_tables_tables_at(&mc->tables_params, mc->tables, mc->next_table);
-    *oc_table_id(&mc->tables_params.tables_params, table) = seed_id;
-    OTPChecker_Table_Generate(mc, table, &mc->calc, key, iv);
-    
-    // update next table number
-    mc->next_table = BMODADD(mc->next_table, 1, mc->num_tables);
-    // update number of used tables if not all are used yet
-    if (mc->tables_used < mc->num_tables) {
-        mc->tables_used++;
-    }
-}
-
-void OTPChecker_RemoveSeeds (OTPChecker *mc)
-{
-    mc->tables_used = 0;
-    mc->next_table = 0;
-}
-
-int OTPChecker_CheckOTP (OTPChecker *mc, uint16_t seed_id, otp_t otp)
-{
-    // try tables in reverse order
-    for (int i = 1; i <= mc->tables_used; i++) {
-        int table_index = BMODADD(mc->next_table, mc->num_tables - i, mc->num_tables);
-        oc_table *table = oc_tables_tables_at(&mc->tables_params, mc->tables, table_index);
-        if (*oc_table_id(&mc->tables_params.tables_params, table) == seed_id) {
-            return OTPChecker_Table_CheckOTP(mc, table, otp);
-        }
-    }
-    
-    return 0;
-}
+int OTPChecker_CheckOTP (OTPChecker *mc, uint16_t seed_id, otp_t otp);
 
 #endif

+ 80 - 0
security/OTPGenerator.c

@@ -0,0 +1,80 @@
+/**
+ * @file OTPGenerator.c
+ * @author Ambroz Bizjak <ambrop7@gmail.com>
+ * 
+ * @section LICENSE
+ * 
+ * This file is part of BadVPN.
+ * 
+ * BadVPN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ * 
+ * BadVPN is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <security/OTPGenerator.h>
+
+int OTPGenerator_Init (OTPGenerator *g, int num_otps, int cipher)
+{
+    ASSERT(num_otps >= 0)
+    ASSERT(BEncryption_cipher_valid(cipher))
+    
+    // init arguments
+    g->num_otps = num_otps;
+    
+    // init position
+    g->position = g->num_otps;
+    
+    // init calculator
+    if (!OTPCalculator_Init(&g->calc, g->num_otps, cipher)) {
+        goto fail0;
+    }
+    
+    // init debug object
+    DebugObject_Init(&g->d_obj);
+
+    return 1;
+    
+fail0:
+    return 0;
+}
+
+void OTPGenerator_Free (OTPGenerator *g)
+{
+    // free debug object
+    DebugObject_Free(&g->d_obj);
+    
+    // free calculator
+    OTPCalculator_Free(&g->calc);
+}
+
+void OTPGenerator_SetSeed (OTPGenerator *g, uint8_t *key, uint8_t *iv)
+{
+    g->otps = OTPCalculator_Generate(&g->calc, key, iv, 1);
+    g->position = 0;
+}
+
+int OTPGenerator_GetPosition (OTPGenerator *g)
+{
+    return g->position;
+}
+
+void OTPGenerator_Reset (OTPGenerator *g)
+{
+    g->position = g->num_otps;
+}
+
+otp_t OTPGenerator_GetOTP (OTPGenerator *g)
+{
+    ASSERT(g->position < g->num_otps)
+    
+    return g->otps[g->position++];
+}

+ 6 - 63
security/OTPGenerator.h

@@ -52,14 +52,14 @@ typedef struct {
  *               according to {@link BEncryption_cipher_valid}.
  * @return 1 on success, 0 on failure
  */
-static int OTPGenerator_Init (OTPGenerator *g, int num_otps, int cipher) WARN_UNUSED;
+int OTPGenerator_Init (OTPGenerator *g, int num_otps, int cipher) WARN_UNUSED;
 
 /**
  * Frees the generator.
  *
  * @param g the object
  */
-static void OTPGenerator_Free (OTPGenerator *g);
+void OTPGenerator_Free (OTPGenerator *g);
 
 /**
  * Assigns a seed to use for generating OTPs.
@@ -69,7 +69,7 @@ static void OTPGenerator_Free (OTPGenerator *g);
  * @param key encryption key
  * @param iv initialization vector
  */
-static void OTPGenerator_SetSeed (OTPGenerator *g, uint8_t *key, uint8_t *iv);
+void OTPGenerator_SetSeed (OTPGenerator *g, uint8_t *key, uint8_t *iv);
 
 /**
  * Returns the number of OTPs used up from the current seed so far.
@@ -78,14 +78,14 @@ static void OTPGenerator_SetSeed (OTPGenerator *g, uint8_t *key, uint8_t *iv);
  * @param g the object
  * @return number of used OTPs
  */
-static int OTPGenerator_GetPosition (OTPGenerator *g);
+int OTPGenerator_GetPosition (OTPGenerator *g);
 
 /**
  * Sets the number of used OTPs to num_otps.
  *
  * @param g the object
  */
-static void OTPGenerator_Reset (OTPGenerator *g);
+void OTPGenerator_Reset (OTPGenerator *g);
 
 /**
  * Generates a single OTP.
@@ -94,63 +94,6 @@ static void OTPGenerator_Reset (OTPGenerator *g);
  *
  * @param g the object
  */
-static otp_t OTPGenerator_GetOTP (OTPGenerator *g);
-
-int OTPGenerator_Init (OTPGenerator *g, int num_otps, int cipher)
-{
-    ASSERT(num_otps >= 0)
-    ASSERT(BEncryption_cipher_valid(cipher))
-    
-    // init arguments
-    g->num_otps = num_otps;
-    
-    // init position
-    g->position = g->num_otps;
-    
-    // init calculator
-    if (!OTPCalculator_Init(&g->calc, g->num_otps, cipher)) {
-        goto fail0;
-    }
-    
-    // init debug object
-    DebugObject_Init(&g->d_obj);
-
-    return 1;
-    
-fail0:
-    return 0;
-}
-
-void OTPGenerator_Free (OTPGenerator *g)
-{
-    // free debug object
-    DebugObject_Free(&g->d_obj);
-    
-    // free calculator
-    OTPCalculator_Free(&g->calc);
-}
-
-void OTPGenerator_SetSeed (OTPGenerator *g, uint8_t *key, uint8_t *iv)
-{
-    g->otps = OTPCalculator_Generate(&g->calc, key, iv, 1);
-    g->position = 0;
-}
-
-int OTPGenerator_GetPosition (OTPGenerator *g)
-{
-    return g->position;
-}
-
-void OTPGenerator_Reset (OTPGenerator *g)
-{
-    g->position = g->num_otps;
-}
-
-otp_t OTPGenerator_GetOTP (OTPGenerator *g)
-{
-    ASSERT(g->position < g->num_otps)
-    
-    return g->otps[g->position++];
-}
+otp_t OTPGenerator_GetOTP (OTPGenerator *g);
 
 #endif

+ 1 - 1
server/CMakeLists.txt

@@ -1,5 +1,5 @@
 add_executable(badvpn-server server.c)
-target_link_libraries(badvpn-server system flow nspr_support predicate listener ${LIBCRYPTO_LIBRARIES} ${NSPR_LIBRARIES} ${NSS_LIBRARIES})
+target_link_libraries(badvpn-server system flow nspr_support predicate listener security ${NSPR_LIBRARIES} ${NSS_LIBRARIES})
 
 install(
     TARGETS badvpn-server

+ 2 - 2
server/server.c

@@ -45,7 +45,6 @@
 #include <misc/nsskey.h>
 #include <misc/dead.h>
 #include <misc/byteorder.h>
-#include <misc/brandom.h>
 #include <misc/loglevel.h>
 #include <misc/loggers_string.h>
 #include <nspr_support/DummyPRFileDesc.h>
@@ -56,6 +55,7 @@
 #include <system/DebugObject.h>
 #include <system/BAddr.h>
 #include <listener/Listener.h>
+#include <security/BRandom.h>
 
 #ifndef BADVPN_USE_WINAPI
 #include <system/BLog_syslog.h>
@@ -479,7 +479,7 @@ int main (int argc, char *argv[])
     LinkedList2_Init(&clients);
     
     // initialize clients-by-id hash table
-    brandom_randomize((uint8_t *)&clients_by_id_initval, sizeof(clients_by_id_initval));
+    BRandom_randomize((uint8_t *)&clients_by_id_initval, sizeof(clients_by_id_initval));
     if (!HashTable_Init(
         &clients_by_id,
         OFFSET_DIFF(struct client_data, id, table_node_id),

+ 1 - 1
server_connection/CMakeLists.txt

@@ -1,2 +1,2 @@
 add_library(server_conection ServerConnection.c)
-target_link_libraries(server_conection system flow nspr_support ${LIBCRYPTO_LIBRARIES} ${NSPR_LIBRARIES} ${NSS_LIBRARIES})
+target_link_libraries(server_conection system flow nspr_support ${NSPR_LIBRARIES} ${NSS_LIBRARIES})