crypto_drv.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 702 行 · 第 1/2 页

C
702
字号
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ *//* * Purpose:  Dynamically loadable driver for cryptography libraries.  * Based on OpenSSL.  */#ifdef __WIN32__#include <windows.h>#endif#include <stdlib.h>#include <stdio.h>#include <string.h>#include "erl_driver.h"#include <openssl/crypto.h>#include <openssl/des.h>#include <openssl/dsa.h>#include <openssl/rsa.h>#include <openssl/aes.h>#include <openssl/md5.h>#include <openssl/sha.h>#include <openssl/bn.h>#include <openssl/objects.h>#define get_int32(s) ((((unsigned char*) (s))[0] << 24) | \                      (((unsigned char*) (s))[1] << 16) | \                      (((unsigned char*) (s))[2] << 8)  | \                      (((unsigned char*) (s))[3]))#define put_int32(s,i) \{ (s)[0] = (char)(((i) >> 24) & 0xff);\  (s)[1] = (char)(((i) >> 16) & 0xff);\  (s)[2] = (char)(((i) >> 8) & 0xff);\  (s)[3] = (char)((i) & 0xff);\}/* Driver interface declarations */static ErlDrvData start(ErlDrvPort port, char *command);static void stop(ErlDrvData drv_data);static int control(ErlDrvData drv_data, unsigned int command, char *buf, 		   int len, char **rbuf, int rlen); static void hmac_md5(char *key, int klen, char *dbuf, int dlen, 		     char *hmacbuf);static void hmac_sha1(char *key, int klen, char *dbuf, int dlen, 		      char *hmacbuf);static ErlDrvEntry crypto_driver_entry = {    NULL,			/* init */    start,     stop,     NULL,			/* output */    NULL,			/* ready_input */    NULL,			/* ready_output */     "crypto_drv",     NULL,			/* finish */    NULL,			/* handle */    control,     NULL,			/* timeout */    NULL			/* outputv */};static ErlDrvPort erlang_port = NULL;static ErlDrvData driver_data = (ErlDrvData) &erlang_port; /* Anything goes *//* Keep the following definitions in alignment with the FUNC_LIST * in crypto.erl.  */#define DRV_INFO		0#define DRV_MD5			1#define DRV_MD5_INIT		2#define DRV_MD5_UPDATE		3#define DRV_MD5_FINAL		4#define DRV_SHA			5#define DRV_SHA_INIT		6#define DRV_SHA_UPDATE		7#define DRV_SHA_FINAL		8#define DRV_MD5_MAC		9#define DRV_MD5_MAC_96		10#define DRV_SHA_MAC		11#define DRV_SHA_MAC_96		12#define DRV_CBC_DES_ENCRYPT	13#define DRV_CBC_DES_DECRYPT	14#define DRV_EDE3_CBC_DES_ENCRYPT 15#define DRV_EDE3_CBC_DES_DECRYPT 16#define DRV_AES_CFB_128_ENCRYPT 17#define DRV_AES_CFB_128_DECRYPT 18#define DRV_RAND_BYTES		19#define DRV_RAND_UNIFORM	20#define DRV_MOD_EXP		21#define DRV_DSS_VERIFY		22#define DRV_RSA_VERIFY		23#define DRV_CBC_AES128_ENCRYPT	24#define DRV_CBC_AES128_DECRYPT	25#define DRV_XOR			26#define NUM_CRYPTO_FUNCS       	26#define MD5_CTX_LEN	(sizeof(MD5_CTX))#define MD5_LEN		16#define MD5_LEN_96	12#define SHA_CTX_LEN	(sizeof(SHA_CTX))#define SHA_LEN		20#define SHA_LEN_96	12#define HMAC_INT_LEN	64#define HMAC_IPAD	0x36#define HMAC_OPAD	0x5c/* INITIALIZATION AFTER LOADING *//*  * This is the init function called after this driver has been loaded. * It must *not* be declared static. Must return the address to  * the driver entry. */DRIVER_INIT(crypto_drv){    return &crypto_driver_entry;}/* DRIVER INTERFACE */static ErlDrvData start(ErlDrvPort port, char *command){     if (erlang_port != NULL)	return ERL_DRV_ERROR_GENERAL;    set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);    CRYPTO_set_mem_functions(driver_alloc, driver_realloc, driver_free);    erlang_port = port;    return driver_data;}static void stop(ErlDrvData drv_data){    erlang_port = NULL;    return;}/* Since we are operating in binary mode, the return value from control * is irrelevant, as long as it is not negative. */static int control(ErlDrvData drv_data, unsigned int command, char *buf, 		   int len, char **rbuf, int rlen){    int klen, dlen, i, j, macsize, from_len, to_len;    int base_len, exponent_len, modulo_len;    int data_len, digest_len, dsa_p_len, dsa_q_len, dsa_r_len;    int dsa_s_len, dsa_g_len, dsa_y_len;    int rsa_e_len, rsa_n_len;    int or_mask;    unsigned int rsa_s_len;    char *key, *key2, *key3, *dbuf, *ivec, *p;    const_DES_cblock *des_key, *des_key2, *des_key3;    const unsigned char *des_dbuf;    BIGNUM *bn_from, *bn_to, *bn_rand, *bn_result;    BIGNUM *bn_base, *bn_exponent, *bn_modulo;    BIGNUM *dsa_p, *dsa_q, *dsa_r, *dsa_s, *dsa_g, *dsa_y;    BIGNUM *rsa_n, *rsa_e;    DES_cblock *des_ivec;    ErlDrvBinary *bin;    DES_key_schedule schedule, schedule2, schedule3;    unsigned char hmacbuf[SHA_DIGEST_LENGTH];    unsigned char *rsa_s;    /* char hmacbuf[SHA_LEN]; */    MD5_CTX md5_ctx;    SHA_CTX sha_ctx;    int new_ivlen = 0;    BN_CTX *bn_ctx;    DSA *dsa;    RSA *rsa;    DSA_SIG *dsa_sig;    AES_KEY aes_key;    switch(command) {    case DRV_INFO:	*rbuf = (char*)(bin = driver_alloc_binary(NUM_CRYPTO_FUNCS));	for (i = 0; i < NUM_CRYPTO_FUNCS; i++) {	    bin->orig_bytes[i] = i + 1;	}	return NUM_CRYPTO_FUNCS;	break;    case DRV_MD5:	*rbuf = (char*)(bin = driver_alloc_binary(MD5_LEN));	MD5(buf, len, bin->orig_bytes);	return MD5_LEN;	break;    case DRV_MD5_INIT:	*rbuf = (char*)(bin = driver_alloc_binary(MD5_CTX_LEN));	MD5_Init((MD5_CTX *)bin->orig_bytes);	return MD5_CTX_LEN;			break;    case DRV_MD5_UPDATE:	if (len < MD5_CTX_LEN)	    return -1;	*rbuf = (char*)(bin = driver_alloc_binary(MD5_CTX_LEN));	memcpy(bin->orig_bytes, buf, MD5_CTX_LEN);	MD5_Update((MD5_CTX *)bin->orig_bytes, buf + MD5_CTX_LEN, 		   len - MD5_CTX_LEN);	return MD5_CTX_LEN;			break;    case DRV_MD5_FINAL:	if (len != MD5_CTX_LEN)	    return -1;	memcpy(&md5_ctx, buf, MD5_CTX_LEN); /* XXX Use buf only? */	*rbuf = (char *)(bin = driver_alloc_binary(MD5_LEN));	MD5_Final(bin->orig_bytes, &md5_ctx);	return MD5_LEN;			break;    case DRV_SHA:	*rbuf = (char *)(bin = driver_alloc_binary(SHA_LEN));	SHA1(buf, len, bin->orig_bytes);	return SHA_LEN;	break;    case DRV_SHA_INIT:	*rbuf = (char *)(bin = driver_alloc_binary(SHA_CTX_LEN));	SHA1_Init((SHA_CTX *)bin->orig_bytes);	return SHA_CTX_LEN;			break;    case DRV_SHA_UPDATE:	if (len < SHA_CTX_LEN)	    return -1;	*rbuf = (char *)(bin = driver_alloc_binary(SHA_CTX_LEN)); 	memcpy(bin->orig_bytes, buf, SHA_CTX_LEN);	SHA1_Update((SHA_CTX *)bin->orig_bytes, buf + SHA_CTX_LEN, 			  len - SHA_CTX_LEN);	return SHA_CTX_LEN;			break;    case DRV_SHA_FINAL:	if (len != SHA_CTX_LEN)	    return -1;	memcpy(&sha_ctx, buf, SHA_CTX_LEN); /* XXX Use buf only? */	*rbuf = (char *)(bin = driver_alloc_binary(SHA_LEN));	SHA1_Final(bin->orig_bytes, &sha_ctx);	return SHA_LEN;			break;    case DRV_MD5_MAC:    case DRV_MD5_MAC_96:	/* buf = klen[4] key data */	rlen = MD5_LEN;	klen = get_int32(buf);	key = buf + 4;	dlen = len - klen - 4;	dbuf = key + klen;	hmac_md5(key, klen, dbuf, dlen, hmacbuf);	macsize = (command == DRV_MD5_MAC) ? MD5_LEN : MD5_LEN_96;	*rbuf = (char *)(bin = driver_alloc_binary(macsize));	memcpy(bin->orig_bytes, hmacbuf, macsize);	return macsize;	break;    case DRV_SHA_MAC:    case DRV_SHA_MAC_96:	/* buf = klen[4] key data */	rlen = SHA_LEN;	klen = get_int32(buf);	key = buf + 4;	dlen = len - klen - 4;	dbuf = key + klen;	hmac_sha1(key, klen, dbuf, dlen, hmacbuf);	macsize = (command == DRV_SHA_MAC) ? SHA_LEN : SHA_LEN_96;	*rbuf = (char *)(bin = driver_alloc_binary(macsize));	memcpy(bin->orig_bytes, hmacbuf, macsize);	return macsize;	break;    case DRV_CBC_DES_ENCRYPT:    case DRV_CBC_DES_DECRYPT:	/* buf = key[8] ivec[8] data */	dlen = len - 16;	if (dlen < 0)	    return -1;	des_key = (const_DES_cblock*) buf; 	des_ivec = (DES_cblock*)(buf + 8); 	des_dbuf = buf + 16;	*rbuf = (char *)(bin = driver_alloc_binary(dlen));	DES_set_key(des_key, &schedule);	DES_ncbc_encrypt(des_dbuf, bin->orig_bytes, dlen, &schedule, des_ivec, 			 (command == DRV_CBC_DES_ENCRYPT));	return dlen;	break;    case DRV_EDE3_CBC_DES_ENCRYPT:    case DRV_EDE3_CBC_DES_DECRYPT:	dlen = len - 32;	if (dlen < 0)	    return -1;	des_key = (const_DES_cblock*) buf; 	des_key2 = (const_DES_cblock*) (buf + 8); 	des_key3 = (const_DES_cblock*) (buf + 16);	des_ivec = (DES_cblock*) (buf + 24); 	des_dbuf = buf + 32;	*rbuf = (char *)(bin = driver_alloc_binary(dlen));	DES_set_key(des_key, &schedule);	DES_set_key(des_key2, &schedule2);	DES_set_key(des_key3, &schedule3);	DES_ede3_cbc_encrypt(des_dbuf, bin->orig_bytes, dlen, &schedule,			     &schedule2, &schedule3, des_ivec, 			     (command == DRV_EDE3_CBC_DES_ENCRYPT));	return dlen;	break;    case DRV_AES_CFB_128_ENCRYPT:    case DRV_AES_CFB_128_DECRYPT:	/* buf = key[16] ivec[16] data */	dlen = len - 32;	if (dlen < 0)	    return -1;	*rbuf = (char *)(bin = driver_alloc_binary(dlen));	AES_set_encrypt_key(buf, 128, &aes_key);	AES_cfb128_encrypt(buf+32, bin->orig_bytes, dlen, &aes_key,			   buf+16, &new_ivlen,			   (command == DRV_AES_CFB_128_ENCRYPT));	return dlen;	break;    case DRV_RAND_BYTES:

⌨️ 快捷键说明

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