mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-07 00:46:17 +08:00
add sdf and skf
This commit is contained in:
@@ -76,7 +76,7 @@ extern "C" {
|
||||
|
||||
typedef struct {
|
||||
uint32_t rk[4 * (AES_MAX_ROUNDS + 1)];
|
||||
int rounds;
|
||||
size_t rounds;
|
||||
} AES_KEY;
|
||||
|
||||
int aes_set_encrypt_key(AES_KEY *aes_key, const uint8_t *key, size_t keylen);
|
||||
|
||||
@@ -54,15 +54,24 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define error_print(fmt, args...) \
|
||||
fprintf(stderr, "error: %s %d: %s: " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ##args)
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
#define error_print() \
|
||||
do { if (DEBUG) fprintf(stderr, "%s:%d:%s():\n",__FILE__, __LINE__, __func__); } while (0)
|
||||
|
||||
#define error_print_msg(fmt, ...) \
|
||||
do { if (DEBUG) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, __VA_ARGS__); } while (0)
|
||||
|
||||
#define error_puts(str) \
|
||||
do { if (DEBUG) fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, __func__, str); } while (0)
|
||||
|
||||
|
||||
void print_der(const uint8_t *in, size_t inlen);
|
||||
void print_bytes(const uint8_t *in, size_t inlen);
|
||||
void print_nodes(const uint32_t *in, size_t inlen);
|
||||
|
||||
@@ -109,8 +109,6 @@ int hash_drbg_generate(HASH_DRBG *drbg,
|
||||
const uint8_t *additional, size_t additional_len,
|
||||
size_t outlen, uint8_t *out);
|
||||
|
||||
void hash_drbg_cleanup(HASH_DRBG *drbg);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -50,32 +50,33 @@
|
||||
#ifndef GMSSL_MD5_H
|
||||
#define GMSSL_MD5_H
|
||||
|
||||
#define MD5_IS_BIG_ENDIAN 0
|
||||
|
||||
#define MD5_DIGEST_SIZE 16
|
||||
#define MD5_BLOCK_SIZE 64
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define MD5_IS_BIG_ENDIAN 0
|
||||
|
||||
#define MD5_DIGEST_SIZE 16
|
||||
#define MD5_BLOCK_SIZE 64
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t state[4];
|
||||
uint64_t nblocks; /* num of processed blocks */
|
||||
unsigned char block[64]; /* buffer */
|
||||
int num; /* buffered bytes in |block| */
|
||||
uint8_t block[64]; /* buffer */
|
||||
size_t num; /* buffered bytes in |block| */
|
||||
} MD5_CTX;
|
||||
|
||||
|
||||
void md5_init(MD5_CTX *ctx);
|
||||
void md5_update(MD5_CTX *ctx, const uint8_t* data, size_t datalen);
|
||||
void md5_update(MD5_CTX *ctx, const uint8_t *data, size_t datalen);
|
||||
void md5_finish(MD5_CTX *ctx, uint8_t dgst[MD5_DIGEST_SIZE]);
|
||||
void md5_compress(uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE]);
|
||||
void md5_digest(const uint8_t *data, size_t datalen, uint8_t dgst[MD5_DIGEST_SIZE]);
|
||||
|
||||
|
||||
|
||||
@@ -49,28 +49,26 @@
|
||||
#ifndef GMSSL_PBKDF2_H
|
||||
#define GMSSL_PBKDF2_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <gmssl/hmac.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define PBKDF2_MIN_ITER 10000
|
||||
#define PBKDF2_MIN_SALT_SIZE 64
|
||||
#define PBKDF2_DEFAULT_SALT_SIZE 8
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
int pbkdf2_genkey(const DIGEST *digest,
|
||||
const char *pass, size_t passlen,
|
||||
const uint8_t *salt, size_t saltlen,
|
||||
unsigned int count, size_t outlen, uint8_t *out);
|
||||
|
||||
size_t count, size_t outlen, uint8_t *out);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -49,10 +49,10 @@
|
||||
#ifndef GMSSL_PKCS8_H
|
||||
#define GMSSL_PKCS8_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/pem.h>
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// EncryptedPrivateKeyInfo
|
||||
int sm2_enced_private_key_info_to_der(const SM2_KEY *key, const char *pass, uint8_t **out, size_t *outlen);
|
||||
int sm2_enced_private_key_info_from_der(SM2_KEY *key, const uint8_t **attrs, size_t *attrslen, const char *pass, const uint8_t **in, size_t *inlen);
|
||||
@@ -160,7 +161,6 @@ int pkcs8_enced_private_key_info_from_der(
|
||||
const uint8_t **in, size_t *inlen);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -46,38 +46,36 @@
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GMSSL_SHA1_H
|
||||
#define GMSSL_SHA1_H
|
||||
|
||||
#define SHA1_IS_BIG_ENDIAN 1
|
||||
|
||||
#define SHA1_DIGEST_LENGTH 20
|
||||
#define SHA1_BLOCK_SIZE 64
|
||||
#define SHA1_STATE_WORDS (SHA1_DIGEST_LENGTH/sizeof(uint32_t))
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define SHA1_IS_BIG_ENDIAN 1
|
||||
|
||||
#define SHA1_DIGEST_SIZE 20
|
||||
#define SHA1_BLOCK_SIZE 64
|
||||
#define SHA1_STATE_WORDS (SHA1_DIGEST_SIZE/sizeof(uint32_t))
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t state[SHA1_STATE_WORDS];
|
||||
uint64_t nblocks; /* num of processed blocks */
|
||||
uint8_t block[SHA1_BLOCK_SIZE]; /* buffer */
|
||||
int num; /* buffered bytes in |block| */
|
||||
size_t num; /* buffered bytes in |block| */
|
||||
} SHA1_CTX;
|
||||
|
||||
void sha1_init(SHA1_CTX *ctx);
|
||||
void sha1_update(SHA1_CTX *ctx, const uint8_t *data, size_t datalen);
|
||||
void sha1_finish(SHA1_CTX *ctx, uint8_t dgst[SHA1_DIGEST_LENGTH]);
|
||||
void sha1_compress(uint32_t state[SHA1_STATE_WORDS], const uint8_t block[SHA1_BLOCK_SIZE]);
|
||||
void sha1_digest(const uint8_t *data, size_t datalen, uint8_t dgst[SHA1_DIGEST_LENGTH]);
|
||||
void sha1_finish(SHA1_CTX *ctx, uint8_t dgst[SHA1_DIGEST_SIZE]);
|
||||
void sha1_digest(const uint8_t *data, size_t datalen, uint8_t dgst[SHA1_DIGEST_SIZE]);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -50,24 +50,6 @@
|
||||
#ifndef GMSSL_SHA2_H
|
||||
#define GMSSL_SHA2_H
|
||||
|
||||
#define SHA2_IS_BIG_ENDIAN 1
|
||||
|
||||
#define SHA224_DIGEST_SIZE 28
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
#define SHA384_DIGEST_SIZE 48
|
||||
#define SHA512_DIGEST_SIZE 64
|
||||
|
||||
#define SHA224_BLOCK_SIZE 64
|
||||
#define SHA256_BLOCK_SIZE 64
|
||||
#define SHA384_BLOCK_SIZE 128
|
||||
#define SHA512_BLOCK_SIZE 128
|
||||
|
||||
#define SHA224_STATE_WORDS 8
|
||||
#define SHA256_STATE_WORDS 8
|
||||
#define SHA384_STATE_WORDS 8
|
||||
#define SHA512_STATE_WORDS 8
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
@@ -77,6 +59,13 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define SHA2_IS_BIG_ENDIAN 1
|
||||
|
||||
|
||||
#define SHA224_DIGEST_SIZE 28
|
||||
#define SHA224_BLOCK_SIZE 64
|
||||
#define SHA224_STATE_WORDS 8
|
||||
|
||||
typedef struct {
|
||||
uint32_t state[SHA224_STATE_WORDS];
|
||||
uint64_t nblocks;
|
||||
@@ -87,10 +76,14 @@ typedef struct {
|
||||
void sha224_init(SHA224_CTX *ctx);
|
||||
void sha224_update(SHA224_CTX *ctx, const unsigned char* data, size_t datalen);
|
||||
void sha224_finish(SHA224_CTX *ctx, unsigned char dgst[SHA224_DIGEST_SIZE]);
|
||||
void sha224_compress(uint32_t dgst[8], const unsigned char block[SHA224_BLOCK_SIZE]);
|
||||
void sha224_digest(const unsigned char *data, size_t datalen,
|
||||
unsigned char dgst[SHA224_DIGEST_SIZE]);
|
||||
|
||||
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
#define SHA256_BLOCK_SIZE 64
|
||||
#define SHA256_STATE_WORDS 8
|
||||
|
||||
typedef struct {
|
||||
uint32_t state[8];
|
||||
uint64_t nblocks;
|
||||
@@ -101,10 +94,14 @@ typedef struct {
|
||||
void sha256_init(SHA256_CTX *ctx);
|
||||
void sha256_update(SHA256_CTX *ctx, const unsigned char* data, size_t datalen);
|
||||
void sha256_finish(SHA256_CTX *ctx, unsigned char dgst[SHA256_DIGEST_SIZE]);
|
||||
void sha256_compress(uint32_t dgst[8], const unsigned char block[SHA256_BLOCK_SIZE]);
|
||||
void sha256_digest(const unsigned char *data, size_t datalen,
|
||||
unsigned char dgst[SHA256_DIGEST_SIZE]);
|
||||
|
||||
|
||||
#define SHA384_DIGEST_SIZE 48
|
||||
#define SHA384_BLOCK_SIZE 128
|
||||
#define SHA384_STATE_WORDS 8
|
||||
|
||||
typedef struct {
|
||||
uint64_t state[8];
|
||||
uint64_t nblocks;
|
||||
@@ -115,10 +112,14 @@ typedef struct {
|
||||
void sha384_init(SHA384_CTX *ctx);
|
||||
void sha384_update(SHA384_CTX *ctx, const unsigned char* data, size_t datalen);
|
||||
void sha384_finish(SHA384_CTX *ctx, unsigned char dgst[SHA384_DIGEST_SIZE]);
|
||||
void sha384_compress(uint64_t dgst[8], const unsigned char block[SHA384_BLOCK_SIZE]);
|
||||
void sha384_digest(const unsigned char *data, size_t datalen,
|
||||
unsigned char dgst[SHA384_DIGEST_SIZE]);
|
||||
|
||||
|
||||
#define SHA512_DIGEST_SIZE 64
|
||||
#define SHA512_BLOCK_SIZE 128
|
||||
#define SHA512_STATE_WORDS 8
|
||||
|
||||
typedef struct {
|
||||
uint64_t state[8];
|
||||
uint64_t nblocks;
|
||||
@@ -129,7 +130,6 @@ typedef struct {
|
||||
void sha512_init(SHA512_CTX *ctx);
|
||||
void sha512_update(SHA512_CTX *ctx, const unsigned char* data, size_t datalen);
|
||||
void sha512_finish(SHA512_CTX *ctx, unsigned char dgst[SHA512_DIGEST_SIZE]);
|
||||
void sha512_compress(uint64_t dgst[8], const unsigned char block[SHA512_BLOCK_SIZE]);
|
||||
void sha512_digest(const unsigned char *data, size_t datalen,
|
||||
unsigned char dgst[SHA512_DIGEST_SIZE]);
|
||||
|
||||
|
||||
@@ -49,34 +49,32 @@
|
||||
#ifndef GMSSL_SM3_H
|
||||
#define GMSSL_SM3_H
|
||||
|
||||
#define SM3_IS_BIG_ENDIAN 1
|
||||
|
||||
#define SM3_DIGEST_SIZE 32
|
||||
#define SM3_BLOCK_SIZE 64
|
||||
#define SM3_STATE_WORDS 8
|
||||
#define SM3_HMAC_SIZE (SM3_DIGEST_SIZE)
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define SM3_IS_BIG_ENDIAN 1
|
||||
|
||||
#define SM3_DIGEST_SIZE 32
|
||||
#define SM3_BLOCK_SIZE 64
|
||||
#define SM3_STATE_WORDS 8
|
||||
#define SM3_HMAC_SIZE (SM3_DIGEST_SIZE)
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t digest[SM3_STATE_WORDS];
|
||||
uint64_t nblocks;
|
||||
uint8_t block[SM3_BLOCK_SIZE];
|
||||
int num;
|
||||
size_t num;
|
||||
} SM3_CTX;
|
||||
|
||||
void sm3_init(SM3_CTX *ctx);
|
||||
void sm3_update(SM3_CTX *ctx, const uint8_t *data, size_t datalen);
|
||||
void sm3_finish(SM3_CTX *ctx, uint8_t dgst[SM3_DIGEST_SIZE]);
|
||||
void sm3_compress(uint32_t dgst[SM3_STATE_WORDS], const uint8_t block[SM3_BLOCK_SIZE]);
|
||||
void sm3_digest(const uint8_t *data, size_t datalen, uint8_t dgst[SM3_DIGEST_SIZE]);
|
||||
|
||||
|
||||
@@ -88,12 +86,10 @@ typedef struct {
|
||||
void sm3_hmac_init(SM3_HMAC_CTX *ctx, const uint8_t *key, size_t keylen);
|
||||
void sm3_hmac_update(SM3_HMAC_CTX *ctx, const uint8_t *data, size_t datalen);
|
||||
void sm3_hmac_finish(SM3_HMAC_CTX *ctx, uint8_t mac[SM3_HMAC_SIZE]);
|
||||
void sm3_hmac_reset(SM3_HMAC_CTX *ctx);
|
||||
void sm3_hmac(const uint8_t *key, size_t keylen,
|
||||
const uint8_t *data, size_t datalen,
|
||||
uint8_t mac[SM3_HMAC_SIZE]);
|
||||
|
||||
int sm3_hmac_finish_and_verify(SM3_HMAC_CTX *ctx, const uint8_t mac[SM3_HMAC_SIZE]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -701,6 +701,9 @@ int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGES
|
||||
|
||||
|
||||
|
||||
int tls_shutdown(TLS_CONNECT *conn);
|
||||
|
||||
|
||||
#define tls_trace printf
|
||||
|
||||
|
||||
|
||||
@@ -49,9 +49,20 @@
|
||||
#ifndef GMSSL_ZUC_H
|
||||
#define GMSSL_ZUC_H
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
# define ZUC_KEY_SIZE 16
|
||||
# define ZUC_IV_SIZE 16
|
||||
# define ZUC_MAC_SIZE 4
|
||||
|
||||
typedef uint32_t ZUC_BIT;
|
||||
typedef uint32_t ZUC_UINT5;
|
||||
typedef uint8_t ZUC_UINT6;
|
||||
@@ -59,76 +70,68 @@ typedef uint32_t ZUC_UINT15;
|
||||
typedef uint32_t ZUC_UINT31;
|
||||
typedef uint32_t ZUC_UINT32;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
# define ZUC_KEY_LENGTH 16
|
||||
# define ZUC_IV_LENGTH 16
|
||||
# define ZUC_MAC_LENGTH 4
|
||||
|
||||
|
||||
typedef struct ZUC_KEY_st {
|
||||
ZUC_UINT31 LFSR[16];
|
||||
ZUC_UINT32 R1;
|
||||
ZUC_UINT32 R2;
|
||||
} ZUC_KEY;
|
||||
|
||||
void zuc_set_key(ZUC_KEY *key, const unsigned char user_key[16], const unsigned char iv[16]);
|
||||
void zuc_set_key(ZUC_KEY *key, const uint8_t user_key[16], const uint8_t iv[16]);
|
||||
void zuc_generate_keystream(ZUC_KEY *key, size_t nwords, ZUC_UINT32 *words);
|
||||
ZUC_UINT32 zuc_generate_keyword(ZUC_KEY *key);
|
||||
|
||||
|
||||
typedef struct ZUC_MAC_CTX_st {
|
||||
ZUC_UINT31 LFSR[16];
|
||||
ZUC_UINT32 R1;
|
||||
ZUC_UINT32 R2;
|
||||
ZUC_UINT32 T;
|
||||
ZUC_UINT32 K0;
|
||||
unsigned char buf[4];
|
||||
int buflen;
|
||||
uint8_t buf[4];
|
||||
size_t buflen;
|
||||
} ZUC_MAC_CTX;
|
||||
|
||||
void zuc_mac_init(ZUC_MAC_CTX *ctx, const unsigned char key[16], const unsigned char iv[16]);
|
||||
void zuc_mac_update(ZUC_MAC_CTX *ctx, const unsigned char *data, size_t len);
|
||||
void zuc_mac_finish(ZUC_MAC_CTX *ctx, const unsigned char *data, size_t nbits, unsigned char mac[4]);
|
||||
void zuc_mac_init(ZUC_MAC_CTX *ctx, const uint8_t key[16], const uint8_t iv[16]);
|
||||
void zuc_mac_update(ZUC_MAC_CTX *ctx, const uint8_t *data, size_t len);
|
||||
void zuc_mac_finish(ZUC_MAC_CTX *ctx, const uint8_t *data, size_t nbits, uint8_t mac[4]);
|
||||
|
||||
void zuc_eea_encrypt(const ZUC_UINT32 *in, ZUC_UINT32 *out, size_t nbits,
|
||||
const unsigned char key[16], ZUC_UINT32 count, ZUC_UINT5 bearer,
|
||||
const uint8_t key[16], ZUC_UINT32 count, ZUC_UINT5 bearer,
|
||||
ZUC_BIT direction);
|
||||
ZUC_UINT32 zuc_eia_generate_mac(const ZUC_UINT32 *data, size_t nbits,
|
||||
const unsigned char user_key[16], ZUC_UINT32 count, ZUC_UINT5 bearer,
|
||||
const uint8_t user_key[16], ZUC_UINT32 count, ZUC_UINT5 bearer,
|
||||
ZUC_BIT direction);
|
||||
|
||||
# define ZUC256_KEY_LENGTH 32
|
||||
# define ZUC256_IV_LENGTH 23
|
||||
# define ZUC256_MAC32_LENGTH 4
|
||||
# define ZUC256_MAC64_LENGTH 8
|
||||
# define ZUC256_MAC128_LENGTH 16
|
||||
# define ZUC256_MIN_MAC_LENGTH ZUC256_MAC32_LENGTH
|
||||
# define ZUC256_MAX_MAC_LENGTH ZUC256_MAC128_LENGTH
|
||||
|
||||
# define ZUC256_KEY_SIZE 32
|
||||
# define ZUC256_IV_SIZE 23
|
||||
# define ZUC256_MAC32_SIZE 4
|
||||
# define ZUC256_MAC64_SIZE 8
|
||||
# define ZUC256_MAC128_SIZE 16
|
||||
# define ZUC256_MIN_MAC_SIZE ZUC256_MAC32_SIZE
|
||||
# define ZUC256_MAX_MAC_SIZE ZUC256_MAC128_SIZE
|
||||
|
||||
typedef ZUC_KEY ZUC256_KEY;
|
||||
|
||||
void zuc256_set_key(ZUC256_KEY *key, const unsigned char user_key[32],
|
||||
const unsigned char iv[23]);
|
||||
void zuc256_set_key(ZUC256_KEY *key, const uint8_t user_key[32], const uint8_t iv[23]);
|
||||
#define zuc256_generate_keystream(k,n,out) zuc_generate_keystream(k,n,out)
|
||||
#define zuc256_generate_keyword(k) zuc_generate_keyword(k)
|
||||
|
||||
|
||||
typedef struct ZUC256_MAC_CTX_st {
|
||||
ZUC_UINT31 LFSR[16];
|
||||
ZUC_UINT32 R1;
|
||||
ZUC_UINT32 R2;
|
||||
ZUC_UINT32 T[4];
|
||||
ZUC_UINT32 K0[4];
|
||||
unsigned char buf[4];
|
||||
uint8_t buf[4];
|
||||
int buflen;
|
||||
int macbits;
|
||||
} ZUC256_MAC_CTX;
|
||||
|
||||
void zuc256_mac_init(ZUC256_MAC_CTX *ctx, const unsigned char key[32], const unsigned char iv[23], int macbits);
|
||||
void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t len);
|
||||
void zuc256_mac_finish(ZUC256_MAC_CTX *ctx, const unsigned char *data, size_t nbits, unsigned char *mac);
|
||||
void zuc256_mac_init(ZUC256_MAC_CTX *ctx, const uint8_t key[32], const uint8_t iv[23], int macbits);
|
||||
void zuc256_mac_update(ZUC256_MAC_CTX *ctx, const uint8_t *data, size_t len);
|
||||
void zuc256_mac_finish(ZUC256_MAC_CTX *ctx, const uint8_t *data, size_t nbits, uint8_t *mac);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user