Sun, 17 Dec 2017 13:20:01 +0100
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];