mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-29 18:27:29 +02:00
Add support for wolfSSL_EVP_PBE_scrypt (#4345)
This commit is contained in:
87
tests/api.c
87
tests/api.c
@ -42625,6 +42625,92 @@ static void test_wolfSSL_EVP_PKEY_derive(void)
|
||||
#endif /* OPENSSL_ALL || WOLFSSL_QT || WOLFSSL_OPENSSH */
|
||||
}
|
||||
|
||||
static void test_wolfSSL_EVP_PBE_scrypt(void)
|
||||
{
|
||||
#if defined(OPENSSL_EXTRA) && defined(HAVE_SCRYPT) && defined(HAVE_PBKDF2)
|
||||
#if !defined(NO_PWDBASED) && !defined(NO_SHA256)
|
||||
|
||||
int ret;
|
||||
|
||||
const char pwd[] = {'p','a','s','s','w','o','r','d'};
|
||||
int pwdlen = sizeof(pwd);
|
||||
const byte salt[] = {'N','a','C','l'};
|
||||
int saltlen = sizeof(salt);
|
||||
byte key[80];
|
||||
word64 numOvr32 = (word64)INT32_MAX + 1;
|
||||
|
||||
/* expected derived key for N:16, r:1, p:1 */
|
||||
const byte expectedKey[] = {
|
||||
0xAE, 0xC6, 0xB7, 0x48, 0x3E, 0xD2, 0x6E, 0x08, 0x80, 0x2B,
|
||||
0x41, 0xF4, 0x03, 0x20, 0x86, 0xA0, 0xE8, 0x86, 0xBE, 0x7A,
|
||||
0xC4, 0x8F, 0xCF, 0xD9, 0x2F, 0xF0, 0xCE, 0xF8, 0x10, 0x97,
|
||||
0x52, 0xF4, 0xAC, 0x74, 0xB0, 0x77, 0x26, 0x32, 0x56, 0xA6,
|
||||
0x5A, 0x99, 0x70, 0x1B, 0x7A, 0x30, 0x4D, 0x46, 0x61, 0x1C,
|
||||
0x8A, 0xA3, 0x91, 0xE7, 0x99, 0xCE, 0x10, 0xA2, 0x77, 0x53,
|
||||
0xE7, 0xE9, 0xC0, 0x9A};
|
||||
|
||||
printf(testingFmt, "wolfSSL_EVP_PBE_scrypt()");
|
||||
|
||||
/* N r p mx key keylen */
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, salt, saltlen, 0, 1, 1, 0, key, 64);
|
||||
AssertIntEQ(ret, 0); /* N must be greater than 1 */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, salt, saltlen, 3, 1, 1, 0, key, 64);
|
||||
AssertIntEQ(ret, 0); /* N must be power of 2 */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, salt, saltlen, 2, 0, 1, 0, key, 64);
|
||||
AssertIntEQ(ret, 0); /* r must be greater than 0 */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, salt, saltlen, 2, 1, 0, 0, key, 64);
|
||||
AssertIntEQ(ret, 0); /* p must be greater than 0 */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, salt, saltlen, 2, 1, 1, 0, key, 0);
|
||||
AssertIntEQ(ret, 0); /* keylen must be greater than 0 */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, salt, saltlen, 2, 9, 1, 0, key, 64);
|
||||
AssertIntEQ(ret, 0); /* r must be smaller than 9 */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, salt, saltlen, 2, 1, 1, 0, NULL, 64);
|
||||
AssertIntEQ(ret, 1); /* should succeed if key is NULL */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, salt, saltlen, 2, 1, 1, 0, key, 64);
|
||||
AssertIntEQ(ret, 1); /* should succeed */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, salt, saltlen, 2, numOvr32, 1, 0,
|
||||
key, 64);
|
||||
AssertIntEQ(ret, 0); /* should fail since r is greater than INT32_MAC */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, salt, saltlen, 2, 1, numOvr32, 0,
|
||||
key, 64);
|
||||
AssertIntEQ(ret, 0); /* should fail since p is greater than INT32_MAC */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, NULL, 0, 2, 1, 1, 0, key, 64);
|
||||
AssertIntEQ(ret, 1); /* should succeed even if salt is NULL */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, NULL, 4, 2, 1, 1, 0, key, 64);
|
||||
AssertIntEQ(ret, 0); /* if salt is NULL, saltlen must be 0, otherwise fail*/
|
||||
|
||||
ret = EVP_PBE_scrypt(NULL, 0, salt, saltlen, 2, 1, 1, 0, key, 64);
|
||||
AssertIntEQ(ret, 1); /* should succeed if pwd is NULL and pwdlen is 0*/
|
||||
|
||||
ret = EVP_PBE_scrypt(NULL, 4, salt, saltlen, 2, 1, 1, 0, key, 64);
|
||||
AssertIntEQ(ret, 0); /* if pwd is NULL, pwdlen must be 0 */
|
||||
|
||||
ret = EVP_PBE_scrypt(NULL, 0, NULL, 0, 2, 1, 1, 0, key, 64);
|
||||
AssertIntEQ(ret, 1); /* should succeed even both pwd and salt are NULL */
|
||||
|
||||
ret = EVP_PBE_scrypt(pwd, pwdlen, salt, saltlen, 16, 1, 1, 0, key, 64);
|
||||
AssertIntEQ(ret, 1);
|
||||
|
||||
ret = XMEMCMP(expectedKey, key, sizeof(expectedKey));
|
||||
AssertIntEQ(ret, 0); /* derived key must be the same as expected-key */
|
||||
|
||||
printf(resultFmt, "passed");
|
||||
|
||||
#endif /* !NO_PWDBASED && !NO_SHA256 */
|
||||
#endif /* OPENSSL_EXTRA && HAVE_SCRYPT && HAVE_PBKDF2 */
|
||||
}
|
||||
|
||||
#ifndef NO_RSA
|
||||
static void test_wolfSSL_RSA_padding_add_PKCS1_PSS(void)
|
||||
{
|
||||
@ -48742,6 +48828,7 @@ void ApiTest(void)
|
||||
test_wolfSSL_OCSP_resp_count();
|
||||
test_wolfSSL_OCSP_resp_get0();
|
||||
test_wolfSSL_EVP_PKEY_derive();
|
||||
test_wolfSSL_EVP_PBE_scrypt();
|
||||
#ifndef NO_RSA
|
||||
test_wolfSSL_RSA_padding_add_PKCS1_PSS();
|
||||
#endif
|
||||
|
@ -3218,6 +3218,71 @@ int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
|
||||
}
|
||||
#endif /* !NO_PWDBASED */
|
||||
|
||||
|
||||
#if defined(HAVE_SCRYPT) && defined(HAVE_PBKDF2) && !defined(NO_PWDBASED) && \
|
||||
!defined(NO_SHA256)
|
||||
/**
|
||||
* Derives a key from the specified password and the salt using SCRYPT
|
||||
* algorithm.
|
||||
*
|
||||
* Parameters:
|
||||
* - pass :password data. no need to be null-terminated. NULL is accepted.
|
||||
* - passlen :length of the password. Must be 0 when pass is NULL.
|
||||
* - salt :salt. NULL is accepted.
|
||||
* - saltlen :length of the salt. Must be 0 when salt is NULL.
|
||||
* - N :cost parameter. Must be grater or equal to 2 and be a power of 2.
|
||||
* - r :block size. Must 1 or greater.
|
||||
* - p :parallelism
|
||||
* - maxmem :maximum size of buffer used for calculation in definition,
|
||||
* Not referred in this implementation.
|
||||
* - key :derived key.
|
||||
* - keylen :length of the derived key
|
||||
*
|
||||
* Returns:
|
||||
* 1 on success, otherwise 0.
|
||||
*/
|
||||
int wolfSSL_EVP_PBE_scrypt(const char *pass, size_t passlen,
|
||||
const unsigned char *salt, size_t saltlen,
|
||||
word64 N, word64 r, word64 p,
|
||||
word64 maxmem, unsigned char *key, size_t keylen)
|
||||
{
|
||||
(void)maxmem;
|
||||
int ret;
|
||||
int exp = 0;
|
||||
|
||||
WOLFSSL_ENTER("wolfSSL_EVP_PBE_scrypt");
|
||||
|
||||
if (r > INT32_MAX || p > INT32_MAX) {
|
||||
WOLFSSL_MSG("Doesn't support greater than 32 bit values of r and p");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
/* N must be a power of 2 and > 2.
|
||||
if (N & (N-1)) is zero, it means N is a power of 2.
|
||||
*/
|
||||
if (N < 2 || (N & (N-1)) || r <= 0 || p <= 0)
|
||||
return WOLFSSL_FAILURE;
|
||||
|
||||
if (key == NULL)
|
||||
return WOLFSSL_SUCCESS;
|
||||
|
||||
/* get exponent of power of 2. Confirmed N is power of 2. */
|
||||
while (N != 1) {
|
||||
N >>= 1;
|
||||
exp++;
|
||||
}
|
||||
|
||||
ret = wc_scrypt(key, (const byte*)pass, (int)passlen, salt, (int)saltlen,
|
||||
exp, (int)r, (int)p, (int)keylen);
|
||||
|
||||
WOLFSSL_LEAVE("wolfSSL_EVP_PBE_scrypt", ret);
|
||||
|
||||
if (ret == 0)
|
||||
return WOLFSSL_SUCCESS;
|
||||
else
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
#endif /* HAVE_SCRYPT && HAVE_PBKDF2 && !NO_PWDBASED && !NO_SHA */
|
||||
|
||||
static const struct cipher{
|
||||
unsigned char type;
|
||||
const char *name;
|
||||
|
@ -723,6 +723,14 @@ WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
|
||||
const WOLFSSL_EVP_MD *digest,
|
||||
int keylen, unsigned char *out);
|
||||
|
||||
#if defined(HAVE_SCRYPT) && defined(HAVE_PBKDF2) && !defined(NO_PWDBASED) && \
|
||||
!defined(NO_SHA)
|
||||
WOLFSSL_API int wolfSSL_EVP_PBE_scrypt(const char *pass, size_t passlen,
|
||||
const unsigned char *salt, size_t saltlen,
|
||||
word64 N, word64 r, word64 p,
|
||||
word64 maxmem, unsigned char *key, size_t keylen);
|
||||
#endif /* HAVE_SCRYPT && HAVE_PBKDF2 && !NO_PWDBASED && !NO_SHA */
|
||||
|
||||
WOLFSSL_LOCAL int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp,
|
||||
int* pHash, int* pHashSz);
|
||||
|
||||
@ -992,6 +1000,7 @@ typedef WOLFSSL_ASN1_PCTX ASN1_PCTX;
|
||||
|
||||
#define PKCS5_PBKDF2_HMAC_SHA1 wolfSSL_PKCS5_PBKDF2_HMAC_SHA1
|
||||
#define PKCS5_PBKDF2_HMAC wolfSSL_PKCS5_PBKDF2_HMAC
|
||||
#define EVP_PBE_scrypt wolfSSL_EVP_PBE_scrypt
|
||||
|
||||
/* OpenSSL compat. ctrl values */
|
||||
#define EVP_CTRL_INIT 0x0
|
||||
|
Reference in New Issue
Block a user