从 python ctypes 访问 OpenSSL FIPS API 不起作用

问题描述 投票:0回答:1

Python:3.9.16 OpenSSL:3.0.8

fips_ccode.c

#include <stdio.h>
#include <stdlib.h>
#include <openssl/provider.h>
#include "openssl/md5.h"

int main(void)
{
        OSSL_PROVIDER* fips;
        OSSL_PROVIDER* base;

        const char* default_search_path = "/tmp/fips_files/";
        OSSL_PROVIDER_set_default_search_path(NULL, default_search_path);
        int load_config = OSSL_LIB_CTX_load_config(NULL, "/tmp/fips_files/openssl.cnf") ;
        printf("loading config:%d\n", load_config);
   
        fips = OSSL_PROVIDER_load(NULL, "fips");
        printf("value:%x\n",fips);

        printf("Success to load FIPS provider\n");

        base = OSSL_PROVIDER_load(NULL, "base");

        printf("Success to load base provider\n");
}

fips_python.py

import ctypes
import os
import ssl
import ssl, os
import hashlib

BASEDIR="/tmp/"
FILENAME="libcrypto.so.3"

def get_crypto_lib_path():
    return os.path.join(BASEDIR, FILENAME)


crypto_context = ctypes.CDLL(os.path.join(BASEDIR, get_crypto_lib_path()))
crypto_context.OSSL_PROVIDER_set_default_search_path.argtypes = [ctypes.c_char_p, ctypes.c_wchar_p]
crypto_context.OSSL_PROVIDER_set_default_search_path.restype = ctypes.c_char
crypto_context.OSSL_PROVIDER_set_default_search_path(None, "/tmp/fips_files/")


crypto_context.OSSL_LIB_CTX_load_config.argtypes = [ctypes.c_char_p, ctypes.c_wchar_p]
crypto_context.OSSL_LIB_CTX_load_config.restype = ctypes.c_int
load_config = crypto_context.OSSL_LIB_CTX_load_config(None, "/tmp/fips_files/openssl.cnf")
print("load config:", load_config)

crypto_context.OSSL_PROVIDER_load.argtypes = [ctypes.c_char_p, ctypes.c_wchar_p]
crypto_context.OSSL_PROVIDER_load.restype = ctypes.c_wchar_p
base_load = crypto_context.OSSL_PROVIDER_load(None, "base")
print("base load ret value:", base_load)

crypto_context.OSSL_PROVIDER_load.argtypes = [ctypes.c_char_p, ctypes.c_wchar_p]
crypto_context.OSSL_PROVIDER_load.restype = ctypes.c_wchar_p
fips_load = crypto_context.OSSL_PROVIDER_load(None, "fips")
print("fips load ret value:", fips_load)

在这里,我在使用 ctypes 的 python 中使用“OSSL_PROVIDER_load”函数加载提供程序“fips”和“base”时遇到问题。 在这里加载 c 函数的正确方法是什么?使用的参数类型是否正确?

python openssl cryptography ctypes fips
1个回答
0
投票

清单 [Python.Docs]:ctypes - Python 的外部函数库

代码中有一堆错误:

  1. LibCrypto的路径计算不正确(BASEDIR前缀两次)

  2. 您想要使用 OpenSSL v3.0 功能,但 LibCrypto 的名称表明是 v1.1。 2者差别很大
    显然(除非 libcrypto.so.1.1 是一个误导性的名称 SymLink),这些函数将不存在,因此无法加载

  3. Python 函数原型与 C 函数原型不同,可以在以下位置找到:

    这会产生Un定义B行为。检查[SO]:通过 ctypes 从 Python 调用的 C 函数返回不正确的值(@CristiFati 的答案)了解更多详细信息

  4. 还有其他的(比如不检查函数返回码),但与之前的相比,这些只是轻量级的

我准备了一个小例子来修复第 3rd 点。

code00.py

#!/usr/bin/env python

import ctypes as cts
import os
import sys


PATH_LIBCRYPTO = "../q069539286/docker/openssl-1.1.1g/lib/libcrypto.so.1.1.1g"
PATH_LIBCRYPTO = "/tmp/libcrypto.so.1.1"
PATH_CFG = b"/tmp/fips_files/"

# @TODO - cfati: Use my paths
PATH_OSSL3_BASE = "/usr/local/pc064/openssl/openssl/3.0.10"
PATH_LIBCRYPTO = os.path.join(PATH_OSSL3_BASE, "lib", "libcrypto.so.3")
PATH_CFG = os.path.join(PATH_OSSL3_BASE.encode(), b"ssl")

POSSL_LIB_CTX = cts.c_void_p
POSSL_PROVIDER = cts.c_void_p


def main(*argv):
    libcrypto = cts.CDLL(PATH_LIBCRYPTO)
    OSSL_PROVIDER_set_default_search_path = libcrypto.OSSL_PROVIDER_set_default_search_path
    OSSL_PROVIDER_set_default_search_path.argtypes = (POSSL_LIB_CTX, cts.c_char_p)
    OSSL_PROVIDER_set_default_search_path.restype = cts.c_int
    OSSL_LIB_CTX_load_config = libcrypto.OSSL_LIB_CTX_load_config
    OSSL_LIB_CTX_load_config.argtypes = (POSSL_LIB_CTX, cts.c_char_p)
    OSSL_LIB_CTX_load_config.restype = cts.c_int
    OSSL_PROVIDER_load = libcrypto.OSSL_PROVIDER_load
    OSSL_PROVIDER_load.argtypes = (POSSL_LIB_CTX, cts.c_char_p)
    OSSL_PROVIDER_load.restype = POSSL_PROVIDER

    res = OSSL_PROVIDER_set_default_search_path(None, PATH_CFG)
    if res == 0:
        print("OSSL_PROVIDER_set_default_search_path error")
        return 1
    res = OSSL_LIB_CTX_load_config(None, os.path.join(PATH_CFG, b"openssl.cnf"))
    if res == 0:
        print("OSSL_LIB_CTX_load_config error")
        return 1
    base_provider = OSSL_PROVIDER_load(None, b"base")
    fips_provider = OSSL_PROVIDER_load(None, b"fips")

    print(f"Base: {base_provider}\nFIPS: {fips_provider}")


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.\n")
    sys.exit(rc)

输出

[cfati@cfati-5510-0:/mnt/e/Work/Dev/StackExchange/StackOverflow/q075889485]> python ./code00.py 
Python 3.8.18 (default, Aug 25 2023, 13:20:30) [GCC 11.4.0] 064bit on linux

Base: 17667472
FIPS: None

Done.

注释

© www.soinside.com 2019 - 2024. All rights reserved.