Make improvements to wolfSSL_EVP_PKEY_encrypt and wolfSSL_EVP_PKEY_decrypt.

- Handle case where output buffer is NULL. In this case, passed in output buffer
  length pointer should be given the maximum output buffer size needed.
- Add better debug messages.
This commit is contained in:
Hayden Roche
2021-08-12 18:46:15 -07:00
parent 8601c14f1c
commit 3be13f7358
2 changed files with 101 additions and 31 deletions

View File

@ -42039,12 +42039,23 @@ static void test_wolfSSL_EVP_PKEY_encrypt(void)
AssertIntEQ(pkey->references, 1); AssertIntEQ(pkey->references, 1);
/* Encrypt data */ /* Encrypt data */
/* Check that we can get the required output buffer length by passing in a
* NULL output buffer. */
AssertIntEQ(EVP_PKEY_encrypt(ctx, NULL, &outEncLen,
(const unsigned char*)in, inlen), WOLFSSL_SUCCESS);
AssertIntEQ(rsaKeySz, outEncLen);
/* Now do the actual encryption. */
AssertIntEQ(EVP_PKEY_encrypt(ctx, outEnc, &outEncLen, AssertIntEQ(EVP_PKEY_encrypt(ctx, outEnc, &outEncLen,
(const unsigned char*)in, inlen), WOLFSSL_SUCCESS); (const unsigned char*)in, inlen), WOLFSSL_SUCCESS);
/* Decrypt data */ /* Decrypt data */
AssertIntEQ(EVP_PKEY_decrypt_init(ctx), WOLFSSL_SUCCESS); AssertIntEQ(EVP_PKEY_decrypt_init(ctx), WOLFSSL_SUCCESS);
/* Check that we can get the required output buffer length by passing in a
* NULL output buffer. */
AssertIntEQ(EVP_PKEY_decrypt(ctx, NULL, &outDecLen, outEnc, outEncLen),
WOLFSSL_SUCCESS);
AssertIntEQ(rsaKeySz, outDecLen);
/* Now do the actual decryption. */
AssertIntEQ(EVP_PKEY_decrypt(ctx, outDec, &outDecLen, outEnc, outEncLen), AssertIntEQ(EVP_PKEY_decrypt(ctx, outDec, &outDecLen, outEnc, outEncLen),
WOLFSSL_SUCCESS); WOLFSSL_SUCCESS);

View File

@ -1626,47 +1626,73 @@ int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_
/* Uses the WOLFSSL_EVP_PKEY_CTX to decrypt a buffer. /* Uses the WOLFSSL_EVP_PKEY_CTX to decrypt a buffer.
* *
* ctx structure to decrypt with * ctx EVP_PKEY context of operation.
* out buffer to hold the results * out Decrypted output buffer. If NULL, puts the maximum output buffer size
* outlen initially holds size of out buffer and gets set to decrypt result size in outLen and returns success.
* in buffer decrypt * outLen If out is NULL, see above. If out is non-NULL, on input outLen holds
* inlen length of in buffer * the size of out. On output holds the length of actual decryption.
* in Encrypted input buffer.
* inLen Length of encrypted data.
* *
* returns WOLFSSL_SUCCESS on success. * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure.
*/ */
int wolfSSL_EVP_PKEY_decrypt(WOLFSSL_EVP_PKEY_CTX *ctx, int wolfSSL_EVP_PKEY_decrypt(WOLFSSL_EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen, unsigned char *out, size_t *outLen,
const unsigned char *in, size_t inlen) const unsigned char *in, size_t inLen)
{ {
int len = 0; int len = 0;
if (ctx == NULL) return 0;
WOLFSSL_ENTER("EVP_PKEY_decrypt"); WOLFSSL_ENTER("EVP_PKEY_decrypt");
if (ctx == NULL || ctx->pkey == NULL) {
WOLFSSL_MSG("Bad parameter.");
return 0;
}
(void)out; (void)out;
(void)outlen; (void)outLen;
(void)in; (void)in;
(void)inlen; (void)inLen;
(void)len; (void)len;
switch (ctx->pkey->type) { switch (ctx->pkey->type) {
#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) #if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
case EVP_PKEY_RSA: case EVP_PKEY_RSA:
len = wolfSSL_RSA_private_decrypt((int)inlen, (unsigned char*)in, out, if (out == NULL) {
if (ctx->pkey->rsa == NULL) {
WOLFSSL_MSG("Internal wolfCrypt RSA object is NULL.");
return WOLFSSL_FAILURE;
}
len = wolfSSL_RSA_size(ctx->pkey->rsa);
if (len <= 0) {
WOLFSSL_MSG("Error getting RSA size.");
return WOLFSSL_FAILURE;
}
if (outLen == NULL) {
WOLFSSL_MSG("outLen is NULL.");
return WOLFSSL_FAILURE;
}
*outLen = len;
return WOLFSSL_SUCCESS;
}
len = wolfSSL_RSA_private_decrypt((int)inLen, (unsigned char*)in, out,
ctx->pkey->rsa, ctx->padding); ctx->pkey->rsa, ctx->padding);
if (len < 0) break; if (len < 0) break;
else { else {
*outlen = len; *outLen = len;
return WOLFSSL_SUCCESS; return WOLFSSL_SUCCESS;
} }
#endif /* NO_RSA */ #endif /* NO_RSA */
case EVP_PKEY_EC: case EVP_PKEY_EC:
WOLFSSL_MSG("not implemented"); WOLFSSL_MSG("EVP_PKEY_EC not implemented.");
FALL_THROUGH; FALL_THROUGH;
default: default:
break; break;
} }
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
@ -1695,49 +1721,82 @@ int wolfSSL_EVP_PKEY_decrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx)
} }
/* Use a WOLFSSL_EVP_PKEY_CTX structure to encrypt data /* Uses the WOLFSSL_EVP_PKEY_CTX to encrypt a buffer.
* *
* ctx WOLFSSL_EVP_PKEY_CTX structure to use with encryption * ctx EVP_PKEY context of operation.
* out buffer to hold encrypted data * out Encrypted output buffer. If NULL, puts the maximum output buffer size
* outlen length of out buffer * in outlen and returns success.
* in data to be encrypted * outLen If out is NULL, see above. If out is non-NULL, on input outLen holds
* inlen length of in buffer * the size of out. On output holds the length of actual encryption.
* in Plaintext input buffer.
* inLen Length of plaintext.
* *
* Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure.
*/ */
int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx, int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen, unsigned char *out, size_t *outLen,
const unsigned char *in, size_t inlen) const unsigned char *in, size_t inLen)
{ {
int len = 0; int len = 0;
if (ctx == NULL) return WOLFSSL_FAILURE;
WOLFSSL_ENTER("EVP_PKEY_encrypt"); WOLFSSL_ENTER("EVP_PKEY_encrypt");
if (ctx->op != EVP_PKEY_OP_ENCRYPT) return WOLFSSL_FAILURE;
if (ctx == NULL || ctx->pkey == NULL) {
WOLFSSL_MSG("Bad parameter.");
return 0;
}
if (ctx->op != EVP_PKEY_OP_ENCRYPT) {
WOLFSSL_MSG("ctx->op must be set to EVP_PKEY_OP_ENCRYPT. Use "
"wolfSSL_EVP_PKEY_encrypt_init.");
return WOLFSSL_FAILURE;
}
(void)out; (void)out;
(void)outlen; (void)outLen;
(void)in; (void)in;
(void)inlen; (void)inLen;
(void)len; (void)len;
switch (ctx->pkey->type) { switch (ctx->pkey->type) {
#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) #if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
case EVP_PKEY_RSA: case EVP_PKEY_RSA:
len = wolfSSL_RSA_public_encrypt((int)inlen, (unsigned char *)in, out, if (out == NULL) {
if (ctx->pkey->rsa == NULL) {
WOLFSSL_MSG("Internal wolfCrypt RSA object is NULL.");
return WOLFSSL_FAILURE;
}
len = wolfSSL_RSA_size(ctx->pkey->rsa);
if (len <= 0) {
WOLFSSL_MSG("Error getting RSA size.");
return WOLFSSL_FAILURE;
}
if (outLen == NULL) {
WOLFSSL_MSG("outLen is NULL.");
return WOLFSSL_FAILURE;
}
*outLen = len;
return WOLFSSL_SUCCESS;
}
len = wolfSSL_RSA_public_encrypt((int)inLen, (unsigned char *)in, out,
ctx->pkey->rsa, ctx->padding); ctx->pkey->rsa, ctx->padding);
if (len < 0) if (len < 0)
break; break;
else { else {
*outlen = len; *outLen = len;
return WOLFSSL_SUCCESS; return WOLFSSL_SUCCESS;
} }
#endif /* NO_RSA */ #endif /* NO_RSA */
case EVP_PKEY_EC: case EVP_PKEY_EC:
WOLFSSL_MSG("not implemented"); WOLFSSL_MSG("EVP_PKEY_EC not implemented");
FALL_THROUGH; FALL_THROUGH;
default: default:
break; break;
} }
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }