⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 symcrypt.c

📁 Linux下的飞鸽传书
💻 C
字号:
/* * Following codes are derived from  * ``Secure Programming Cookbook for C and C++''. * URL:http://www.oreilly.com/catalog/secureprgckbk/  *     http://www.secureprogramming.com/ *  * Licensing Information can be obtain from following URL: * *  http://www.secureprogramming.com/?action=license * * Copyright  2003 by John Viega and Matt Messier. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met:  * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. 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. * * 3. Neither the name of the developer of this software 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 THE COPYRIGHT * OWNER OR CONTRIBUTORS 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 <openssl/evp.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <glib.h>#include "common.h"static unsigned long key_select_table[]={  IPMSG_BLOWFISH_256,    IPMSG_RC2_256,  IPMSG_BLOWFISH_128,  IPMSG_RC2_128,  IPMSG_RC2_40,  -1,};intsymcrypt_get_skey_length(unsigned long type,size_t *ret_len){  size_t key_len;  if (!ret_len)    return -EINVAL;  switch(type){  case IPMSG_RC2_40:    key_len=5;    break;  case IPMSG_RC2_128:  case IPMSG_BLOWFISH_128:    key_len=16;    break;  case IPMSG_RC2_256:  case IPMSG_BLOWFISH_256:    key_len=32;    break;  default:    return -EINVAL;    break;  }  *ret_len=key_len;  return 0;}intblowfish_cbc_encrypt_setup(const char *key,size_t key_len_byte,const char *iv,EVP_CIPHER_CTX **ret){  EVP_CIPHER_CTX *ctx=NULL;  if (!ret)    return -EINVAL;  ctx = (EVP_CIPHER_CTX *)g_malloc(sizeof(EVP_CIPHER_CTX));  if (!ctx)    return -ENOMEM;  EVP_CIPHER_CTX_init(ctx);    EVP_EncryptInit(ctx, EVP_bf_cbc(), NULL,NULL);  EVP_CIPHER_CTX_set_key_length(ctx,key_len_byte);  EVP_EncryptInit(ctx, NULL, key, iv);  *ret=ctx;  return 0;}intblowfish_cbc_decrypt_setup(const char *key,size_t key_len_byte,const char *iv,EVP_CIPHER_CTX **ret){  EVP_CIPHER_CTX *ctx=NULL;  if (!ret)    return -EINVAL;  ctx = (EVP_CIPHER_CTX *)g_malloc(sizeof(EVP_CIPHER_CTX));  if (!ctx)    return -ENOMEM;  EVP_CIPHER_CTX_init(ctx);    EVP_DecryptInit(ctx, EVP_bf_cbc(), NULL, NULL);  EVP_CIPHER_CTX_set_key_length(ctx,key_len_byte);  EVP_DecryptInit(ctx, NULL, key, iv);  *ret=ctx;  return 0;}intrc2_cbc_encrypt_setup(const char *key,size_t key_len_byte,const char *iv,EVP_CIPHER_CTX **ret){  EVP_CIPHER_CTX *ctx=NULL;  if (!ret)    return -EINVAL;  ctx = (EVP_CIPHER_CTX *)g_malloc(sizeof(EVP_CIPHER_CTX));  if (!ctx)    return -ENOMEM;  EVP_CIPHER_CTX_init(ctx);    EVP_EncryptInit(ctx, EVP_rc2_cbc(), NULL,NULL);  EVP_CIPHER_CTX_set_key_length(ctx,key_len_byte);  EVP_EncryptInit(ctx, NULL, key, iv);  *ret=ctx;  return 0;}intrc2_cbc_decrypt_setup(const char *key,size_t key_len_byte,const char *iv,EVP_CIPHER_CTX **ret){  EVP_CIPHER_CTX *ctx=NULL;  if (!ret)    return -EINVAL;  ctx = (EVP_CIPHER_CTX *)g_malloc(sizeof(EVP_CIPHER_CTX));  if (!ctx)    return -ENOMEM;  EVP_CIPHER_CTX_init(ctx);    EVP_DecryptInit(ctx, EVP_rc2_cbc(), NULL, NULL);  EVP_CIPHER_CTX_set_key_length(ctx,key_len_byte);  EVP_DecryptInit(ctx, NULL, key,iv);  *ret=ctx;  return 0;}intcommon_cbc_encrypt(EVP_CIPHER_CTX *ctx, const char *data, int inl, int *rb,char **ret_buff) {  int  i, ol, tmp;  char *ret;  if ( (!ctx) || (!data) || (!ret_buff) )    return -EINVAL;  dbg_out("encrypt inl:%d\n", inl);  ol = 0;  if (!(ret = (char *)g_malloc(i = inl + EVP_CIPHER_CTX_block_size(ctx))))     g_assert_not_reached();  if (i < inl)    g_assert_not_reached();  for (i = 0;  i < inl / 100;  i++) {    if (!EVP_EncryptUpdate(ctx, &ret[ol], &tmp, &data[i*100], 100))       g_assert_not_reached();    ol += tmp;  }  if (inl % 100) {    if (!EVP_EncryptUpdate(ctx, &ret[ol], &tmp, &data[(inl/100)*100], inl % 100))       g_assert_not_reached();    ol += tmp;  }  dbg_out("Encrypt update %d length\n",ol);  if (!EVP_EncryptFinal_ex(ctx, &ret[ol], &tmp))     g_assert_not_reached();  ol += tmp;  dbg_out("Encrypt final %d length\n",ol);  if (rb)     *rb = ol;  *ret_buff=ret;  return 0;}int common_cbc_decrypt(EVP_CIPHER_CTX *ctx, const char *ct, int inl,char **ret_buff,size_t *outl) {  int rc;  int  ol,i,tlen;  char *pt;  char errbuf[1024];  if ( (!ctx) || (!ct) || (!ret_buff) || (!outl) )    return -EINVAL;  i = inl + EVP_CIPHER_CTX_block_size(ctx) + 1;  pt = (char *)g_malloc(i);  if (!pt)     g_assert_not_reached();  if (i < inl)     g_assert_not_reached();  dbg_out("Decrypt try to :%d length\n",inl);  rc=EVP_DecryptUpdate(ctx, pt, &ol, ct, inl);  if (!rc) {    rc=ERR_get_error();    err_out("Can not decrypt update message err=%s\n", ERR_error_string(rc, errbuf));    rc=-rc;    g_free(pt);    return -ENOENT;  }  dbg_out("Decrypt update %d length\n",ol);  rc=EVP_DecryptFinal (ctx, pt + ol, &tlen);  if (!rc) {    rc=ERR_get_error();    err_out("Can not decrypt finalize message err=%s\n", ERR_error_string(rc, errbuf));    rc=-rc;    g_free(pt);    return -ENOENT;  }  ol+=tlen;  pt[ol]=0;  *ret_buff=pt;  *outl=ol;  return 0;}intcommon_cbc_finalize(EVP_CIPHER_CTX **ctx_p) {  EVP_CIPHER_CTX *ctx;  if ( (!ctx_p) || ( !(*ctx_p) ) )    return -EINVAL;  ctx=*ctx_p;  EVP_CIPHER_CTX_cleanup(ctx);  g_free(ctx);  *ctx_p=NULL;  return 0;}intsymcrypt_encrypt_message(unsigned long type,const unsigned char *plain,			 char **key_p, size_t *key_len_p,char **enc_p,			 size_t *enc_len_p){  size_t key_len;  size_t enc_len;  EVP_CIPHER_CTX *ctx=NULL;  char *key;  char iv[EVP_MAX_IV_LENGTH];  char *enc=NULL;  int rc;  if ( (!plain) || (!key_p) || (!key_len_p) || (!enc_p) || (!enc_len_p) )    return -EINVAL;  rc=symcrypt_get_skey_length(type, &key_len);  if (rc)    return rc;  key=g_malloc(key_len);  if (!key)    return -ENOMEM;    rc=generate_rand(key,key_len);  if (rc)     goto key_free_out;  memset(iv,0,EVP_MAX_IV_LENGTH);  rc=-EINVAL;  switch(type){  case IPMSG_RC2_40:  case IPMSG_RC2_128:  case IPMSG_RC2_256:    rc=rc2_cbc_encrypt_setup(key,key_len,NULL,&ctx);    break;  case IPMSG_BLOWFISH_128:  case IPMSG_BLOWFISH_256:    rc=blowfish_cbc_encrypt_setup(key,key_len,NULL,&ctx);    break;  default:    goto key_free_out;    break;  }  if (rc) {    err_out("Can not set key\n");    goto key_free_out;  }  rc=common_cbc_finalize(&ctx);  if (rc) {    err_out("Can not clean up encrypt\n");    goto enc_free_out;  }  *key_p=key;  *key_len_p=key_len;  *enc_p=enc;  *enc_len_p=enc_len;  return 0; enc_free_out:  if (enc)    g_free(enc); ctx_free_out:  if (ctx)    common_cbc_finalize(&ctx); key_free_out:  if (key)    g_free(key);  return rc;}intsymcrypt_decrypt_message(unsigned long type,const unsigned char *encoded,			 size_t enc_len, const char *key,char **dec_p,size_t *dec_len_p){  size_t key_len;  EVP_CIPHER_CTX *ctx=NULL;  char *dec=NULL;  char *new_dec=NULL;  size_t dec_len;  int rc;  if ( (!encoded) || (!key) || (!dec_p) || (!dec_len_p) )    return -EINVAL;  rc=symcrypt_get_skey_length(type, &key_len);  if (rc)    return rc;  rc=-EINVAL;  switch(type){  case IPMSG_RC2_40:  case IPMSG_RC2_128:  case IPMSG_RC2_256:    dbg_out("Use RC2 key %d\n",key_len);    rc=rc2_cbc_decrypt_setup(key,key_len,NULL,&ctx);    break;  case IPMSG_BLOWFISH_128:  case IPMSG_BLOWFISH_256:    dbg_out("Use blowfish key %d\n",key_len);    rc=blowfish_cbc_decrypt_setup(key,key_len,NULL,&ctx);    break;  default:    return -EINVAL;    break;  }  dbg_out("Decrypt:%s (len=%d) into plain\n",encoded,enc_len);  rc=common_cbc_decrypt(ctx, encoded, enc_len, &dec,&dec_len);  if (rc) {    err_out("Can not decrypt\n");    goto ctx_free_out;  }  dbg_out("Decrypt len:%d\n",dec_len);  rc=common_cbc_finalize(&ctx);  if (rc) {    err_out("Can not clean up decrypt\n");    goto dec_free_out;  }  if (dec[dec_len-1] != '\0') {    new_dec=g_malloc(dec_len+1);    if (!new_dec)      goto dec_free_out;    memcpy(new_dec,dec,dec_len);    new_dec[dec_len]='\0';    g_free(dec);    dec=new_dec;  }  *dec_p=dec;  *dec_len_p=dec_len;  dbg_out("decoded:%s %d\n",dec,dec_len);  return 0; dec_free_out:  if (dec)    g_free(dec); ctx_free_out:  if (ctx)    common_cbc_finalize(&ctx);  return rc;}int select_symmetric_key(unsigned long peer_cap,unsigned long *selected_key,int speed){  unsigned long candidates;  int i;  int added_num=1;  int first=0;  int key_type;  if (!selected_key)    return -EINVAL;  candidates=(get_symkey_part(peer_cap) & hostinfo_get_ipmsg_crypt_capability());  if (speed) {    first=SYMCRYPT_MAX_KEY_TYPE-1;    added_num=-1;  }  for (i=first;       ((i>=0) && (i<SYMCRYPT_MAX_KEY_TYPE) && (!(key_select_table[i] & candidates)));       i+=added_num);  if (!( (i>=0) && (i<SYMCRYPT_MAX_KEY_TYPE) ))    return -ENOENT;  *selected_key=key_select_table[i];  dbg_out("Selected key name in ipmsg:0x%x\n",key_select_table[i]);  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -