📄 symcrypt.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 + -