Skip to content

Commit

Permalink
add daemon
Browse files Browse the repository at this point in the history
  • Loading branch information
user authored and user committed Dec 1, 2021
1 parent 7408587 commit 373bb47
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 91 deletions.
49 changes: 14 additions & 35 deletions google/auth/transport/cpp/windows_signer.cpp
Expand Up @@ -10,7 +10,14 @@

#include <openssl/ec.h>
#include <openssl/bn.h>
struct ECDSA_SIG_st { BIGNUM *r; BIGNUM *s;};
#include <openssl/opensslv.h>

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
typedef struct ECDSA_SIG_st {
BIGNUM *r;
BIGNUM *s;
} ECDSA_SIG;
#endif

#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
Expand Down Expand Up @@ -269,11 +276,9 @@ bool WinCertStoreKey::Sign(unsigned char *sig, size_t *sig_len, const unsigned c
return 1;
}

extern "C"
#ifdef _WIN32
__declspec(dllexport)
#endif
WinCertStoreKey* CreateCustomKey(bool is_rsa_type, bool local_machine_store, const char *store_name, const char *subject) {
extern "C" {

__declspec(dllexport) WinCertStoreKey* CreateCustomKey(bool is_rsa_type, bool local_machine_store, const char *store_name, const char *subject) {
// creating custom key
std::cout << "is_rsa_type: " << is_rsa_type << std::endl;
std::cout << "local_machine_store: " << local_machine_store << std::endl;
Expand All @@ -284,45 +289,19 @@ WinCertStoreKey* CreateCustomKey(bool is_rsa_type, bool local_machine_store, con
return key;
}

extern "C"
#ifdef _WIN32
__declspec(dllexport)
#endif
void DestroyCustomKey(WinCertStoreKey *key) {
__declspec(dllexport) void DestroyCustomKey(WinCertStoreKey *key) {
// deleting custom key
printf("In DestroyCustomKey\n");
delete key;
}

static PyObject* sign_rsa(PyObject *self, PyObject *args) {
printf("calling sign\n");
std::string store_name = "MY", subject = "localhost";
WinCertStoreKey signer(true, false, store_name.c_str(), subject.c_str());
signer.GetSignerCert();
signer.GetPrivateKey();
static const BYTE rgbMsg[] = {0x61, 0x62, 0x63};
signer.CreateHash((PBYTE)rgbMsg, sizeof(rgbMsg));
signer.NCryptSign(NULL, NULL);
Py_INCREF(Py_None);
return Py_None;
__declspec(dllexport) bool Sign(WinCertStoreKey *key, unsigned char *sig, size_t *sig_len, const unsigned char *tbs, size_t tbs_len) {
return key->Sign(sig, sig_len, tbs, tbs_len);
}

static PyObject* sign_ec(PyObject *self, PyObject *args) {
printf("calling sign\n");
std::string store_name = "MY", subject = "localhost";
WinCertStoreKey signer(false, true, store_name.c_str(), subject.c_str());
signer.GetSignerCert();
signer.GetPrivateKey();
static const BYTE rgbMsg[] = {0x61, 0x62, 0x63};
signer.CreateHash((PBYTE)rgbMsg, sizeof(rgbMsg));
signer.NCryptSign(NULL, NULL);
Py_INCREF(Py_None);
return Py_None;
}

static PyMethodDef Methods[] = {
{"sign_rsa", sign_rsa, METH_VARARGS, "The signer function"},
{"sign_ec", sign_ec, METH_VARARGS, "The signer function"},
{NULL, NULL, 0, NULL}
};

Expand Down
4 changes: 2 additions & 2 deletions google/auth/transport/requests.py
Expand Up @@ -264,8 +264,8 @@ def __init__(self, cert, key):
self._ctx_proxymanager = ctx_proxymanager

self.signer = tls_sign.CustomSigner(cert, key)
tls_sign.configure_tls_offload(self.signer, cert, ctx_poolmanager)
tls_sign.configure_tls_offload(self.signer, cert, ctx_proxymanager)
tls_sign.attach_signer_and_cert_to_ssl_context(self.signer, cert, ctx_poolmanager)
tls_sign.attach_signer_and_cert_to_ssl_context(self.signer, cert, ctx_proxymanager)

super(_MutualTlsOffloadAdapter, self).__init__()

Expand Down
112 changes: 60 additions & 52 deletions google/auth/transport/tls_sign.py
@@ -1,17 +1,28 @@
import atexit
import base64
import cffi
import copy
import ctypes
import os
import re

from google.auth import exceptions
import requests

callback_type = ctypes.CFUNCTYPE(
ctypes.c_int,
ctypes.POINTER(ctypes.c_ubyte),
ctypes.POINTER(ctypes.c_size_t),
ctypes.POINTER(ctypes.c_ubyte),
ctypes.c_size_t,
)
custom_key_handle_type = ctypes.POINTER(ctypes.c_char)

def _cast_ssl_ctx_to_void_p(ssl_ctx):
return ctypes.cast(int(cffi.FFI().cast("intptr_t", ssl_ctx)), ctypes.c_void_p)


def offload_signing_ext():
def _load_offload_signing_ext():
tls_offload_ext = None
root_path = os.path.join(os.path.dirname(__file__), "../../../")
for filename in os.listdir(root_path):
Expand All @@ -21,20 +32,13 @@ def offload_signing_ext():
raise exceptions.MutualTLSChannelError(
"tls_offload_ext shared library is not found"
)
custom_key_handle = ctypes.POINTER(ctypes.c_char)
callback_type = ctypes.CFUNCTYPE(
ctypes.c_int,
ctypes.POINTER(ctypes.c_ubyte),
ctypes.POINTER(ctypes.c_size_t),
ctypes.POINTER(ctypes.c_ubyte),
ctypes.c_size_t,
)
tls_offload_ext.CreateCustomKey.argtypes = [callback_type]
tls_offload_ext.CreateCustomKey.restype = custom_key_handle
tls_offload_ext.DestroyCustomKey.argtypes = [custom_key_handle]
tls_offload_ext.CreateCustomKey.restype = custom_key_handle_type
tls_offload_ext.DestroyCustomKey.argtypes = [custom_key_handle_type]
return tls_offload_ext

def windows_signer_ext():

def _load_windows_signer_ext():
windows_signer_ext = None
root_path = os.path.join(os.path.dirname(__file__), "../../../")
for filename in os.listdir(root_path):
Expand All @@ -44,28 +48,12 @@ def windows_signer_ext():
raise exceptions.MutualTLSChannelError(
"windows_signer_ext shared library is not found"
)
custom_key_handle = ctypes.POINTER(ctypes.c_char)
callback_type = ctypes.CFUNCTYPE(
ctypes.c_int,
ctypes.POINTER(ctypes.c_ubyte),
ctypes.POINTER(ctypes.c_size_t),
ctypes.POINTER(ctypes.c_ubyte),
ctypes.c_size_t,
)
windows_signer_ext.CreateCustomKey.restype = custom_key_handle
windows_signer_ext.DestroyCustomKey.argtypes = [custom_key_handle]
windows_signer_ext.CreateCustomKey.restype = custom_key_handle_type
windows_signer_ext.DestroyCustomKey.argtypes = [custom_key_handle_type]
return windows_signer_ext


def _create_pkcs11_sign_callback(key_info):
callback_type = ctypes.CFUNCTYPE(
ctypes.c_int,
ctypes.POINTER(ctypes.c_ubyte),
ctypes.POINTER(ctypes.c_size_t),
ctypes.POINTER(ctypes.c_ubyte),
ctypes.c_size_t,
)

def sign_callback(sig, sig_len, tbs, tbs_len):
import pkcs11
from pkcs11 import KeyType, Mechanism, MGF
Expand Down Expand Up @@ -111,14 +99,6 @@ def sign_callback(sig, sig_len, tbs, tbs_len):


def _create_raw_sign_callback(key_info):
callback_type = ctypes.CFUNCTYPE(
ctypes.c_int,
ctypes.POINTER(ctypes.c_ubyte),
ctypes.POINTER(ctypes.c_size_t),
ctypes.POINTER(ctypes.c_ubyte),
ctypes.c_size_t,
)

def sign_callback(sig, sig_len, tbs, tbs_len):
print("calling sign_callback for raw key....\n")

Expand Down Expand Up @@ -156,28 +136,47 @@ def sign_callback(sig, sig_len, tbs, tbs_len):
return callback_type(sign_callback)


def get_sign_callback(key):
if key["type"] == "pkc11":
return _create_pkcs11_sign_callback(key["key_info"])
elif key["type"] == "raw":
return _create_raw_sign_callback(key["key_info"])
raise exceptions.MutualTLSChannelError(
"currently only pkcs11 and raw type are supported"
)
def _create_daemon_sign_callback(key_info):
def sign_callback(sig, sig_len, tbs, tbs_len):
print("calling sign_callback using daemon....\n")

body = copy.deepcopy(key_info)
data = ctypes.string_at(tbs, tbs_len)
body["data"] = base64.encodebytes(data).decode('ascii')
print(body)
daemon_sign_endpoint = os.getenv("DAEMON_SIGN_ENDPOINT")

res = requests.post(daemon_sign_endpoint, json=body)
if not res.ok:
print(res.json())
return 0

signature = res.json()["signature"]
signature = base64.b64decode(signature)

sig_len[0] = len(signature)
if sig:
for i in range(len(signature)):
sig[i] = signature[i]

return 1

return callback_type(sign_callback)


class CustomSigner(object):
def __init__(self, cert, key):
key_info = key["key_info"]
self.offload_signing_ext = _load_offload_signing_ext()
if os.name == "nt" and key["type"] == "windows":
from cryptography import x509
from cryptography.hazmat.primitives.asymmetric import rsa
public_key = x509.load_pem_x509_certificate(cert).public_key()
is_rsa = (isinstance(public_key, rsa.RSAPublicKey))
print(f"is_rsa is: {is_rsa}")
key_info = key["key_info"]
is_local_machine_store = (key_info["provider"] == "local_machine")
self.offload_signing_ext = offload_signing_ext()
self.offload_signing_function = self.offload_signing_ext.OffloadSigning
self.windows_signer_ext = windows_signer_ext()
self.windows_signer_ext = _load_windows_signer_ext()
self.signer = self.windows_signer_ext.CreateCustomKey(
ctypes.c_bool(is_rsa),
ctypes.c_bool(is_local_machine_store),
Expand All @@ -187,9 +186,17 @@ def __init__(self, cert, key):
self.cleanup_func = self.windows_signer_ext.DestroyCustomKey
atexit.register(self.cleanup)
else:
self.offload_signing_ext = offload_signing_ext()
self.offload_signing_function = self.offload_signing_ext.OffloadSigning
self.sign_callback = get_sign_callback(key)
if key["type"] == "pkc11":
self.sign_callback = _create_pkcs11_sign_callback(key_info)
elif key["type"] == "raw":
self.sign_callback = _create_raw_sign_callback(key_info)
elif key["type"] == "daemon":
self.sign_callback = _create_daemon_sign_callback(key_info)
else:
raise exceptions.MutualTLSChannelError(
"currently only pkcs11 and raw type are supported"
)
self.signer = self.offload_signing_ext.CreateCustomKey(self.sign_callback)
self.cleanup_func = self.offload_signing_ext.DestroyCustomKey
atexit.register(self.cleanup)
Expand All @@ -199,7 +206,8 @@ def cleanup(self):
print("calling self.offload_signing_ext.DestroyCustomKey")
self.cleanup_func(self.signer)

def configure_tls_offload(signer, cert, ctx):

def attach_signer_and_cert_to_ssl_context(signer, cert, ctx):
if not signer.offload_signing_function(
signer.signer,
ctypes.c_char_p(cert),
Expand Down
4 changes: 3 additions & 1 deletion offload_sample/daemon.py
@@ -1,4 +1,6 @@
from flask import Flask, request, jsonify
import google.auth.transport.tls_sign


app = Flask(__name__)

Expand All @@ -14,5 +16,5 @@ def home():
@app.route('/sign', methods=['POST'])
def sign():
content = request.json
print(content['mytext'])
print(content)
return jsonify({"size":1, "signature": "haha"})
22 changes: 21 additions & 1 deletion offload_sample/sample.py
Expand Up @@ -75,6 +75,24 @@ def callback():
return cert, key
return callback

def callback_daemon_windows_rsa():
with open(rsa_cert_file, "rb") as f:
cert = f.read()

key = {
"type": "daemon",
"key_info": {
"type": "windows",
"key_info": {
"provider": "local_machine",
"store_name": "MY",
"subject": "localhost"
}
}
}

return cert, key

def run_sample(callback):
authed_session = AuthorizedSession(creds)
print("=== before configure_mtls_channel===")
Expand All @@ -101,4 +119,6 @@ def run_sample(callback):
print("================= using raw rsa key")
run_sample(callback_raw(rsa_cert_file, rsa_key_file))
print("================= using raw ec key")
run_sample(callback_raw(ec_cert_file, ec_key_file))
run_sample(callback_raw(ec_cert_file, ec_key_file))

# run_sample(callback_daemon_windows_rsa)

0 comments on commit 373bb47

Please sign in to comment.