unit UtilOpenSSL;
{$MODE DELPHI}{$H+}
{$Packrecords C}
interface
uses
Classes, SysUtils;
const
// PADDING constants
RSA_PKCS1_PADDING = 1;
RSA_SSLV23_PADDING = 2;
RSA_NO_PADDING = 3;
RSA_PKCS1_OAEP_PADDING = 4;
// ASN1 type constants
NID_undef = 0;
NID_rsaEncryption = 6;
NID_pkcs7_signed = 22;
NID_pkcs7_signedAndEnveloped = 24;
NID_basic_constraints = 87;
NID_subject_alt_name = 85;
V_ASN1_INTEGER = $02;
V_ASN1_ENUMERATED = 10;
V_ASN1_NEG_INTEGER = $102;
V_ASN1_UTCTIME = 23;
V_ASN1_GENERALIZEDTIME = 24;
V_ASN1_CONTEXT_SPECIFIC = $80;
B_ASN1_NUMERICSTRING = $0001;
B_ASN1_PRINTABLESTRING = $0002;
B_ASN1_T61STRING = $0004;
B_ASN1_TELETEXSTRING = $0008;
B_ASN1_VIDEOTEXSTRING = $0008;
B_ASN1_IA5STRING = $0010;
B_ASN1_GRAPHICSTRING = $0020;
B_ASN1_ISO64STRING = $0040;
B_ASN1_VISIBLESTRING = $0040;
B_ASN1_GENERALSTRING = $0080;
B_ASN1_UNIVERSALSTRING = $0100;
B_ASN1_OCTET_STRING = $0200;
B_ASN1_BIT_STRING = $0400;
B_ASN1_BMPSTRING = $0800;
B_ASN1_UNKNOWN = $1000;
B_ASN1_UTF8STRING = $2000;
MBSTRING_FLAG = $1000;
MBSTRING_ASC = MBSTRING_FLAG or 1;
MBSTRING_BMP = MBSTRING_FLAG or 2;
MBSTRING_UNIV = MBSTRING_FLAG or 3;
MBSTRING_UTF8 = MBSTRING_FLAG or 4;
// These are the 'types' of BIOs
BIO_TYPE_NONE = $0000;
BIO_TYPE_MEM = $0001 or $0400;
BIO_TYPE_FILE = $0002 or $0400;
BIO_TYPE_FD = $0004 or $0400 or $0100;
BIO_TYPE_SOCKET = $0005 or $0400 or $0100;
BIO_TYPE_NULL = $0006 or $0400;
BIO_TYPE_SSL = $0007 or $0200;
BIO_TYPE_MD = $0008 or $0200; // passive filter
BIO_TYPE_BUFFER = $0009 or $0200; // filter
BIO_TYPE_CIPHER = $00010 or $0200; // filter
BIO_TYPE_BASE64 = $00011 or $0200; // filter
BIO_TYPE_CONNECT = $00012 or $0400 or $0100; // socket - connect
BIO_TYPE_ACCEPT = $00013 or $0400 or $0100; // socket for accept
BIO_TYPE_PROXY_CLIENT = $00014 or $0200; // client proxy BIO
BIO_TYPE_PROXY_SERVER = $00015 or $0200; // server proxy BIO
BIO_TYPE_NBIO_TEST = $00016 or $0200; // server proxy BIO
BIO_TYPE_NULL_FILTER = $00017 or $0200;
BIO_TYPE_BER = $00018 or $0200; // BER -> bin filter
BIO_TYPE_BIO = $00019 or $0400; // (half a; BIO pair
BIO_TYPE_LINEBUFFER = $00020 or $0200; // filter
BIO_TYPE_DESCRIPTOR = $0100; // socket, fd, connect or accept
BIO_TYPE_FILTER = $0200;
BIO_TYPE_SOURCE_SINK = $0400;
// BIO ops constants
// BIO_FILENAME_READ|BIO_CLOSE to open or close on free.
// BIO_set_fp(in,stdin,BIO_NOCLOSE);
BIO_NOCLOSE = $00;
BIO_CLOSE = $01;
BIO_FP_READ = $02;
BIO_FP_WRITE = $04;
BIO_FP_APPEND = $08;
BIO_FP_TEXT = $10;
BIO_C_SET_FILENAME = 108;
BIO_CTRL_RESET = 1; // opt - rewind/zero etc
BIO_CTRL_EOF = 2; // opt - are we at the eof
BIO_CTRL_INFO = 3; // opt - extra tit-bits
BIO_CTRL_SET = 4; // man - set the 'IO' type
BIO_CTRL_GET = 5; // man - get the 'IO' type
BIO_CTRL_PUSH = 6; // opt - internal, used to signify change
BIO_CTRL_POP = 7; // opt - internal, used to signify change
BIO_CTRL_GET_CLOSE = 8; // man - set the 'close' on free
BIO_CTRL_SET_CLOSE = 9; // man - set the 'close' on free
BIO_CTRL_PENDING = 10; // opt - is their more data buffered
BIO_CTRL_FLUSH = 11; // opt - 'flush' buffered output
BIO_CTRL_DUP = 12; // man - extra stuff for 'duped' BIO
BIO_CTRL_WPENDING = 13; // opt - number of bytes still to write
BIO_C_GET_MD_CTX = 120;
BN_CTX_NUM = 16;
BN_CTX_NUM_POS = 12;
// RSA key exponent
RSA_3: longint = $3;
RSA_F4: longint = $10001;
FORMAT_UNDEF = 0;
FORMAT_ASN1 = 1;
FORMAT_TEXT = 2;
FORMAT_PEM = 3;
FORMAT_NETSCAPE = 4;
FORMAT_PKCS12 = 5;
FORMAT_SMIME = 6;
FORMAT_X509 = 509;
PKCS7_TEXT = $001;
PKCS7_NOCERTS = $002;
PKCS7_NOSIGS = $004;
PKCS7_NOCHAIN = $008;
PKCS7_NOINTERN = $010;
PKCS7_NOVERIFY = $020;
PKCS7_DETACHED = $040;
PKCS7_BINARY = $080;
PKCS7_NOATTR = $100;
PKCS7_NOSMIMECAP = $200;
PKCS7_NOOLDMIMETYPE = $400;
PKCS7_CRLFEOL = $800;
PKCS7_STREAM = $1000;
PKCS7_NOCRL = $2000;
PKCS7_PARTIAL = $4000;
PKCS7_REUSE_DIGEST = $8000;
X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 18;
SHA_DIGEST_LENGTH = 20;
EVP_MAX_MD_SIZE = 16 + 20; // SSLv3 md5+sha1
EVP_PKEY_RSA = NID_rsaEncryption;
EXFLAG_KUSAGE = $02;
EXFLAG_BCONS = $1;
EXFLAG_CA = $10;
EXFLAG_SS = $20;
EXFLAG_V1 = $40;
KU_KEY_CERT_SIGN = $0004;
V1_ROOT = EXFLAG_V1 or EXFLAG_SS;
GEN_OTHERNAME = 0 or V_ASN1_CONTEXT_SPECIFIC;
GEN_EMAIL = 1 or V_ASN1_CONTEXT_SPECIFIC;
GEN_DNS = 2 or V_ASN1_CONTEXT_SPECIFIC;
GEN_X400 = 3 or V_ASN1_CONTEXT_SPECIFIC;
GEN_DIRNAME = 4 or V_ASN1_CONTEXT_SPECIFIC;
GEN_EDIPARTY = 5 or V_ASN1_CONTEXT_SPECIFIC;
GEN_URI = 6 or V_ASN1_CONTEXT_SPECIFIC;
GEN_IPADD = 7 or V_ASN1_CONTEXT_SPECIFIC;
GEN_RID = 8 or V_ASN1_CONTEXT_SPECIFIC;
type
PCharacter = PChar;
pSTACK = pointer;
// ASN1 types
pASN1_OBJECT = pointer;
pASN1_STRING = ^ASN1_STRING;
ASN1_STRING = record
length: integer;
asn1_type: integer;
Data: pointer;
flags: longint;
end;
pASN1_IA5STRING = pASN1_STRING;
pASN1_INTEGER = pASN1_STRING;
pASN1_ENUMERATED = pASN1_STRING;
pASN1_TIME = pASN1_STRING;
pASN1_OCTET_STRING = pASN1_STRING;
pBN_ULONG = ^BN_ULONG;
BN_ULONG = array of byte;
pBIGNUM = ^BIGNUM;
BIGNUM = record
d: pBN_ULONG;
top: integer;
dmax: integer;
neg: integer;
flags: integer;
end;
pBN_CTX = ^BN_CTX;
BN_CTX = record
tos: integer;
bn: array [0..BN_CTX_NUM - 1] of BIGNUM;
flags: integer;
depth: integer;
pos: array [0..BN_CTX_NUM_POS - 1] of integer;
too_many: integer;
end;
pBN_BLINDING = ^BN_BLINDING;
BN_BLINDING = record
init: integer;
A: pBIGNUM;
Ai: pBIGNUM;
_mod: pBIGNUM;
end;
pBN_MONT_CTX = ^BN_MONT_CTX;
BN_MONT_CTX = record
ri: integer;
RR: BIGNUM;
N: BIGNUM;
Ni: BIGNUM;
n0: BN_ULONG;
flags: integer;
end;
pBN_RECP_CTX = ^BN_RECP_CTX;
BN_RECP_CTX = record
N: BIGNUM;
Nr: BIGNUM;
num_bits: integer;
shift: integer;
flags: integer;
end;
pX509_STORE_CTX = pointer;
TPWCallbackFunction = function(buffer: PCharacter; length: integer; verify: integer; Data: pointer): integer; cdecl;
TCertificateVerifyFunction = function(ok: integer; ctx: pX509_STORE_CTX): integer; cdecl;
pBIO = pointer;
pBIO_METHOD = pointer;
pBUF_MEM = pointer;
des_cblock = array [0..7] of byte;
MD2_CTX = record
num: integer;
Data: array [0..15] of byte;
cksm: array [0..15] of cardinal;
state: array [0..15] of cardinal;
end;
MD4_CTX = record
A, B, C, D: cardinal;
Nl, Nh: cardinal;
Data: array [0..15] of cardinal;
num: integer;
end;
MD5_CTX = record
A, B, C, D: cardinal;
Nl, Nh: cardinal;
Data: array [0..15] of cardinal;
num: integer;
end;
RIPEMD160_CTX = record
A, B, C, D, E: cardinal;
Nl, Nh: cardinal;
Data: array [0..15] of cardinal;
num: integer;
end;
SHA_CTX = record
h0, h1, h2, h3, h4: cardinal;
Nl, Nh: cardinal;
Data: array [0..16] of cardinal;
num: integer;
end;
MDC2_CTX = record
num: integer;
Data: array [0..7] of byte;
h, hh: des_cblock;
pad_type: integer;
end;
CRYPTO_EX_DATA = record
sk: pointer;
dummy: integer;
end;
pAES_KEY = pointer;
pRSA = pointer;
pRSA_METHOD = pointer;
RSA = record
pad: integer;
version: integer;
meth: pRSA_METHOD;
n: pBIGNUM;
e: pBIGNUM;
d: pBIGNUM;
p: pBIGNUM;
q: pBIGNUM;
dmp1: pBIGNUM;
dmq1: pBIGNUM;
iqmp: pBIGNUM;
ex_data: CRYPTO_EX_DATA;
references: integer;
flags: integer;
_method_mod_n: pBN_MONT_CTX;
_method_mod_p: pBN_MONT_CTX;
_method_mod_q: pBN_MONT_CTX;
bignum_data: ^byte;
blinding: ^BN_BLINDING;
end;
pDSA = ^DSA;
DSA = record
pad: integer;
version: integer;
write_params: integer;
p: pointer;
q: pointer;
g: pointer;
pub_key: pointer;
priv_key: pointer;
kinv: pointer;
r: pointer;
flags: integer;
method_mont_p: PCharacter;
references: integer;
ex_data: record
sk: pointer;
dummy: integer;
end;
meth: pointer;
end;
pDH = pointer;
pEC_KEY = pointer;
pEVP_CIPHER = pointer;
pEVP_MD = ^EVP_MD;
EVP_MD = record
_type: integer;
pkey_type: integer;
md_size: integer;
init: pointer;
update: pointer;
final: pointer;
sign: pointer;
verify: pointer;
required_pkey_type: array [0..4] of integer;
block_size: integer;
ctx_size: integer;
end;
pEVP_MD_CTX = ^EVP_MD_CTX;
EVP_MD_CTX = record
digest: pEVP_MD;
case integer of
0: (base: array [0..3] of byte);
1: (md2: MD2_CTX);
8: (md4: MD4_CTX);
2: (md5: MD5_CTX);
16: (ripemd160: RIPEMD160_CTX);
4: (sha: SHA_CTX);
32: (mdc2: MDC2_CTX);
end;
pX509_NAME_ENTRY = ^X509_NAME_ENTRY;
X509_NAME_ENTRY = record
obj: pASN1_OBJECT;
Value: pASN1_STRING;
_set: integer;
size: integer; // temp variable
end;
pX509_NAME = ^X509_NAME;
pDN = ^X509_NAME;
X509_NAME = record
entries: pointer;
modified: integer;
bytes: pointer;
hash: cardinal;
end;
pX509_VAL = ^X509_VAL;
X509_VAL = record
notBefore: pASN1_TIME;
notAfter: pASN1_TIME;
end;
pX509_CINF = ^X509_CINF;
X509_CINF = record
version: pointer;
serialNumber: pointer;
signature: pointer;
issuer: pointer;
validity: pX509_VAL;
subject: pointer;
key: pointer;
issuerUID: pointer;
subjectUID: pointer;
extensions: pointer;
end;
pX509 = ^X509;
X509 = record
cert_info: pX509_CINF;
sig_alg: pointer; // ^X509_ALGOR
signature: pointer; // ^ASN1_BIT_STRING
valid: integer;
references: integer;
Name: PCharacter;
ex_data: CRYPTO_EX_DATA;
ex_pathlen: integer;
ex_flags: integer;
ex_kusage: integer;
ex_xkusage: integer;
ex_nscert: integer;
skid: pASN1_OCTET_STRING;
akid: pointer; // ?
sha1_hash: array [0..SHA_DIGEST_LENGTH - 1] of char;
aux: pointer; // ^X509_CERT_AUX
end;
pSTACK_OFX509 = pointer;
pX509_STORE = ^X509_STORE;
pX509_LOOKUP = pointer;
pSTACK_OF509LOOKUP = pointer;
pX509_LOOKUP_METHOD = pointer;
X509_STORE = record
cache: integer;
objs: pSTACK_OFX509;
get_cert_methods: pSTACK_OF509LOOKUP;
verify: pointer; // function called to verify a certificate
verify_cb: TCertificateVerifyFunction;
ex_data: pointer;
references: integer;
depth: integer;
end;
pX509V3_CTX = pointer;
pX509_REQ = ^X509_REQ;
pX509_REQ_INFO = ^X509_REQ_INFO;
X509_REQ_INFO = record
asn1: pointer;
length: integer;
version: pointer;
subject: pX509_NAME;
pubkey: pointer;
attributes: pointer;
req_kludge: integer;
end;
X509_REQ = record
req_info: pX509_REQ_INFO;
sig_alg: pointer;
signature: pointer;
references: integer;
end;
pX509_EXTENSION = ^X509_EXTENSION;
X509_EXTENSION = record
obj: pASN1_OBJECT;
critical: smallint;
netscape_hack: smallint;
Value: pASN1_OCTET_STRING;
method: pointer; // struct v3_ext_method *: V3 method to use
ext_val: pointer; // extension value
end;
pSTACK_OFX509_EXTENSION = pointer;
pX509_CRL = pointer;
pX509_SIG = ^X509_SIG;
X509_SIG = record
algor: Pointer; // X509_ALGOR *algor;
digest: pASN1_OCTET_STRING;
end;
pBASIC_CONSTRAINTS = ^BASIC_CONSTRAINTS;
BASIC_CONSTRAINTS = record
ca: integer;
pathlen: pASN1_INTEGER;
end;
pOTHERNAME = ^OTHERNAME;
OTHERNAME = record
type_id: pASN1_OBJECT; //There is a bug in x509v3/x509v3.h ?
Value: pointer; //pASN1_TYPE;
end;
pGENERAL_NAME = ^GENERAL_NAME;
pGENERAL_NAMEDATA = record
case integer of
GEN_EMAIL: (ia5: pASN1_IA5STRING); // also DNS and URI
GEN_IPADD: (ip: pASN1_OCTET_STRING);
GEN_DIRNAME: (dirn: pX509_NAME);
GEN_RID: (rid: pASN1_OBJECT);
GEN_OTHERNAME: (otherName: pOTHERNAME);
GEN_X400: (other: pointer); // also EDI
end;
GENERAL_NAME = record
nametype: integer;
d: pGENERAL_NAMEDATA;
end;
pEVP_PKEY = ^EVP_PKEY;
EVP_PKEY_PKEY = record
case integer of
0: (ptr: PCharacter);
1: (rsa: pRSA); // ^rsa_st
2: (dsa: pDSA); // ^dsa_st
3: (dh: pDH); // ^dh_st
end;
EVP_PKEY = record
ktype: integer;
save_type: integer;
references: integer;
pkey: EVP_PKEY_PKEY;
save_parameters: integer;
attributes: pSTACK_OFX509;
end;
pPKCS7_SIGNER_INFO = pointer;
pSTACK_OFPKCS7_SIGNER_INFO = pointer;
pPKCS7_signed = ^PKCS7_signed;
PKCS7_signed = record
version: pASN1_INTEGER;
md_algs: pointer; // ^STACK_OF(X509_ALGOR)
cert: pointer; // ^STACK_OF(X509)
crl: pointer; // ^STACK_OF(X509_CRL)
signer_info: pSTACK_OFPKCS7_SIGNER_INFO;
contents: pointer; // ^struct pkcs7_st
end;
pPKCS7_signedandenveloped = ^PKCS7_signedandenveloped;
PKCS7_signedandenveloped = record
version: pASN1_INTEGER;
md_algs: pointer; // ^STACK_OF(X509_ALGOR)
cert: pointer; // ^STACK_OF(X509)
crl: pointer; // ^STACK_OF(X509_CRL)
signer_info: pSTACK_OFPKCS7_SIGNER_INFO;
enc_data: pointer; // ^PKCS7_ENC_CONTENT
recipientinfo: pointer; // ^STACK_OF(PKCS7_RECIP_INFO)
end;
pPKCS7 = ^PKCS7;
PKCS7 = record
asn1: PCharacter;
length: integer;
state: integer;
detached: integer;
asn1_type: pointer; // ^ASN1_OBJECT
case integer of
0: (ptr: pASN1_OCTET_STRING);
1: (Data: pointer); // ^PKCS7_SIGNED
2: (sign: pPKCS7_signed); // ^PKCS7_SIGNED
3: (enveloped: pointer); // ^PKCS7_ENVELOPE
4: (signed_and_enveloped: pPKCS7_signedandenveloped);
5: (digest: pointer); // ^PKCS7_DIGEST
6: (encrypted: pointer); // ^PKCS7_ENCRYPT
7: (other: pointer); // ^ASN1_TYPE
end;
{
void OpenSSL_add_all_algorithms(void);
void OpenSSL_add_all_ciphers(void);
void OpenSSL_add_all_digests(void);
}
procedure OpenSSL_add_all_algorithms; cdecl;
procedure OpenSSL_add_all_ciphers; cdecl;
procedure OpenSSL_add_all_digests; cdecl;
procedure CRYPTO_cleanup_all_ex_data(); cdecl;
procedure EVP_cleanup(); cdecl;
procedure ERR_load_crypto_strings; cdecl;
procedure ERR_free_strings; cdecl;
// BIO
function BIO_new(_type: pBIO_METHOD): pBIO; cdecl;
function BIO_free(a: pBIO): integer; cdecl;
procedure BIO_free_all(a: pBIO); cdecl;
function BIO_ctrl(bp: pBIO; cmd: integer; larg: longint; parg: Pointer): longint; cdecl;
function BIO_read(b: pBIO; buf: pointer; len: integer): integer; cdecl;
function BIO_reset(bp: pBIO): integer;
function BIO_pending(bp: pBIO): integer;
function BIO_read_filename(bp: pBIO; filename: PCharacter): integer;
function BIO_s_mem: pBIO_METHOD; cdecl;
function BIO_new_mem_buf(buf: pointer; len: integer): pBIO; cdecl;
function BIO_s_file: pBIO_METHOD; cdecl;
// PEM
function PEM_read_bio_X509(bp: pBIO; var x: pX509; cb: TPWCallbackFunction; u: pointer): pX509; cdecl;
function PEM_read_bio_PrivateKey(bp: pBIO; var x: pEVP_PKEY; cb: TPWCallbackFunction; u: pointer): pEVP_PKEY; cdecl;
// PKCS#7 functions
function PKCS7_sign(signcert: pX509; pkey: pEVP_PKEY; certs: pointer; Data: pBIO; flags: integer): pPKCS7; cdecl;
procedure PKCS7_free(p7: pPKCS7); cdecl;
// SMIME
function SMIME_write_PKCS7(bp: pBIO; p7: pPKCS7; Data: pBIO; flags: integer): integer; cdecl;
function SMIME_read_PKCS7(bp: pBIO; var bcont: pBIO): pPKCS7; cdecl;
implementation
const
Crypto_DLL_Names = 'libeay32.dll'; //libcrypto-1_1 o libcrypto-3
procedure OpenSSL_add_all_algorithms; external Crypto_DLL_Names;
procedure OpenSSL_add_all_ciphers; external Crypto_DLL_Names;
procedure OpenSSL_add_all_digests; external Crypto_DLL_Names;
procedure EVP_cleanup; external Crypto_DLL_Names;
procedure CRYPTO_cleanup_all_ex_data; external Crypto_DLL_Names;
procedure ERR_load_crypto_strings; external Crypto_DLL_Names;
procedure ERR_free_strings; external Crypto_DLL_Names;
//BIO
function BIO_new; external Crypto_DLL_Names;
function BIO_free; external Crypto_DLL_Names;
procedure BIO_vfree; external Crypto_DLL_Names;
procedure BIO_free_all; external Crypto_DLL_Names;
function BIO_ctrl; external Crypto_DLL_Names;
function BIO_read; external Crypto_DLL_Names;
function BIO_s_mem; external Crypto_DLL_Names;
procedure BIO_set_mem_buf; external Crypto_DLL_Names;
procedure BIO_get_mem_ptr; external Crypto_DLL_Names;
function BIO_new_mem_buf; external Crypto_DLL_Names;
function BIO_s_file; external Crypto_DLL_Names;
function BIO_reset(bp: pBIO): integer;
begin
Result := BIO_ctrl(bp, BIO_CTRL_RESET, 0, nil);
end;
function BIO_pending(bp: pBIO): integer;
begin
Result := BIO_ctrl(bp, BIO_CTRL_PENDING, 0, nil);
end;
function BIO_read_filename(bp: pBIO; filename: PCharacter): integer;
begin
Result := BIO_ctrl(bp, BIO_C_SET_FILENAME, BIO_CLOSE or BIO_FP_READ, filename);
end;
// PEM
function PEM_read_bio_X509; external Crypto_DLL_Names;
function PEM_read_bio_PrivateKey; external Crypto_DLL_Names;
// PKCS#7
function PKCS7_sign; external Crypto_DLL_Names;
procedure PKCS7_free; external Crypto_DLL_Names;
// SMIME
function SMIME_write_PKCS7; external Crypto_DLL_Names;
function SMIME_read_PKCS7; external Crypto_DLL_Names;
end.