diff --git a/lib/pclsync/pssl-openssl.c b/lib/pclsync/pssl-openssl.c deleted file mode 100644 index 5c136d4..0000000 --- a/lib/pclsync/pssl-openssl.c +++ /dev/null @@ -1,989 +0,0 @@ -/* - Copyright (c) 2013 Anton Titov. - - Copyright (c) 2013 pCloud Ltd. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. Redistributions in binary form must reproduce the - above copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. Neither the name of pCloud Ltd nor the - names of its contributors may be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL pCloud - Ltd BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - DAMAGE. -*/ - -#include "plibs.h" -#include "pssl.h" -#include "psynclib.h" -#include "psslcerts.h" -#include "psettings.h" -#include "pcache.h" -#include "ptimer.h" -#include "pmemlock.h" -#include -#include -#include -#include - -#define SSL_CIPHERS \ - "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:"\ - "DHE-RSA-AES256-GCM-SHA384:ECDH-RSA-AES256-GCM-SHA384:"\ - "ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:"\ - "AES256-GCM-SHA384:AES256-SHA256;" - - -#if defined(PSYNC_AES_HW_MSC) -#include -#include -#endif - -typedef struct { - SSL *ssl; - int isbroken; - char cachekey[]; -} ssl_connection_t; - -static SSL_CTX *globalctx=NULL; -static pthread_mutex_t *olocks; - -#if defined(PSYNC_AES_HW) -int psync_ssl_hw_aes; -#endif - -PSYNC_THREAD int psync_ssl_errno; - -static void openssl_locking_callback(int mode, int type, const char *file, int line){ - if (mode&CRYPTO_LOCK) - pthread_mutex_lock(&(olocks[type])); - else - pthread_mutex_unlock(&(olocks[type])); -} - -static void openssl_thread_id(CRYPTO_THREADID *id){ - CRYPTO_THREADID_set_pointer(id, &psync_ssl_errno); -} - -static int openssl_locking_default(int *num, int cnt, int type, const char *file, int line){ - openssl_locking_callback(CRYPTO_LOCK|CRYPTO_WRITE, type, file, line); - cnt+=*num; - *num=cnt; - openssl_locking_callback(CRYPTO_UNLOCK|CRYPTO_WRITE, type, file, line); - return cnt; -} - -static int openssl_locking_add(int *num, int cnt, int type, const char *file, int line){ -#if defined(P_OS_WINDOWS) - if (sizeof(LONG)==sizeof(int)) - return _InterlockedAdd(num, cnt); - else - return openssl_locking_default(num, cnt, type, file, line); -#elif defined(__GNUC__) - if (1) - return __sync_add_and_fetch(num, cnt); - else - return openssl_locking_default(num, cnt, type, file, line); -#else - return openssl_locking_default(num, cnt, type, file, line); -#endif -} - -static void openssl_thread_setup(){ - int i, n; - n=CRYPTO_num_locks(); - olocks=psync_new_cnt(pthread_mutex_t, n); - for (i=0; i>25)&1; - if (ecx) - debug(D_NOTICE, "hardware AES support detected"); - else - debug(D_NOTICE, "hardware AES support not detected"); - return ecx; -} -#elif defined(PSYNC_AES_HW_MSC) -static int psync_ssl_detect_aes_hw(){ - int info[4]; - int ret; - __cpuid(info, 1); - ret=(info[2]>>25)&1; - if (ret) - debug(D_NOTICE, "hardware AES support detected"); - else - debug(D_NOTICE, "hardware AES support not detected"); - return ret; -} -#endif - -int psync_ssl_init(){ - BIO *bio; - X509 *cert; - psync_uint_t i; - unsigned char seed[PSYNC_LHASH_DIGEST_LEN]; -#if defined(PSYNC_AES_HW) - psync_ssl_hw_aes=psync_ssl_detect_aes_hw(); -#else - debug(D_NOTICE, "hardware AES is not supported for this compiler"); -#endif - if (!CRYPTO_set_locked_mem_functions(psync_locked_malloc, psync_locked_free)) - debug(D_WARNING, "failed to set locked functions for OpenSSL"); - SSL_library_init(); - OpenSSL_add_all_algorithms(); - OpenSSL_add_all_ciphers(); - SSL_load_error_strings(); - openssl_thread_setup(); - globalctx=SSL_CTX_new(TLSv1_2_client_method()); - if (likely_log(globalctx)){ - if (unlikely_log(SSL_CTX_set_cipher_list(globalctx, SSL_CIPHERS)!=1)){ - SSL_CTX_free(globalctx); - globalctx=NULL; - return -1; - } - SSL_CTX_set_verify(globalctx, SSL_VERIFY_NONE, NULL); - SSL_CTX_set_read_ahead(globalctx, 0); // readahed breaks SSL_Pending - SSL_CTX_set_session_cache_mode(globalctx, SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_NO_INTERNAL); - SSL_CTX_set_options(globalctx, SSL_OP_NO_COMPRESSION); - SSL_CTX_set_mode(globalctx, SSL_MODE_RELEASE_BUFFERS); - SSL_CTX_set_mode(globalctx, SSL_MODE_ENABLE_PARTIAL_WRITE); - for (i=0; iisbroken=1; - debug(D_NOTICE, "got error %d from OpenSSL: %s", err, ERR_error_string(err, NULL)); - } -} - -// Returns non-zero when CN and hostname match. -// Does case sensititive comparison, fine for now. Replace memcmp with str(n)casecmp if case insensitivity is needed -static int psync_ssl_compare_cn_hostname(const char *cn, size_t cnlen, const char *hostname, size_t hostnamelen){ - if (cn[0]=='*' && cn[1]=='.') // assumes valid null terminated string - return cnlen<=hostnamelen && - !memcmp(cn+1, hostname+hostnamelen-cnlen+1, cnlen) && //this will also compare the null byte - !memchr(hostname, '.', hostnamelen-cnlen+1); - else - return cnlen==hostnamelen && !memcmp(cn, hostname, cnlen); -} - -static int psync_ssl_cn_match_hostname(X509 *cert, const char *hostname){ - X509_NAME *sname; - X509_NAME_ENTRY *cnentry; - ASN1_STRING *cnasn; - const char *cnstr; - size_t cnstrlen; - int idx; - sname=X509_get_subject_name(cert); - if (unlikely_log(!sname)) - return -1; - idx=X509_NAME_get_index_by_NID(sname, NID_commonName, -1); - if (unlikely_log(idx<0)) - return -1; - cnentry=X509_NAME_get_entry(sname, idx); - if (unlikely_log(!cnentry)) - return -1; - cnasn=X509_NAME_ENTRY_get_data(cnentry); - if (unlikely_log(!cnasn)) - return -1; - cnstr=(const char *)ASN1_STRING_data(cnasn); - if (unlikely_log(!cnstr)) - return -1; - cnstrlen=strlen(cnstr); - if (unlikely_log(ASN1_STRING_length(cnasn)!=cnstrlen)) - return -1; - debug(D_NOTICE, "got certificate with commonName: %s", cnstr); - if (psync_ssl_compare_cn_hostname(cnstr, cnstrlen, hostname, strlen(hostname))) - return 0; - else{ - debug(D_WARNING, "hostname %s does not match certificate common name %s", hostname, cnstr); - return -1; - } -} - -static int psync_ssl_verify_cert(SSL *ssl, const char *hostname){ - X509 *cert; - int ret; - if (unlikely_log(SSL_get_verify_result(ssl)!=X509_V_OK)) - return -1; - cert=SSL_get_peer_certificate(ssl); - if (unlikely_log(!cert)) - return -1; - ret=psync_ssl_cn_match_hostname(cert, hostname); - X509_free(cert); - return ret; -} - -static ssl_connection_t *psync_ssl_alloc_conn(SSL *ssl, const char *hostname){ - ssl_connection_t *conn; - size_t len; - len=strlen(hostname)+1; - conn=(ssl_connection_t *)psync_malloc(offsetof(ssl_connection_t, cachekey)+len+4); - conn->ssl=ssl; - conn->isbroken=0; - memcpy(conn->cachekey, "SSLS", 4); - memcpy(conn->cachekey+4, hostname, len); - return conn; -} - -int psync_ssl_connect(psync_socket_t sock, void **sslconn, const char *hostname){ - ssl_connection_t *conn; - SSL *ssl; - SSL_SESSION *sess; - int res, err; - ssl=SSL_new(globalctx); - if (!ssl) - return PRINT_RETURN_CONST(PSYNC_SSL_FAIL); - SSL_set_fd(ssl, sock); - conn=psync_ssl_alloc_conn(ssl, hostname); - if ((sess=(SSL_SESSION *)psync_cache_get(conn->cachekey))){ - debug(D_NOTICE, "reusing cached session for %s", hostname); - SSL_set_session(ssl, sess); - SSL_SESSION_free(sess); - } - res=SSL_connect(ssl); - if (res==1){ - if (unlikely(psync_ssl_verify_cert(ssl, hostname))) - goto fail; - *sslconn=conn; - if (IS_DEBUG && SSL_session_reused(ssl)) - debug(D_NOTICE, "successfully reused session"); - return PSYNC_SSL_SUCCESS; - } - err=SSL_get_error(ssl, res); - psync_set_ssl_error(conn, err); - if (likely_log(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE)){ - *sslconn=conn; - return PSYNC_SSL_NEED_FINISH; - } -fail: - SSL_free(ssl); - psync_free(conn); - return PRINT_RETURN_CONST(PSYNC_SSL_FAIL); -} - -int psync_ssl_connect_finish(void *sslconn, const char *hostname){ - ssl_connection_t *conn; - int res, err; - conn=(ssl_connection_t *)sslconn; - res=SSL_connect(conn->ssl); - if (res==1){ - if (unlikely(psync_ssl_verify_cert(conn->ssl, hostname))) - goto fail; - if (IS_DEBUG && SSL_session_reused(conn->ssl)) - debug(D_NOTICE, "successfully reused session"); - return PSYNC_SSL_SUCCESS; - } - err=SSL_get_error(conn->ssl, res); - psync_set_ssl_error(conn, err); - if (likely_log(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE)) - return PSYNC_SSL_NEED_FINISH; -fail: - SSL_free(conn->ssl); - psync_free(conn); - return PRINT_RETURN_CONST(PSYNC_SSL_FAIL); -} - -static void psync_ssl_free_session(void *ptr){ - SSL_SESSION_free((SSL_SESSION *)ptr); -} - -int psync_ssl_shutdown(void *sslconn){ - ssl_connection_t *conn; - SSL_SESSION *sess; - int res, err; - conn=(ssl_connection_t *)sslconn; - sess=SSL_get1_session(conn->ssl); - if (sess) - psync_cache_add(conn->cachekey, sess, PSYNC_SSL_SESSION_CACHE_TIMEOUT, psync_ssl_free_session, PSYNC_MAX_SSL_SESSIONS_PER_DOMAIN); - if (conn->isbroken) - goto noshutdown; - res=SSL_shutdown(conn->ssl); - if (res!=-1) - goto noshutdown; - err=SSL_get_error(conn->ssl, res); - psync_set_ssl_error(conn, err); - if (likely_log(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE)) - return PSYNC_SSL_NEED_FINISH; -noshutdown: - SSL_free(conn->ssl); - psync_free(conn); - return PSYNC_SSL_SUCCESS; -} - -void psync_ssl_free(void *sslconn){ - ssl_connection_t *conn; - conn=(ssl_connection_t *)sslconn; - SSL_free(conn->ssl); - psync_free(conn); -} - -int psync_ssl_pendingdata(void *sslconn){ - return SSL_pending(((ssl_connection_t *)sslconn)->ssl); -} - -int psync_ssl_read(void *sslconn, void *buf, int num){ - ssl_connection_t *conn; - int res, err; - conn=(ssl_connection_t *)sslconn; - res=SSL_read(conn->ssl, buf, num); - if (res>=0) - return res; - err=SSL_get_error(conn->ssl, res); - psync_set_ssl_error(conn, err); - return PSYNC_SSL_FAIL; -} - -int psync_ssl_write(void *sslconn, const void *buf, int num){ - ssl_connection_t *conn; - int res, err; - conn=(ssl_connection_t *)sslconn; - res=SSL_write(conn->ssl, buf, num); - if (res>=0) - return res; - err=SSL_get_error(conn->ssl, res); - psync_set_ssl_error(conn, err); - return PSYNC_SSL_FAIL; -} - -void psync_ssl_rand_strong(unsigned char *buf, int num){ - static int seeds=0; - int ret; - if (seeds<2){ - unsigned char seed[PSYNC_LHASH_DIGEST_LEN]; - psync_get_random_seed(seed, buf, num, 1); - RAND_seed(seed, PSYNC_LHASH_DIGEST_LEN); - seeds++; - } - ret=RAND_bytes(buf, num); - if (unlikely(ret==0)){ - unsigned char seed[PSYNC_LHASH_DIGEST_LEN]; - psync_uint_t cnt; - cnt=0; - while (ret==0 && cnt++<20){ - psync_get_random_seed(seed, NULL, 0, 0); - RAND_seed(seed, PSYNC_LHASH_DIGEST_LEN); - ret=RAND_bytes(buf, num); - } - } - if (unlikely(ret!=1)){ - debug(D_CRITICAL, "could not generate %d random bytes, error %s, exiting", num, ERR_error_string(ERR_get_error(), NULL)); - exit(1); - } -} - -void psync_ssl_rand_weak(unsigned char *buf, int num){ - int ret; - ret=RAND_pseudo_bytes(buf, num); - if (unlikely(ret==-1)){ - debug(D_CRITICAL, "could not generate %d weak random bytes, error %s, exiting", num, ERR_error_string(ERR_get_error(), NULL)); - exit(1); - } - else if (unlikely(ret==0)) - debug(D_WARNING, "RAND_pseudo_bytes returned weak numbers"); -} - -/* this function comes from OpenSSL's crypto/rsa/rsa_lib.c, this version is not (that) buggy and reformatted */ -static int RSA_memory_lock_fixed(RSA *r){ - int i, j, k, off; - char *p; - BIGNUM *bn, **t[6], *b; - BN_ULONG *ul; - if (r->d==NULL) - return 1; - t[0]=&r->d; - t[1]=&r->p; - t[2]=&r->q; - t[3]=&r->dmp1; - t[4]=&r->dmq1; - t[5]=&r->iqmp; - k=sizeof(BIGNUM)*6; - off=k/sizeof(BN_ULONG)+1; - j=1; - for (i=0; i<6; i++) - j+=(*t[i])->top; - if ((p=OPENSSL_malloc_locked((off+j)*sizeof(BN_ULONG)))==NULL){ - RSAerr(RSA_F_RSA_MEMORY_LOCK, ERR_R_MALLOC_FAILURE); - return 0; - } - bn=(BIGNUM *)p; - ul=(BN_ULONG *)&p[k]; - for (i=0; i<6; i++){ - b= *(t[i]); - *(t[i])= &(bn[i]); - memcpy((char *)&(bn[i]), (char *)b, sizeof(BIGNUM)); - bn[i].flags=BN_FLG_STATIC_DATA; - bn[i].d=ul; - memcpy((char *)ul, b->d, sizeof(BN_ULONG)*b->top); - ul+=b->top; - BN_clear_free(b); - } - r->flags&=~(RSA_FLAG_CACHE_PRIVATE|RSA_FLAG_CACHE_PUBLIC); - r->bignum_data=p; - return 1; -} - -psync_rsa_t psync_ssl_gen_rsa(int bits){ - RSA *rsa; - BIGNUM *bn; - unsigned char seed[PSYNC_LHASH_DIGEST_LEN]; - psync_get_random_seed(seed, seed, sizeof(seed), 0); - RAND_seed(seed, PSYNC_LHASH_DIGEST_LEN); - rsa=RSA_new(); - if (unlikely_log(!rsa)) - goto err0; - bn=BN_new(); - if (unlikely_log(!bn)) - goto err1; - if (unlikely_log(!BN_set_word(bn, RSA_F4))) - goto err2; - if (unlikely_log(!RSA_generate_key_ex(rsa, bits, bn, NULL))) - goto err2; - RSA_memory_lock_fixed(rsa); - BN_free(bn); - return rsa; -err2: - BN_free(bn); -err1: - RSA_free(rsa); -err0: - return PSYNC_INVALID_RSA; -} - -static void psync_ssl_lock_rsa(RSA *rsa){ - RSA_memory_lock_fixed(rsa); -} - -void psync_ssl_free_rsa(psync_rsa_t rsa){ - RSA_free(rsa); -} - -psync_rsa_publickey_t psync_ssl_rsa_get_public(psync_rsa_t rsa){ - return RSAPublicKey_dup(rsa); -} - -void psync_ssl_rsa_free_public(psync_rsa_publickey_t key){ - RSA_free(key); -} - -psync_rsa_privatekey_t psync_ssl_rsa_get_private(psync_rsa_t rsa){ - RSA *rsap=RSAPrivateKey_dup(rsa); - if (rsap) - psync_ssl_lock_rsa(rsap); - return rsap; -} - -void psync_ssl_rsa_free_private(psync_rsa_privatekey_t key){ - RSA_free(key); -} - -psync_binary_rsa_key_t psync_ssl_rsa_public_to_binary(psync_rsa_publickey_t rsa){ - psync_binary_rsa_key_t ret; - unsigned char *p; - int len; - len=i2d_RSAPublicKey(rsa, NULL); - if (unlikely_log(len<0)) - return PSYNC_INVALID_BIN_RSA; - ret=psync_locked_malloc(offsetof(psync_encrypted_data_struct_t, data)+len); - ret->datalen=len; - p=ret->data; - if (unlikely_log(i2d_RSAPublicKey(rsa, &p)!=len)){ - psync_locked_free(ret); - return PSYNC_INVALID_BIN_RSA; - } - return ret; -} - -psync_binary_rsa_key_t psync_ssl_rsa_private_to_binary(psync_rsa_privatekey_t rsa){ - psync_binary_rsa_key_t ret; - unsigned char *p; - int len; - len=i2d_RSAPrivateKey(rsa, NULL); - if (unlikely_log(len<0)) - return PSYNC_INVALID_BIN_RSA; - ret=psync_locked_malloc(offsetof(psync_encrypted_data_struct_t, data)+len); - ret->datalen=len; - p=ret->data; - if (unlikely_log(i2d_RSAPrivateKey(rsa, &p)!=len)){ - psync_locked_free(ret); - return PSYNC_INVALID_BIN_RSA; - } - return ret; -} - -psync_rsa_publickey_t psync_ssl_rsa_load_public(const unsigned char *keydata, size_t keylen){ - return d2i_RSAPublicKey(NULL, &keydata, keylen); -} - -psync_rsa_privatekey_t psync_ssl_rsa_load_private(const unsigned char *keydata, size_t keylen){ - RSA *rsa=d2i_RSAPrivateKey(NULL, &keydata, keylen); - if (rsa) - psync_ssl_lock_rsa(rsa); - return rsa; -} - -psync_rsa_publickey_t psync_ssl_rsa_binary_to_public(psync_binary_rsa_key_t bin){ - return psync_ssl_rsa_load_public(bin->data, bin->datalen); -} - -psync_rsa_privatekey_t psync_ssl_rsa_binary_to_private(psync_binary_rsa_key_t bin){ - return psync_ssl_rsa_load_private(bin->data, bin->datalen); -} - -psync_symmetric_key_t psync_ssl_gen_symmetric_key_from_pass(const char *password, size_t keylen, const unsigned char *salt, size_t saltlen, size_t iterations){ - psync_symmetric_key_t key=(psync_symmetric_key_t)psync_locked_malloc(keylen+offsetof(psync_symmetric_key_struct_t, key)); - key->keylen=keylen; - PKCS5_PBKDF2_HMAC(password, strlen(password), salt, - saltlen, iterations, EVP_sha512(), keylen, key->key); - return key; -} - -psync_encrypted_symmetric_key_t psync_ssl_rsa_encrypt_data(psync_rsa_publickey_t rsa, const unsigned char *data, size_t datalen){ - psync_encrypted_symmetric_key_t ret; - int len; - ret=(psync_encrypted_symmetric_key_t)psync_malloc(offsetof(psync_encrypted_data_struct_t, data)+RSA_size(rsa)); - len=RSA_public_encrypt(datalen, data, ret->data, rsa, RSA_PKCS1_OAEP_PADDING); - if (unlikely_log(len==-1)){ - psync_free(ret); - return PSYNC_INVALID_ENC_SYM_KEY; - } - ret->datalen=len; - return ret; -} - -psync_symmetric_key_t psync_ssl_rsa_decrypt_data(psync_rsa_privatekey_t rsa, const unsigned char *data, size_t datalen){ - unsigned char buff[2048]; - psync_symmetric_key_t ret; - int len; - len=RSA_private_decrypt(datalen, data, buff, rsa, RSA_PKCS1_OAEP_PADDING); - if (unlikely(len==-1)){ -#if IS_DEBUG - unsigned long e; - e=ERR_get_error(); - debug(D_WARNING, "could not decrypt key, RSA_private_decrypt returned error %lu: %s", e, ERR_error_string(e, (char *)buff)); -#endif - return PSYNC_INVALID_SYM_KEY; - } - ret=(psync_symmetric_key_t)psync_locked_malloc(offsetof(psync_symmetric_key_struct_t, key)+len); - ret->keylen=len; - memcpy(ret->key, buff, len); - psync_ssl_memclean(buff, len); - return ret; -} - -psync_encrypted_symmetric_key_t psync_ssl_rsa_encrypt_symmetric_key(psync_rsa_publickey_t rsa, const psync_symmetric_key_t key){ - return psync_ssl_rsa_encrypt_data(rsa, key->key, key->keylen); -} - -psync_symmetric_key_t psync_ssl_rsa_decrypt_symmetric_key(psync_rsa_privatekey_t rsa, const psync_encrypted_symmetric_key_t enckey){ - return psync_ssl_rsa_decrypt_data(rsa, enckey->data, enckey->datalen); -} - -static AES_KEY *psync_ssl_get_aligned_aes_key(){ - unsigned char *m, *a; - m=(unsigned char *)psync_locked_malloc(PSYNC_AES256_BLOCK_SIZE+sizeof(AES_KEY)); - a=(unsigned char *)(((((uintptr_t)m)+PSYNC_AES256_BLOCK_SIZE-1)/PSYNC_AES256_BLOCK_SIZE)*PSYNC_AES256_BLOCK_SIZE); - a[sizeof(AES_KEY)]=a-m; - return (AES_KEY *)a; -} - -static void psync_ssl_free_aligned_aes_key(AES_KEY *aes){ - unsigned char *a; - a=(unsigned char *)aes; - a-=a[sizeof(AES_KEY)]; - psync_ssl_memclean(aes, sizeof(AES_KEY)); - psync_locked_free(a); -} - -psync_aes256_encoder psync_ssl_aes256_create_encoder(psync_symmetric_key_t key){ - AES_KEY *aes; - assert(key->keylen>=PSYNC_AES256_KEY_SIZE); - aes=psync_ssl_get_aligned_aes_key(); - AES_set_encrypt_key(key->key, 256, aes); - return aes; -} - -void psync_ssl_aes256_free_encoder(psync_aes256_encoder aes){ - psync_ssl_free_aligned_aes_key(aes); -} - -psync_aes256_encoder psync_ssl_aes256_create_decoder(psync_symmetric_key_t key){ - AES_KEY *aes; - assert(key->keylen>=PSYNC_AES256_KEY_SIZE); - aes=psync_ssl_get_aligned_aes_key(); - AES_set_decrypt_key(key->key, 256, aes); - return aes; -} - -void psync_ssl_aes256_free_decoder(psync_aes256_encoder aes){ - psync_ssl_free_aligned_aes_key(aes); -} - -#if defined(PSYNC_AES_HW_GCC) - -#define SSE2FUNC __attribute__((__target__("sse2"))) - -#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," -#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," -#define AESENC ".byte 0x66,0x0F,0x38,0xDC," -#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," - -#define xmm0_xmm1 "0xC8" -#define xmm0_xmm2 "0xD0" -#define xmm0_xmm3 "0xD8" -#define xmm0_xmm4 "0xE0" -#define xmm0_xmm5 "0xE8" -#define xmm1_xmm0 "0xC1" -#define xmm1_xmm2 "0xD1" -#define xmm1_xmm3 "0xD9" -#define xmm1_xmm4 "0xE1" -#define xmm1_xmm5 "0xE9" - -SSE2FUNC void psync_aes256_encode_block_hw(psync_aes256_encoder enc, const unsigned char *src, unsigned char *dst){ - asm("movdqa (%0), %%xmm0\n" - "lea 16(%0), %0\n" - "movdqa (%1), %%xmm1\n" - "dec %3\n" - "pxor %%xmm0, %%xmm1\n" - "movdqa (%0), %%xmm0\n" - "1:\n" - "lea 16(%0), %0\n" - "dec %3\n" - AESENC xmm0_xmm1 "\n" - "movdqa (%0), %%xmm0\n" - "jnz 1b\n" - AESENCLAST xmm0_xmm1 "\n" - "movdqa %%xmm1, (%2)\n" - : - : "r" (enc->rd_key), "r" (src), "r" (dst), "r" (enc->rounds) - : "memory", "cc", "xmm0", "xmm1" - ); -} - -SSE2FUNC void psync_aes256_decode_block_hw(psync_aes256_decoder enc, const unsigned char *src, unsigned char *dst){ - asm("movdqa (%0), %%xmm0\n" - "lea 16(%0), %0\n" - "movdqa (%1), %%xmm1\n" - "dec %3\n" - "pxor %%xmm0, %%xmm1\n" - "movdqa (%0), %%xmm0\n" - "1:\n" - "lea 16(%0), %0\n" - "dec %3\n" - AESDEC xmm0_xmm1 "\n" - "movdqa (%0), %%xmm0\n" - "jnz 1b\n" - AESDECLAST xmm0_xmm1 "\n" - "movdqa %%xmm1, (%2)\n" - : - : "r" (enc->rd_key), "r" (src), "r" (dst), "r" (enc->rounds) - : "memory", "cc", "xmm0", "xmm1" - ); -} - -SSE2FUNC void psync_aes256_encode_2blocks_consec_hw(psync_aes256_encoder enc, const unsigned char *src, unsigned char *dst){ - asm("movdqa (%0), %%xmm0\n" - "movdqa (%1), %%xmm1\n" - "dec %3\n" - "movdqa 16(%1), %%xmm2\n" - "lea 16(%0), %0\n" - "xorps %%xmm0, %%xmm1\n" - "pxor %%xmm0, %%xmm2\n" - "movdqa (%0), %%xmm0\n" - "1:\n" - "lea 16(%0), %0\n" - AESENC xmm0_xmm1 "\n" - "dec %3\n" - AESENC xmm0_xmm2 "\n" - "movdqa (%0), %%xmm0\n" - "jnz 1b\n" - AESENCLAST xmm0_xmm1 "\n" - AESENCLAST xmm0_xmm2 "\n" - "movdqa %%xmm1, (%2)\n" - "movdqa %%xmm2, 16(%2)\n" - : - : "r" (enc->rd_key), "r" (src), "r" (dst), "r" (enc->rounds) - : "memory", "cc", "xmm0", "xmm1", "xmm2" - ); -} - -SSE2FUNC void psync_aes256_decode_2blocks_consec_hw(psync_aes256_decoder enc, const unsigned char *src, unsigned char *dst){ - asm("movdqa (%0), %%xmm0\n" - "movdqa (%1), %%xmm1\n" - "dec %3\n" - "movdqa 16(%1), %%xmm2\n" - "lea 16(%0), %0\n" - "xorps %%xmm0, %%xmm1\n" - "pxor %%xmm0, %%xmm2\n" - "movdqa (%0), %%xmm0\n" - "1:\n" - "lea 16(%0), %0\n" - AESDEC xmm0_xmm1 "\n" - "dec %3\n" - AESDEC xmm0_xmm2 "\n" - "movdqa (%0), %%xmm0\n" - "jnz 1b\n" - AESDECLAST xmm0_xmm1 "\n" - AESDECLAST xmm0_xmm2 "\n" - "movdqa %%xmm1, (%2)\n" - "movdqa %%xmm2, 16(%2)\n" - : - : "r" (enc->rd_key), "r" (src), "r" (dst), "r" (enc->rounds) - : "memory", "cc", "xmm0", "xmm1", "xmm2" - ); -} - -SSE2FUNC void psync_aes256_decode_4blocks_consec_xor_hw(psync_aes256_decoder enc, const unsigned char *src, unsigned char *dst, unsigned char *bxor){ - asm("movdqa (%0), %%xmm0\n" - "shr %4\n" - "movdqa (%1), %%xmm2\n" - "dec %4\n" - "movdqa 16(%1), %%xmm3\n" - "xorps %%xmm0, %%xmm2\n" - "movdqa 32(%1), %%xmm4\n" - "xorps %%xmm0, %%xmm3\n" - "movdqa 48(%1), %%xmm5\n" - "pxor %%xmm0, %%xmm4\n" - "movdqa 16(%0), %%xmm1\n" - "pxor %%xmm0, %%xmm5\n" - "1:\n" - "lea 32(%0), %0\n" - "dec %4\n" - AESDEC xmm1_xmm2 "\n" - "movdqa (%0), %%xmm0\n" - AESDEC xmm1_xmm3 "\n" - AESDEC xmm1_xmm4 "\n" - AESDEC xmm1_xmm5 "\n" - AESDEC xmm0_xmm2 "\n" - "movdqa 16(%0), %%xmm1\n" - AESDEC xmm0_xmm3 "\n" - AESDEC xmm0_xmm4 "\n" - AESDEC xmm0_xmm5 "\n" - "jnz 1b\n" - AESDEC xmm1_xmm2 "\n" - "movdqa 32(%0), %%xmm0\n" - AESDEC xmm1_xmm3 "\n" - AESDEC xmm1_xmm4 "\n" - AESDEC xmm1_xmm5 "\n" - AESDECLAST xmm0_xmm2 "\n" - AESDECLAST xmm0_xmm3 "\n" - AESDECLAST xmm0_xmm4 "\n" - "pxor (%3), %%xmm2\n" - AESDECLAST xmm0_xmm5 "\n" - "pxor 16(%3), %%xmm3\n" - "movdqa %%xmm2, (%2)\n" - "pxor 32(%3), %%xmm4\n" - "movdqa %%xmm3, 16(%2)\n" - "pxor 48(%3), %%xmm5\n" - "movdqa %%xmm4, 32(%2)\n" - "movdqa %%xmm5, 48(%2)\n" - : - : "r" (enc->rd_key), "r" (src), "r" (dst), "r" (bxor), "r" (enc->rounds) - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" - ); -} - -#elif defined(PSYNC_AES_HW_MSC) - -void psync_aes256_encode_block_hw(psync_aes256_encoder enc, const unsigned char *src, unsigned char *dst){ - __m128i r0, r1; - unsigned char *key; - unsigned cnt; - key=(unsigned char *)enc->rd_key; - r0=_mm_load_si128((__m128i *)key); - r1=_mm_load_si128((__m128i *)src); - cnt=enc->rounds-1; - key+=16; - r1=_mm_xor_si128(r0, r1); - r0=_mm_load_si128((__m128i *)key); - do{ - key+=16; - r1=_mm_aesenc_si128(r1, r0); - r0=_mm_load_si128((__m128i *)key); - } while (--cnt); - r1=_mm_aesenclast_si128(r1, r0); - _mm_store_si128((__m128i *)dst, r1); -} - -void psync_aes256_decode_block_hw(psync_aes256_encoder enc, const unsigned char *src, unsigned char *dst){ - __m128i r0, r1; - unsigned char *key; - unsigned cnt; - key=(unsigned char *)enc->rd_key; - r0=_mm_load_si128((__m128i *)key); - r1=_mm_load_si128((__m128i *)src); - cnt=enc->rounds-1; - key+=16; - r1=_mm_xor_si128(r0, r1); - r0=_mm_load_si128((__m128i *)key); - do{ - key+=16; - r1=_mm_aesdec_si128(r1, r0); - r0=_mm_load_si128((__m128i *)key); - } while (--cnt); - r1=_mm_aesdeclast_si128(r1, r0); - _mm_store_si128((__m128i *)dst, r1); -} - -void psync_aes256_encode_2blocks_consec_hw(psync_aes256_encoder enc, const unsigned char *src, unsigned char *dst){ - __m128i r0, r1, r2; - unsigned char *key; - unsigned cnt; - key=(unsigned char *)enc->rd_key; - r0=_mm_load_si128((__m128i *)key); - r1=_mm_load_si128((__m128i *)src); - r2=_mm_load_si128((__m128i *)(src+16)); - cnt=enc->rounds-1; - key+=16; - r1=_mm_xor_si128(r0, r1); - r2=_mm_xor_si128(r0, r2); - r0=_mm_load_si128((__m128i *)key); - do{ - key+=16; - r1=_mm_aesenc_si128(r1, r0); - r2=_mm_aesenc_si128(r2, r0); - r0=_mm_load_si128((__m128i *)key); - } while (--cnt); - r1=_mm_aesenclast_si128(r1, r0); - r2=_mm_aesenclast_si128(r2, r0); - _mm_store_si128((__m128i *)dst, r1); - _mm_store_si128((__m128i *)(dst+16), r2); -} - -void psync_aes256_decode_2blocks_consec_hw(psync_aes256_decoder enc, const unsigned char *src, unsigned char *dst){ - __m128i r0, r1, r2; - unsigned char *key; - unsigned cnt; - key=(unsigned char *)enc->rd_key; - r0=_mm_load_si128((__m128i *)key); - r1=_mm_load_si128((__m128i *)src); - r2=_mm_load_si128((__m128i *)(src+16)); - cnt=enc->rounds-1; - key+=16; - r1=_mm_xor_si128(r0, r1); - r2=_mm_xor_si128(r0, r2); - r0=_mm_load_si128((__m128i *)key); - do{ - key+=16; - r1=_mm_aesdec_si128(r1, r0); - r2=_mm_aesdec_si128(r2, r0); - r0=_mm_load_si128((__m128i *)key); - } while (--cnt); - r1=_mm_aesdeclast_si128(r1, r0); - r2=_mm_aesdeclast_si128(r2, r0); - _mm_store_si128((__m128i *)dst, r1); - _mm_store_si128((__m128i *)(dst+16), r2); -} - -void psync_aes256_decode_4blocks_consec_xor_hw(psync_aes256_decoder enc, const unsigned char *src, unsigned char *dst, unsigned char *bxor){ - __m128i r0, r1, r2, r3, r4; - unsigned char *key; - unsigned cnt; - key=(unsigned char *)enc->rd_key; - r0=_mm_load_si128((__m128i *)key); - r1=_mm_load_si128((__m128i *)src); - r2=_mm_load_si128((__m128i *)(src+16)); - r3=_mm_load_si128((__m128i *)(src+32)); - r4=_mm_load_si128((__m128i *)(src+48)); - cnt=enc->rounds-1; - key+=16; - r1=_mm_xor_si128(r0, r1); - r2=_mm_xor_si128(r0, r2); - r3=_mm_xor_si128(r0, r3); - r4=_mm_xor_si128(r0, r4); - r0=_mm_load_si128((__m128i *)key); - do{ - key+=16; - r1=_mm_aesdec_si128(r1, r0); - r2=_mm_aesdec_si128(r2, r0); - r3=_mm_aesdec_si128(r3, r0); - r4=_mm_aesdec_si128(r4, r0); - r0=_mm_load_si128((__m128i *)key); - } while (--cnt); - r1=_mm_aesdeclast_si128(r1, r0); - r2=_mm_aesdeclast_si128(r2, r0); - r3=_mm_aesdeclast_si128(r3, r0); - r4=_mm_aesdeclast_si128(r4, r0); - r0=_mm_load_si128((__m128i *)bxor); - r1=_mm_xor_si128(r0, r1); - r0=_mm_load_si128((__m128i *)(bxor+16)); - _mm_store_si128((__m128i *)dst, r1); - r2=_mm_xor_si128(r0, r2); - r0=_mm_load_si128((__m128i *)(bxor+32)); - _mm_store_si128((__m128i *)(dst+16), r2); - r3=_mm_xor_si128(r0, r3); - r0=_mm_load_si128((__m128i *)(bxor+48)); - _mm_store_si128((__m128i *)(dst+32), r3); - r4=_mm_xor_si128(r0, r4); - _mm_store_si128((__m128i *)(dst+48), r4); -} - -#endif - -#if defined(PSYNC_AES_HW) - -void psync_aes256_decode_4blocks_consec_xor_sw(psync_aes256_decoder enc, const unsigned char *src, unsigned char *dst, unsigned char *bxor){ - unsigned long i; - AES_decrypt(src, dst, enc); - AES_decrypt(src+PSYNC_AES256_BLOCK_SIZE, dst+PSYNC_AES256_BLOCK_SIZE, enc); - AES_decrypt(src+PSYNC_AES256_BLOCK_SIZE*2, dst+PSYNC_AES256_BLOCK_SIZE*2, enc); - AES_decrypt(src+PSYNC_AES256_BLOCK_SIZE*3, dst+PSYNC_AES256_BLOCK_SIZE*3, enc); - for (i=0; i -#include -#include -#include -#include -#include -#include -#include - -#define kSecPaddingOAEP 2 - -OSStatus SecKeyEncrypt( - SecKeyRef key, - SecPadding padding, - const uint8_t *plainText, - size_t plainTextLen, - uint8_t *cipherText, - size_t *cipherTextLen); - -OSStatus SecKeyDecrypt( - SecKeyRef key, - SecPadding padding, - const uint8_t *cipherText, - size_t cipherTextLen, - uint8_t *plainText, - size_t *plainTextLen); - -PSYNC_THREAD int psync_ssl_errno; - -int psync_ssl_init(){ - return 0; -} - -void psync_ssl_memclean(void *ptr, size_t len){ - volatile unsigned char *c=(volatile unsigned char *)ptr; - while (len--) - *c++=0; -} - -static OSStatus psync_myread(SSLConnectionRef conn, void *data, size_t *len){ - psync_socket_t sock=(psync_socket_t)conn; - size_t llen=*len; - ssize_t rd=read(sock, data, llen); - if (likely(rd>0)){ - *len=rd; - if (rd==llen) - return noErr; - psync_ssl_errno=PSYNC_SSL_ERR_WANT_READ; - return errSSLWouldBlock; - } - else if (rd==0){ - *len=0; - return errSSLClosedNoNotify; - } - else { - *len=0; - if (errno==EAGAIN || errno==EINTR){ - psync_ssl_errno=PSYNC_SSL_ERR_WANT_READ; - return errSSLWouldBlock; - } - else - return errSSLClosedAbort; - } -} - -static OSStatus psync_mywrite(SSLConnectionRef conn, const void *data, size_t *len){ - psync_socket_t sock=(psync_socket_t)conn; - size_t llen=*len; - ssize_t rd=write(sock, data, llen); - if (likely(rd>=0)){ - *len=rd; - if (rd==llen) - return noErr; - psync_ssl_errno=PSYNC_SSL_ERR_WANT_WRITE; - return errSSLWouldBlock; - } - else { - *len=0; - if (errno==EAGAIN || errno==EINTR){ - psync_ssl_errno=PSYNC_SSL_ERR_WANT_WRITE; - return errSSLWouldBlock; - } - else - return errSSLClosedAbort; - } -} - -int psync_ssl_connect(psync_socket_t sock, void **sslconn, const char *hostname){ - SSLContextRef ref; - OSStatus st; - ref=SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType); - if (unlikely_log(!ref)) - goto err1; - if (unlikely_log(SSLSetIOFuncs(ref, psync_myread, psync_mywrite)!=noErr)) - goto err2; - if (unlikely_log(SSLSetConnection(ref, (SSLConnectionRef)(uintptr_t)sock)!=noErr)) - goto err2; - if (hostname && unlikely_log(SSLSetPeerDomainName(ref, hostname, strlen(hostname))!=noErr)) - goto err2; - st=SSLHandshake(ref); - if (st==noErr){ - *sslconn=ref; - return PSYNC_SSL_SUCCESS; - } - else if (st==errSSLWouldBlock){ - *sslconn=ref; - return PSYNC_SSL_NEED_FINISH; - } - debug(D_WARNING, "connection failed with status %d", (int)st); -err2: - CFRelease(ref); -err1: - psync_ssl_errno=PSYNC_SSL_ERR_UNKNOWN; - return PSYNC_SSL_FAIL; -} - -int psync_ssl_connect_finish(void *sslconn, const char *hostname){ - SSLContextRef ref; - OSStatus st; - ref=(SSLContextRef)sslconn; - st=SSLHandshake(ref); - if (st==noErr) - return PSYNC_SSL_SUCCESS; - else if (st==errSSLWouldBlock) - return PSYNC_SSL_NEED_FINISH; - CFRelease(ref); - debug(D_WARNING, "connection failed with status %d", (int)st); - psync_ssl_errno=PSYNC_SSL_ERR_UNKNOWN; - return PSYNC_SSL_FAIL; -} - -int psync_ssl_shutdown(void *sslconn){ - SSLContextRef ref; - OSStatus st; - ref=(SSLContextRef)sslconn; - st=SSLClose(ref); - if (st==errSSLWouldBlock) - return PSYNC_SSL_NEED_FINISH; - CFRelease(ref); - if (st==noErr) - return PSYNC_SSL_SUCCESS; - psync_ssl_errno=PSYNC_SSL_ERR_UNKNOWN; - return PSYNC_SSL_FAIL; -} - -void psync_ssl_free(void *sslconn){ - CFRelease((SSLContextRef)sslconn); -} - -int psync_ssl_pendingdata(void *sslconn){ - size_t p; - if (SSLGetBufferedReadSize((SSLContextRef)sslconn, &p)==noErr) - return p; - else - return 0; -} - -int psync_ssl_read(void *sslconn, void *buf, int num){ - size_t ret; - OSStatus st; - psync_ssl_errno=PSYNC_SSL_ERR_UNKNOWN; - st=SSLRead((SSLContextRef)sslconn, buf, num, &ret); - if (st!=noErr){ - if (st==errSSLWouldBlock && ret) - return ret; - else if (st==errSSLClosedGraceful) - return 0; - else{ - if (st!=errSSLWouldBlock) - debug(D_WARNING, "read failed with error %d", (int)st); - return PSYNC_SSL_FAIL; - } - } - else - return ret; -} - -int psync_ssl_write(void *sslconn, const void *buf, int num){ - size_t ret; - OSStatus st; - psync_ssl_errno=PSYNC_SSL_ERR_UNKNOWN; - st=SSLWrite((SSLContextRef)sslconn, buf, num, &ret); - if (st!=noErr){ - if (st==errSSLWouldBlock && ret) - return ret; - else{ - if (st!=errSSLWouldBlock) - debug(D_WARNING, "write failed with error %d", (int)st); - return PSYNC_SSL_FAIL; - } - } - else - return ret; -} - -void psync_ssl_rand_strong(unsigned char *buf, int num){ - ssize_t ret; - int fd; - fd=open("/dev/random", O_RDONLY); - if (unlikely_log(fd==-1)) - goto err; - while (num){ - ret=read(fd, buf, num); - if (unlikely_log(ret<=0)) - goto err; - num-=ret; - buf+=ret; - } - close(fd); - return; -err: - debug(D_CRITICAL, "could not open /dev/random"); - exit(1); -} - -void psync_ssl_rand_weak(unsigned char *buf, int num){ - sqlite3_randomness(num, buf); -} - -psync_rsa_t psync_ssl_gen_rsa(int bits){ - psync_rsa_t ret; - SecKeyRef public_key, private_key; - CFDictionaryRef dict; - CFTypeRef keys[2], values[2]; - OSStatus st; - keys[0]=kSecAttrKeyType; - values[0]=kSecAttrKeyTypeRSA; - keys[1]=kSecAttrKeySizeInBits; - values[1]=CFNumberCreate(NULL, kCFNumberIntType, &bits); - dict=CFDictionaryCreate(NULL, keys, values, ARRAY_SIZE(keys), NULL, NULL); - st=SecKeyGeneratePair(dict, &public_key, &private_key); - CFRelease(dict); - CFRelease(values[1]); - if (unlikely(st!=errSecSuccess)){ - debug(D_ERROR, "RSA key generation failed with error %d", (int)st); - return PSYNC_INVALID_RSA; - } - ret=psync_new(psync_rsa_struct_t); - ret->public_key=public_key; - ret->private_key=private_key; - return ret; -} - -void psync_ssl_free_rsa(psync_rsa_t rsa){ - CFRelease(rsa->public_key); - CFRelease(rsa->private_key); - psync_free(rsa); -} - -psync_rsa_publickey_t psync_ssl_rsa_get_public(psync_rsa_t rsa){ - CFRetain(rsa->public_key); - return rsa->public_key; -} - -void psync_ssl_rsa_free_public(psync_rsa_publickey_t key){ - CFRelease(key); -} - -psync_rsa_privatekey_t psync_ssl_rsa_get_private(psync_rsa_t rsa){ - CFRetain(rsa->private_key); - return rsa->private_key; -} - -void psync_ssl_rsa_free_private(psync_rsa_privatekey_t key){ - CFRelease(key); -} - -psync_binary_rsa_key_t psync_ssl_rsa_public_to_binary(psync_rsa_publickey_t rsa){ - psync_binary_rsa_key_t ret; - CFDictionaryRef dict; - CFTypeRef keys[4], values[4], arrval[1]; - CFArrayRef arr; - OSStatus st; - CFDataRef data; - CFIndex len; - arrval[0]=rsa; - arr=CFArrayCreate(NULL, arrval, 1, NULL); - keys[0]=kSecAttrKeyType; - values[0]=kSecAttrKeyTypeRSA; - keys[1]=kSecReturnData; - values[1]=kCFBooleanTrue; - keys[2]=kSecClass; - values[2]=kSecClassKey; - keys[3]=kSecMatchItemList; - values[3]=arr; - dict=CFDictionaryCreate(NULL, keys, values, ARRAY_SIZE(keys), NULL, NULL); - data=NULL; - st=SecItemCopyMatching(dict, (CFTypeRef *)&data); - CFRelease(dict); - CFRelease(arr); - if (unlikely_log(st!=errSecSuccess)) - return PSYNC_INVALID_BIN_RSA; - len=CFDataGetLength(data); - ret=psync_malloc(offsetof(psync_encrypted_data_struct_t, data)+len); - ret->datalen=len; - memcpy(ret->data, CFDataGetBytePtr(data), len); - CFRelease(data); - return ret; -} - -psync_binary_rsa_key_t psync_ssl_rsa_private_to_binary(psync_rsa_privatekey_t rsa){ - psync_binary_rsa_key_t ret; - CFDictionaryRef dict; - CFTypeRef keys[4], values[4], arrval[1]; - CFArrayRef arr; - OSStatus st; - CFDataRef data; - CFIndex len; - arrval[0]=rsa; - arr=CFArrayCreate(NULL, arrval, 1, NULL); - keys[0]=kSecAttrKeyType; - values[0]=kSecAttrKeyTypeRSA; - keys[1]=kSecReturnData; - values[1]=kCFBooleanTrue; - keys[2]=kSecClass; - values[2]=kSecAttrKeyClassPrivate; - keys[3]=kSecMatchItemList; - values[3]=arr; - dict=CFDictionaryCreate(NULL, keys, values, ARRAY_SIZE(keys), NULL, NULL); - data=NULL; - st=SecItemCopyMatching(dict, (CFTypeRef *)&data); - CFRelease(dict); - CFRelease(arr); - if (unlikely_log(st!=errSecSuccess)) - return PSYNC_INVALID_BIN_RSA; - len=CFDataGetLength(data); - ret=psync_malloc(offsetof(psync_encrypted_data_struct_t, data)+len); - ret->datalen=len; - memcpy(ret->data, CFDataGetBytePtr(data), len); - CFRelease(data); - return ret; -} -psync_rsa_publickey_t psync_ssl_rsa_binary_to_public(psync_binary_rsa_key_t bin){ - /* on iOS SecKeyCreateRSAPublicKey can be used */ - SecKeyRef ret; - SecExternalFormat form; - SecExternalItemType type; - CFDataRef data; - CFArrayRef out; - OSStatus st; - - form=kSecFormatUnknown; - type=kSecItemTypePublicKey; - data=CFDataCreate(NULL, bin->data, bin->datalen); - st=SecItemImport(data, NULL, &form, &type, 0, NULL, NULL, &out); - CFRelease(data); - if (unlikely_log(st!=errSecSuccess)) - PSYNC_INVALID_RSA; - ret=(SecKeyRef)CFArrayGetValueAtIndex(out, 0); - if (unlikely_log(ret==NULL)){ - CFRelease(out); - return PSYNC_INVALID_RSA; - } - CFRetain(ret); - CFRelease(out); - return ret; -} - -psync_rsa_privatekey_t psync_ssl_rsa_binary_to_private(psync_binary_rsa_key_t bin){ - SecKeyRef ret; - SecExternalFormat form; - SecExternalItemType type; - CFDataRef data; - CFArrayRef out; - OSStatus st; - - form=kSecFormatUnknown; - type=kSecItemTypePrivateKey; - data=CFDataCreate(NULL, bin->data, bin->datalen); - st=SecItemImport(data, NULL, &form, &type, 0, NULL, NULL, &out); - CFRelease(data); - if (unlikely_log(st!=errSecSuccess)) - PSYNC_INVALID_RSA; - ret=(SecKeyRef)CFArrayGetValueAtIndex(out, 0); - if (unlikely_log(ret==NULL)){ - CFRelease(out); - return PSYNC_INVALID_RSA; - } - CFRetain(ret); - CFRelease(out); - return ret; -} - - -static void PKCS5_PBKDF2_HMAC_SHA1(const char *pass, size_t passlen, const unsigned char *salt, size_t saltlen, - unsigned long cnt, size_t keylen, unsigned char *out){ - unsigned char sha1hmacbin[CC_SHA1_DIGEST_LENGTH], itmp[4]; - size_t clen; - uint32_t iter, i, j; - CCHmacContext hctx; - iter=1; - while (keylen){ - if (keylen>CC_SHA1_DIGEST_LENGTH) - clen=CC_SHA1_DIGEST_LENGTH; - else - clen=keylen; - itmp[0]=(unsigned char)((iter>>24)&0xff); - itmp[1]=(unsigned char)((iter>>16)&0xff); - itmp[2]=(unsigned char)((iter>>8)&0xff); - itmp[3]=(unsigned char)(iter&0xff); - CCHmacInit(&hctx, kCCHmacAlgSHA1, pass, passlen); - CCHmacUpdate(&hctx, salt, saltlen); - CCHmacUpdate(&hctx, itmp, 4); - CCHmacFinal(&hctx, sha1hmacbin); - memcpy(out, sha1hmacbin, clen); - for (i=1; ikeylen=keylen; - PKCS5_PBKDF2_HMAC_SHA1(password, strlen(password), (const unsigned char *)salt, - saltlen, PSYNC_CRYPTO_PASS_TO_KEY_ITERATIONS, keylen, key->key); - return key; -/* CFDictionaryRef dict; - CFTypeRef keys[4], values[4]; - CFStringRef pass; - SecKeyRef ret; - int num; - keys[0]=kSecAttrSalt; - values[0]=CFDataCreate(kCFAllocatorDefault, (const unsigned char *)PSYNC_CRYPTO_PASS_TO_KEY_SALT, sizeof(PSYNC_CRYPTO_PASS_TO_KEY_SALT)-1); - keys[1]=kSecAttrPRF; - values[1]=kSecAttrPRFHmacAlgSHA1; - num=PSYNC_CRYPTO_PASS_TO_KEY_ITERATIONS; - keys[2]=kSecAttrRounds; - values[2]=CFNumberCreate(NULL, kCFNumberIntType, &num); - num=keylen*8; - keys[3]=kSecAttrKeySizeInBits; - values[3]=CFNumberCreate(NULL, kCFNumberIntType, &num); - dict=CFDictionaryCreate(NULL, keys, values, ARRAY_SIZE(keys), NULL, NULL); - pass=CFStringCreateWithCStringNoCopy(NULL, password, kCFStringEncodingUTF8, NULL); - ret=SecKeyDeriveFromPassword(pass, dict, NULL); - CFRelease(pass); - CFRelease(dict); - CFRelease(values[0]); - CFRelease(values[2]); - CFRelease(values[3]); - return ret;*/ -} - -psync_encrypted_symmetric_key_t psync_ssl_rsa_encrypt_symmetric_key(psync_rsa_publickey_t rsa, const psync_symmetric_key_t key){ - size_t elen; - psync_encrypted_symmetric_key_t ret; - OSStatus st; - elen=SecKeyGetBlockSize(rsa); - ret=(psync_encrypted_symmetric_key_t)psync_malloc(offsetof(psync_encrypted_data_struct_t, data)+elen); - st=SecKeyEncrypt(rsa, kSecPaddingOAEP, key->key, key->keylen, ret->data, &elen); - if (unlikely_log(st!=errSecSuccess)){ - psync_free(ret); - return PSYNC_INVALID_ENC_SYM_KEY; - } - ret->datalen=elen; - return ret; -} - -psync_symmetric_key_t psync_ssl_rsa_decrypt_symmetric_key(psync_rsa_privatekey_t rsa, const psync_encrypted_symmetric_key_t enckey){ - unsigned char buff[2048]; - size_t len; - psync_symmetric_key_t ret; - OSStatus st; - st=SecKeyDecrypt(rsa, kSecPaddingOAEP, enckey->data, enckey->datalen, buff, &len); - if (unlikely_log(st!=errSecSuccess)) - return PSYNC_INVALID_SYM_KEY; - ret=(psync_symmetric_key_t)psync_malloc(offsetof(psync_symmetric_key_struct_t, key)+len); - ret->keylen=len; - memcpy(ret->key, buff, len); - return ret; -} - -psync_aes256_encoder psync_ssl_aes256_create_encoder(psync_symmetric_key_t key){ - CCCryptorRef ret; - assert(key->keylen>=PSYNC_AES256_KEY_SIZE); - if (unlikely_log(CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode, key->key, PSYNC_AES256_KEY_SIZE, NULL, &ret)!=kCCSuccess)) - return PSYNC_INVALID_ENCODER; - else - return ret; -} - -void psync_ssl_aes256_free_encoder(psync_aes256_encoder aes){ - CCCryptorRelease(aes); -} - -psync_aes256_encoder psync_ssl_aes256_create_decoder(psync_symmetric_key_t key){ - CCCryptorRef ret; - assert(key->keylen>=PSYNC_AES256_KEY_SIZE); - if (unlikely_log(CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES128, kCCOptionECBMode, key->key, PSYNC_AES256_KEY_SIZE, NULL, &ret)!=kCCSuccess)) - return PSYNC_INVALID_ENCODER; - else - return ret; -} - -void psync_ssl_aes256_free_decoder(psync_aes256_encoder aes){ - CCCryptorRelease(aes); -}