mirror of https://github.com/wolfSSL/wolfssl.git
Merge pull request #1386 from JacobBarthelmeh/RSA
add WC_RSA_NO_PADDING macro and WC_RSA_NO_PAD enumpull/1379/head^2
commit
6500c40015
|
@ -871,6 +871,23 @@ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock,
|
|||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WC_RSA_NO_PADDING
|
||||
case WC_RSA_NO_PAD:
|
||||
WOLFSSL_MSG("wolfSSL Using NO padding");
|
||||
|
||||
/* In the case of no padding being used check that input is exactly
|
||||
* the RSA key length */
|
||||
if (bits <= 0 || inputLen != ((word32)bits/WOLFSSL_BIT_SIZE)) {
|
||||
WOLFSSL_MSG("Bad input size");
|
||||
ret = RSA_PAD_E;
|
||||
}
|
||||
else {
|
||||
XMEMCPY(pkcsBlock, input, inputLen);
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
WOLFSSL_MSG("Unknown RSA Pad Type");
|
||||
ret = RSA_PAD_E;
|
||||
|
@ -1099,7 +1116,10 @@ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
|
|||
return outputLen;
|
||||
}
|
||||
|
||||
/* helper function to direct unpadding */
|
||||
/* helper function to direct unpadding
|
||||
*
|
||||
* bits is the key modulus size in bits
|
||||
*/
|
||||
static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out,
|
||||
byte padValue, int padType, enum wc_HashType hType,
|
||||
int mgf, byte* optLabel, word32 labelLen, int saltLen,
|
||||
|
@ -1129,6 +1149,25 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out,
|
|||
break;
|
||||
#endif
|
||||
|
||||
#ifdef WC_RSA_NO_PADDING
|
||||
case WC_RSA_NO_PAD:
|
||||
WOLFSSL_MSG("wolfSSL Using NO un-padding");
|
||||
|
||||
/* In the case of no padding being used check that input is exactly
|
||||
* the RSA key length */
|
||||
if (bits <= 0 || pkcsBlockLen != ((word32)bits/WOLFSSL_BIT_SIZE)) {
|
||||
WOLFSSL_MSG("Bad input size");
|
||||
ret = RSA_PAD_E;
|
||||
}
|
||||
else {
|
||||
if (out != NULL) {
|
||||
*out = pkcsBlock;
|
||||
}
|
||||
ret = pkcsBlockLen;
|
||||
}
|
||||
break;
|
||||
#endif /* WC_RSA_NO_PADDING */
|
||||
|
||||
default:
|
||||
WOLFSSL_MSG("Unknown RSA UnPad Type");
|
||||
ret = RSA_PAD_E;
|
||||
|
@ -1470,6 +1509,103 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out,
|
|||
}
|
||||
#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_RSA */
|
||||
|
||||
#ifdef WC_RSA_NO_PADDING
|
||||
/* Function that does the RSA operation directly with no padding.
|
||||
*
|
||||
* in buffer to do operation on
|
||||
* inLen length of input buffer
|
||||
* out buffer to hold results
|
||||
* outSz gets set to size of result buffer. Should be passed in as length
|
||||
* of out buffer. If the pointer "out" is null then outSz gets set to
|
||||
* the expected buffer size needed and LENGTH_ONLY_E gets returned.
|
||||
* key RSA key to use for encrypt/decrypt
|
||||
* type if using private or public key {RSA_PUBLIC_ENCRYPT,
|
||||
* RSA_PUBLIC_DECRYPT, RSA_PRIVATE_ENCRYPT, RSA_PRIVATE_DECRYPT}
|
||||
* rng wolfSSL RNG to use if needed
|
||||
*
|
||||
* returns size of result on success
|
||||
*/
|
||||
int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz,
|
||||
RsaKey* key, int type, WC_RNG* rng)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (in == NULL || outSz == NULL || key == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* sanity check on type of RSA operation */
|
||||
switch (type) {
|
||||
case RSA_PUBLIC_ENCRYPT:
|
||||
case RSA_PUBLIC_DECRYPT:
|
||||
case RSA_PRIVATE_ENCRYPT:
|
||||
case RSA_PRIVATE_DECRYPT:
|
||||
break;
|
||||
default:
|
||||
WOLFSSL_MSG("Bad RSA type");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if ((ret = wc_RsaEncryptSize(key)) < 0) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (inLen != (word32)ret) {
|
||||
WOLFSSL_MSG("Bad input length. Should be RSA key size");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (out == NULL) {
|
||||
*outSz = inLen;
|
||||
return LENGTH_ONLY_E;
|
||||
}
|
||||
|
||||
switch (key->state) {
|
||||
case RSA_STATE_NONE:
|
||||
case RSA_STATE_ENCRYPT_PAD:
|
||||
case RSA_STATE_ENCRYPT_EXPTMOD:
|
||||
case RSA_STATE_DECRYPT_EXPTMOD:
|
||||
case RSA_STATE_DECRYPT_UNPAD:
|
||||
key->state = (type == RSA_PRIVATE_ENCRYPT ||
|
||||
type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_EXPTMOD:
|
||||
RSA_STATE_DECRYPT_EXPTMOD;
|
||||
|
||||
key->dataLen = *outSz;
|
||||
|
||||
ret = wc_RsaFunction(in, inLen, out, &key->dataLen, type, key, rng);
|
||||
if (ret >= 0 || ret == WC_PENDING_E) {
|
||||
key->state = (type == RSA_PRIVATE_ENCRYPT ||
|
||||
type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_RES:
|
||||
RSA_STATE_DECRYPT_RES;
|
||||
}
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
FALL_THROUGH;
|
||||
|
||||
case RSA_STATE_ENCRYPT_RES:
|
||||
case RSA_STATE_DECRYPT_RES:
|
||||
ret = key->dataLen;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = BAD_STATE_E;
|
||||
}
|
||||
|
||||
/* if async pending then skip cleanup*/
|
||||
if (ret == WC_PENDING_E) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
key->state = RSA_STATE_NONE;
|
||||
wc_RsaCleanup(key);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* WC_RSA_NO_PADDING */
|
||||
|
||||
|
||||
int wc_RsaFunction(const byte* in, word32 inLen, byte* out,
|
||||
word32* outLen, int type, RsaKey* key, WC_RNG* rng)
|
||||
{
|
||||
|
@ -1517,8 +1653,8 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out,
|
|||
rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT,
|
||||
RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT
|
||||
pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2
|
||||
pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD or
|
||||
WC_RSA_PSS_PAD
|
||||
pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD,
|
||||
WC_RSA_NO_PAD or WC_RSA_PSS_PAD
|
||||
hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h
|
||||
mgf : type of mask generation function to use
|
||||
label : optional label
|
||||
|
@ -1548,6 +1684,11 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out,
|
|||
}
|
||||
|
||||
if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) {
|
||||
#ifdef WC_RSA_NO_PADDING
|
||||
/* In the case that no padding is used the input length can and should
|
||||
* be the same size as the RSA key. */
|
||||
if (pad_type != WC_RSA_NO_PAD)
|
||||
#endif
|
||||
return RSA_BUFFER_E;
|
||||
}
|
||||
|
||||
|
@ -1630,8 +1771,8 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out,
|
|||
rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT,
|
||||
RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT
|
||||
pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2
|
||||
pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD
|
||||
WC_RSA_PSS_PAD
|
||||
pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD,
|
||||
WC_RSA_NO_PAD, WC_RSA_PSS_PAD
|
||||
hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h
|
||||
mgf : type of mask generation function to use
|
||||
label : optional label
|
||||
|
@ -1777,7 +1918,7 @@ int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
|
|||
}
|
||||
|
||||
|
||||
#ifndef WC_NO_RSA_OAEP
|
||||
#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING)
|
||||
int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
|
||||
word32 outLen, RsaKey* key, WC_RNG* rng, int type,
|
||||
enum wc_HashType hash, int mgf, byte* label,
|
||||
|
@ -1829,7 +1970,7 @@ int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
|
|||
WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng);
|
||||
}
|
||||
|
||||
#ifndef WC_NO_RSA_OAEP
|
||||
#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING)
|
||||
int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out,
|
||||
word32 outLen, RsaKey* key, int type,
|
||||
enum wc_HashType hash, int mgf, byte* label,
|
||||
|
@ -1843,7 +1984,7 @@ int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out,
|
|||
RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash, mgf, label,
|
||||
labelSz, 0, rng);
|
||||
}
|
||||
#endif /* WC_NO_RSA_OAEP */
|
||||
#endif /* WC_NO_RSA_OAEP || WC_RSA_NO_PADDING */
|
||||
|
||||
|
||||
int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
|
||||
|
|
|
@ -250,6 +250,7 @@ int gmac_test(void);
|
|||
int aesccm_test(void);
|
||||
int aeskeywrap_test(void);
|
||||
int camellia_test(void);
|
||||
int rsa_no_pad_test(void);
|
||||
int rsa_test(void);
|
||||
int dh_test(void);
|
||||
int dsa_test(void);
|
||||
|
@ -737,6 +738,12 @@ int wolfcrypt_test(void* args)
|
|||
#endif
|
||||
|
||||
#ifndef NO_RSA
|
||||
#ifdef WC_RSA_NO_PADDING
|
||||
if ( (ret = rsa_no_pad_test()) != 0)
|
||||
return err_sys("RSA NOPAD test failed!\n", ret);
|
||||
else
|
||||
printf( "RSA NOPAD test passed!\n");
|
||||
#endif
|
||||
if ( (ret = rsa_test()) != 0)
|
||||
return err_sys("RSA test failed!\n", ret);
|
||||
else
|
||||
|
@ -8626,6 +8633,201 @@ exit_rsa_pss:
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef WC_RSA_NO_PADDING
|
||||
int rsa_no_pad_test(void)
|
||||
{
|
||||
WC_RNG rng;
|
||||
RsaKey key;
|
||||
byte* tmp = NULL;
|
||||
size_t bytes;
|
||||
int ret;
|
||||
word32 inLen = 0;
|
||||
word32 idx = 0;
|
||||
word32 outSz = RSA_TEST_BYTES;
|
||||
word32 plainSz = RSA_TEST_BYTES;
|
||||
#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) \
|
||||
&& !defined(NO_FILESYSTEM)
|
||||
FILE *file;
|
||||
#endif
|
||||
DECLARE_VAR(out, byte, RSA_TEST_BYTES, HEAP_HINT);
|
||||
DECLARE_VAR(plain, byte, RSA_TEST_BYTES, HEAP_HINT);
|
||||
|
||||
/* initialize stack structures */
|
||||
XMEMSET(&rng, 0, sizeof(rng));
|
||||
XMEMSET(&key, 0, sizeof(key));
|
||||
#ifdef USE_CERT_BUFFERS_1024
|
||||
bytes = (size_t)sizeof_client_key_der_1024;
|
||||
if (bytes < (size_t)sizeof_client_cert_der_1024)
|
||||
bytes = (size_t)sizeof_client_cert_der_1024;
|
||||
#elif defined(USE_CERT_BUFFERS_2048)
|
||||
bytes = (size_t)sizeof_client_key_der_2048;
|
||||
if (bytes < (size_t)sizeof_client_cert_der_2048)
|
||||
bytes = (size_t)sizeof_client_cert_der_2048;
|
||||
#else
|
||||
bytes = FOURK_BUF;
|
||||
#endif
|
||||
|
||||
tmp = (byte*)XMALLOC(bytes, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (tmp == NULL
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
|| out == NULL || plain == NULL
|
||||
#endif
|
||||
) {
|
||||
return -500;
|
||||
}
|
||||
|
||||
#ifdef USE_CERT_BUFFERS_1024
|
||||
XMEMCPY(tmp, client_key_der_1024, (size_t)sizeof_client_key_der_1024);
|
||||
#elif defined(USE_CERT_BUFFERS_2048)
|
||||
XMEMCPY(tmp, client_key_der_2048, (size_t)sizeof_client_key_der_2048);
|
||||
#elif !defined(NO_FILESYSTEM)
|
||||
file = fopen(clientKey, "rb");
|
||||
if (!file) {
|
||||
err_sys("can't open ./certs/client-key.der, "
|
||||
"Please run from wolfSSL home dir", -40);
|
||||
ERROR_OUT(-501, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
bytes = fread(tmp, 1, FOURK_BUF, file);
|
||||
fclose(file);
|
||||
#else
|
||||
/* No key to use. */
|
||||
ERROR_OUT(-502, exit_rsa_nopadding);
|
||||
#endif /* USE_CERT_BUFFERS */
|
||||
|
||||
ret = wc_InitRsaKey_ex(&key, HEAP_HINT, devId);
|
||||
if (ret != 0) {
|
||||
ERROR_OUT(-503, exit_rsa_nopadding);
|
||||
}
|
||||
ret = wc_RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes);
|
||||
if (ret != 0) {
|
||||
ERROR_OUT(-504, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
/* after loading in key use tmp as the test buffer */
|
||||
|
||||
#ifndef HAVE_FIPS
|
||||
ret = wc_InitRng_ex(&rng, HEAP_HINT, devId);
|
||||
#else
|
||||
ret = wc_InitRng(&rng);
|
||||
#endif
|
||||
if (ret != 0) {
|
||||
ERROR_OUT(-505, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
inLen = wc_RsaEncryptSize(&key);
|
||||
XMEMSET(tmp, 7, inLen);
|
||||
do {
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT)
|
||||
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
|
||||
#endif
|
||||
if (ret >= 0) {
|
||||
ret = wc_RsaDirect(tmp, inLen, out, &outSz, &key,
|
||||
RSA_PRIVATE_ENCRYPT, &rng);
|
||||
}
|
||||
} while (ret == WC_PENDING_E);
|
||||
if (ret <= 0) {
|
||||
ERROR_OUT(-506, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
/* encrypted result should not be the same as input */
|
||||
if (XMEMCMP(out, tmp, inLen) == 0) {
|
||||
ERROR_OUT(-507, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
/* decrypt with public key and compare result */
|
||||
do {
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT)
|
||||
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
|
||||
#endif
|
||||
if (ret >= 0) {
|
||||
ret = wc_RsaDirect(out, outSz, plain, &plainSz, &key,
|
||||
RSA_PUBLIC_DECRYPT, &rng);
|
||||
}
|
||||
} while (ret == WC_PENDING_E);
|
||||
if (ret <= 0) {
|
||||
ERROR_OUT(-508, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
if (XMEMCMP(plain, tmp, inLen) != 0) {
|
||||
ERROR_OUT(-509, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
#ifdef WC_RSA_BLINDING
|
||||
ret = wc_RsaSetRNG(&key, &rng);
|
||||
if (ret < 0) {
|
||||
ERROR_OUT(-510, exit_rsa_nopadding);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* test encrypt and decrypt using WC_RSA_NO_PAD */
|
||||
do {
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT)
|
||||
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
|
||||
#endif
|
||||
if (ret >= 0) {
|
||||
ret = wc_RsaPublicEncrypt_ex(tmp, inLen, out, (int)outSz, &key, &rng,
|
||||
WC_RSA_NO_PAD, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0);
|
||||
}
|
||||
} while (ret == WC_PENDING_E);
|
||||
if (ret < 0) {
|
||||
ERROR_OUT(-511, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
do {
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT)
|
||||
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
|
||||
#endif
|
||||
if (ret >= 0) {
|
||||
ret = wc_RsaPrivateDecrypt_ex(out, outSz, plain, (int)plainSz, &key,
|
||||
WC_RSA_NO_PAD, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0);
|
||||
}
|
||||
} while (ret == WC_PENDING_E);
|
||||
if (ret < 0) {
|
||||
ERROR_OUT(-512, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
if (XMEMCMP(plain, tmp, inLen) != 0) {
|
||||
ERROR_OUT(-513, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
/* test some bad arguments */
|
||||
ret = wc_RsaDirect(out, outSz, plain, &plainSz, &key, -1,
|
||||
&rng);
|
||||
if (ret != BAD_FUNC_ARG) {
|
||||
ERROR_OUT(-514, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
ret = wc_RsaDirect(out, outSz, plain, &plainSz, NULL, RSA_PUBLIC_DECRYPT,
|
||||
&rng);
|
||||
if (ret != BAD_FUNC_ARG) {
|
||||
ERROR_OUT(-515, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
ret = wc_RsaDirect(out, outSz, NULL, &plainSz, &key, RSA_PUBLIC_DECRYPT,
|
||||
&rng);
|
||||
if (ret != LENGTH_ONLY_E || plainSz != inLen) {
|
||||
ERROR_OUT(-516, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
ret = wc_RsaDirect(out, outSz - 10, plain, &plainSz, &key,
|
||||
RSA_PUBLIC_DECRYPT, &rng);
|
||||
if (ret != BAD_FUNC_ARG) {
|
||||
ERROR_OUT(-517, exit_rsa_nopadding);
|
||||
}
|
||||
|
||||
/* if making it to this point of code without hitting an ERROR_OUT then
|
||||
* all tests have passed */
|
||||
ret = 0;
|
||||
|
||||
exit_rsa_nopadding:
|
||||
wc_FreeRsaKey(&key);
|
||||
wc_FreeRng(&rng);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* WC_RSA_NO_PADDING */
|
||||
|
||||
int rsa_test(void)
|
||||
{
|
||||
int ret;
|
||||
|
|
|
@ -217,6 +217,7 @@ WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng);
|
|||
#define WC_RSA_PKCSV15_PAD 0
|
||||
#define WC_RSA_OAEP_PAD 1
|
||||
#define WC_RSA_PSS_PAD 2
|
||||
#define WC_RSA_NO_PAD 3
|
||||
|
||||
WOLFSSL_API int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out,
|
||||
word32 outLen, RsaKey* key, WC_RNG* rng, int type,
|
||||
|
@ -227,6 +228,8 @@ WOLFSSL_API int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen,
|
|||
WOLFSSL_API int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen,
|
||||
byte** out, RsaKey* key, int type, enum wc_HashType hash,
|
||||
int mgf, byte* label, word32 lableSz);
|
||||
WOLFSSL_API int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz,
|
||||
RsaKey* key, int type, WC_RNG* rng);
|
||||
#endif /* HAVE_FIPS*/
|
||||
WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*,
|
||||
word32*);
|
||||
|
|
Loading…
Reference in New Issue