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 + -
显示快捷键?