Skip to content

[DRAFT] Add EVP_read_pw_string #2402

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ add_library(
pem/pem_info.c
pem/pem_lib.c
pem/pem_oth.c
pem/pem_passwd.c
pem/pem_pk8.c
pem/pem_pkey.c
pem/pem_x509.c
Expand Down
59 changes: 59 additions & 0 deletions crypto/fipsmodule/evp/evp.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
#include <openssl/thread.h>

#include "../../evp_extra/internal.h"
#include "../../pem/internal.h"
#include "../../internal.h"
#include "internal.h"

Expand Down Expand Up @@ -156,6 +157,64 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
return -2;
}

static const char* prompt_string = "Enter PEM pass phrase:";

char *EVP_get_pw_prompt(void) {
return (char*)prompt_string;
}

int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify) {
return EVP_read_pw_string_min(buf, 0, length, prompt, verify);
}

int EVP_read_pw_string_min(char *buf, int min_length, int length,
const char *prompt, int verify) {
int ret = -1;
char verify_buf[1024];

if (prompt == NULL) {
prompt = EVP_get_pw_prompt();
}

if (!openssl_console_open()) {
return ret;
}

// Write initial password prompt
if (!openssl_console_write(prompt)) {
return ret;
}

// Read password with echo disabled, returns 1 on success, 0 on error, -2 on interrupt
ret = openssl_console_read(buf, min_length, length, 0);
if (ret != 0) {
OPENSSL_cleanse(buf, sizeof(buf));
OPENSSL_PUT_ERROR(PEM, PEM_R_PROBLEMS_GETTING_PASSWORD);
return ret;
}

if (verify) {
openssl_console_write("Verifying - ");
openssl_console_write(prompt);

ret = openssl_console_read(verify_buf, min_length, sizeof(verify_buf), 0);

if (ret == 0) {
if (strcmp(buf, verify_buf) != 0) {
openssl_console_write("Verify failure\n");
ret = -1;
}
} else {
OPENSSL_PUT_ERROR(PEM, PEM_R_PROBLEMS_GETTING_PASSWORD);
}
}

openssl_console_close();

OPENSSL_cleanse(verify_buf, sizeof(verify_buf));
return ret;
}

int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
SET_DIT_AUTO_RESET;
if (to->type == EVP_PKEY_NONE) {
Expand Down
16 changes: 16 additions & 0 deletions crypto/pem/internal.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#include <openssl/pem.h>

#define MIN_LENGTH 4

#if defined(__cplusplus)
extern "C" {
#endif

// PEM utility functions
// PEM_proc_type appends a Proc-Type header to |buf|, determined by |type|.
Expand All @@ -9,3 +14,14 @@ void PEM_proc_type(char buf[PEM_BUFSIZE], int type);
// and a single parameter, specified by hex-encoding |len| bytes from |str|.
void PEM_dek_info(char buf[PEM_BUFSIZE], const char *type, size_t len,
char *str);

// Console Management Functions
OPENSSL_EXPORT int openssl_console_open(void);
OPENSSL_EXPORT int openssl_console_close(void);
OPENSSL_EXPORT int openssl_console_write(const char *str);
OPENSSL_EXPORT int openssl_console_read(char *buf, int minsize, int maxsize, int echo);


#if defined(__cplusplus)
} // extern C
#endif
36 changes: 29 additions & 7 deletions crypto/pem/pem_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@
#include "../fipsmodule/evp/internal.h"


#define MIN_LENGTH 4

static int load_iv(char **fromp, unsigned char *to, size_t num);
static int check_pem(const char *nm, const char *name);

Expand Down Expand Up @@ -785,13 +783,37 @@ int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
}

int PEM_def_callback(char *buf, int size, int rwflag, void *userdata) {
if (!buf || !userdata || size < 0) {
if (!buf || size < 0) {
return 0;
}
size_t len = strlen((char *)userdata);
if (len >= (size_t)size) {

if (userdata) {
size_t len = strlen((char *)userdata);
if (len >= (size_t)size) {
return 0;
}
OPENSSL_strlcpy(buf, userdata, (size_t)size);
return (int)len;
}

const char *prompt = EVP_get_pw_prompt();
if (prompt == NULL) {
prompt = "Enter PEM pass phrase:";
}

/*
* rwflag == 0 means decryption
* rwflag == 1 means encryption
*
* We assume that for encryption, we want a minimum length, while for
* decryption, we cannot know any minimum length, so we assume zero.
*/
int min_len = rwflag ? MIN_LENGTH : 0;

int ret = EVP_read_pw_string_min(buf, min_len, size, prompt, rwflag);
if (ret != 0 || size > INT_MAX) {
return 0;
}
OPENSSL_strlcpy(buf, userdata, (size_t)size);
return (int)len;

return (int)OPENSSL_strnlen(buf, size);
}
Loading
Loading