crypto_drv.c

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

C
702
字号
	/* buf = <<rlen:32/integer,topmask:8/integer,bottommask:8/integer>> */	if (len != 6)	    return -1;	rlen = get_int32(buf);	*rbuf = (char *)(bin = driver_alloc_binary(rlen));	RAND_pseudo_bytes(bin->orig_bytes,rlen);	or_mask = ((unsigned char*)buf)[4];	bin->orig_bytes[rlen-1] |= or_mask; /* topmask */	or_mask = ((unsigned char*)buf)[5];	bin->orig_bytes[0] |= or_mask; /* bottommask */	return rlen;	break;          case DRV_RAND_UNIFORM:      /* buf = <<from_len:32/integer,bn_from:from_len/binary,   *       *         to_len:32/integer,bn_to:to_len/binary>>        */      if (len < 8)	return -1;      from_len = get_int32(buf);      if (len < (8 + from_len))	return -1;      to_len = get_int32(buf + 4 + from_len);      if (len != (8 + from_len + to_len))	return -1;      bn_from = BN_new();      BN_bin2bn((unsigned char *)(buf + 4), from_len, bn_from);      bn_rand = BN_new();      BN_bin2bn((unsigned char *)(buf + 8 + from_len), to_len, bn_rand);      bn_to = BN_new();      BN_sub(bn_to, bn_rand, bn_from);      BN_pseudo_rand_range(bn_rand, bn_to);      BN_add(bn_rand, bn_rand, bn_from);      rlen = BN_num_bytes(bn_rand);      *rbuf = (char *)(bin = driver_alloc_binary(rlen + 4));      put_int32(bin->orig_bytes, rlen);      BN_bn2bin(bn_rand,(unsigned char*)(bin->orig_bytes + 4));      BN_free(bn_rand);      BN_free(bn_from);      BN_free(bn_to);      return rlen + 4;      break;          case DRV_MOD_EXP:      /* buf = <<base_len:32/integer,base/binary,          *       *         exponent_len:32/integer,exponent/binary,  *       *         modulo_len:32/integer, modulo/binary>>    */      if (len < 12)	return -1;      base_len = get_int32(buf);      if (len < (12 + base_len))	return -1;      exponent_len = get_int32(buf + 4 + base_len);      if (len < (12 + base_len + exponent_len))	return -1;      modulo_len = get_int32(buf + 8 + base_len + exponent_len);      if (len != (12 + base_len + exponent_len + modulo_len))	return -1;      bn_base = BN_new();      BN_bin2bn((unsigned char *)(buf + 4),		base_len, bn_base);      bn_exponent = BN_new();      BN_bin2bn((unsigned char *)(buf + 8 + base_len),		exponent_len, bn_exponent);      bn_modulo = BN_new();      BN_bin2bn((unsigned char *)(buf + 12 + base_len + exponent_len),		modulo_len, bn_modulo);      bn_result = BN_new();      bn_ctx = BN_CTX_new();      BN_mod_exp(bn_result, bn_base, bn_exponent,		 bn_modulo, bn_ctx);      rlen = BN_num_bytes(bn_result);      *rbuf = (char *)(bin = driver_alloc_binary(rlen + 4));      put_int32(bin->orig_bytes, rlen);      BN_bn2bin(bn_result,(unsigned char*)(bin->orig_bytes + 4));      BN_free(bn_result);      BN_free(bn_modulo);      BN_free(bn_exponent);      BN_free(bn_base);      BN_CTX_free(bn_ctx);      return rlen + 4;      break;    case DRV_DSS_VERIFY:      /* buf = <<data_len:32/integer,data:data_len/binary,       *         dsa_r:20/binary,       *         dsa_s:20/binary,       *         dsa_p_len:32/integer, dsa_p:dsa_p_len/binary,       *         dsa_q_len:32/integer, dsa_q:dsa_q_len/binary,       *         dsa_g_len:32/integer, dsa_r:dsa_r_len/binary,       *         dsa_y_len:32/integer, dsa_y:dsa_y_len/binary>> */      i = 0;      j = 0;      if (len < 60)	return -1;      data_len = get_int32(buf + i + j);      j += data_len; i += 44;      if (len < (60 + j))	return -1;      dsa_p_len = get_int32(buf + i + j);      j += dsa_p_len; i += 4;      if (len < (60 + j))	return -1;      dsa_q_len = get_int32(buf + i + j);      j += dsa_q_len; i += 4;      if (len < (60 + j))	return -1;      dsa_g_len = get_int32(buf + i + j);      j += dsa_g_len; i += 4;      if (len < (60 + j))	return -1;      dsa_y_len = get_int32(buf + i + j);      j += dsa_y_len;      if (len < (60 + j))	return -1;      i = 4;      SHA1((unsigned char *) (buf + i), data_len, hmacbuf);      dsa_sig = DSA_SIG_new();      dsa_r = BN_new();      i += data_len;      BN_bin2bn((unsigned char *)(buf + i), 20, dsa_r);      i += 20;      dsa_s = BN_new();      BN_bin2bn((unsigned char *)(buf + i), 20, dsa_s);      i += 24;      dsa_sig->r = dsa_r;      dsa_sig->s = dsa_s;      dsa_p = BN_new();      BN_bin2bn((unsigned char *)(buf + i), dsa_p_len, dsa_p);      i += (dsa_p_len + 4);      dsa_q = BN_new();      BN_bin2bn((unsigned char *)(buf + i), dsa_q_len, dsa_q);      i += (dsa_q_len + 4);      dsa_g = BN_new();      BN_bin2bn((unsigned char *)(buf + i), dsa_g_len, dsa_g);      i += (dsa_g_len + 4);      dsa_y = BN_new();      BN_bin2bn((unsigned char *)(buf + i), dsa_y_len, dsa_y);      dsa = DSA_new();      dsa->p = dsa_p;      dsa->q = dsa_q;      dsa->g = dsa_g;      dsa->priv_key = NULL;      dsa->pub_key = dsa_y;      i =  DSA_do_verify(hmacbuf, SHA_DIGEST_LENGTH,			 dsa_sig, dsa);      *rbuf = (char *)(bin = driver_alloc_binary(1));      (bin->orig_bytes)[0] = (char)(i & 0xff);      DSA_free(dsa);      DSA_SIG_free(dsa_sig);      /* Apparently, the DSA_do_verify operation allocates some space       * which must be freed this way: */      CRYPTO_cleanup_all_ex_data();      return 1;      break;    case DRV_RSA_VERIFY:      /* buf = <<data_len:32/integer, data:data_len/binary,       *         rsa_s_len:32/integer, rsa_s:rsa_s_len/binary,       *         rsa_e_len:32/integer, rsa_e:rsa_e_len/binary,       *         rsa_n_len:32/integer, rsa_n:rsa_n_len/binary>> */      i = 0;      j = 0;      if (len < 16)	return -1;      data_len = get_int32(buf + i + j);      j += data_len; i += 4;      if (len < (16 + j))	return -1;      rsa_s_len = get_int32(buf + i + j);      j += rsa_s_len; i += 4;      if (len < (16 + j))	return -1;      rsa_e_len = get_int32(buf + i + j);      j += rsa_e_len; i += 4;      if (len < (16 + j))	return -1;      rsa_n_len = get_int32(buf + i + j);      j += rsa_n_len; i += 4;      if (len < (16 + j))	return -1;      i = 4;      SHA1((unsigned char *) (buf + i), data_len, hmacbuf);      i += (data_len + 4);      rsa_s = (unsigned char *)(buf + i);      i += (rsa_s_len + 4);      rsa_e = BN_new();      BN_bin2bn((unsigned char *)(buf + i), rsa_e_len, rsa_e);      i += (rsa_e_len + 4);      rsa_n = BN_new();      BN_bin2bn((unsigned char *)(buf + i), rsa_n_len, rsa_n);      rsa = RSA_new();      rsa->n = rsa_n;      rsa->e = rsa_e;      i =  RSA_verify(NID_sha1, hmacbuf, SHA_DIGEST_LENGTH, 		      rsa_s, rsa_s_len, rsa);      *rbuf = (char *)(bin = driver_alloc_binary(1));      (bin->orig_bytes)[0] = (char)(i & 0xff);      RSA_free(rsa);      /* Apparently, the RSA_verify operation allocates some space       * which must be freed this way, but perhaps it would suffice to       * do it in stop()? */      CRYPTO_cleanup_all_ex_data();      return 1;      break;    case DRV_CBC_AES128_ENCRYPT:      /* buf = <<key:16/binary, ivec:16/binary, data/binary>> */      dlen = len - 32;      if (dlen < 0)	return -1;      /* There is no AES_KEY_new, probably meant to be used through	 EVP_xxx, so: */      *rbuf = (char *)(bin = driver_alloc_binary(dlen));      AES_set_encrypt_key((unsigned char *) buf, 128, &aes_key);      AES_cbc_encrypt((unsigned char *) (buf + 32),		      (unsigned char *) bin->orig_bytes,		      dlen,		      &aes_key, 		      (unsigned char *) (buf + 16),		      AES_ENCRYPT);      return dlen;      break;    case DRV_CBC_AES128_DECRYPT:      /* buf = key[16] ivec[16] data */      dlen = len - 32;      if (dlen < 0)	return -1;      /* There is no AES_KEY_new, probably meant to be used through	 EVP_xxx, so: */      *rbuf = (char *)(bin = driver_alloc_binary(dlen));      AES_set_decrypt_key((unsigned char *) buf,			  128,			  &aes_key);      AES_cbc_encrypt((unsigned char *) (buf + 32),		      (unsigned char *) bin->orig_bytes,		      dlen,		      &aes_key, 		      (unsigned char *) (buf + 16),		      AES_DECRYPT);      return dlen;      break;    case DRV_XOR:	/* buf = data1, data2 with same size */	dlen = len / 2;	if (len != dlen * 2)	    return -1;	*rbuf = p = (char *)(bin = driver_alloc_binary(dlen));	dbuf = buf + dlen;	for (key = buf, key2 = dbuf; key != dbuf; ++key, ++key2, ++p)	    *p = *key ^ *key2;	return dlen;	break;    default:	break;    }    return -1;}/* HMAC */static void hmac_md5(char *key, int klen, char *dbuf, int dlen, char *hmacbuf){    MD5_CTX ctx;    char ipad[HMAC_INT_LEN];    char opad[HMAC_INT_LEN];    char nkey[MD5_LEN];    int i;    /* Change key if longer than 64 bytes */    if (klen > HMAC_INT_LEN) {	MD5_CTX kctx;	MD5_Init(&kctx);	MD5_Update(&kctx, key, klen);	MD5_Final(nkey, &kctx);	key = nkey;	klen = MD5_LEN;    }    memset(ipad, '\0', sizeof(ipad));    memset(opad, '\0', sizeof(opad));    memcpy(ipad, key, klen);    memcpy(opad, key, klen);    for (i = 0; i < HMAC_INT_LEN; i++) {	ipad[i] ^= HMAC_IPAD;	opad[i] ^= HMAC_OPAD;    }    /* inner MD5 */    MD5_Init(&ctx);    MD5_Update(&ctx, ipad, HMAC_INT_LEN);    MD5_Update(&ctx, dbuf, dlen);    MD5_Final(hmacbuf, &ctx);    /* outer MD5 */    MD5_Init(&ctx);    MD5_Update(&ctx, opad, HMAC_INT_LEN);    MD5_Update(&ctx, hmacbuf, MD5_LEN);    MD5_Final(hmacbuf, &ctx);}static void hmac_sha1(char *key, int klen, char *dbuf, int dlen, 		      char *hmacbuf){    SHA_CTX ctx;    char ipad[HMAC_INT_LEN];    char opad[HMAC_INT_LEN];    char nkey[SHA_LEN];    int i;    /* Change key if longer than 64 bytes */    if (klen > HMAC_INT_LEN) {	SHA_CTX kctx;	SHA1_Init(&kctx);	SHA1_Update(&kctx, key, klen);	SHA1_Final(nkey, &kctx);	key = nkey;	klen = SHA_LEN;    }    memset(ipad, '\0', sizeof(ipad));    memset(opad, '\0', sizeof(opad));    memcpy(ipad, key, klen);    memcpy(opad, key, klen);    for (i = 0; i < HMAC_INT_LEN; i++) {	ipad[i] ^= HMAC_IPAD;	opad[i] ^= HMAC_OPAD;    }    /* inner SHA */    SHA1_Init(&ctx);    SHA1_Update(&ctx, ipad, HMAC_INT_LEN);    SHA1_Update(&ctx, dbuf, dlen);    SHA1_Final(hmacbuf, &ctx);    /* outer SHA */    SHA1_Init(&ctx);    SHA1_Update(&ctx, opad, HMAC_INT_LEN);    SHA1_Update(&ctx, hmacbuf, SHA_LEN);    SHA1_Final(hmacbuf, &ctx);}

⌨️ 快捷键说明

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