Initial commit
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
commit
2e64118f8c
@ -0,0 +1,44 @@
|
||||
---
|
||||
name: default
|
||||
kind: pipeline
|
||||
type: docker
|
||||
|
||||
steps:
|
||||
- name: composer
|
||||
image: d.xr.to/eater/php7.4rc6
|
||||
volumes:
|
||||
- name: composer
|
||||
path: /composer
|
||||
environment:
|
||||
COMPOSER_HOME: /composer
|
||||
commands:
|
||||
- composer install --no-ansi --no-interaction
|
||||
|
||||
- name: code styling
|
||||
image: d.xr.to/eater/php7.4rc6
|
||||
commands:
|
||||
- ./vendor/bin/php-cs-fixer fix --dry-run src
|
||||
depends_on:
|
||||
- composer
|
||||
|
||||
- name: static analysis
|
||||
image: d.xr.to/eater/php7.4rc6
|
||||
commands:
|
||||
- ./vendor/bin/phpstan analyse --no-ansi --no-interaction -l max -a vendor/autoload.php src
|
||||
depends_on:
|
||||
- composer
|
||||
|
||||
- name: testing
|
||||
image: d.xr.to/eater/php7.4rc6
|
||||
commands:
|
||||
- ./vendor/bin/phpunit --colors=always
|
||||
depends_on:
|
||||
- composer
|
||||
|
||||
volumes:
|
||||
- name: composer
|
||||
host:
|
||||
path: /tank/var/composer-cache
|
||||
---
|
||||
kind: signature
|
||||
hmac: 6efb9d8750e04696b55086860be359b58bbedb51944d7e0234032f1cc3230229
|
@ -0,0 +1,2 @@
|
||||
.phpunit.result.cache
|
||||
/vendor
|
@ -0,0 +1,31 @@
|
||||
# COpenSSL
|
||||
|
||||
|
||||
[![Build Status](https://drone.cijber.net/api/badges/cijber/copenssl/status.svg)](https://drone.cijber.net/cijber/copenssl)
|
||||
|
||||
An effort to make OpenSSL more accessible in PHP via FFI bindings.
|
||||
|
||||
**⚠ WARNING:** If you just need a solution to encrypt and sign stuff please look at `libsodium`,
|
||||
COpenSSL is only meant to be used for in-depth crypto routines.
|
||||
|
||||
---
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
composer install cijber/copenssl
|
||||
```
|
||||
|
||||
## Details
|
||||
|
||||
Currently this library is implemented as needed. on the current roadmap is PKCS#7 support.
|
||||
|
||||
BIO is almost fully implemented
|
||||
|
||||
## Headers
|
||||
|
||||
`resources` contain the headers used for FFI, these are all concatenated into one string and then loaded in `Cijber\OpenSSL\Instance`.
|
||||
|
||||
`resources/gen` contains `template.h` and `full.h`, `full.h` is a fully pre-processed header generated from `template.h`
|
||||
by running `gcc -E template.h > full.h`, this file helps with creating the headers needed for FFI
|
||||
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "cijber/copenssl",
|
||||
"description": "C binding to OpenSSL with FFI",
|
||||
"type": "library",
|
||||
"require": {
|
||||
"ext-FFI": "*",
|
||||
"php": "^7.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Cijber\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": "GPLv3",
|
||||
"authors": [
|
||||
{
|
||||
"name": "eater",
|
||||
"email": "=@eater.me"
|
||||
}
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
|
||||
bootstrap="vendor/autoload.php"
|
||||
>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>src/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="suite">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
@ -0,0 +1,76 @@
|
||||
struct asn1_string_st {
|
||||
int length;
|
||||
int type;
|
||||
unsigned char *data;
|
||||
long flags;
|
||||
};
|
||||
|
||||
typedef struct asn1_string_st ASN1_INTEGER;
|
||||
typedef struct asn1_string_st ASN1_ENUMERATED;
|
||||
typedef struct asn1_string_st ASN1_BIT_STRING;
|
||||
typedef struct asn1_string_st ASN1_OCTET_STRING;
|
||||
typedef struct asn1_string_st ASN1_PRINTABLESTRING;
|
||||
typedef struct asn1_string_st ASN1_T61STRING;
|
||||
typedef struct asn1_string_st ASN1_IA5STRING;
|
||||
typedef struct asn1_string_st ASN1_GENERALSTRING;
|
||||
typedef struct asn1_string_st ASN1_UNIVERSALSTRING;
|
||||
typedef struct asn1_string_st ASN1_BMPSTRING;
|
||||
typedef struct asn1_string_st ASN1_UTCTIME;
|
||||
typedef struct asn1_string_st ASN1_TIME;
|
||||
typedef struct asn1_string_st ASN1_GENERALIZEDTIME;
|
||||
typedef struct asn1_string_st ASN1_VISIBLESTRING;
|
||||
typedef struct asn1_string_st ASN1_UTF8STRING;
|
||||
typedef struct asn1_string_st ASN1_STRING;
|
||||
typedef int ASN1_BOOLEAN;
|
||||
typedef int ASN1_NULL;
|
||||
|
||||
typedef struct ASN1_VALUE_st ASN1_VALUE;
|
||||
|
||||
typedef struct asn1_object_st {
|
||||
const char *sn, *ln;
|
||||
int nid;
|
||||
int length;
|
||||
const unsigned char *data;
|
||||
int flags;
|
||||
} ASN1_OBJECT;
|
||||
|
||||
typedef struct asn1_type_st {
|
||||
int type;
|
||||
union {
|
||||
char *ptr;
|
||||
ASN1_BOOLEAN boolean;
|
||||
ASN1_STRING *asn1_string;
|
||||
ASN1_OBJECT *object;
|
||||
ASN1_INTEGER *integer;
|
||||
ASN1_ENUMERATED *enumerated;
|
||||
ASN1_BIT_STRING *bit_string;
|
||||
ASN1_OCTET_STRING *octet_string;
|
||||
ASN1_PRINTABLESTRING *printablestring;
|
||||
ASN1_T61STRING *t61string;
|
||||
ASN1_IA5STRING *ia5string;
|
||||
ASN1_GENERALSTRING *generalstring;
|
||||
ASN1_BMPSTRING *bmpstring;
|
||||
ASN1_UNIVERSALSTRING *universalstring;
|
||||
ASN1_UTCTIME *utctime;
|
||||
ASN1_GENERALIZEDTIME *generalizedtime;
|
||||
ASN1_VISIBLESTRING *visiblestring;
|
||||
ASN1_UTF8STRING *utf8string;
|
||||
|
||||
ASN1_STRING *set;
|
||||
ASN1_STRING *sequence;
|
||||
ASN1_VALUE *asn1_value;
|
||||
} value;
|
||||
} ASN1_TYPE;
|
||||
|
||||
typedef struct ASN1_ENCODING_st {
|
||||
unsigned char *enc;
|
||||
long len;
|
||||
int modified;
|
||||
} ASN1_ENCODING;
|
||||
|
||||
struct stack_st_ASN1_OBJECT {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
ASN1_OBJECT *OBJ_nid2obj(int n);
|
||||
int OBJ_obj2nid(const ASN1_OBJECT *o);
|
@ -0,0 +1,65 @@
|
||||
typedef struct crypto_ex_data_st CRYPTO_EX_DATA;
|
||||
struct crypto_ex_data_st {
|
||||
struct stack_st_void *sk;
|
||||
};
|
||||
struct stack_st_void {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
typedef struct bio_st BIO;
|
||||
|
||||
typedef void bio_info_cb(struct bio_st *, int, const char *, int, long, long);
|
||||
typedef int BIO_info_cb(BIO *, int, int);
|
||||
|
||||
typedef struct bio_method_st {
|
||||
int type;
|
||||
const char *name;
|
||||
int (*bwrite)(BIO *, const char *, int);
|
||||
int (*bread)(BIO *, char *, int);
|
||||
int (*bputs)(BIO *, const char *);
|
||||
int (*bgets)(BIO *, char *, int);
|
||||
long (*ctrl)(BIO *, int, long, void *);
|
||||
int (*create)(BIO *);
|
||||
int (*destroy)(BIO *);
|
||||
long (*callback_ctrl)(BIO *, int, bio_info_cb *);
|
||||
} BIO_METHOD;
|
||||
|
||||
struct bio_st {
|
||||
const BIO_METHOD *method;
|
||||
|
||||
long (*callback)(struct bio_st *, int, const char *, int, long, long);
|
||||
char *cb_arg;
|
||||
|
||||
int init;
|
||||
int shutdown;
|
||||
int flags;
|
||||
int retry_reason;
|
||||
int num;
|
||||
void *ptr;
|
||||
struct bio_st *next_bio;
|
||||
struct bio_st *prev_bio;
|
||||
int references;
|
||||
unsigned long num_read;
|
||||
unsigned long num_write;
|
||||
|
||||
CRYPTO_EX_DATA ex_data;
|
||||
};
|
||||
|
||||
BIO *BIO_new_file(const char *filename, const char *mode);
|
||||
BIO *BIO_new(const BIO_METHOD *type);
|
||||
|
||||
int BIO_set(BIO *a, const BIO_METHOD *type);
|
||||
int BIO_free(BIO *a);
|
||||
|
||||
int BIO_read(BIO *b, void *buf, int len);
|
||||
int BIO_gets(BIO *b, char *buf, int size);
|
||||
int BIO_write(BIO *b, const void *buf, int len);
|
||||
int BIO_puts(BIO *b, const char *buf);
|
||||
int BIO_test_flags(const BIO *b, int flags);
|
||||
|
||||
long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg);
|
||||
|
||||
int BIO_method_type(const BIO *b);
|
||||
|
||||
const BIO_METHOD *BIO_s_mem(void);
|
||||
BIO *BIO_new_mem_buf(const void *buf, int len);
|
@ -0,0 +1 @@
|
||||
typedef struct engine_st ENGINE;
|
@ -0,0 +1,63 @@
|
||||
void EVP_cleanup(void);
|
||||
|
||||
typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
|
||||
|
||||
typedef struct evp_pkey_st EVP_PKEY;
|
||||
typedef struct evp_cipher_st EVP_CIPHER;
|
||||
typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
|
||||
|
||||
struct evp_pkey_st {
|
||||
int type;
|
||||
int save_type;
|
||||
int references;
|
||||
const EVP_PKEY_ASN1_METHOD *ameth;
|
||||
ENGINE *engine;
|
||||
union {
|
||||
char *ptr;
|
||||
struct rsa_st *rsa;
|
||||
struct dsa_st *dsa;
|
||||
struct dh_st *dh;
|
||||
struct ec_key_st *ec;
|
||||
struct gost_key_st *gost;
|
||||
} pkey;
|
||||
int save_parameters;
|
||||
struct stack_st_X509_ATTRIBUTE *attributes;
|
||||
};
|
||||
|
||||
struct evp_cipher_st {
|
||||
int nid;
|
||||
int block_size;
|
||||
int key_len;
|
||||
int iv_len;
|
||||
unsigned long flags;
|
||||
int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc);
|
||||
int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t inl);
|
||||
int (*cleanup)(EVP_CIPHER_CTX *);
|
||||
int ctx_size;
|
||||
int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *);
|
||||
int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *);
|
||||
int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
|
||||
void *app_data;
|
||||
};
|
||||
|
||||
struct evp_cipher_ctx_st {
|
||||
const EVP_CIPHER *cipher;
|
||||
ENGINE *engine;
|
||||
int encrypt;
|
||||
int buf_len;
|
||||
|
||||
unsigned char oiv[16];
|
||||
unsigned char iv[16];
|
||||
unsigned char buf[32];
|
||||
int num;
|
||||
|
||||
void *app_data;
|
||||
int key_len;
|
||||
unsigned long flags;
|
||||
void *cipher_data;
|
||||
int final_used;
|
||||
int block_mask;
|
||||
unsigned char final[32];
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pkcs7.h>
|
@ -0,0 +1,17 @@
|
||||
typedef struct stack_st {
|
||||
int num;
|
||||
char **data;
|
||||
int sorted;
|
||||
|
||||
int num_alloc;
|
||||
int (*comp)(const void *, const void *);
|
||||
} _STACK;
|
||||
|
||||
struct buf_mem_st {
|
||||
size_t length;
|
||||
char *data;
|
||||
size_t max;
|
||||
};
|
||||
|
||||
typedef struct buf_mem_st BUF_MEM;
|
||||
typedef long int time_t;
|
@ -0,0 +1,9 @@
|
||||
void OPENSSL_config(const char *config_name);
|
||||
void OPENSSL_no_config(void);
|
||||
|
||||
void CRYPTO_cleanup_all_ex_data(void);
|
||||
void OPENSSL_add_all_algorithms_conf(void);
|
||||
void OPENSSL_add_all_algorithms_noconf(void);
|
||||
|
||||
void ERR_load_crypto_strings(void);
|
||||
void ERR_free_strings(void);
|
@ -0,0 +1,113 @@
|
||||
typedef struct pkcs7_issuer_and_serial_st {
|
||||
X509_NAME *issuer;
|
||||
ASN1_INTEGER *serial;
|
||||
} PKCS7_ISSUER_AND_SERIAL;
|
||||
|
||||
typedef struct pkcs7_signer_info_st {
|
||||
ASN1_INTEGER *version;
|
||||
PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
|
||||
X509_ALGOR *digest_alg;
|
||||
struct stack_st_X509_ATTRIBUTE *auth_attr;
|
||||
X509_ALGOR *digest_enc_alg;
|
||||
ASN1_OCTET_STRING *enc_digest;
|
||||
struct stack_st_X509_ATTRIBUTE *unauth_attr;
|
||||
|
||||
EVP_PKEY *pkey;
|
||||
} PKCS7_SIGNER_INFO;
|
||||
|
||||
struct stack_st_PKCS7_SIGNER_INFO {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
typedef struct pkcs7_recip_info_st {
|
||||
ASN1_INTEGER *version;
|
||||
PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
|
||||
X509_ALGOR *key_enc_algor;
|
||||
ASN1_OCTET_STRING *enc_key;
|
||||
X509 *cert;
|
||||
} PKCS7_RECIP_INFO;
|
||||
|
||||
struct stack_st_PKCS7_RECIP_INFO {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
typedef struct pkcs7_signed_st {
|
||||
ASN1_INTEGER *version;
|
||||
struct stack_st_X509_ALGOR *md_algs;
|
||||
struct stack_st_X509 *cert;
|
||||
struct stack_st_X509_CRL *crl;
|
||||
struct stack_st_PKCS7_SIGNER_INFO *signer_info;
|
||||
struct pkcs7_st *contents;
|
||||
} PKCS7_SIGNED;
|
||||
|
||||
typedef struct pkcs7_enc_content_st {
|
||||
ASN1_OBJECT *content_type;
|
||||
X509_ALGOR *algorithm;
|
||||
ASN1_OCTET_STRING *enc_data;
|
||||
const EVP_CIPHER *cipher;
|
||||
} PKCS7_ENC_CONTENT;
|
||||
|
||||
typedef struct pkcs7_enveloped_st {
|
||||
ASN1_INTEGER *version;
|
||||
|
||||
struct stack_st_PKCS7_RECIP_INFO *recipientinfo;
|
||||
PKCS7_ENC_CONTENT *enc_data;
|
||||
} PKCS7_ENVELOPE;
|
||||
|
||||
typedef struct pkcs7_signedandenveloped_st {
|
||||
ASN1_INTEGER *version;
|
||||
|
||||
struct stack_st_X509_ALGOR *md_algs;
|
||||
|
||||
struct stack_st_X509 *cert;
|
||||
|
||||
struct stack_st_X509_CRL *crl;
|
||||
|
||||
struct stack_st_PKCS7_SIGNER_INFO *signer_info;
|
||||
|
||||
PKCS7_ENC_CONTENT *enc_data;
|
||||
|
||||
struct stack_st_PKCS7_RECIP_INFO *recipientinfo;
|
||||
} PKCS7_SIGN_ENVELOPE;
|
||||
|
||||
typedef struct pkcs7_digest_st {
|
||||
ASN1_INTEGER *version;
|
||||
X509_ALGOR *md;
|
||||
struct pkcs7_st *contents;
|
||||
ASN1_OCTET_STRING *digest;
|
||||
} PKCS7_DIGEST;
|
||||
|
||||
typedef struct pkcs7_encrypted_st {
|
||||
ASN1_INTEGER *version;
|
||||
PKCS7_ENC_CONTENT *enc_data;
|
||||
} PKCS7_ENCRYPT;
|
||||
|
||||
typedef struct pkcs7_st {
|
||||
unsigned char *asn1;
|
||||
long length;
|
||||
int state;
|
||||
int detached;
|
||||
ASN1_OBJECT *type;
|
||||
|
||||
union {
|
||||
char *ptr;
|
||||
ASN1_OCTET_STRING *data;
|
||||
PKCS7_SIGNED *sign;
|
||||
PKCS7_ENVELOPE *enveloped;
|
||||
PKCS7_SIGN_ENVELOPE *signed_and_enveloped;
|
||||
PKCS7_DIGEST *digest;
|
||||
PKCS7_ENCRYPT *encrypted;
|
||||
ASN1_TYPE *other;
|
||||
} d;
|
||||
} PKCS7;
|
||||
|
||||
struct stack_st_PKCS7 {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
PKCS7 *PKCS7_new(void);
|
||||
void PKCS7_free(PKCS7 *a);
|
||||
PKCS7 *d2i_PKCS7(PKCS7 **a, const unsigned char **in, long len);
|
||||
int i2d_PKCS7(PKCS7 *a, unsigned char **out);
|
||||
int PKCS7_verify(PKCS7 *p7, struct stack_st_X509 *certs, X509_STORE *store,
|
||||
BIO *indata, BIO *out, int flags);
|
@ -0,0 +1,241 @@
|
||||
typedef struct x509_st X509;
|
||||
typedef struct X509_algor_st X509_ALGOR;
|
||||
typedef struct X509_crl_st X509_CRL;
|
||||
typedef struct x509_crl_method_st X509_CRL_METHOD;
|
||||
typedef struct x509_revoked_st X509_REVOKED;
|
||||
typedef struct X509_name_st X509_NAME;
|
||||
typedef struct X509_pubkey_st X509_PUBKEY;
|
||||
typedef struct x509_store_st X509_STORE;
|
||||
typedef struct x509_store_ctx_st X509_STORE_CTX;
|
||||
|
||||
typedef struct stack_st_X509_ALGOR X509_ALGORS;
|
||||
|
||||
struct stack_st_X509_ALGOR {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
struct X509_algor_st {
|
||||
ASN1_OBJECT *algorithm;
|
||||
ASN1_TYPE *parameter;
|
||||
};
|
||||
|
||||
struct stack_st_X509_NAME_ENTRY {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
struct X509_name_st {
|
||||
struct stack_st_X509_NAME_ENTRY *entries;
|
||||
int modified;
|
||||
BUF_MEM *bytes;
|
||||
unsigned char *canon_enc;
|
||||
int canon_enclen;
|
||||
};
|
||||
|
||||
typedef struct X509_VERIFY_PARAM_ID_st X509_VERIFY_PARAM_ID;
|
||||
|
||||
typedef struct X509_VERIFY_PARAM_st {
|
||||
char *name;
|
||||
time_t check_time;
|
||||
unsigned long inh_flags;
|
||||
unsigned long flags;
|
||||
int purpose;
|
||||
int trust;
|
||||
int depth;
|
||||
struct stack_st_ASN1_OBJECT *policies;
|
||||
X509_VERIFY_PARAM_ID *id;
|
||||
} X509_VERIFY_PARAM;
|
||||
|
||||
struct stack_st_X509_VERIFY_PARAM {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
struct x509_store_st {
|
||||
|
||||
int cache;
|
||||
struct stack_st_X509_OBJECT *objs;
|
||||
|
||||
struct stack_st_X509_LOOKUP *get_cert_methods;
|
||||
|
||||
X509_VERIFY_PARAM *param;
|
||||
|
||||
int (*verify)(X509_STORE_CTX *ctx);
|
||||
int (*verify_cb)(int ok, X509_STORE_CTX *ctx);
|
||||
int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
|
||||
int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
|
||||
int (*check_revocation)(X509_STORE_CTX *ctx);
|
||||
int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x);
|
||||
int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl);
|
||||
int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
|
||||
struct stack_st_X509 *(*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm);
|
||||
struct stack_st_X509_CRL *(*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm);
|
||||
int (*cleanup)(X509_STORE_CTX *ctx);
|
||||
|
||||
CRYPTO_EX_DATA ex_data;
|
||||
int references;
|
||||
};
|
||||
|
||||
typedef struct X509_extension_st {
|
||||
ASN1_OBJECT *object;
|
||||
ASN1_BOOLEAN critical;
|
||||
ASN1_OCTET_STRING *value;
|
||||
} X509_EXTENSION;
|
||||
|
||||
typedef struct stack_st_X509_EXTENSION X509_EXTENSIONS;
|
||||
|
||||
struct stack_st_X509_EXTENSION {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
struct X509_pubkey_st {
|
||||
X509_ALGOR *algor;
|
||||
ASN1_BIT_STRING *public_key;
|
||||
EVP_PKEY *pkey;
|
||||
};
|
||||
|
||||
typedef struct X509_pubkey_st X509_PUBKEY;
|
||||
|
||||
typedef struct X509_val_st {
|
||||
ASN1_TIME *notBefore;
|
||||
ASN1_TIME *notAfter;
|
||||
} X509_VAL;
|
||||
|
||||
typedef struct x509_cinf_st {
|
||||
ASN1_INTEGER *version;
|
||||
ASN1_INTEGER *serialNumber;
|
||||
X509_ALGOR *signature;
|
||||
X509_NAME *issuer;
|
||||
X509_VAL *validity;
|
||||
X509_NAME *subject;
|
||||
X509_PUBKEY *key;
|
||||
ASN1_BIT_STRING *issuerUID;
|
||||
ASN1_BIT_STRING *subjectUID;
|
||||
|
||||
struct stack_st_X509_EXTENSION *extensions;
|
||||
ASN1_ENCODING enc;
|
||||
} X509_CINF;
|
||||
|
||||
typedef struct X509_POLICY_NODE_st X509_POLICY_NODE;
|
||||
typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL;
|
||||
typedef struct X509_POLICY_TREE_st X509_POLICY_TREE;
|
||||
typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE;
|
||||
|
||||
typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID;
|
||||
typedef struct DIST_POINT_st DIST_POINT;
|
||||
typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT;
|
||||
typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS;
|
||||
|
||||
typedef struct x509_cert_aux_st {
|
||||
struct stack_st_ASN1_OBJECT *trust;
|
||||
struct stack_st_ASN1_OBJECT *reject;
|
||||
ASN1_UTF8STRING *alias;
|
||||
ASN1_OCTET_STRING *keyid;
|
||||
struct stack_st_X509_ALGOR *other;
|
||||
} X509_CERT_AUX;
|
||||
|
||||
struct x509_st {
|
||||
X509_CINF *cert_info;
|
||||
X509_ALGOR *sig_alg;
|
||||
ASN1_BIT_STRING *signature;
|
||||
int valid;
|
||||
int references;
|
||||
char *name;
|
||||
CRYPTO_EX_DATA ex_data;
|
||||
|
||||
long ex_pathlen;
|
||||
long ex_pcpathlen;
|
||||
unsigned long ex_flags;
|
||||
unsigned long ex_kusage;
|
||||
unsigned long ex_xkusage;
|
||||
unsigned long ex_nscert;
|
||||
ASN1_OCTET_STRING *skid;
|
||||
AUTHORITY_KEYID *akid;
|
||||
X509_POLICY_CACHE *policy_cache;
|
||||
struct stack_st_DIST_POINT
|
||||
|
||||
*crldp;
|
||||
|
||||
struct stack_st_GENERAL_NAME
|
||||
|
||||
*altname;
|
||||
NAME_CONSTRAINTS *nc;
|
||||
|
||||
unsigned char sha1_hash[20];
|
||||
X509_CERT_AUX *aux;
|
||||
};
|
||||
|
||||
typedef struct x509_trust_st {
|
||||
int trust;
|
||||
int flags;
|
||||
int (*check_trust)(struct x509_trust_st *, X509 *, int);
|
||||
char *name;
|
||||
int arg1;
|
||||
void *arg2;
|
||||
} X509_TRUST;
|
||||
|
||||
struct stack_st_X509_TRUST {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
typedef struct x509_cert_pair_st {
|
||||
X509 *forward;
|
||||
X509 *reverse;
|
||||
} X509_CERT_PAIR;
|
||||
struct x509_revoked_st {
|
||||
ASN1_INTEGER *serialNumber;
|
||||
ASN1_TIME *revocationDate;
|
||||
struct stack_st_X509_EXTENSION *extensions;
|
||||
|
||||
struct stack_st_GENERAL_NAME *issuer;
|
||||
|
||||
int reason;
|
||||
int sequence;
|
||||
};
|
||||
|
||||
struct stack_st_X509_REVOKED {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
typedef struct X509_crl_info_st {
|
||||
ASN1_INTEGER *version;
|
||||
X509_ALGOR *sig_alg;
|
||||
X509_NAME *issuer;
|
||||
ASN1_TIME *lastUpdate;
|
||||
ASN1_TIME *nextUpdate;
|
||||
struct stack_st_X509_REVOKED *revoked;
|
||||
struct stack_st_X509_EXTENSION *extensions;
|
||||
ASN1_ENCODING enc;
|
||||
} X509_CRL_INFO;
|
||||
|
||||
struct X509_crl_st {
|
||||
|
||||
X509_CRL_INFO *crl;
|
||||
X509_ALGOR *sig_alg;
|
||||
ASN1_BIT_STRING *signature;
|
||||
int references;
|
||||
int flags;
|
||||
|
||||
AUTHORITY_KEYID *akid;
|
||||
ISSUING_DIST_POINT *idp;
|
||||
|
||||
int idp_flags;
|
||||
int idp_reasons;
|
||||
|
||||
ASN1_INTEGER *crl_number;
|
||||
ASN1_INTEGER *base_crl_number;
|
||||
|
||||
unsigned char sha1_hash[20];
|
||||
|
||||
struct stack_st_GENERAL_NAMES *issuers;
|
||||
const X509_CRL_METHOD *meth;
|
||||
void *meth_data;
|
||||
};
|
||||
|
||||
struct stack_st_X509_CRL {
|
||||
_STACK stack;
|
||||
};
|
||||
|
||||
X509 *X509_new(void);
|
||||
void X509_free(X509 *a);
|
||||
|
||||
X509_STORE *X509_STORE_new(void);
|
||||
void X509_STORE_free(X509_STORE *v);
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber;
|
||||
|
||||
|
||||
use Cijber\OpenSSL\Instance;
|
||||
use FFI;
|
||||
|
||||
/**
|
||||
* Class OpenSSL
|
||||
* @package Cijber
|
||||
*/
|
||||
class OpenSSL
|
||||
{
|
||||
private static ?Instance $instance = null;
|
||||
private static ?FFI $stdLib = null;
|
||||
|
||||
/**
|
||||
* Get an OpenSSL instance which holds the FFI object,
|
||||
* And initializes OpenSSL and frees when destructed
|
||||
*
|
||||
* @return Instance
|
||||
*/
|
||||
static function getInstance(): Instance
|
||||
{
|
||||
if (static::$instance === null) {
|
||||
static::$instance = new Instance();
|
||||
static::$instance->init();
|
||||
}
|
||||
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
public static function getFFI(): FFI
|
||||
{
|
||||
return static::getInstance()->getFFI();
|
||||
}
|
||||
|
||||
public static function getStdLib(): FFI
|
||||
{
|
||||
if (static::$stdLib === null) {
|
||||
static::$stdLib = FFI::cdef("void* malloc (size_t size);", "libc.so.6");
|
||||
}
|
||||
|
||||
return static::$stdLib;
|
||||
}
|
||||
|
||||
public static function malloc(int $size): FFI\CData
|
||||
{
|
||||
return static::getStdLib()->malloc($size);
|
||||
}
|
||||
}
|
@ -0,0 +1,320 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL;
|
||||
|
||||
|
||||
use Cijber\OpenSSL;
|
||||
use Cijber\OpenSSL\C\CBackedObjectWithOwner;
|
||||
use RuntimeException;
|
||||
|
||||
class BIO extends CBackedObjectWithOwner
|
||||
{
|
||||
const CTRL_RESET = 1;
|
||||
const CTRL_EOF = 2;
|
||||
const CTRL_INFO = 3;
|
||||
const CTRL_SET = 4;
|
||||
const CTRL_GET = 5;
|
||||
const CTRL_PUSH = 6;
|
||||
const CTRL_POP = 7;
|
||||
const CTRL_GET_CLOSE = 8;
|
||||
const CTRL_SET_CLOSE = 9;
|
||||
const CTRL_PENDING = 10;
|
||||
const CTRL_FLUSH = 11;
|
||||
const CTRL_DUP = 12;
|
||||
const CTRL_WPENDING = 13;
|
||||
const CTRL_SET_CALLBACK = 14;
|
||||
const CTRL_GET_CALLBACK = 15;
|
||||
const CTRL_SET_FILENAME = 30;
|
||||
const CTRL_DGRAM_CONNECT = 31;
|
||||
const CTRL_DGRAM_SET_CONNECTED = 32;
|
||||
const CTRL_DGRAM_SET_RECV_TIMEOUT = 33;
|
||||
const CTRL_DGRAM_GET_RECV_TIMEOUT = 34;
|
||||
const CTRL_DGRAM_SET_SEND_TIMEOUT = 35;
|
||||
const CTRL_DGRAM_GET_SEND_TIMEOUT = 36;
|
||||
const CTRL_DGRAM_GET_RECV_TIMER_EXP = 37;
|
||||
const CTRL_DGRAM_GET_SEND_TIMER_EXP = 38;
|
||||
const CTRL_DGRAM_MTU_DISCOVER = 39;
|
||||
const CTRL_DGRAM_QUERY_MTU = 40;
|
||||
const CTRL_DGRAM_GET_FALLBACK_MTU = 47;
|
||||
const CTRL_DGRAM_GET_MTU = 41;
|
||||
const CTRL_DGRAM_SET_MTU = 42;
|
||||
const CTRL_DGRAM_MTU_EXCEEDED = 43;
|
||||
const CTRL_DGRAM_GET_PEER = 46;
|
||||
const CTRL_DGRAM_SET_PEER = 44;
|
||||
const CTRL_DGRAM_SET_NEXT_TIMEOUT = 45;
|
||||
|
||||
const C_SET_CONNECT = 100;
|
||||
const C_DO_STATE_MACHINE = 101;
|
||||
const C_SET_NBIO = 102;
|
||||
const C_SET_PROXY_PARAM = 103;
|
||||
const C_SET_FD = 104;
|
||||
const C_GET_FD = 105;
|
||||
const C_SET_FILE_PTR = 106;
|
||||
const C_GET_FILE_PTR = 107;
|
||||
const C_SET_FILENAME = 108;
|
||||
const C_SET_SSL = 109;
|
||||
const C_GET_SSL = 110;
|
||||
const C_SET_MD = 111;
|
||||
const C_GET_MD = 112;
|
||||
const C_GET_CIPHER_STATUS = 113;
|
||||
const C_SET_BUF_MEM = 114;
|
||||
const C_GET_BUF_MEM_PTR = 115;
|
||||
const C_GET_BUFF_NUM_LINES = 116;
|
||||
const C_SET_BUFF_SIZE = 117;
|
||||
const C_SET_ACCEPT = 118;
|
||||
const C_SSL_MODE = 119;
|
||||
const C_GET_MD_CTX = 120;
|
||||
const C_GET_PROXY_PARAM = 121;
|
||||
/**
|
||||
* data to read first
|
||||
*/
|
||||
const C_SET_BUFF_READ_DATA = 122;
|
||||
const C_GET_CONNECT = 123;
|
||||
const C_GET_ACCEPT = 124;
|
||||
const C_SET_SSL_RENEGOTIATE_BYTES = 125;
|
||||
const C_GET_SSL_NUM_RENEGOTIATES = 126;
|
||||
const C_SET_SSL_RENEGOTIATE_TIMEOUT = 127;
|
||||
const C_FILE_SEEK = 128;
|
||||
const C_GET_CIPHER_CTX = 129;
|
||||
/**
|
||||
* return end of input value
|
||||
*/
|
||||
const C_SET_BUF_MEM_EOF_RETURN = 130;
|
||||
const C_SET_BIND_MODE = 131;
|
||||
const C_GET_BIND_MODE = 132;
|
||||
const C_FILE_TELL = 133;
|
||||
const C_GET_SOCKS = 134;
|
||||
const C_SET_SOCKS = 135;
|
||||
/**
|
||||
* for BIO_s_bio
|
||||
*/
|
||||
const C_SET_WRITE_BUF_SIZE = 136;
|
||||
const C_GET_WRITE_BUF_SIZE = 137;
|
||||
const C_MAKE_BIO_PAIR = 138;
|
||||
const C_DESTROY_BIO_PAIR = 139;
|
||||
const C_GET_WRITE_GUARANTEE = 140;
|
||||
const C_GET_READ_REQUEST = 141;
|
||||
const C_SHUTDOWN_WR = 142;
|
||||
const C_NREAD0 = 143;
|
||||
const C_NREAD = 144;
|
||||
const C_NWRITE0 = 145;
|
||||
const C_NWRITE = 146;
|
||||
const C_RESET_READ_REQUEST = 147;
|
||||
const C_SET_MD_CTX = 148;
|
||||
const C_SET_PREFIX = 149;
|
||||
const C_GET_PREFIX = 150;
|
||||
const C_SET_SUFFIX = 151;
|
||||
const C_GET_SUFFIX = 152;
|
||||
const C_SET_EX_ARG = 153;
|
||||
const C_GET_EX_ARG = 154;
|
||||
|
||||
|
||||
const TYPE_NONE = 0;
|
||||
const TYPE_MEM = (1 | 0x0400);
|
||||
const TYPE_FILE = (2 | 0x0400);
|
||||
const TYPE_FD = (4 | 0x0400 | 0x0100);
|
||||
const TYPE_SOCKET = (5 | 0x0400 | 0x0100);
|
||||
const TYPE_NULL = (6 | 0x0400);
|
||||
const TYPE_SSL = (7 | 0x0200);
|
||||
/**
|
||||
* passive filter
|
||||
*/
|
||||
const TYPE_MD = (8 | 0x0200);
|
||||
/**
|
||||
* filter
|
||||
*/
|
||||
const TYPE_BUFFER = (9 | 0x0200);
|
||||
/**
|
||||
* filter
|
||||
*/
|
||||
const TYPE_CIPHER = (10 | 0x0200);
|
||||
/**
|
||||
* filter
|
||||
*/
|
||||
const TYPE_BASE64 = (11 | 0x0200);
|
||||
|
||||
/**
|
||||
* socket - connect
|
||||
*/
|
||||
const TYPE_CONNECT = (12 | 0x0400 | 0x0100);
|
||||
/**
|
||||
* socket for accept
|
||||
*/
|
||||
const TYPE_ACCEPT = (13 | 0x0400 | 0x0100);
|
||||
/**
|
||||
* client proxy BIO
|
||||
*/
|
||||
const TYPE_PROXY_CLIENT = (14 | 0x0200);
|
||||
/**
|
||||
* server proxy BIO
|
||||
*/
|
||||
const TYPE_PROXY_SERVER = (15 | 0x0200);
|
||||
/**
|
||||
* server proxy BIO
|
||||
*/
|
||||
const TYPE_NBIO_TEST = (16 | 0x0200);
|
||||
const TYPE_NULL_FILTER = (17 | 0x0200);
|
||||
/**
|
||||
* BER -> bin filter
|
||||
*/
|
||||
const TYPE_BER = (18 | 0x0200);
|
||||
/**
|
||||
* (half a) BIO pair
|
||||
*/
|
||||
const TYPE_BIO = (19 | 0x0400);
|
||||
/**
|
||||
* filter
|
||||
*/
|
||||
const TYPE_LINEBUFFER = (20 | 0x0200);
|
||||
const TYPE_DGRAM = (21 | 0x0400 | 0x0100);
|
||||
/**
|
||||
* filter
|
||||
*/
|
||||
const TYPE_ASN1 = (22 | 0x0200);
|
||||
/**
|
||||
* filter
|
||||
*/
|
||||
const TYPE_COMP = (23 | 0x0200);
|
||||
/**
|
||||
* socket, fd, connect or accept
|
||||
*/
|
||||
const TYPE_DESCRIPTOR = 0x0100;
|
||||
const TYPE_FILTER = 0x0200;
|
||||
const TYPE_SOURCE_SINK = 0x0400;
|
||||
|
||||
/**
|
||||
* BIO_TYPE_START is the first user-allocated BIO type. No pre-defined type,
|
||||
* flag bits aside, may exceed this value.
|
||||
*/
|
||||
const TYPE_START = 128;
|
||||
|
||||
|
||||
const FLAG_READ = 0x01;
|
||||
const FLAG_WRITE = 0x02;
|
||||
const FLAG_IO_SPECIAL = 0x04;
|
||||
const FLAG_RWS = self::FLAG_READ | self::FLAG_WRITE | self::FLAG_IO_SPECIAL;
|
||||
const FLAG_SHOULD_RETRY = 0x08;
|
||||
|
||||
|
||||
public static function new()
|
||||
{
|
||||
$ffi = OpenSSL::getFFI();
|
||||
$bio = $ffi->BIO_new($ffi->BIO_s_mem());
|
||||
return new BIO($ffi, $bio);
|
||||
}
|
||||
|
||||
public static function buffer(string $data)
|
||||
{
|
||||
$ffi = OpenSSL::getFFI();
|
||||
$bio = $ffi->BIO_new_mem_buf($data, strlen($data));
|
||||
return new BIO($ffi, $bio);
|
||||
}
|
||||
|
||||
public static function open($fileName, $flags)
|
||||
{
|
||||
$ffi = OpenSSL::getFFI();
|
||||
$bio = $ffi->BIO_new_file($fileName, $flags);
|
||||
return new BIO($ffi, $bio);
|
||||
}
|
||||
|
||||
protected function freeObject()
|
||||
{
|
||||
$this->ffi->BIO_free($this->cObj);
|
||||
}
|
||||
|
||||
function write(string $data): int
|
||||
{
|
||||
$len = $this->ffi->BIO_write($this->cObj, $data, strlen($data));
|
||||
if ($len === -2) {
|
||||
throw new RuntimeException("Can't wrote to this BIO");
|
||||
}
|
||||
|
||||
if ($len === 0 || $len === -1) {
|
||||
if ($this->cObj->flags & self::FLAG_SHOULD_RETRY) {
|
||||
return $len;
|
||||
}
|
||||
|
||||
throw new RuntimeException("Error occured while reading BIO");
|
||||
}
|
||||
|
||||
return $len;
|
||||
}
|
||||
|
||||
function getType(): int
|
||||
{
|
||||
return $this->ffi->BIO_method_type($this->cObj);
|
||||
}
|
||||
|
||||
function read(int $chunkSize = 4096): string
|
||||
{
|
||||
$data = OpenSSL\C\Memory::new($chunkSize);
|
||||
$len = $this->ffi->BIO_read($this->cObj, $data->get(), $chunkSize);
|
||||
if ($len === -2) {
|
||||
throw new RuntimeException("Can't read from this BIO");
|
||||
}
|
||||
|
||||
if ($len === 0 || $len === -1) {
|
||||
if ($this->cObj->flags & self::FLAG_SHOULD_RETRY) {
|
||||
return "";
|
||||
}
|
||||
|
||||
throw new RuntimeException("Error occured while reading BIO");
|
||||
}
|
||||
|
||||
return $data->string($len);
|
||||
}
|
||||
|
||||
function tell()
|
||||
{
|
||||
if (($this->getType() & self::TYPE_FILE) !== self::TYPE_FILE) {
|
||||
throw new RuntimeException("Can't tell on non-file BIO");
|
||||
}
|
||||
|
||||
$pos = (int)$this->ctrl(self::C_FILE_TELL, 0, null);
|
||||
|
||||
if ($pos === -1) {
|
||||
throw new RuntimeException("Failed to tell position in BIO");
|
||||
}
|
||||
|
||||
return $pos;
|
||||
}
|
||||
|
||||
function reset()
|
||||
{
|
||||
$res = (int)$this->ctrl(self::CTRL_RESET, 0, null);
|
||||
|
||||
if (($this->getType() & self::TYPE_FILE) === self::TYPE_FILE && $res === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($res > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("Failed to reset BIO");
|
||||
}
|
||||
|
||||
function seek(int $offset)
|
||||
{
|
||||
if (($this->getType() & self::TYPE_FILE) !== self::TYPE_FILE) {
|
||||
throw new RuntimeException("Can't seek in non-file BIO");
|
||||
}
|
||||
|
||||
$pos = (int)$this->ctrl(self::C_FILE_SEEK, $offset, null);
|
||||
|
||||
if ($pos === -1) {
|
||||
throw new RuntimeException("Failed seeking in BIO");
|
||||
}
|
||||
}
|
||||
|
||||
function eof(): bool
|
||||
{
|
||||
return (int)$this->ctrl(self::CTRL_EOF, 0, null) === 1;
|
||||
}
|
||||
|
||||
function ctrl($prop, ?int $larg, $parg)
|
||||
{
|
||||
return $this->ffi->BIO_ctrl($this->cObj, $prop, $larg, $parg);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL\C;
|
||||
|
||||
|
||||
use FFI;
|
||||
use FFI\CData;
|
||||
|
||||
class CBackedObject
|
||||
{
|
||||
protected CData $cObj;
|
||||
protected bool $freed = false;
|
||||
|
||||
/**
|
||||
* CBackedObject constructor.
|
||||
* @param CData $cObj
|
||||
*/
|
||||
protected function __construct(CData $cObj)
|
||||
{
|
||||
$this->cObj = $cObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark backing C object as freed
|
||||
*/
|
||||
public function freed()
|
||||
{
|
||||
$this->freed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free backing C object, object is useless after this operation
|
||||
*/
|
||||
public final function free()
|
||||
{
|
||||
if ($this->freed) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->freeObject();
|
||||
$this->freed();
|
||||
}
|
||||
|
||||
protected function freeObject()
|
||||
{
|
||||
FFI::free($this->cObj);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->free();
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL\C;
|
||||
|
||||
|
||||
use FFI;
|
||||
use FFI\CData;
|
||||
|
||||
class CBackedObjectWithOwner extends CBackedObject
|
||||
{
|
||||
protected FFI $ffi;
|
||||
|
||||
protected function __construct(FFI $ffi, CData $cObj)
|
||||
{
|
||||
parent::__construct($cObj);
|
||||
$this->ffi = $ffi;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL\C;
|
||||
|
||||
|
||||
use Cijber\OpenSSL;
|
||||
use FFI;
|
||||
use FFI\CData;
|
||||
|
||||
class Memory extends CBackedObject
|
||||
{
|
||||
private int $size;
|
||||
|
||||
public function __construct(int $size)
|
||||
{
|
||||
$this->size = $size;
|
||||
parent::__construct(OpenSSL::malloc($size));
|
||||
}
|
||||
|
||||
public static function new(int $chunkSize): Memory
|
||||
{
|
||||
return new Memory($chunkSize);
|
||||
}
|
||||
|
||||
public function get(): CData
|
||||
{
|
||||
return $this->cObj;
|
||||
}
|
||||
|
||||
public function string(int $length, int $offset = 0)
|
||||
{
|
||||
return substr(FFI::string($this->cObj, $length + $offset), $offset);
|
||||
}
|
||||
|
||||
public static function buffer(string $data): Memory
|
||||
{
|
||||
$len = strlen($data);
|
||||
$mem = new Memory($len);
|
||||
FFI::memcpy($mem->cObj, $data, $len);
|
||||
return $mem;
|
||||
}
|
||||
|
||||
public function pointer(): CData
|
||||
{
|
||||
return FFI::addr($this->cObj);
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL;
|
||||
|
||||
|
||||
use FFI;
|
||||
|
||||
/**
|
||||
* Holds instance of the FFI object
|
||||
* This class is also responsible for free-ing all global used resources
|
||||
* @package Cijber\OpenSSL
|
||||
*/
|
||||
class Instance
|
||||
{
|
||||
const HEADERS = [
|
||||
"openssl.h",
|
||||
"engine.h",
|
||||
"generic.h",
|
||||
"crypto.h",
|
||||
"asn1.h",
|
||||
"evp.h",
|
||||
"x509.h",
|
||||
"pkcs7.h"
|
||||
];
|
||||
|
||||
/**
|
||||
* @var FFI
|
||||
*/
|
||||
private ?FFI $ffi = null;
|
||||
|
||||
|
||||
/**
|
||||
* Load FFI object based on header file located in resources/openssl.h
|
||||
*/
|
||||
public function load()
|
||||
{
|
||||
$code = "";
|
||||
$lineCounter = 0;
|
||||
$lines = [];
|
||||
|
||||
foreach (static::HEADERS as $header) {
|
||||
$lines[$header] = $lineCounter;
|
||||
$code .= file_get_contents(__DIR__ . "/../../resources/" . $header);
|
||||
$code .= "\n";
|
||||
$lineCounter = count(explode("\n", $code));
|
||||
}
|
||||
|
||||
$this->ffi = FFI::cdef($code, "libcrypto.so");
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
$this->load();
|
||||
$this->ffi->ERR_load_crypto_strings();
|
||||
$this->ffi->OPENSSL_add_all_algorithms_conf();
|
||||
$this->ffi->OPENSSL_config(null);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->ffi === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->ffi->EVP_cleanup();
|
||||
$this->ffi->CRYPTO_cleanup_all_ex_data();
|
||||
$this->ffi->ERR_free_strings();
|
||||
}
|
||||
|
||||
public function getFFI(): FFI
|
||||
{
|
||||
return $this->ffi;
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL;
|
||||
|
||||
|
||||
use Cijber\OpenSSL;
|
||||
use Cijber\OpenSSL\C\Memory;
|
||||
use FFI;
|
||||
|
||||
class PKCS7 extends OpenSSL\C\CBackedObjectWithOwner
|
||||
{
|
||||
/**
|
||||
* NID_pkcs7
|
||||
*/
|
||||
const NID = 20;
|
||||
const NID_DATA = 21;
|
||||
const NID_SIGNED = 22;
|
||||
const NID_ENVELOPED = 23;
|
||||
const NID_SIGNED_AND_ENVELOPED = 24;
|
||||
const NID_DIGEST = 25;
|
||||
const NID_ENCRYPTED = 26;
|
||||
|
||||
/**
|
||||
* Verify with NID_ consts defined in Cijber\OpenSSL\PKCS7
|
||||
* @return int
|
||||
*/
|
||||
public function getType(): int
|
||||
{
|
||||
return $this->ffi->OBJ_obj2nid($this->cObj->type);
|
||||
}
|
||||
|
||||
public function verify(string $plain): bool
|
||||
{
|
||||
$type = $this->getType();
|
||||
if (!in_array($type, [PKCS7::NID_DIGEST, self::NID_SIGNED, self::NID_SIGNED_AND_ENVELOPED])) {
|
||||
throw new \RuntimeException("Can only verify signed or digested data");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function freeObject()
|
||||
{
|
||||
$this->ffi->PKCS7_free($this->cObj);
|
||||
}
|
||||
|
||||
public static function new(): PKCS7
|
||||
{
|
||||
$ffi = OpenSSL::getFFI();
|
||||
$cObj = $ffi->PKCS7_new();
|
||||
return new PKCS7($ffi, $cObj);
|
||||
}
|
||||
|
||||
public static function loadFromDER(string $der): PKCS7
|
||||
{
|
||||
$pkcs = static::new();
|
||||
$pkcs->loadDER($der);
|
||||
return $pkcs;
|
||||
}
|
||||
|
||||
private function loadDER(string $der)
|
||||
{
|
||||
$derLen = strlen($der);
|
||||
$mem = Memory::buffer($der);
|
||||
$this->ffi->d2i_PKCS7(FFI::addr($this->cObj), $mem->pointer(), $derLen);
|
||||
$mem->freed();
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL;
|
||||
|
||||
|
||||
use Cijber\OpenSSL;
|
||||
use Cijber\OpenSSL\C\CBackedObjectWithOwner;
|
||||
|
||||
class X509 extends CBackedObjectWithOwner
|
||||
{
|
||||
public static function new(): X509
|
||||
{
|
||||
$ffi = OpenSSL::getFFI();
|
||||
$x509 = $ffi->X509_new();
|
||||
return new X509($ffi, $x509);
|
||||
}
|
||||
|
||||
public function freeObject()
|
||||
{
|
||||
$this->ffi->X509_free($this->cObj);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL;
|
||||
|
||||
|
||||
use Cijber\OpenSSL;
|
||||
use Cijber\OpenSSL\C\CBackedObjectWithOwner;
|
||||
|
||||
class X509Store extends CBackedObjectWithOwner
|
||||
{
|
||||
public static function new(): X509Store
|
||||
{
|
||||
$ffi = OpenSSL::getFFI();
|
||||
$x509 = $ffi->X509_STORE_new();
|
||||
return new X509Store($ffi, $x509);
|
||||
}
|
||||
|
||||
public function freeObject()
|
||||
{
|
||||
$this->ffi->X509_STORE_free($this->cObj);
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL\Tests;
|
||||
|
||||
|
||||
use Cijber\OpenSSL\BIO;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class BIOTest extends TestCase
|
||||
{
|
||||
public function testCreationAndDestruction()
|
||||
{
|
||||
$bio = BIO::new();
|
||||
$this->assertEquals(11, $bio->write("Hello world"));
|
||||
$this->assertEquals("Hello world", $bio->read());
|
||||
$bio->write("Hello world");
|
||||
$bio->reset();
|
||||
$this->assertEquals('', $bio->read());
|
||||
}
|
||||
|
||||
public function testOpen()
|
||||
{
|
||||
$bio = BIO::open(__DIR__ . "/data/pkcs7/1.SF", "r");
|
||||
$part = $bio->read(5);
|
||||
$this->assertEquals("Signa", $part);
|
||||
$this->assertEquals(5, $bio->tell());
|
||||
$bio->seek(6);
|
||||
$this->assertEquals(6, $bio->tell());
|
||||
$part = $bio->read(3);
|
||||
$this->assertEquals("ure", $part);
|
||||
$bio->reset();
|
||||
$this->assertEquals(0, $bio->tell());
|
||||
}
|
||||
|
||||
public function testBuffer()
|
||||
{
|
||||
$bio = BIO::buffer("Hello world");
|
||||
$this->assertEquals("Hello world", $bio->read());
|
||||
$this->assertTrue($bio->eof());
|
||||
$bio->reset();
|
||||
$part = $bio->read(3);
|
||||
$this->assertEquals("Hel", $part);
|
||||
$this->assertEquals("lo", $bio->read(2));
|
||||
$bio->reset();
|
||||
$part = $bio->read(3);
|
||||
$this->assertEquals("Hel", $part);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL\Tests;
|
||||
|
||||
|
||||
use Cijber\OpenSSL;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class OpenSSLTest extends TestCase
|
||||
{
|
||||
public function testInit()
|
||||
{
|
||||
$this->expectNotToPerformAssertions();
|
||||
OpenSSL::getInstance();
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Cijber\OpenSSL\Tests;
|
||||
|
||||
use Cijber\OpenSSL\PKCS7;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class PKCS7Test extends TestCase
|
||||
{
|
||||
public function testCreationAndDestruction()
|
||||
{
|
||||
$this->expectNotToPerformAssertions();
|
||||
$pkcs7 = PKCS7::new();
|
||||
unset($pkcs7);
|
||||
}
|
||||
|
||||
public function testLoadDER() {
|
||||
$der = file_get_contents(__DIR__ . "/data/pkcs7/1.RSA");
|
||||
$pkcs7 = PKCS7::loadFromDER($der);
|
||||
$this->assertEquals(PKCS7::NID_SIGNED, $pkcs7->getType());
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL\Tests;
|
||||
|
||||
|
||||
use Cijber\OpenSSL\X509Store;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class X509StoreTest extends TestCase
|
||||
{
|
||||
function testCreationAndDestruction()
|
||||
{
|
||||
$this->expectNotToPerformAssertions();
|
||||
X509Store::new();
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Cijber\OpenSSL\Tests;
|
||||
|
||||
|
||||
use Cijber\OpenSSL\X509;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class X509Test extends TestCase
|
||||
{
|
||||
function testCreationAndDestruction() {
|
||||
$this->expectNotToPerformAssertions();
|
||||
X509::new();
|
||||
}
|
||||
}
|
Binary file not shown.
@ -0,0 +1,8 @@
|
||||
Signature-Version: 1.0
|
||||
SHA1-Digest-Manifest-Main-Attributes: RsH+8ih8p183k9Q4ABmKLR6jIHo=
|
||||
SHA1-Digest-Manifest: J7qj3my1C0KOZy2YdxpoU2ZmK5o=
|
||||
Created-By: 1.8.0_121 (Oracle Corporation)
|
||||
|
||||
Name: index-v1.json
|
||||
SHA1-Digest: alc1Iq9v5FcKXgyckS9Cha3eibo=
|
||||
|
Loading…
Reference in New Issue