Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Implemented crypto functions needed for SSL

Some of them required OpenSSL (libcrypto) so we're dependent on it again.

Change-Id: I1c9d5fabd4a3cbc68d3d95089ce89d47569851ea
Reviewed-on: http://review.couchbase.org/10513
Reviewed-by: Chris Anderson <jchris@couchbase.com>
Tested-by: Jens Alfke <jens@couchbase.com>
  • Loading branch information...
commit 3c9db5346d932b46b743f3b6eece631fc1e97200 1 parent f44a7d7
Jens Alfke authored
20  iErl14.xcodeproj/project.pbxproj
@@ -339,9 +339,11 @@
339 339
 		27167DCC13C4E1BF001CC5B6 /* vm.c in Sources */ = {isa = PBXBuildFile; fileRef = D93F40621256660000AF842F /* vm.c */; };
340 340
 		27167DCE13C4E1BF001CC5B6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACBBE490F95108600F1A2B1 /* Foundation.framework */; };
341 341
 		27167DCF13C4E1BF001CC5B6 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D9E24C5B124031A700AC152E /* libicucore.dylib */; };
342  
-		2796230C142106A80051455D /* crypto_drv_ios.c in Sources */ = {isa = PBXBuildFile; fileRef = 2796230014201AC60051455D /* crypto_drv_ios.c */; };
  342
+		27235618145F050F00F349AD /* crypto_drv_ios.c in Sources */ = {isa = PBXBuildFile; fileRef = 2796230014201AC60051455D /* crypto_drv_ios.c */; };
343 343
 		27A37446143E98C7005A577D /* CouchbaseAppServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 27A37444143E98C7005A577D /* CouchbaseAppServer.h */; };
344 344
 		27A37447143E98C7005A577D /* CouchbaseAppServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 27A37445143E98C7005A577D /* CouchbaseAppServer.m */; };
  345
+		27C5709D145B70DB008EC203 /* libcrypto-iphoneos.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27C5709B145B70DB008EC203 /* libcrypto-iphoneos.a */; };
  346
+		27C5709E145B70DB008EC203 /* libcrypto-iphonesimulator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27C5709C145B70DB008EC203 /* libcrypto-iphonesimulator.a */; };
345 347
 		27CB653C143A395400EEA1F2 /* CouchbaseViewDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CB653A143A395400EEA1F2 /* CouchbaseViewDispatcher.h */; };
346 348
 		27CB653D143A395400EEA1F2 /* CouchbaseViewDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CB653B143A395400EEA1F2 /* CouchbaseViewDispatcher.m */; };
347 349
 		27CB6545143A423E00EEA1F2 /* CouchbaseCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = 27CB6543143A423D00EEA1F2 /* CouchbaseCallbacks.h */; };
@@ -387,9 +389,11 @@
387 389
 		270F4E5D143688E300234600 /* term_to_objc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = term_to_objc.h; sourceTree = "<group>"; };
388 390
 		270F4E5E143688E300234600 /* term_to_objc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = term_to_objc.m; sourceTree = "<group>"; };
389 391
 		27167DD413C4E1BF001CC5B6 /* libiErl14.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libiErl14.a; sourceTree = BUILT_PRODUCTS_DIR; };
390  
-		2796230014201AC60051455D /* crypto_drv_ios.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = crypto_drv_ios.c; path = src/crypto_drv_ios.c; sourceTree = "<group>"; };
  392
+		2796230014201AC60051455D /* crypto_drv_ios.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = crypto_drv_ios.c; path = src/crypto_drv_ios.c; sourceTree = "<group>"; tabWidth = 4; usesTabs = 0; };
391 393
 		27A37444143E98C7005A577D /* CouchbaseAppServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CouchbaseAppServer.h; sourceTree = "<group>"; };
392 394
 		27A37445143E98C7005A577D /* CouchbaseAppServer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CouchbaseAppServer.m; sourceTree = "<group>"; };
  395
+		27C5709B145B70DB008EC203 /* libcrypto-iphoneos.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libcrypto-iphoneos.a"; path = "../ios-openssl/lib/libcrypto-iphoneos.a"; sourceTree = SOURCE_ROOT; };
  396
+		27C5709C145B70DB008EC203 /* libcrypto-iphonesimulator.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libcrypto-iphonesimulator.a"; path = "../ios-openssl/lib/libcrypto-iphonesimulator.a"; sourceTree = SOURCE_ROOT; };
393 397
 		27CB653A143A395400EEA1F2 /* CouchbaseViewDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CouchbaseViewDispatcher.h; sourceTree = "<group>"; };
394 398
 		27CB653B143A395400EEA1F2 /* CouchbaseViewDispatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CouchbaseViewDispatcher.m; sourceTree = "<group>"; };
395 399
 		27CB6543143A423D00EEA1F2 /* CouchbaseCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CouchbaseCallbacks.h; sourceTree = "<group>"; };
@@ -431,14 +435,14 @@
431 435
 		D93F40631256660000AF842F /* vm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vm.h; path = src/vm.h; sourceTree = SOURCE_ROOT; };
432 436
 		D9ABA80113DFB5CC00D072BE /* erl_nif_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = erl_nif_compat.h; sourceTree = "<group>"; };
433 437
 		D9ABA80313DFB5CC00D072BE /* AUTHORS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AUTHORS; sourceTree = "<group>"; };
434  
-		D9ABA80413DFB5CC00D072BE /* snappy-config.h */ = {isa = PBXFileReference; fileEncoding = 4; path = "snappy-config.h"; sourceTree = "<group>"; };
  438
+		D9ABA80413DFB5CC00D072BE /* snappy-config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "snappy-config.h"; sourceTree = "<group>"; };
435 439
 		D9ABA80513DFB5CC00D072BE /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = COPYING; sourceTree = "<group>"; };
436 440
 		D9ABA80613DFB5CC00D072BE /* snappy-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "snappy-internal.h"; sourceTree = "<group>"; };
437 441
 		D9ABA80713DFB5CC00D072BE /* snappy-sinksource.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "snappy-sinksource.cc"; sourceTree = "<group>"; };
438 442
 		D9ABA80813DFB5CC00D072BE /* snappy-sinksource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "snappy-sinksource.h"; sourceTree = "<group>"; };
439 443
 		D9ABA80913DFB5CC00D072BE /* snappy-stubs-internal.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "snappy-stubs-internal.cc"; sourceTree = "<group>"; };
440 444
 		D9ABA80A13DFB5CC00D072BE /* snappy-stubs-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "snappy-stubs-internal.h"; sourceTree = "<group>"; };
441  
-		D9ABA80B13DFB5CC00D072BE /* snappy-stubs-public.h */ = {isa = PBXFileReference; fileEncoding = 4; path = "snappy-stubs-public.h"; sourceTree = "<group>"; };
  445
+		D9ABA80B13DFB5CC00D072BE /* snappy-stubs-public.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "snappy-stubs-public.h"; sourceTree = "<group>"; };
442 446
 		D9ABA80C13DFB5CC00D072BE /* snappy.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = snappy.cc; sourceTree = "<group>"; };
443 447
 		D9ABA80D13DFB5CC00D072BE /* snappy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = snappy.h; sourceTree = "<group>"; };
444 448
 		D9ABA80E13DFB5CC00D072BE /* snappy_nif.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = snappy_nif.cc; sourceTree = "<group>"; };
@@ -703,7 +707,7 @@
703 707
 		D9E24262123EA87000AC152E /* erl_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = erl_main.c; sourceTree = "<group>"; };
704 708
 		D9E24263123EA87000AC152E /* erl_unix_sys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = erl_unix_sys.h; sourceTree = "<group>"; };
705 709
 		D9E24264123EA87000AC152E /* erl_unix_sys_ddll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = erl_unix_sys_ddll.c; sourceTree = "<group>"; };
706  
-		D9E24265123EA87000AC152E /* sys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys.c; sourceTree = "<group>"; };
  710
+		D9E24265123EA87000AC152E /* sys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys.c; sourceTree = "<group>"; tabWidth = 8; };
707 711
 		D9E24266123EA87000AC152E /* sys_float.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_float.c; sourceTree = "<group>"; };
708 712
 		D9E24267123EA87000AC152E /* sys_time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_time.c; sourceTree = "<group>"; };
709 713
 		D9E2430A123EA87000AC152E /* erl_fixed_size_int_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = erl_fixed_size_int_types.h; sourceTree = "<group>"; };
@@ -773,6 +777,8 @@
773 777
 				D9F85BF313F193FC00A73E46 /* CoreFoundation.framework in Frameworks */,
774 778
 				27167DCE13C4E1BF001CC5B6 /* Foundation.framework in Frameworks */,
775 779
 				27167DCF13C4E1BF001CC5B6 /* libicucore.dylib in Frameworks */,
  780
+				27C5709D145B70DB008EC203 /* libcrypto-iphoneos.a in Frameworks */,
  781
+				27C5709E145B70DB008EC203 /* libcrypto-iphonesimulator.a in Frameworks */,
776 782
 			);
777 783
 			runOnlyForDeploymentPostprocessing = 0;
778 784
 		};
@@ -783,6 +789,8 @@
783 789
 			isa = PBXGroup;
784 790
 			children = (
785 791
 				D9E24C5B124031A700AC152E /* libicucore.dylib */,
  792
+				27C5709B145B70DB008EC203 /* libcrypto-iphoneos.a */,
  793
+				27C5709C145B70DB008EC203 /* libcrypto-iphonesimulator.a */,
786 794
 			);
787 795
 			name = Libraries;
788 796
 			sourceTree = "<group>";
@@ -1903,13 +1911,13 @@
1903 1911
 				D9ABA81513DFB5CC00D072BE /* snappy.cc in Sources */,
1904 1912
 				D9ABA81713DFB5CC00D072BE /* snappy_nif.cc in Sources */,
1905 1913
 				D9F85BF113F191A700A73E46 /* ios_drv.m in Sources */,
1906  
-				2796230C142106A80051455D /* crypto_drv_ios.c in Sources */,
1907 1914
 				2849E7AF1424A2B10075C6DE /* objc-dispatch-main.m in Sources */,
1908 1915
 				270F4E60143688E300234600 /* objc_to_term.m in Sources */,
1909 1916
 				270F4E62143688E300234600 /* term_to_objc.m in Sources */,
1910 1917
 				27CB653D143A395400EEA1F2 /* CouchbaseViewDispatcher.m in Sources */,
1911 1918
 				27CB6546143A423E00EEA1F2 /* CouchbaseCallbacks.m in Sources */,
1912 1919
 				27A37447143E98C7005A577D /* CouchbaseAppServer.m in Sources */,
  1920
+				27235618145F050F00F349AD /* crypto_drv_ios.c in Sources */,
1913 1921
 			);
1914 1922
 			runOnlyForDeploymentPostprocessing = 0;
1915 1923
 		};
650  src/crypto_drv_ios.c
@@ -27,29 +27,65 @@
27 27
 #include <string.h>
28 28
 #include "erl_driver.h"
29 29
 
  30
+#include <CommonCrypto/CommonCryptor.h>
30 31
 #include <CommonCrypto/CommonDigest.h>
31 32
 #include <CommonCrypto/CommonHMAC.h>
32  
-#include <CoreFoundation/CFByteOrder.h>
  33
+#include <CoreFoundation/CoreFoundation.h>
33 34
 #include <Security/SecRandom.h>
34 35
 
  36
+#define OPENSSL_THREAD_DEFINES
  37
+#define RC4_INT unsigned int
  38
+#include "openssl/opensslconf.h"
  39
+#ifndef OPENSSL_THREADS
  40
+#  ifdef __GNUC__
  41
+#    warning No thread support by openssl. Driver will use coarse grain locking.
  42
+#  endif
  43
+#endif
  44
+
  45
+#include "openssl/bn.h"
  46
+#include "openssl/crypto.h"
  47
+#include "openssl/dh.h"
  48
+#include "openssl/rsa.h"
  49
+#include "openssl/md5.h"
  50
+#include "openssl/objects.h"
  51
+#include "openssl/sha.h"
  52
+#include "openssl/rc4.h"
  53
+
35 54
 
36 55
 #define get_int32(s) CFSwapInt32BigToHost(*(const int32_t*)(s))
37 56
 #define put_int32(s,i) {*(int32_t*)(s) = CFSwapInt32HostToBig((i));}
38 57
 
39  
-static unsigned char* return_binary(char **rbuf, int rlen, int len);
  58
+#define ERL_VALGRIND_MAKE_MEM_DEFINED(ptr,size)
  59
+#define ERL_VALGRIND_ASSERT_MEM_DEFINED(ptr,size)
40 60
 
  61
+static unsigned char* return_binary(char **rbuf, int rlen, int len);
  62
+static unsigned char* return_binary_shrink(char **rbuf, int rlen, unsigned char* data, int len);
41 63
 static int generateUniformRandom(int from_len, const void* from_ptr,
42 64
 								 int to_len, const void* to_ptr,
43 65
 								 void* result_ptr);
  66
+static void hmac_md5(char *key, int klen, char *dbuf, int dlen, char *hmacbuf);
  67
+static void hmac_sha1(char *key, int klen, char *dbuf, int dlen,  char *hmacbuf);
  68
+
  69
+/* openssl callbacks */
  70
+#ifdef OPENSSL_THREADS
  71
+static void locking_function(int mode, int n, const char *file, int line);
  72
+static unsigned long id_function(void);
  73
+static struct CRYPTO_dynlock_value* dyn_create_function(const char *file,
  74
+                                                 int line);
  75
+static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value* ptr,
  76
+                       const char *file, int line);
  77
+static void dyn_destroy_function(struct CRYPTO_dynlock_value *ptr,
  78
+                          const char *file, int line);
  79
+#endif /* OPENSSL_THREADS */
44 80
 
45 81
 
46 82
 #pragma mark - DRIVER INTERFACE
47 83
 
48  
-int crypto_init();
49  
-void crypto_finish();
50  
-ErlDrvData crypto_start(ErlDrvPort port, char *command);
51  
-void crypto_stop(ErlDrvData drv_data);
52  
-int crypto_control(ErlDrvData drv_data, unsigned int command, char *buf,
  84
+static int crypto_init();
  85
+static void crypto_finish();
  86
+static ErlDrvData crypto_start(ErlDrvPort port, char *command);
  87
+static void crypto_stop(ErlDrvData drv_data);
  88
+static int crypto_control(ErlDrvData drv_data, unsigned int command, char *buf,
53 89
                    int len, char **rbuf, int rlen);
54 90
 
55 91
 ErlDrvEntry crypto_driver_entry = {
@@ -163,6 +199,8 @@ ErlDrvEntry crypto_driver_entry = {
163 199
  * Calc RSA_VERIFY_*  and RSA_SIGN once */
164 200
 #define NUM_CRYPTO_FUNCS        46
165 201
 
  202
+#define MD5_LEN_96      12
  203
+
166 204
 
167 205
 /* List of implemented commands. Returned by DRV_INFO. */
168 206
 static const uint8_t kImplementedFuncs[] = {
@@ -171,35 +209,80 @@ static const uint8_t kImplementedFuncs[] = {
171 209
 	DRV_MD5_UPDATE,
172 210
 	DRV_MD5_FINAL,
173 211
 	DRV_SHA,
  212
+    DRV_SHA_INIT,
  213
+    DRV_SHA_UPDATE,
  214
+    DRV_SHA_FINAL,
  215
+    DRV_MD5_MAC,
  216
+    DRV_MD5_MAC_96,
174 217
 	DRV_SHA_MAC,
175 218
 	DRV_RAND_BYTES,
176  
-	DRV_RAND_UNIFORM
  219
+	DRV_RAND_UNIFORM,
  220
+    DRV_RSA_VERIFY_MD5,
  221
+    DRV_XOR,
  222
+    DRV_CBC_AES128_ENCRYPT,
  223
+    DRV_CBC_AES128_DECRYPT,
  224
+    DRV_CBC_AES256_ENCRYPT,
  225
+    DRV_CBC_AES256_DECRYPT,
  226
+    DRV_RSA_VERIFY_SHA,
  227
+    DRV_RSA_PUBLIC_ENCRYPT,
  228
+    DRV_RSA_PUBLIC_DECRYPT,
  229
+    DRV_DH_GENERATE_KEY,
  230
+    DRV_DH_COMPUTE_KEY
177 231
 };
178 232
 
179 233
 
  234
+static ErlDrvRWLock** lock_vec = NULL; /* Static locks used by openssl */
  235
+
  236
+
180 237
 #pragma mark - DRIVER INTERFACE
181 238
 
182  
-int crypto_init(void)
  239
+static int crypto_init(void)
183 240
 {
  241
+    ErlDrvSysInfo sys_info;
  242
+    int i;
  243
+
  244
+    CRYPTO_set_mem_functions(driver_alloc, driver_realloc, driver_free);
  245
+
  246
+#ifdef OPENSSL_THREADS
  247
+    driver_system_info(&sys_info, sizeof(sys_info));
  248
+
  249
+    if(sys_info.scheduler_threads > 1) {
  250
+        lock_vec = driver_alloc(CRYPTO_num_locks()*sizeof(*lock_vec));
  251
+        if (lock_vec==NULL) return -1;
  252
+        memset(lock_vec,0,CRYPTO_num_locks()*sizeof(*lock_vec));
  253
+
  254
+        for(i=CRYPTO_num_locks()-1; i>=0; --i) {
  255
+            lock_vec[i] = erl_drv_rwlock_create("crypto_drv_stat");
  256
+            if (lock_vec[i]==NULL) return -1;
  257
+        }
  258
+        CRYPTO_set_locking_callback(locking_function);
  259
+        CRYPTO_set_id_callback(id_function);
  260
+        CRYPTO_set_dynlock_create_callback(dyn_create_function);
  261
+        CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
  262
+        CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
  263
+    }
  264
+    /* else no need for locks */
  265
+#endif /* OPENSSL_THREADS */
  266
+
184 267
     return 0;
185 268
 }
186 269
 
187  
-void crypto_finish(void)
  270
+static void crypto_finish(void)
188 271
 {
189 272
 }
190 273
 
191  
-ErlDrvData crypto_start(ErlDrvPort port, char *command)
  274
+static ErlDrvData crypto_start(ErlDrvPort port, char *command)
192 275
 {
193 276
     set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
194 277
     return 0; /* not used */
195 278
 }
196 279
 
197  
-void crypto_stop(ErlDrvData drv_data)
  280
+static void crypto_stop(ErlDrvData drv_data)
198 281
 {
199 282
 }
200 283
 
201 284
 /* Main entry point for crypto functions. Spec is at http://www.erlang.org/doc/man/crypto.html */
202  
-int crypto_control(ErlDrvData drv_data, unsigned int command,
  285
+static int crypto_control(ErlDrvData drv_data, unsigned int command,
203 286
 				   char *buf, int len,
204 287
 				   char **rbuf, int rlen)
205 288
 {
@@ -211,6 +294,7 @@ int crypto_control(ErlDrvData drv_data, unsigned int command,
211 294
 			memcpy(bin, kImplementedFuncs, sizeof(kImplementedFuncs));
212 295
 			return sizeof(kImplementedFuncs);
213 296
 		}
  297
+
214 298
 		case DRV_MD5: {
215 299
 			bin = return_binary(rbuf,rlen,CC_MD5_DIGEST_LENGTH);
216 300
 			if (bin==NULL) return -1;
@@ -237,15 +321,58 @@ int crypto_control(ErlDrvData drv_data, unsigned int command,
237 321
 				return -1;
238 322
 			bin = return_binary(rbuf, rlen, CC_MD5_DIGEST_LENGTH);
239 323
 			if (bin==NULL) return -1;
240  
-			CC_MD5_Final(bin, (CC_MD5_CTX*)buf);
  324
+            CC_MD5_CTX ctx = *(CC_MD5_CTX*)buf;  // not safe to modify contents of buf, so copy
  325
+			CC_MD5_Final(bin, &ctx);
241 326
 			return CC_MD5_DIGEST_LENGTH;
242 327
 		}
  328
+
243 329
 		case DRV_SHA: {
244 330
 			bin = return_binary(rbuf,rlen,CC_SHA1_DIGEST_LENGTH);
245 331
 			if (bin==NULL) return -1;
246 332
 			CC_SHA1(buf, len, bin);
247 333
 			return CC_SHA1_DIGEST_LENGTH;
248 334
 		}
  335
+		case DRV_SHA_INIT: {
  336
+			bin = return_binary(rbuf,rlen,sizeof(CC_SHA1_CTX));
  337
+			if (bin==NULL) return -1;
  338
+			CC_SHA1_Init((CC_SHA1_CTX*)bin);
  339
+			return sizeof(CC_SHA1_CTX);
  340
+		}
  341
+		case DRV_SHA_UPDATE: {
  342
+			if (len < sizeof(CC_SHA1_CTX))
  343
+				return -1;
  344
+			bin = return_binary(rbuf,rlen,sizeof(CC_SHA1_CTX));
  345
+			if (bin==NULL) return -1;
  346
+			memcpy(bin, buf, sizeof(CC_SHA1_CTX));
  347
+			CC_SHA1_Update((CC_SHA1_CTX*)bin, buf + sizeof(CC_SHA1_CTX), len - sizeof(CC_SHA1_CTX));
  348
+			return sizeof(CC_SHA1_CTX);
  349
+		}
  350
+		case DRV_SHA_FINAL: {
  351
+			if (len != sizeof(CC_SHA1_CTX))
  352
+				return -1;
  353
+			bin = return_binary(rbuf, rlen, CC_SHA1_DIGEST_LENGTH);
  354
+			if (bin==NULL) return -1;
  355
+            CC_SHA1_CTX ctx = *(CC_SHA1_CTX*)buf;  // not safe to modify contents of buf, so copy
  356
+			CC_SHA1_Final(bin, &ctx);
  357
+			return CC_SHA1_DIGEST_LENGTH;
  358
+		}
  359
+
  360
+        case DRV_MD5_MAC:
  361
+        case DRV_MD5_MAC_96: {
  362
+            /* buf = klen[4] key data */
  363
+            int klen = get_int32(buf);
  364
+            char* key = buf + 4;
  365
+            int dlen = len - klen - 4;
  366
+            char* dbuf = key + klen;
  367
+            char hmacbuf[CC_MD5_DIGEST_LENGTH];
  368
+            hmac_md5(key, klen, dbuf, dlen, hmacbuf);
  369
+            int macsize = (command == DRV_MD5_MAC) ? CC_MD5_DIGEST_LENGTH : MD5_LEN_96;
  370
+            bin = return_binary(rbuf,rlen,macsize);
  371
+            if (bin==NULL) return -1;
  372
+            memcpy(bin, hmacbuf, macsize);
  373
+            return macsize;
  374
+        }
  375
+
249 376
 		case DRV_SHA_MAC: {
250 377
 			/* buf = klen:32/integer,key:klen/binary,dbuf:remainder/binary */
251 378
 			if (len < 4)
@@ -262,6 +389,7 @@ int crypto_control(ErlDrvData drv_data, unsigned int command,
262 389
 			CCHmac(kCCHmacAlgSHA1, key, klen, dbuf, dlen, bin);
263 390
 			return CC_SHA1_DIGEST_LENGTH;
264 391
 		}
  392
+
265 393
 		case DRV_RAND_BYTES: {
266 394
 			/* buf = <<rlen:32/integer,topmask:8/integer,bottommask:8/integer>> */
267 395
 			if (len != 6)
@@ -302,6 +430,352 @@ int crypto_control(ErlDrvData drv_data, unsigned int command,
302 430
 			memcpy(bin+4, result, result_len);
303 431
 			return 4+result_len;
304 432
 		}
  433
+
  434
+        case DRV_CBC_AES128_ENCRYPT:
  435
+        case DRV_CBC_AES256_ENCRYPT:
  436
+        case DRV_CBC_AES128_DECRYPT:
  437
+        case DRV_CBC_AES256_DECRYPT: {
  438
+            /* buf = key[klen] ivec[16] data */
  439
+            bool encrypting = (command==DRV_CBC_AES128_ENCRYPT || command==DRV_CBC_AES256_ENCRYPT);
  440
+            int klen;
  441
+            if (command == DRV_CBC_AES256_ENCRYPT || command == DRV_CBC_AES256_DECRYPT)
  442
+                klen = 32;
  443
+            else
  444
+                klen = 16;
  445
+            const char* key = buf;
  446
+            const char* ivec = buf + klen;
  447
+            const char* data = ivec + 16;
  448
+            int dlen = len - klen - 16;
  449
+            if (dlen < 0)
  450
+                return -1;
  451
+            if (dlen % 16 != 0)
  452
+                return -1;
  453
+            bin = return_binary(rbuf,rlen,dlen);
  454
+            if (bin==NULL) return -1;
  455
+            size_t actual_dlen;
  456
+            CCCryptorStatus result = CCCrypt(encrypting ? kCCEncrypt : kCCDecrypt,
  457
+                                             kCCAlgorithmAES128, 0,
  458
+                                             key, klen, ivec,
  459
+                                             data, dlen,
  460
+                                             bin, dlen, &actual_dlen);
  461
+            if (result != kCCSuccess) {
  462
+                fprintf(stderr, "ERROR: crypto_drv_ios: CCCrypt returned %i\n", result);
  463
+                return -1;
  464
+            }
  465
+            return actual_dlen;
  466
+        }
  467
+
  468
+        case DRV_RC4_SETKEY: {
  469
+            /* buf = key */
  470
+            RC4_KEY rc4_key;
  471
+            int dlen = sizeof(rc4_key);
  472
+            bin = return_binary(rbuf,rlen,dlen);
  473
+            if (bin==NULL) return -1;
  474
+            RC4_set_key(&rc4_key, len, (unsigned char *) buf);
  475
+            memcpy(bin, &rc4_key, dlen);
  476
+            return dlen;
  477
+        }
  478
+        case DRV_RC4_ENCRYPT_WITH_STATE: {
  479
+            /* buf = statelength[4] state data, return statelength[4] state data */
  480
+            int klen = get_int32(buf);
  481
+            char* key = buf + 4;
  482
+            int dlen = len - klen - 4;
  483
+            char* dbuf = key + klen;
  484
+            bin = return_binary(rbuf,rlen,len);
  485
+            if (bin==NULL) return -1;
  486
+            RC4_KEY rc4_key;
  487
+            memcpy(&rc4_key, key, klen);
  488
+            RC4(&rc4_key, dlen, (unsigned char *) dbuf, bin + klen + 4);
  489
+            memcpy(bin, buf, 4);
  490
+            memcpy(bin + 4, &rc4_key, klen);
  491
+            return len;
  492
+        }
  493
+            
  494
+        case DRV_XOR: {
  495
+            /* buf = data1, data2 with same size */
  496
+            int dlen = len / 2;
  497
+            if (len != dlen * 2)
  498
+                return -1;
  499
+            bin = return_binary(rbuf,rlen,dlen);
  500
+            if (bin==NULL) return -1;
  501
+            unsigned char* p = bin;
  502
+            char* dbuf = buf + dlen;
  503
+            for (char* key = buf, *key2 = dbuf; key != dbuf; ++key, ++key2, ++p)
  504
+                *p = *key ^ *key2;
  505
+            return dlen;
  506
+        }
  507
+
  508
+        case DRV_RSA_VERIFY_MD5:
  509
+        case DRV_RSA_VERIFY_SHA: {
  510
+            /* buf = <<data_len:32/integer, data:data_len/binary,
  511
+             *         rsa_s_len:32/integer, rsa_s:rsa_s_len/binary,
  512
+             *         rsa_e_len:32/integer, rsa_e:rsa_e_len/binary,
  513
+             *         rsa_n_len:32/integer, rsa_n:rsa_n_len/binary>> */
  514
+            int i = 0;
  515
+            int j = 0;
  516
+            if (len < 16)
  517
+                return -1;
  518
+            int data_len = get_int32(buf + i + j);
  519
+            j += data_len; i += 4;
  520
+            if (len < (16 + j))
  521
+                return -1;
  522
+            int rsa_s_len = get_int32(buf + i + j);
  523
+            j += rsa_s_len; i += 4;
  524
+            if (len < (16 + j))
  525
+                return -1;
  526
+            int rsa_e_len = get_int32(buf + i + j);
  527
+            j += rsa_e_len; i += 4;
  528
+            if (len < (16 + j))
  529
+                return -1;
  530
+            int rsa_n_len = get_int32(buf + i + j);
  531
+            j += rsa_n_len; i += 4;
  532
+            if (len != (16 + j))
  533
+                return -1;
  534
+            i = 4;
  535
+            i += (data_len + 4);
  536
+            unsigned char* rsa_s = (unsigned char *)(buf + i);
  537
+            i += (rsa_s_len + 4);
  538
+            BIGNUM* rsa_e = BN_new();
  539
+            BN_bin2bn((unsigned char *)(buf + i), rsa_e_len, rsa_e);
  540
+            i += (rsa_e_len + 4);
  541
+            BIGNUM* rsa_n = BN_new();
  542
+            BN_bin2bn((unsigned char *)(buf + i), rsa_n_len, rsa_n);
  543
+            RSA* rsa = RSA_new();
  544
+            rsa->n = rsa_n;
  545
+            rsa->e = rsa_e;
  546
+            i = 4;
  547
+            char hmacbuf[CC_SHA1_DIGEST_LENGTH];
  548
+            if(command == DRV_RSA_VERIFY_SHA) {
  549
+                SHA1((unsigned char *) (buf + i), data_len,
  550
+                     (unsigned char *) hmacbuf);
  551
+                i = RSA_verify(NID_sha1, (unsigned char *) hmacbuf, SHA_DIGEST_LENGTH,
  552
+                               rsa_s, rsa_s_len, rsa);
  553
+            } else {
  554
+                MD5((unsigned char *) (buf + i), data_len, (unsigned char *) hmacbuf);
  555
+                i =  RSA_verify(NID_md5, (unsigned char *) hmacbuf, MD5_DIGEST_LENGTH,
  556
+                                rsa_s, rsa_s_len, rsa);
  557
+            }
  558
+
  559
+            bin = return_binary(rbuf,rlen,1);
  560
+            if (bin==NULL) return -1;
  561
+            bin[0] = (char)(i & 0xff);
  562
+            RSA_free(rsa);
  563
+            return 1;
  564
+        }
  565
+
  566
+        case DRV_RSA_PUBLIC_ENCRYPT:
  567
+        case DRV_RSA_PUBLIC_DECRYPT: {
  568
+            /* buf = <<data_len:32/integer, data:data_len/binary,
  569
+             *         rsa_e_len:32/integer, rsa_e:rsa_e_len/binary,
  570
+             *         rsa_n_len:32/integer, rsa_n:rsa_n_len/binary,
  571
+             *         pad:8/integer >> */
  572
+
  573
+            ERL_VALGRIND_ASSERT_MEM_DEFINED(buf,len);
  574
+            int i = 0;
  575
+            int j = 0;
  576
+
  577
+            if (len < 13)
  578
+                return -1;
  579
+            int data_len = get_int32(buf + i + j);
  580
+            j += data_len; i += 4;
  581
+            if (len < (13 + j))
  582
+                return -1;
  583
+            int rsa_e_len = get_int32(buf + i + j);
  584
+            j += rsa_e_len; i += 4;
  585
+            if (len < (13 + j))
  586
+                return -1;
  587
+            int rsa_n_len = get_int32(buf + i + j);
  588
+            j += rsa_n_len; i += 4;
  589
+            if (len < (13 + j))
  590
+                return -1;
  591
+            int padding = *(unsigned char *) (buf + i + j);
  592
+            if (len != (13 + j))
  593
+                return -1;
  594
+
  595
+            i = 4;
  596
+            i += (data_len + 4);
  597
+            BIGNUM* rsa_e = BN_new();
  598
+            ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,rsa_e_len);
  599
+            BN_bin2bn((unsigned char *)(buf + i), rsa_e_len, rsa_e);
  600
+            i += (rsa_e_len + 4);
  601
+            BIGNUM* rsa_n = BN_new();
  602
+            ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,rsa_n_len);
  603
+            BN_bin2bn((unsigned char *)(buf + i), rsa_n_len, rsa_n);
  604
+            i += (rsa_n_len + 4);
  605
+
  606
+            switch(padding) {
  607
+                case 0:
  608
+                    padding = RSA_NO_PADDING;
  609
+                    break;
  610
+                case 1:
  611
+                    padding = RSA_PKCS1_PADDING;
  612
+                    break;
  613
+                case 2:
  614
+                    padding = RSA_PKCS1_OAEP_PADDING;
  615
+                    break;
  616
+                case 3:
  617
+                    padding = RSA_SSLV23_PADDING;
  618
+                    break;
  619
+                default:
  620
+                    return -1;
  621
+            }
  622
+
  623
+            RSA* rsa = RSA_new();
  624
+            rsa->e = rsa_e;
  625
+            rsa->n = rsa_n;
  626
+
  627
+            int dlen = RSA_size(rsa) + 1;
  628
+            bin = return_binary(rbuf,rlen,dlen);
  629
+            if (bin==NULL) return -1;
  630
+            i = 4;
  631
+            if(command == DRV_RSA_PUBLIC_ENCRYPT) {
  632
+                ERL_VALGRIND_ASSERT_MEM_DEFINED(buf+i,data_len);
  633
+                i = RSA_public_encrypt(data_len, (unsigned char *) (buf+i),
  634
+                                       (unsigned char *) &bin[1],
  635
+                                       rsa, padding);
  636
+                if (i > 0) {
  637
+                    ERL_VALGRIND_MAKE_MEM_DEFINED(bin+1, i);
  638
+                }
  639
+            } else {
  640
+                i = RSA_public_decrypt(data_len, (unsigned char *) (buf+i),
  641
+                                       (unsigned char *) &bin[1],
  642
+                                       rsa, padding);
  643
+                if(i > 0) {
  644
+                    ERL_VALGRIND_MAKE_MEM_DEFINED(bin+1, i);
  645
+                    bin = return_binary_shrink(rbuf,rlen,bin, i+1);
  646
+                    if (bin==NULL) return -1;
  647
+                }
  648
+            }
  649
+
  650
+            RSA_free(rsa);
  651
+            if(i > 0) {
  652
+                bin[0] = 1;
  653
+                return i + 1;
  654
+            } else {
  655
+                /* 	  ERR_load_crypto_strings(); */
  656
+                /* 	  fprintf(stderr, "%d: %s \r\n", __LINE__, ERR_reason_error_string(ERR_get_error())); */
  657
+                bin[0] = 0;
  658
+                return 1;
  659
+            }
  660
+            break;
  661
+        }
  662
+
  663
+        case DRV_DH_GENERATE_KEY: {
  664
+            /* buf = <<key_len:32,  key:key_len/binary,            *
  665
+             *         dh_p_len:32/integer, dh_p:dh_p_len/binary,  *
  666
+             *         dh_g_len:32/integer, dh_g:dh_g_len/binary>> */
  667
+            ERL_VALGRIND_ASSERT_MEM_DEFINED(buf,len);
  668
+            int i = 0;
  669
+            int j = 0;
  670
+            if(len < 12)        return -1;
  671
+            int base_len = get_int32(buf + i + j);
  672
+            j += base_len; i += 4;
  673
+            if (len < (12 + j)) return -1;
  674
+            int dh_p_len = get_int32(buf + i + j);
  675
+            j += dh_p_len; i += 4;
  676
+            if (len < (12 + j)) return -1;
  677
+            int dh_g_len = get_int32(buf + i + j);
  678
+            j += dh_g_len; i += 4;
  679
+            if(len != (12 + j))   return -1;
  680
+            i=4;
  681
+            i += (base_len + 4);
  682
+            BIGNUM* dh_p = BN_new();
  683
+            BN_bin2bn((unsigned char *)(buf + i), dh_p_len, dh_p);
  684
+            i += (dh_p_len + 4);
  685
+            BIGNUM* dh_g = BN_new();
  686
+            BN_bin2bn((unsigned char *)(buf + i), dh_g_len, dh_g);
  687
+            /* i += (dsa_g_len + 4); */
  688
+
  689
+            DH* dh_params = DH_new();
  690
+            dh_params->p = dh_p;
  691
+            dh_params->g = dh_g;
  692
+            if(base_len > 0) {
  693
+                dh_params->priv_key = BN_new();
  694
+                BN_bin2bn((unsigned char *)(buf + i), base_len,
  695
+                          dh_params->priv_key);
  696
+            }
  697
+            i=0;
  698
+            int dlen;
  699
+            if(DH_generate_key(dh_params)) {
  700
+                int privkey_len = BN_num_bytes(dh_params->priv_key);
  701
+                int pubkey_len = BN_num_bytes(dh_params->pub_key);
  702
+                dlen = 1 + 4 + 4 + pubkey_len + privkey_len;
  703
+                bin = return_binary(rbuf,rlen, dlen);
  704
+                if (bin==NULL) return -1;
  705
+                bin[0] = 1;
  706
+                put_int32(bin+1, pubkey_len);
  707
+                BN_bn2bin(dh_params->pub_key, bin+5);
  708
+                ERL_VALGRIND_MAKE_MEM_DEFINED(bin+5, pubkey_len);
  709
+                put_int32(bin+5+pubkey_len, privkey_len);
  710
+                BN_bn2bin(dh_params->priv_key, bin+5+pubkey_len+4);
  711
+                ERL_VALGRIND_MAKE_MEM_DEFINED(bin+5+pubkey_len+4, privkey_len);
  712
+            } else {
  713
+                dlen = 1;
  714
+                bin = return_binary(rbuf,rlen,dlen);
  715
+                if (bin==NULL) return -1;
  716
+                bin[0] = 0;
  717
+            }
  718
+            DH_free(dh_params);
  719
+            return dlen;
  720
+        }
  721
+
  722
+        case DRV_DH_COMPUTE_KEY: {
  723
+            /* buf = <<pubkey_len:32,  pubkey:pubkey_len/binary,   *
  724
+             *         privkey_len:32, privkey:privkey_len/binary, *
  725
+             *         dh_p_len:32/integer, dh_p:dh_p_len/binary,  *
  726
+             *         dh_g_len:32/integer, dh_g:dh_g_len/binary>> */
  727
+            int i = 0;
  728
+            int j = 0;
  729
+            if(len < 16)        return -1;
  730
+            int pubkey_len = get_int32(buf + i + j);
  731
+            j += pubkey_len; i += 4;
  732
+            if (len < (16 + j)) return -1;
  733
+            int privkey_len = get_int32(buf + i + j);
  734
+            j += privkey_len; i += 4;
  735
+            if (len < (16 + j)) return -1;
  736
+            int dh_p_len = get_int32(buf + i + j);
  737
+            j += dh_p_len; i += 4;
  738
+            if (len < (16 + j)) return -1;
  739
+            int dh_g_len = get_int32(buf + i + j);
  740
+            j += dh_g_len; i += 4;
  741
+            if(len != (16 + j))   return -1;
  742
+            i=4;
  743
+            BIGNUM* pubkey = BN_new();
  744
+            BN_bin2bn((unsigned char *)(buf + i), pubkey_len, pubkey);
  745
+            i += (pubkey_len + 4);
  746
+            BIGNUM* privkey = BN_new();
  747
+            BN_bin2bn((unsigned char *)(buf + i), privkey_len, privkey);
  748
+            i += (privkey_len + 4);
  749
+            BIGNUM* dh_p = BN_new();
  750
+            BN_bin2bn((unsigned char *)(buf + i), dh_p_len, dh_p);
  751
+            i += (dh_p_len + 4);
  752
+            BIGNUM* dh_g = BN_new();
  753
+            BN_bin2bn((unsigned char *)(buf + i), dh_g_len, dh_g);
  754
+            /* i += (dsa_g_len + 4); */
  755
+
  756
+            DH* dh_params = DH_new();
  757
+            dh_params->p = dh_p;
  758
+            dh_params->g = dh_g;
  759
+            dh_params->priv_key = privkey;
  760
+
  761
+            int klen = DH_size(dh_params);
  762
+            bin = return_binary(rbuf,rlen,1+klen);
  763
+            if (bin==NULL) return -1;
  764
+            i = DH_compute_key(&bin[1], pubkey, dh_params);
  765
+            DH_free(dh_params);
  766
+            if (i > 0) {
  767
+                if (i != klen) {
  768
+                    bin = return_binary_shrink(rbuf,rlen,bin,1+i);
  769
+                }
  770
+                bin[0] = 1;
  771
+                return i + 1;
  772
+            }
  773
+            else {
  774
+                bin[0] = 0;
  775
+                return 1;
  776
+            }
  777
+        }
  778
+
305 779
 		// NOTE: If you implement more cases, you must add them to kImplementedFuncs[].
306 780
 		default: {
307 781
             fprintf(stderr, "ERROR: crypto_drv_ios.c: unsupported crypto_control command %u\n",
@@ -327,6 +801,19 @@ static unsigned char* return_binary(char **rbuf, int rlen, int len)
327 801
     }
328 802
 }
329 803
 
  804
+static unsigned char* return_binary_shrink(char **rbuf, int rlen, unsigned char* data, int len)
  805
+{
  806
+    if ((char *) data == *rbuf) { /* default buffer */
  807
+        assert(len <= rlen);
  808
+        return (unsigned char *) data;
  809
+    }
  810
+    else {
  811
+        ErlDrvBinary* bin = (ErlDrvBinary*) *rbuf;
  812
+        *rbuf = (char*) (bin=driver_realloc_binary(bin, len));
  813
+        return (bin==NULL) ? NULL : (unsigned char *) bin->orig_bytes;
  814
+    }
  815
+}
  816
+
330 817
 
331 818
 /* Returns a random number n such that from <= n < to.  On failure returns 'to'. */
332 819
 static uint64_t randomNumberInRange(uint64_t from, uint64_t to) {
@@ -371,3 +858,138 @@ static int generateUniformRandom(int from_len, const void* from_ptr,
371 858
 	*(uint64_t*)result_ptr = CFSwapInt64HostToBig(result);
372 859
 	return sizeof(result);
373 860
 }
  861
+
  862
+
  863
+#define HMAC_INT_LEN    64
  864
+#define HMAC_IPAD       0x36
  865
+#define HMAC_OPAD       0x5c
  866
+
  867
+static void hmac_md5(char *key, int klen, char *dbuf, int dlen, char *hmacbuf)
  868
+{
  869
+    CC_MD5_CTX ctx;
  870
+    char ipad[HMAC_INT_LEN];
  871
+    char opad[HMAC_INT_LEN];
  872
+    unsigned char nkey[CC_MD5_DIGEST_LENGTH];
  873
+    int i;
  874
+
  875
+    /* Change key if longer than 64 bytes */
  876
+    if (klen > HMAC_INT_LEN) {
  877
+        CC_MD5(key, klen, nkey);
  878
+        key = (char *) nkey;
  879
+        klen = CC_MD5_DIGEST_LENGTH;
  880
+    }
  881
+
  882
+    memset(ipad, '\0', sizeof(ipad));
  883
+    memset(opad, '\0', sizeof(opad));
  884
+    memcpy(ipad, key, klen);
  885
+    memcpy(opad, key, klen);
  886
+
  887
+    for (i = 0; i < HMAC_INT_LEN; i++) {
  888
+        ipad[i] ^= HMAC_IPAD;
  889
+        opad[i] ^= HMAC_OPAD;
  890
+    }
  891
+
  892
+    /* inner MD5 */
  893
+    CC_MD5_Init(&ctx);
  894
+    CC_MD5_Update(&ctx, ipad, HMAC_INT_LEN);
  895
+    CC_MD5_Update(&ctx, dbuf, dlen);
  896
+    CC_MD5_Final((unsigned char *) hmacbuf, &ctx);
  897
+    /* outer MD5 */
  898
+    CC_MD5_Init(&ctx);
  899
+    CC_MD5_Update(&ctx, opad, HMAC_INT_LEN);
  900
+    CC_MD5_Update(&ctx, hmacbuf, CC_MD5_DIGEST_LENGTH);
  901
+    CC_MD5_Final((unsigned char *) hmacbuf, &ctx);
  902
+}
  903
+
  904
+static void hmac_sha1(char *key, int klen, char *dbuf, int dlen,  char *hmacbuf)
  905
+{
  906
+    CC_SHA1_CTX ctx;
  907
+    char ipad[HMAC_INT_LEN];
  908
+    char opad[HMAC_INT_LEN];
  909
+    unsigned char nkey[CC_SHA1_DIGEST_LENGTH];
  910
+    int i;
  911
+
  912
+    /* Change key if longer than 64 bytes */
  913
+    if (klen > HMAC_INT_LEN) {
  914
+        CC_SHA1(key, klen, nkey);
  915
+        key = (char *) nkey;
  916
+        klen = CC_SHA1_DIGEST_LENGTH;
  917
+    }
  918
+
  919
+    memset(ipad, '\0', sizeof(ipad));
  920
+    memset(opad, '\0', sizeof(opad));
  921
+    memcpy(ipad, key, klen);
  922
+    memcpy(opad, key, klen);
  923
+
  924
+    for (i = 0; i < HMAC_INT_LEN; i++) {
  925
+        ipad[i] ^= HMAC_IPAD;
  926
+        opad[i] ^= HMAC_OPAD;
  927
+    }
  928
+
  929
+    /* inner SHA */
  930
+    CC_SHA1_Init(&ctx);
  931
+    CC_SHA1_Update(&ctx, ipad, HMAC_INT_LEN);
  932
+    CC_SHA1_Update(&ctx, dbuf, dlen);
  933
+    CC_SHA1_Final((unsigned char *) hmacbuf, &ctx);
  934
+    /* outer SHA */
  935
+    CC_SHA1_Init(&ctx);
  936
+    CC_SHA1_Update(&ctx, opad, HMAC_INT_LEN);
  937
+    CC_SHA1_Update(&ctx, hmacbuf, CC_SHA1_DIGEST_LENGTH);
  938
+    CC_SHA1_Final((unsigned char *) hmacbuf, &ctx);
  939
+}
  940
+
  941
+
  942
+#ifdef OPENSSL_THREADS /* vvvvvvvvvvvvvvv OPENSSL_THREADS vvvvvvvvvvvvvvvv */
  943
+
  944
+static void locking(int mode, ErlDrvRWLock* lock)
  945
+{
  946
+    switch(mode) {
  947
+        case CRYPTO_LOCK|CRYPTO_READ:
  948
+            erl_drv_rwlock_rlock(lock);
  949
+            break;
  950
+        case CRYPTO_LOCK|CRYPTO_WRITE:
  951
+            erl_drv_rwlock_rwlock(lock);
  952
+            break;
  953
+        case CRYPTO_UNLOCK|CRYPTO_READ:
  954
+            erl_drv_rwlock_runlock(lock);
  955
+            break;
  956
+        case CRYPTO_UNLOCK|CRYPTO_WRITE:
  957
+            erl_drv_rwlock_rwunlock(lock);
  958
+            break;
  959
+        default:
  960
+            assert(!"Invalid lock mode");
  961
+    }
  962
+}
  963
+
  964
+/* Callback from openssl for static locking
  965
+ */
  966
+static void locking_function(int mode, int n, const char *file, int line)
  967
+{
  968
+    assert(n>=0 && n<CRYPTO_num_locks());
  969
+
  970
+    locking(mode, lock_vec[n]);
  971
+}
  972
+
  973
+/* Callback from openssl for thread id
  974
+ */
  975
+static unsigned long id_function(void)
  976
+{
  977
+    return (unsigned long) erl_drv_thread_self();
  978
+}
  979
+
  980
+/* Callbacks for dynamic locking, not used by current openssl version (0.9.8)
  981
+ */
  982
+static struct CRYPTO_dynlock_value* dyn_create_function(const char *file, int line)
  983
+{
  984
+    return (struct CRYPTO_dynlock_value*) erl_drv_rwlock_create("crypto_drv_dyn");
  985
+}
  986
+static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value* ptr,const char *file, int line)
  987
+{
  988
+    locking(mode, (ErlDrvRWLock*)ptr);
  989
+}
  990
+static void dyn_destroy_function(struct CRYPTO_dynlock_value *ptr, const char *file, int line)
  991
+{
  992
+    erl_drv_rwlock_destroy((ErlDrvRWLock*)ptr);
  993
+}
  994
+
  995
+#endif /* ^^^^^^^^^^^^^^^^^^^^^^ OPENSSL_THREADS ^^^^^^^^^^^^^^^^^^^^^^ */

0 notes on commit 3c9db53

Please sign in to comment.
Something went wrong with that request. Please try again.