Skip to content

Commit d840323

Browse files
committed
Move password buffer into the library
The design before was not completely fine. The user had to allocate the buffer and passed ownership to the library. As of [0] this seems to be a problem in some environments. [0] #587 (comment) Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
1 parent 1bad644 commit d840323

File tree

14 files changed

+76
-69
lines changed

14 files changed

+76
-69
lines changed

demos/openssh-privkey.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,11 @@ static void die_(int err, int line)
2929
#define die(i) do { die_(i, __LINE__); } while(0)
3030
#define DIE(s, ...) do { print_err("%3d: " s "\n", __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); } while(0)
3131

32-
static char* getpassword(const char *prompt, size_t maxlen)
32+
static int getpassword(const char *prompt, char *pass, unsigned long *len)
3333
{
34-
char *wr, *end, *pass = XCALLOC(1, maxlen + 1);
3534
struct termios tio;
3635
tcflag_t c_lflag;
37-
if (pass == NULL)
38-
return NULL;
39-
wr = pass;
40-
end = pass + maxlen;
36+
unsigned long maxlen = *len, wr = 0;
4137

4238
tcgetattr(0, &tio);
4339
c_lflag = tio.c_lflag;
@@ -46,24 +42,25 @@ static char* getpassword(const char *prompt, size_t maxlen)
4642

4743
printf("%s", prompt);
4844
fflush(stdout);
49-
while (pass < end) {
45+
while (1) {
5046
int c = getchar();
5147
if (c == '\r' || c == '\n' || c == -1)
5248
break;
53-
*wr++ = c;
49+
if (wr < maxlen)
50+
pass[wr] = c;
51+
wr++;
5452
}
53+
*len = wr;
5554
tio.c_lflag = c_lflag;
5655
tcsetattr(0, TCSAFLUSH, &tio);
5756
printf("\n");
58-
return pass;
57+
return wr <= maxlen;
5958
}
6059

61-
static int password_get(void **p, unsigned long *l, void *u)
60+
static int password_get(void *p, unsigned long *l, void *u)
6261
{
6362
(void)u;
64-
*p = getpassword("Enter passphrase: ", 256);
65-
*l = strlen(*p);
66-
return 0;
63+
return getpassword("Enter passphrase: ", p, l);
6764
}
6865

6966
static void print(ltc_pka_key *k)

src/headers/tomcrypt_custom.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,10 @@
627627
#define LTC_PBES
628628
#endif
629629

630+
#if defined(LTC_PEM) || defined(LTC_PKCS_8) && !defined(LTC_MAX_PASSWORD_LEN)
631+
#define LTC_MAX_PASSWORD_LEN 256
632+
#endif
633+
630634
#if defined(LTC_CLEAN_STACK)
631635
/* if you're sure that you want to use it, remove the line below */
632636
#error LTC_CLEAN_STACK is considered as broken

src/headers/tomcrypt_pk.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,12 @@ typedef struct {
55
/**
66
Callback function that is called when a password is required.
77
8-
Please be aware that the library takes ownership of the pointer that is
9-
returned to the library via `str`.
10-
`str` shall be allocated via the same function as `XMALLOC` points to.
11-
The data will be zeroed and `XFREE`'d as soon as it isn't required anymore.
12-
13-
@param str Pointer to pointer where the password will be stored.
14-
@param len Pointer to the length of the password.
8+
@param str Pointer to where the password shall be stored.
9+
@param len [in/out] The max length resp. resulting length of the password.
1510
@param userdata `userdata` that was passed in the `password_ctx` struct.
1611
@return CRYPT_OK on success
1712
*/
18-
int (*callback)(void **str, unsigned long *len, void *userdata);
13+
int (*callback)(void *str, unsigned long *len, void *userdata);
1914
/** Opaque `userdata` pointer passed when the callback is called */
2015
void *userdata;
2116
} password_ctx;

src/headers/tomcrypt_private.h

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,18 @@ typedef struct {
8383
unsigned long blocklen;
8484
} pbes_properties;
8585

86+
struct password {
87+
/* usually a `char*` but could also contain binary data
88+
* so use a `void*` + length to be on the safe side.
89+
*/
90+
unsigned char pw[LTC_MAX_PASSWORD_LEN];
91+
unsigned long l;
92+
};
93+
8694
typedef struct
8795
{
8896
pbes_properties type;
89-
void *pwd;
90-
unsigned long pwdlen;
97+
struct password pwd;
9198
ltc_asn1_list *enc_data;
9299
ltc_asn1_list *salt;
93100
ltc_asn1_list *iv;
@@ -259,14 +266,6 @@ enum cipher_mode {
259266
cm_none, cm_cbc, cm_cfb, cm_ctr, cm_ofb, cm_stream, cm_gcm
260267
};
261268

262-
struct password {
263-
/* usually a `char*` but could also contain binary data
264-
* so use a `void*` + length to be on the safe side.
265-
*/
266-
void *pw;
267-
unsigned long l;
268-
};
269-
270269
struct blockcipher_info {
271270
const char *name;
272271
const char *algo;

src/misc/crypt/crypt.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,9 @@ const char *crypt_build_settings =
470470
" PBES1 "
471471
" PBES2 "
472472
#endif
473+
#if defined(LTC_MAX_PASSWORD_LEN)
474+
" " NAME_VALUE(LTC_MAX_PASSWORD_LEN) " "
475+
#endif
473476
#if defined(LTC_PEM)
474477
" PEM "
475478
" " NAME_VALUE(LTC_PEM_DECODE_BUFSZ) " "

src/misc/pbes/pbes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *d
5050

5151
if (klen > sizeof(k)) return CRYPT_INVALID_ARG;
5252

53-
if ((err = arg->type.kdf(arg->pwd, arg->pwdlen, arg->salt->data, arg->salt->size, arg->iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
53+
if ((err = arg->type.kdf(arg->pwd.pw, arg->pwd.l, arg->salt->data, arg->salt->size, arg->iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
5454
if ((err = cbc_start(cid, iv, k, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
5555
if ((err = cbc_decrypt(arg->enc_data->data, dec_data, arg->enc_data->size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
5656
if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;

src/misc/pem/pem_pkcs.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ static int s_decrypt_pem(unsigned char *pem, unsigned long *l, const struct pem_
2525
if (hdr->info.keylen > sizeof(key)) {
2626
return CRYPT_BUFFER_OVERFLOW;
2727
}
28-
if (!hdr->pw->pw) {
29-
return CRYPT_INVALID_ARG;
30-
}
3128

3229
ivlen = sizeof(iv);
3330
if ((err = base16_decode(hdr->info.iv, XSTRLEN(hdr->info.iv), iv, &ivlen)) != CRYPT_OK) {
@@ -202,7 +199,7 @@ static int s_decode(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_c
202199
unsigned long w, l, n;
203200
int err = CRYPT_ERROR;
204201
struct pem_headers hdr = { 0 };
205-
struct password pw;
202+
struct password pw = { 0 };
206203
enum ltc_pka_id pka;
207204
XMEMSET(k, 0, sizeof(*k));
208205
w = LTC_PEM_READ_BUFSIZE * 2;
@@ -241,7 +238,8 @@ static int s_decode(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_c
241238
}
242239

243240
hdr.pw = &pw;
244-
if (pw_ctx->callback(&hdr.pw->pw, &hdr.pw->l, pw_ctx->userdata)) {
241+
hdr.pw->l = LTC_MAX_PASSWORD_LEN;
242+
if (pw_ctx->callback(hdr.pw->pw, &hdr.pw->l, pw_ctx->userdata)) {
245243
err = CRYPT_ERROR;
246244
goto cleanup;
247245
}
@@ -266,8 +264,7 @@ static int s_decode(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_c
266264

267265
cleanup:
268266
if (hdr.pw) {
269-
zeromem(hdr.pw->pw, hdr.pw->l);
270-
XFREE(hdr.pw->pw);
267+
zeromem(hdr.pw->pw, sizeof(hdr.pw->pw));
271268
}
272269
XFREE(pem);
273270
return err;

src/misc/pem/pem_ssh.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,8 @@ static int s_decode_openssh(struct get_char *g, ltc_pka_key *k, const password_c
570570
err = CRYPT_PW_CTX_MISSING;
571571
goto cleanup;
572572
}
573-
if (pw_ctx->callback(&opts.pw.pw, &opts.pw.l, pw_ctx->userdata)) {
573+
opts.pw.l = LTC_MAX_PASSWORD_LEN;
574+
if (pw_ctx->callback(opts.pw.pw, &opts.pw.l, pw_ctx->userdata)) {
574575
err = CRYPT_ERROR;
575576
goto cleanup;
576577
}
@@ -589,8 +590,8 @@ static int s_decode_openssh(struct get_char *g, ltc_pka_key *k, const password_c
589590
}
590591

591592
cleanup:
592-
if (opts.pw.pw) {
593-
XFREE(opts.pw.pw);
593+
if (opts.pw.l) {
594+
zeromem(&opts.pw, sizeof(opts.pw));
594595
}
595596
if (privkey) {
596597
zeromem(privkey, privkey_len);

src/pk/asn1/pkcs8/pkcs8_decode_flexi.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,11 @@ int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
2323
unsigned char *dec_data = NULL;
2424
ltc_asn1_list *l = NULL;
2525
int err;
26-
pbes_arg pbes;
26+
pbes_arg pbes = { 0 };
2727

2828
LTC_ARGCHK(in != NULL);
2929
LTC_ARGCHK(decoded_list != NULL);
3030

31-
XMEMSET(&pbes, 0, sizeof(pbes));
32-
3331
*decoded_list = NULL;
3432
if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) {
3533
/* the following "if" detects whether it is encrypted or not */
@@ -63,7 +61,8 @@ int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
6361
goto LBL_DONE;
6462
}
6563

66-
if (pw_ctx->callback(&pbes.pwd, &pbes.pwdlen, pw_ctx->userdata)) {
64+
pbes.pwd.l = LTC_MAX_PASSWORD_LEN;
65+
if (pw_ctx->callback(pbes.pwd.pw, &pbes.pwd.l, pw_ctx->userdata)) {
6766
err = CRYPT_ERROR;
6867
goto LBL_DONE;
6968
}
@@ -95,9 +94,8 @@ int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen,
9594

9695
LBL_DONE:
9796
if (l) der_free_sequence_flexi(l);
98-
if (pbes.pwd) {
99-
zeromem(pbes.pwd, pbes.pwdlen);
100-
XFREE(pbes.pwd);
97+
if (pbes.pwd.l) {
98+
zeromem(&pbes.pwd, sizeof(pbes.pwd));
10199
}
102100
if (dec_data) {
103101
zeromem(dec_data, dec_size);

tests/ecc_test.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -660,12 +660,14 @@ static int s_ecc_new_api(void)
660660
}
661661

662662

663-
static int password_get(void **p, unsigned long *l, void *u)
663+
static int password_get(void *p, unsigned long *l, void *u)
664664
{
665+
int ret = *l < 6;
665666
LTC_UNUSED_PARAM(u);
666-
*p = strdup("secret");
667+
if (!ret)
668+
XMEMCPY(p, "secret", 6);
667669
*l = 6;
668-
return 0;
670+
return ret;
669671
}
670672

671673
static int s_ecc_import_export(void) {

0 commit comments

Comments
 (0)