ports openssl code to commoncrypto (macos)

Sun, 17 Dec 2017 13:20:01 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 17 Dec 2017 13:20:01 +0100
changeset 349
0b4ecadaf3f9
parent 348
b79fb94f9e0a
child 350
5fc457fb2cb1

ports openssl code to commoncrypto (macos)

libidav/crypto.c file | annotate | diff | comparison | revisions
libidav/crypto.h file | annotate | diff | comparison | revisions
libidav/resource.c file | annotate | diff | comparison | revisions
libidav/utils.c file | annotate | diff | comparison | revisions
osx.mk file | annotate | diff | comparison | revisions
--- a/libidav/crypto.c	Sun Dec 17 10:53:08 2017 +0100
+++ b/libidav/crypto.c	Sun Dec 17 13:20:01 2017 +0100
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2016 Olaf Wintermann. All rights reserved.
+ * Copyright 2017 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -29,11 +29,15 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
 #include <libidav/utils.h>
-#include <openssl/rand.h>
 
 #include "crypto.h"
 
+/* -------------------- OpenSSL Crypto Functions -------------------- */
+#ifdef DAV_USE_OPENSSL
+
 #if OPENSSL_VERSION_NUMBER < 10000000
 
 static EVP_CIPHER_CTX* create_evp_cipher_ctx() {
@@ -324,6 +328,349 @@
 }
 
 
-void dav_get_hash(SHA256_CTX *sha256, unsigned char *buf) {
+void dav_get_hash(SHA_CTX *sha256, unsigned char *buf) {
     SHA256_Final((unsigned char*)buf, sha256);
 }
+
+#endif
+
+
+/* -------------------- Apple Crypto Functions -------------------- */
+#ifdef __APPLE__
+
+#define RANDOM_BUFFER_LENGTH 256
+static char randbuf[RANDOM_BUFFER_LENGTH];
+static int rbufpos = RANDOM_BUFFER_LENGTH;
+
+int dav_rand_bytes(unsigned char *buf, size_t len) {
+    if(len + rbufpos > RANDOM_BUFFER_LENGTH) {
+        int devr = open("/dev/urandom", O_RDONLY);
+        if(devr == -1) {
+            return 1;
+        }
+        
+        if(read(devr, randbuf, RANDOM_BUFFER_LENGTH) < RANDOM_BUFFER_LENGTH) {
+            close(devr);
+            return 1;
+        }
+        
+        rbufpos = 0;
+        if(len > RANDOM_BUFFER_LENGTH) {
+            int err = 0;
+            if(read(devr, buf, len) < len) {
+                err = 1;
+            }
+            close(devr);
+            return err;
+        }
+        
+        close(devr);
+    }
+    
+    char *r = randbuf;
+    memcpy(buf, r + rbufpos, len);
+    rbufpos += len;
+    
+    return 0;
+}
+
+AESDecrypter* aes_decrypter_new(DavKey *key, void *stream, dav_write_func write_func) {
+    AESDecrypter *dec = calloc(1, sizeof(AESDecrypter));
+    CC_SHA256_Init(&dec->sha256);
+    dec->stream = stream;
+    dec->write = write_func;
+    dec->key = key;
+    dec->init = 0;
+    dec->ivpos = 0;
+    
+    return dec;
+}
+
+
+void aes_decrypter_init(AESDecrypter *dec) {
+    //EVP_CIPHER_CTX_init(&dec->ctx);
+    dec->init = 1;
+    
+    CCCryptorRef cryptor;
+    CCCryptorStatus status;
+    if(dec->key->type == DAV_KEY_AES128) {
+        status = CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, dec->key->data, dec->key->length, dec->ivtmp, &cryptor);
+    } else if(dec->key->type == DAV_KEY_AES256) {
+        status = CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, dec->key->data, dec->key->length, dec->ivtmp, &cryptor);
+    } else {
+        fprintf(stderr, "unknown key type\n");
+        exit(-1);
+    }
+    dec->ctx = cryptor;
+}
+
+size_t aes_write(const void *buf, size_t s, size_t n, AESDecrypter *dec) {
+    int len = s*n;
+    if(!dec->init) {
+        size_t n = 16 - dec->ivpos;
+        size_t cp = n > len ? len : n;
+        memcpy(dec->ivtmp + dec->ivpos, buf, cp);
+        dec->ivpos += cp;
+        if(dec->ivpos >= 16) {
+            aes_decrypter_init(dec);
+        }
+        if(len == cp) {
+            return len;
+        } else {
+            buf = (char*)buf + cp;
+            len -= cp;
+        }
+    }
+    
+    int outlen = len + 16;
+    unsigned char *out = malloc(outlen);
+    
+    CCCryptorStatus status;
+    size_t avail = outlen;
+    size_t moved = 0;
+    status = CCCryptorUpdate(dec->ctx, buf, len, out, avail, &moved);
+    
+    ssize_t wlen = dec->write(out, 1, moved, dec->stream);
+    CC_SHA256_Update(&dec->sha256, out, wlen);
+    free(out);
+    return (s*n) / s;
+}
+
+void aes_decrypter_shutdown(AESDecrypter *dec) {
+    if(dec->init) {
+        void *out = malloc(128);
+        size_t len = 0;
+        //EVP_DecryptFinal_ex(dec->ctx, out, &len);
+        CCCryptorFinal(dec->ctx, out, 128, &len);
+        
+        
+        dec->write(out, 1, len, dec->stream);
+        CC_SHA256_Update(&dec->sha256, out, len);
+        free(out);
+        //EVP_CIPHER_CTX_cleanup(&dec->ctx);
+        //EVP_CIPHER_CTX_free(dec->ctx);
+    }
+}
+
+void aes_decrypter_close(AESDecrypter *dec) {
+    
+}
+
+AESEncrypter* aes_encrypter_new(DavKey *key, void *stream, dav_read_func read_func) {
+    unsigned char *iv = malloc(16);
+    if(dav_rand_bytes(iv, 16)) {
+        return NULL;
+    }
+    
+    CCCryptorRef cryptor;
+    CCCryptorStatus status;
+    if(key->type == DAV_KEY_AES128) {
+        status = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, key->data, key->length, iv, &cryptor);
+    } else if(key->type == DAV_KEY_AES256) {
+        status = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, key->data, key->length, iv, &cryptor);
+    } else {
+        free(iv);
+        return NULL;
+    }
+    
+    AESEncrypter *enc = malloc(sizeof(AESEncrypter));
+    enc->ctx = cryptor;
+    CC_SHA256_Init(&enc->sha256);
+    enc->stream = stream;
+    enc->read = read_func;
+    enc->tmp = NULL;
+    enc->tmplen = 0;
+    enc->tmpoff = 0;
+    enc->end = 0;
+    enc->iv = iv;
+    enc->ivlen = 16;
+    
+    return enc;
+}
+
+size_t aes_read(void *buf, size_t s, size_t n, AESEncrypter *enc) {
+    size_t len = s*n;
+    if(enc->tmp) {
+        size_t tmp_diff = enc->tmplen - enc->tmpoff;
+        size_t cp_len = tmp_diff > len ? len : tmp_diff;
+        memcpy(buf, enc->tmp + enc->tmpoff, cp_len);
+        enc->tmpoff += cp_len;
+        if(enc->tmpoff >= enc->tmplen) {
+            free(enc->tmp);
+            enc->tmp = NULL;
+            enc->tmplen = 0;
+            enc->tmpoff = 0;
+        }
+        return cp_len / s;
+    }
+    
+    if(enc->end) {
+        return 0;
+    }
+    
+    void *in = malloc(len);
+    size_t in_len = enc->read(in, 1, len, enc->stream);
+    
+    CC_SHA256_Update(&enc->sha256, in, in_len);
+    
+    unsigned char *out = NULL;
+    size_t outlen = 0;
+    size_t ivl = enc->ivlen;
+    if(in_len != 0) {
+        outlen = len + 16;
+        out = malloc(outlen + ivl);
+        if(enc->iv) {
+            memcpy(out, enc->iv, ivl);
+        }
+        
+        CCCryptorStatus status;
+        size_t avail = outlen;
+        status = CCCryptorUpdate(enc->ctx, in, in_len, out + ivl, avail, &outlen);
+        
+        free(in);
+    } else {
+        out = malloc(32);
+        CCCryptorStatus status;
+        size_t avail = outlen;
+        status = CCCryptorFinal(enc->ctx, out, 32, &outlen);
+        enc->end = 1;
+        free(in);
+    }
+    enc->tmp = (char*)out;
+    enc->tmplen = outlen + ivl;
+    enc->tmpoff = 0;
+    
+    if(enc->iv) {
+        free(enc->iv);
+        enc->iv = NULL;
+        enc->ivlen = 0;
+    }
+    
+    return aes_read(buf, s, n, enc);
+}
+
+void aes_encrypter_close(AESEncrypter *enc) {
+    if(enc->tmp) {
+        free(enc->tmp);
+    }
+    if(enc->iv) {
+        free(enc->iv);
+    }
+    // TODO: cleanup cryptor
+    free(enc);
+}
+
+char* aes_encrypt(char *in, size_t len, DavKey *key) {
+    unsigned char iv[16];
+    if(dav_rand_bytes(iv, 16)) {
+        return NULL;
+    }
+    
+    CCCryptorRef cryptor;
+    CCCryptorStatus status;
+    if(key->type == DAV_KEY_AES128) {
+        status = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, key->data, key->length, iv, &cryptor);
+    } else if(key->type == DAV_KEY_AES256) {
+        status = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, key->data, key->length, iv, &cryptor);
+    } else {
+        return NULL;
+    }
+    
+    if(status != kCCSuccess) {
+        return NULL;
+    }
+    
+    int buflen = len + 64;
+    char *buf = calloc(1, buflen);
+    memcpy(buf, iv, 16);
+    
+    int pos = 16;
+    size_t avail = buflen - 16;
+    size_t moved;
+    char *out = buf + 16;
+    
+    status = CCCryptorUpdate(cryptor, in,
+         len, out, avail,
+         &moved);
+    if(status != kCCSuccess) {
+        free(buf);
+        return NULL;
+    }
+    
+    pos += moved;
+    avail -= moved;
+    out += moved;
+    
+    status = CCCryptorFinal(cryptor, out, avail, &moved);
+    if(status != kCCSuccess) {
+        free(buf);
+        return NULL;
+    }
+    
+    pos += moved;
+    
+    char *b64enc = util_base64encode(buf, pos);
+    free(buf);
+    
+    return b64enc;
+}
+
+char* aes_decrypt(char *in, size_t *len, DavKey *key) {
+    int inlen;
+    unsigned char *buf = (unsigned char*)util_base64decode_len(in, &inlen);
+    
+    CCCryptorRef cryptor;
+    CCCryptorStatus status;
+    if(key->type == DAV_KEY_AES128) {
+        status = CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, key->data, key->length, buf, &cryptor);
+    } else if(key->type == DAV_KEY_AES256) {
+        status = CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, key->data, key->length, buf, &cryptor);
+    } else {
+        free(buf);
+        return NULL;
+    }
+    
+    if(status != kCCSuccess) {
+        free(buf);
+        return NULL;
+    }
+    
+    char *out = malloc(inlen + 1);
+    size_t outavail = inlen;
+    size_t outlen = 0;
+    
+    unsigned char *inbuf = buf + 16;
+    inlen -= 16;
+    
+    size_t moved = 0;
+    status = CCCryptorUpdate(cryptor, inbuf, inlen, out, outavail, &moved);
+    if(status != kCCSuccess) {
+        free(buf);
+        free(out);
+        // TODO cryptor
+        return NULL;
+    }
+    
+    outlen += moved;
+    outavail -= moved;
+    
+    status = CCCryptorFinal(cryptor, out + outlen, outavail, &moved);
+    if(status != kCCSuccess) {
+        free(buf);
+        free(out);
+        // TODO cryptor
+        return NULL;
+    }
+    
+    outlen += moved;
+    out[outlen] = 0;
+    
+    *len = outlen;
+    return out;
+}
+
+void dav_get_hash(DAV_SHA_CTX *sha256, unsigned char *buf) {
+    CC_SHA256_Final(buf, sha256);
+}
+
+#endif
--- a/libidav/crypto.h	Sun Dec 17 10:53:08 2017 +0100
+++ b/libidav/crypto.h	Sun Dec 17 13:20:01 2017 +0100
@@ -30,8 +30,27 @@
 #define	DAV_CRYPTO_H
 
 #include "webdav.h"
+#include <ucx/string.h>
+
+#ifdef __APPLE__
+/* macos */
+#define DAV_AES_CTX              CCCryptorRef
+#define DAV_SHA_CTX              CC_SHA256_CTX
+#define DAV_SHA256_DIGEST_LENGTH 32
+
+#include <CommonCrypto/CommonCrypto.h>
+#include <CommonCrypto/CommonDigest.h>
+
+#else
+/* unix/linux and still windows */
+#define DAV_AES_CTX              EVP_CIPHER_CTX*
+#define DAV_SHA_CTX              SHA256_CTX
+#define DAV_SHA256_DIGEST_LENGTH 32
+
+#define DAV_USE_OPENSSL
+
 #include <openssl/evp.h>
-#include <ucx/string.h>
+#include <openssl/rand.h>
 
 #if defined(__sun) && defined(__SunOS_5_10)
 #include <sha2.h>
@@ -42,13 +61,15 @@
 #include <openssl/sha.h>
 #endif
 
+#endif
+
 #ifdef	__cplusplus
 extern "C" {
 #endif
 
 typedef struct {
-    EVP_CIPHER_CTX *ctx;
-    SHA256_CTX     sha256;
+    DAV_AES_CTX    ctx;
+    DAV_SHA_CTX    sha256;
     void           *stream;
     dav_write_func write;
     DavKey         *key;
@@ -58,8 +79,8 @@
 } AESDecrypter;
 
 typedef struct {
-    EVP_CIPHER_CTX *ctx;
-    SHA256_CTX     sha256;
+    DAV_AES_CTX    ctx;
+    DAV_SHA_CTX    sha256;
     void           *iv;
     size_t         ivlen;
     void           *stream;
@@ -70,6 +91,8 @@
     int            end;
 } AESEncrypter;
 
+int dav_rand_bytes(unsigned char *buf, size_t len);
+
 AESDecrypter* aes_decrypter_new(DavKey *key, void *stream, dav_write_func write_func);
 size_t aes_write(const void *buf, size_t s, size_t n, AESDecrypter *dec);
 void aes_decrypter_shutdown(AESDecrypter *dec);
@@ -82,7 +105,7 @@
 char* aes_encrypt(char *in, size_t len, DavKey *key);
 char* aes_decrypt(char *in, size_t *len, DavKey *key);
 
-void dav_get_hash(SHA256_CTX *sha256, unsigned char *buf);
+void dav_get_hash(DAV_SHA_CTX *sha256, unsigned char *buf);
 
 #ifdef	__cplusplus
 }
--- a/libidav/resource.c	Sun Dec 17 10:53:08 2017 +0100
+++ b/libidav/resource.c	Sun Dec 17 13:20:01 2017 +0100
@@ -664,9 +664,9 @@
                     0);
             
             // get sha256 hash
-            unsigned char sha[SHA256_DIGEST_LENGTH];
+            unsigned char sha[DAV_SHA256_DIGEST_LENGTH];
             dav_get_hash(&enc->sha256, sha);
-            char *enc_hash = aes_encrypt((char*)sha, SHA256_DIGEST_LENGTH, sn->key);
+            char *enc_hash = aes_encrypt((char*)sha, DAV_SHA256_DIGEST_LENGTH, sn->key);
             
             aes_encrypter_close(enc);
             if(buf) {
@@ -772,9 +772,9 @@
         aes_decrypter_shutdown(dec); // get final bytes
         
         // get hash
-        unsigned char sha[SHA256_DIGEST_LENGTH];
+        unsigned char sha[DAV_SHA256_DIGEST_LENGTH];
         dav_get_hash(&dec->sha256, sha);
-        hash = util_hexstr(sha, 32);
+        hash = util_hexstr(sha, DAV_SHA256_DIGEST_LENGTH);
         
         aes_decrypter_close(dec);
     }
--- a/libidav/utils.c	Sun Dec 17 10:53:08 2017 +0100
+++ b/libidav/utils.c	Sun Dec 17 13:20:01 2017 +0100
@@ -46,16 +46,18 @@
 #define getpasswordchar() getchar()
 #endif
 
+#include "webdav.h"
+#include "utils.h"
+#include "crypto.h"
+#include "session.h"
+
+/*
 #include <openssl/hmac.h>
 #include <openssl/evp.h>
 #include <openssl/bio.h>
 #include <openssl/buffer.h>
 #include <openssl/rand.h>
-
-#include "webdav.h"
-#include "utils.h"
-#include "crypto.h"
-#include "session.h"
+*/
 
 static size_t extractval(sstr_t str, char *result, char delim) {
     size_t n = 0;
@@ -490,7 +492,7 @@
     char *outbuf = malloc(bufsize+1);
     *outlen = -1;
     
-    unsigned char *out = outbuf;
+    unsigned char *out = (unsigned char*)outbuf;
     
     char *end = in + inlen;
     char iter = 0;
@@ -653,7 +655,11 @@
             "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
     const unsigned char *table = (const unsigned char*)t.ptr;
     
+#ifdef DAV_USE_OPENSSL
     RAND_bytes(str, 24);
+#else
+    dav_rand_bytes(str, 24);
+#endif
     for(int i=0;i<24;i++) {
         int c = str[i] % t.length;
         str[i] = table[c];
--- a/osx.mk	Sun Dec 17 10:53:08 2017 +0100
+++ b/osx.mk	Sun Dec 17 13:20:01 2017 +0100
@@ -43,4 +43,4 @@
 APP_EXT =
 
 DAV_CFLAGS = `xml2-config --cflags`
-DAV_LDFLAGS = -lcurl -lxml2 -lssl -lcrypto -lpthread
+DAV_LDFLAGS = -lcurl -lxml2 -lpthread

mercurial