|
|
|
|
|
|
|
|
#include <openssl/rsa.h> |
|
|
|
|
|
#include <openssl/pem.h> |
|
|
|
|
|
#include <openssl/sha.h> |
|
|
|
|
|
#include <openssl/rand.h> |
|
|
|
|
|
#include <string.h> |
|
|
|
|
|
#include <assert.h> |
|
|
|
|
|
|
|
|
|
|
|
#include "lc6_crypto.h" |
|
|
|
|
|
|
|
|
|
|
|
int lc6crypto_seeded = 0; |
|
|
|
|
|
|
|
|
|
|
|
libchat_user* lc6crypto_genuserkey(libchat_user *user) { |
|
|
|
|
|
|
|
|
|
|
|
BIGNUM *bn; |
|
|
|
|
|
RSA *rsa; |
|
|
|
|
|
BIO *pub; |
|
|
|
|
|
BIO *priv; |
|
|
|
|
|
size_t publen; |
|
|
|
|
|
size_t privlen; |
|
|
|
|
|
|
|
|
|
|
|
assert(user); |
|
|
|
|
|
|
|
|
|
|
|
bn = BN_new(); |
|
|
|
|
|
BN_set_word(bn, RSA_F4); |
|
|
|
|
|
|
|
|
|
|
|
rsa = RSA_new(); |
|
|
|
|
|
RSA_generate_key_ex(rsa, 2048, bn, NULL); |
|
|
|
|
|
|
|
|
|
|
|
priv = BIO_new(BIO_s_mem()); |
|
|
|
|
|
pub = BIO_new(BIO_s_mem()); |
|
|
|
|
|
|
|
|
|
|
|
PEM_write_bio_RSAPrivateKey(priv, rsa, NULL, NULL, 0, NULL, NULL); |
|
|
|
|
|
PEM_write_bio_RSAPublicKey(pub, rsa); |
|
|
|
|
|
|
|
|
|
|
|
RSA_free(rsa); |
|
|
|
|
|
|
|
|
|
|
|
privlen = BIO_pending(priv); |
|
|
|
|
|
publen = BIO_pending(pub); |
|
|
|
|
|
|
|
|
|
|
|
user->priv_key = malloc(privlen); |
|
|
|
|
|
user->pub_key = malloc(publen); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BIO_read(priv, user->priv_key, privlen); |
|
|
|
|
|
BIO_read(pub, user->pub_key, publen); |
|
|
|
|
|
|
|
|
|
|
|
user->priv_key[privlen-1] = '\0'; |
|
|
|
|
|
user->pub_key[publen-1] = '\0'; |
|
|
|
|
|
|
|
|
|
|
|
BIO_free_all(priv); |
|
|
|
|
|
BIO_free_all(pub); |
|
|
|
|
|
BN_free(bn); |
|
|
|
|
|
|
|
|
|
|
|
return user; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
RSA * __lc6crypto_createRSA(unsigned char *key, int public) |
|
|
|
|
|
{ |
|
|
|
|
|
RSA *rsa= NULL; |
|
|
|
|
|
BIO *keybio = NULL; |
|
|
|
|
|
keybio = BIO_new_mem_buf(key, -1); |
|
|
|
|
|
|
|
|
|
|
|
assert(keybio); |
|
|
|
|
|
|
|
|
|
|
|
if(public) { |
|
|
|
|
|
PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL); |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(rsa); |
|
|
|
|
|
|
|
|
|
|
|
return rsa; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int lc6crypto_public_encrypt( |
|
|
|
|
|
unsigned char *data, |
|
|
|
|
|
int data_len, |
|
|
|
|
|
unsigned char *key, |
|
|
|
|
|
unsigned char *enc_data) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
RSA *rsa = __lc6crypto_createRSA(key,1); |
|
|
|
|
|
int result = RSA_public_encrypt(data_len, data, enc_data, rsa, RSA_PKCS1_OAEP_PADDING); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int lc6crypto_private_decrypt( |
|
|
|
|
|
unsigned char *enc_data, |
|
|
|
|
|
int enc_len, |
|
|
|
|
|
unsigned char *key, |
|
|
|
|
|
unsigned char *data) |
|
|
|
|
|
{ |
|
|
|
|
|
RSA *rsa = __lc6crypto_createRSA(key,0); |
|
|
|
|
|
int result = RSA_private_decrypt(enc_len, enc_data, data, rsa, RSA_PKCS1_OAEP_PADDING); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int lc6crypto_private_encrypt( |
|
|
|
|
|
unsigned char *data, |
|
|
|
|
|
int data_len, |
|
|
|
|
|
unsigned char *key, |
|
|
|
|
|
unsigned char *enc_data) |
|
|
|
|
|
{ |
|
|
|
|
|
RSA *rsa = __lc6crypto_createRSA(key,0); |
|
|
|
|
|
int result = RSA_private_encrypt(data_len, data, enc_data, rsa, RSA_PKCS1_OAEP_PADDING); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int lc6crypto_public_decrypt( |
|
|
|
|
|
unsigned char *enc_data, |
|
|
|
|
|
int enc_len, |
|
|
|
|
|
unsigned char *key, |
|
|
|
|
|
unsigned char *data) |
|
|
|
|
|
{ |
|
|
|
|
|
RSA *rsa = __lc6crypto_createRSA(key,1); |
|
|
|
|
|
int result = RSA_public_decrypt(enc_len, enc_data, data, rsa, RSA_PKCS1_OAEP_PADDING); |
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void lc6crypto_sha256( |
|
|
|
|
|
unsigned char *data, |
|
|
|
|
|
int data_len, |
|
|
|
|
|
unsigned char *hash) |
|
|
|
|
|
{ |
|
|
|
|
|
SHA256_CTX sha256; |
|
|
|
|
|
SHA256_Init(&sha256); |
|
|
|
|
|
SHA256_Update(&sha256, data, data_len); |
|
|
|
|
|
SHA256_Final(hash, &sha256); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int lc6crypto_encrypt( |
|
|
|
|
|
unsigned char *data, |
|
|
|
|
|
int data_len, |
|
|
|
|
|
unsigned char *encrypted, |
|
|
|
|
|
unsigned char *key, |
|
|
|
|
|
unsigned char *iv) |
|
|
|
|
|
{ |
|
|
|
|
|
EVP_CIPHER_CTX *ctx; |
|
|
|
|
|
int encrypted_len = 0; |
|
|
|
|
|
int len = 0; |
|
|
|
|
|
|
|
|
|
|
|
if(!(ctx = EVP_CIPHER_CTX_new())) |
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) { |
|
|
|
|
|
EVP_CIPHER_CTX_free(ctx); |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(1 != EVP_EncryptUpdate(ctx, encrypted, &len, data, data_len)) { |
|
|
|
|
|
EVP_CIPHER_CTX_free(ctx); |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
encrypted_len += len; |
|
|
|
|
|
|
|
|
|
|
|
if(1 != EVP_EncryptFinal_ex(ctx, encrypted + len, &len)) { |
|
|
|
|
|
EVP_CIPHER_CTX_free(ctx); |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
encrypted_len += len; |
|
|
|
|
|
|
|
|
|
|
|
EVP_CIPHER_CTX_free(ctx); |
|
|
|
|
|
|
|
|
|
|
|
return encrypted_len; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int lc6crypto_decrypt( |
|
|
|
|
|
unsigned char *encrypted, |
|
|
|
|
|
int encrypted_len, |
|
|
|
|
|
unsigned char *data, |
|
|
|
|
|
unsigned char *key, |
|
|
|
|
|
unsigned char *iv) |
|
|
|
|
|
{ |
|
|
|
|
|
EVP_CIPHER_CTX *ctx; |
|
|
|
|
|
int data_len = 0; |
|
|
|
|
|
int len = 0; |
|
|
|
|
|
|
|
|
|
|
|
if(!(ctx = EVP_CIPHER_CTX_new())) |
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) { |
|
|
|
|
|
EVP_CIPHER_CTX_free(ctx); |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(1 != EVP_DecryptUpdate(ctx, data, &len, encrypted, encrypted_len)) { |
|
|
|
|
|
EVP_CIPHER_CTX_free(ctx); |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
data_len += len; |
|
|
|
|
|
|
|
|
|
|
|
if(1 != EVP_DecryptFinal_ex(ctx, encrypted + len, &len)) { |
|
|
|
|
|
EVP_CIPHER_CTX_free(ctx); |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
data_len += len; |
|
|
|
|
|
|
|
|
|
|
|
EVP_CIPHER_CTX_free(ctx); |
|
|
|
|
|
|
|
|
|
|
|
return data_len; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int lc6crypto_random(unsigned char *data, int data_len) { |
|
|
|
|
|
|
|
|
|
|
|
if ( ! lc6crypto_seeded ) { |
|
|
|
|
|
RAND_poll(); |
|
|
|
|
|
lc6crypto_seeded=1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ( RAND_bytes(data, data_len) != 1 ) |
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
return data_len; |
|
|
|
|
|
} |
|
|
|