openssl3.2 - exp - buf to bio

2024-02-27 16:28
文章标签 exp bio buf openssl3.2

本文主要是介绍openssl3.2 - exp - buf to bio,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • openssl3.2 - exp - buf to bio
    • 概述
    • 笔记
    • bio_get_length
      • 调用端代码
      • 函数实现
      • bio_to_buffer
    • END

openssl3.2 - exp - buf to bio

概述

不想让程序调用openssl API时, 有文件落地的动作.
如果程序有配置文件要用, 也是自己读文件到buffer, 然后转成BIO给openssl的相关有BIO入参的API用.
如果在程序中用数组定义了一些PEM内容的数组, 也可以将数组转成BIO来用.

从openssl测试代码中, 找到了BIO_new_mem_buf(), 可以做这个事情.
那么程序需要的文件输入, 都可以读入buffer, 转成BIO, 后续都用BIO来处理.

笔记

/*!
* \file main.cpp
* \note buffer to bio
*/#include "my_openSSL_lib.h"#include <stdlib.h>
#include <stdio.h>
#include <cstdint>
#include <assert.h>#include <openssl/bio.h>int test_bio_new_mem_buf(void);int main(int argc, char** argv)
{test_bio_new_mem_buf();return 0;
}int test_bio_new_mem_buf(void)
{int ok = 0;BIO* bio = NULL;BUF_MEM* bufmem = NULL;char data[16];int i_rc = 0;do {// BIO_free(bio); // openssl做了处理, 即使入参为NULL, 也不会报错// BIO_new_mem_buf是直接将入参的buffer指到内部指针上, 所以入参指针如果是自己new出来的, 就需要自己释放// 如果是文件输入, 可以自己读文件到buffer中, 然后就用BIO来操作.bio = BIO_new_mem_buf("Hello World\n", 12);if (NULL == bio){break; }i_rc = BIO_get_mem_ptr(bio, &bufmem);if (i_rc <= 0){break;}memset(data, 0, sizeof(data));if (5 != BIO_read(bio, data, 5)) { break; }if (0 != strncmp(data, "Hello", 5)){break;}// b->flags & BIO_FLAGS_MEM_RDONLY// bio默认是只读的, 是写不进去的.i_rc = BIO_write(bio, "test", 4);assert(i_rc <= 0);memset(data, 0, sizeof(data));i_rc = BIO_read(bio, data, 16); // 连续调用BIO_read时, 是继续往后读, 读一点, 内容就少一点assert(7 == i_rc); // 返回值是读了多少个字节if (0 != strncmp(data, " World\n", 7)){break;}i_rc = BIO_reset(bio); // 只读的bio可以恢复到刚创建时的状态, 可以从头开始读.assert(i_rc > 0);i_rc = BIO_read(bio, data, 16);assert(12 == i_rc);if (0 != strncmp(data, "Hello World\n", 12)){break;}ok = 1;} while (false);if (NULL != bio){BIO_free_all(bio);bio = NULL;}return ok;
}

bio_get_length

openssl 并不提供如何得到BIO对象内容的size.
因为很多BIO是不知道有多长的(e.g. bio for ssl)
但是对于由buffer转成BIO之后, 其实BIO内的数据长度是确定的.
翻翻openssl实现, 感觉也就只能通过试读来确定BIO的数据长度.
封装了一个函数bio_get_length(), 好使.

调用端代码

        // 如果是文件输入, 可以自己读文件到buffer中, 然后就用BIO来操作.bio = BIO_new_mem_buf("Hello World\n", 12);if (NULL == bio){break; }bio_length = bio_get_length(bio);assert(bio_length == 12);

函数实现

long bio_get_length(BIO* bio)
{long bio_length = 0;uint8_t* pBuf = NULL;int buf_len = 1024 * 1024;int i_rc = 0;// 只适合与已经全部装载了mem buffer内容的BIO// 因为 BIO_BUF_MEM 没有对外, 所以只能通过试读来确定BIO内容的长度do {if (NULL == bio){break;}pBuf = (uint8_t*)OPENSSL_malloc(buf_len);if (NULL == pBuf){break;}BIO_reset(bio);do {i_rc = BIO_read(bio, pBuf, buf_len);if (i_rc <= 0){break;}bio_length += i_rc;if (i_rc != buf_len){break;}} while (true);BIO_reset(bio);} while (false);if (NULL != pBuf){OPENSSL_free(pBuf);pBuf = NULL;}return bio_length;
}

bio_to_buffer

如果想对一个已经包含了内容的BIO中的内容, 转为buffer. 以下代码好使.

int test_bio_to_buffer(void)
{int ok = 0;BIO* bio = NULL;char data[16];int i_rc = 0;long bio_length = 0;uint8_t* pBufToLoadBIO = NULL;do {bio = BIO_new_mem_buf("Hello World\n", 12);if (NULL == bio){break;}// 得到BIO的数据长度, 才好去开bufferbio_length = bio_get_length(bio);assert(bio_length == 12);// 多开一个字节, 留一个'\0'的位置, 如果内容是可见字符, 看字符串方便pBufToLoadBIO = new uint8_t[bio_length + 1];if (NULL == pBufToLoadBIO){break;}pBufToLoadBIO[bio_length] = '\0';i_rc = BIO_read(bio, pBufToLoadBIO, bio_length);// 如果 bio_length 太大(> imax), 再分段读来处理, 现在先这样, 就当一次就读完了assert(i_rc == bio_length);// 现在可以拿pBufToLoadBIO去干活了(自己存文件, 或作其他处理)ok = 1;} while (false);if (NULL != bio){BIO_free_all(bio);bio = NULL;}if (NULL != pBufToLoadBIO){delete []pBufToLoadBIO;pBufToLoadBIO = NULL;}return ok;
}

END

这篇关于openssl3.2 - exp - buf to bio的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/752988

相关文章

springboot体会BIO(阻塞式IO)

使用springboot体会阻塞式IO 大致的思路为: 创建一个socket服务端,监听socket通道,并打印出socket通道中的内容。 创建两个socket客户端,向socket服务端写入消息。 1.创建服务端 public class RedisServer {public static void main(String[] args) throws IOException {

还不懂BIO,NIO,AIO吗

BIO(Blocking I/O)、NIO(Non-blocking I/O)和 AIO(Asynchronous I/O)是 Java 中三种不同的 I/O 模型,主要用于处理输入 / 输出操作。 一、BIO(Blocking I/O) 定义与工作原理: BIO 即阻塞式 I/O(同步阻塞,传统IO)。在这种模型下,当一个线程发起一个 I/O 操作(如读取文件或网络数据)时,此线

linux 内核提权总结(demo+exp分析) -- 任意读写(四)

hijack_modprobe_path篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm     原理同hijack_prctl, 当用户执行错误格式的elf文件时内核调用call_usermod

linux 内核提权总结(demo+exp分析) -- 任意读写(三)

hijack_prctl篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm   prctl函数: 用户态函数,可用于定制进程参数,非常适合和内核进行交互 用户态执行prctl函数后触发prctl系统

linux 内核提权总结(demo+exp分析) -- 任意读写(二)

hijack_vdso篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm     vdso: 内核实现的一个动态库,存在于内核,然后映射到用户态空间,可由用户态直接调用 内核中的vdso如果被修改

linux 内核提权总结(demo+exp分析) -- 任意读写(一)

cred篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm   每个线程在内核中都对应一个线程结构块thread_infothread_info中存在task_struct类型结构体 struct t

linux 内核提权总结(demo+exp分析) -- ROP(二)

ret2usr CR4篇 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm   smep: smep是内核的一种保护措施, 使得内核不可执行用户态代码 内核通过CR4寄存器的第20位来控制smep,

linux 内核提权总结(demo+exp分析) -- ROP(一)

基础ROP篇(linux 5.0.21) 本文转自网络文章,内容均为非盈利,版权归原作者所有。 转载此文章仅为个人收藏,分享知识,如有侵权,马上删除。 原文作者:jmpcall 专栏地址:https://zhuanlan.kanxue.com/user-815036.htm   内核提权与用户态攻击的区别 攻击流程 用户态攻击: 执行 system("/bin/sh") 获得shel

AtCoder Beginner Contest 369 D - Bonus EXP 动态规划

原题链接: https://atcoder.jp/contests/abc369/tasks/abc369_d 思路:   这道题为什么要用动态规划呢,其实,对于第i个怪物,我们有打与不打两种处理方式,而对于打,我们是获得两倍的经验值,还是一倍的经验值,与我们打了奇数只怪物还是打了偶数只怪物有关了,因此我们定义dp[i][0] 为前i只怪物总共打了偶数次,dp[i][1] 为前i只怪物总

AUTOSAR_EXP_ARAComAPI的5章笔记(1)

5.1 High Level API Structure ara::com提供了一个支持AUTOSAR服务模型的API。服务有Method、Event、Filed和Trigger。 Method:在服务应用程序中执行一个可以返回值的函数(如校准方法)。 Event:当特定条件发生时(例如制动事件),服务应用程序发送一个事件(也可能包括一个值)。客户端应用程序可以订阅事件。 Filed:在