mirror of
https://github.com/libssh2/libssh2.git
synced 2026-10-24 03:48:58 +03:00
crypto: de-duplicate/merge most file/blob codepaths
Replace separate codepath for loading private keys from filenames vs. memory buffers (blobs), with unified functions that handle both. Either filename or blob pointer + size must be passed to these functions. To reduce code duplication and small/large differences and bugs between these codepaths. Also to improve readability and ease maintenance. Also fix: - mbedtls: do not pass redundant null-terminator to `mbed_parse_openssh_key()` on in ECDSA blob codepath. (benign) - libgcrypt: add support for RSA/DSA blobs. - openssl: error handling code now applies to from-file codepath. Reported-and-alternate-patch-by: Martin Nowak Fixes #1652 - openssl: add file support for `ssh2_sk_pubkey()`. (not exposed via public API at this time.) - openssl: fix to call `OSSL_INIT_IF_NEEDED()` from `ssh2_pub_privkey()`. (for wolfSSL-debug enabled builds.) - openssl: fix error code returned by `ssh2_sk_pubkey()`. (to be consistent with rest of code.) - openssl: fix potential NULL deref in `ssh2_ed25519_new_priv()` blob codepaths. - openssl: fix potential dangling pointer in RSA, DSA, ECDSA codepaths (both file and blob) if BIO init failed. - os400qc3: fix uninitialized structs in `os400_pub_privkey_*()`. - os400qc3: drop unused local variable. Notes: - os400: use wrappers without actually merging the code. They are very different and difficult to read, also not possible to build test. - openssl: ed25519 loader code has outlier code where the file/blob code is different (both rather short.) - openssl: there is a file/blob function pair left to merge. - pem: there remain two pairs of file/blob internal APIs. Follow-up to6a951168ce#2362 Follow-up tofe9442be4d#2359 Follow-up to5b94157f1c#2354 Closes #2379
This commit is contained in:
@@ -414,29 +414,17 @@ Format of an ED25519 public key:
|
||||
Each item is preceded by its 32-bit byte length, MSB first.
|
||||
|
||||
```c
|
||||
int ssh2_pub_privkey_file(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *passphrase);
|
||||
int ssh2_pub_privkey(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase);
|
||||
```
|
||||
Reads a private key from file `privatekey` and extracts the public key -->
|
||||
(`pubkeydata`, `pubkeydata_len`). Store the associated method (ssh-rsa or
|
||||
ssh-dss) into (`method`, `method_len`).
|
||||
Both buffers have to be allocated using `SSH2_ALLOC()`.
|
||||
Returns 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
|
||||
```c
|
||||
int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase);
|
||||
```
|
||||
Gets a private key from bytes at (`privkeyblob`, `privkeyblob_len`) and
|
||||
extracts the public key --> (`pubkeydata`, `pubkeydata_len`). Store the
|
||||
associated method (ssh-rsa or ssh-dss) into (`method`, `method_len`).
|
||||
Gets a private key from file `privatekey`, or bytes at (`privkeyblob`,
|
||||
`privkeyblob_len`) and extracts the public key --> (`pubkeydata`,
|
||||
`pubkeydata_len`). Store the associated method (e.g., `ssh-rsa`, `ssh-ed25519`)
|
||||
into (`method`, `method_len`).
|
||||
Both buffers have to be allocated using `SSH2_ALLOC()`.
|
||||
Returns 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
@@ -478,23 +466,14 @@ key parameters): unless used internally by the backend, it is not needed to
|
||||
support the private key and the other parameters here.
|
||||
|
||||
```c
|
||||
int ssh2_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase);
|
||||
int ssh2_rsa_new_priv(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
```
|
||||
Reads an RSA private key from file `filename` into a new RSA context.
|
||||
Must call `ssh2_init_if_needed()`.
|
||||
Return 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
|
||||
```c
|
||||
int ssh2_rsa_new_priv_from_blob(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
```
|
||||
Gets an RSA private key from `blob` into a new RSA context.
|
||||
Reads an RSA private key from file `filename`, or `blob` into a new RSA
|
||||
context.
|
||||
Must call `ssh2_init_if_needed()`.
|
||||
Return 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
@@ -618,23 +597,14 @@ Returns 0 if OK.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
|
||||
```c
|
||||
int ssh2_dsa_new_priv_from_file(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase);
|
||||
int ssh2_dsa_new_priv(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
```
|
||||
Gets a DSA private key from file `filename` into a new DSA context.
|
||||
Must call `ssh2_init_if_needed()`.
|
||||
Return 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
|
||||
```c
|
||||
int ssh2_dsa_new_priv_from_blob(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
```
|
||||
Gets a DSA private key from the `blob_len`-bytes `blob` into a new DSA context.
|
||||
Reads a DSA private key from file `filename`, or `blob` into a new DSA
|
||||
context.
|
||||
Must call `ssh2_init_if_needed()`.
|
||||
Returns 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
@@ -694,24 +664,14 @@ Return 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
|
||||
```c
|
||||
int ssh2_ecdsa_new_priv_from_file(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase);
|
||||
int ssh2_ecdsa_new_priv(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
```
|
||||
Reads an ECDSA private key from PEM file `filename` into a new ECDSA context.
|
||||
Must call `ssh2_init_if_needed()`.
|
||||
Return 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
|
||||
```c
|
||||
int ssh2_ecdsa_new_priv_from_blob(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
```
|
||||
Builds an ECDSA private key from PEM data at `blob` of length `blob_len`
|
||||
into a new ECDSA context stored at `ec_ctx`.
|
||||
Reads an ECDSA private key from file `filename`, or `blob` into a new ECDSA
|
||||
context stored at `ec_ctx`.
|
||||
Must call `ssh2_init_if_needed()`.
|
||||
Return 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
@@ -797,18 +757,6 @@ Key buffers are allocated and should be released by caller after use.
|
||||
Returns 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
|
||||
```c
|
||||
int ssh2_ed25519_new_priv_from_file(ssh2_ed25519_ctx **ed_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase);
|
||||
```
|
||||
Reads an ED25519 private key from PEM file `filename` into a new ED25519
|
||||
context.
|
||||
Must call `ssh2_init_if_needed()`.
|
||||
Return 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
|
||||
```c
|
||||
int ssh2_ed25519_new_public(ssh2_ed25519_ctx **ed_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
@@ -821,13 +769,14 @@ Return 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
|
||||
```c
|
||||
int ssh2_ed25519_new_priv_from_blob(ssh2_ed25519_ctx **ed_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
int ssh2_ed25519_new_priv(ssh2_ed25519_ctx **ed_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
```
|
||||
Builds an ED25519 private key from PEM data at `blob` of length `blob_len`
|
||||
into a new ED25519 context stored at `ed_ctx`.
|
||||
Reads an ED25519 private key from file `filename`, or `blob` into a new ED25519
|
||||
context stored at `ed_ctx`.
|
||||
Must call `ssh2_init_if_needed()`.
|
||||
Return 0 if OK, else -1.
|
||||
This procedure is already prototyped in `crypto.h`.
|
||||
|
||||
86
src/crypto.h
86
src/crypto.h
@@ -133,14 +133,11 @@ int ssh2_rsa_new(ssh2_rsa_ctx **rsa,
|
||||
const unsigned char *e1data, size_t e1len,
|
||||
const unsigned char *e2data, size_t e2len,
|
||||
const unsigned char *coeffdata, size_t coefflen);
|
||||
int ssh2_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase);
|
||||
int ssh2_rsa_new_priv_from_blob(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
int ssh2_rsa_new_priv(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
#if LIBSSH2_RSA_SHA1
|
||||
int ssh2_rsa_sha1_sign(ssh2_rsa_ctx *rsa, LIBSSH2_SESSION *session,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
@@ -169,14 +166,11 @@ int ssh2_dsa_new(ssh2_dsa_ctx **dsa,
|
||||
const unsigned char *gdata, size_t glen,
|
||||
const unsigned char *ydata, size_t ylen,
|
||||
const unsigned char *xdata, size_t xlen);
|
||||
int ssh2_dsa_new_priv_from_file(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase);
|
||||
int ssh2_dsa_new_priv_from_blob(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
int ssh2_dsa_new_priv(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
int ssh2_dsa_sha1_sign(ssh2_dsa_ctx *dsa,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
unsigned char *signature);
|
||||
@@ -210,14 +204,11 @@ int ssh2_ecdsa_curve_name_with_octal_new(
|
||||
const unsigned char *publickey_encoded, size_t publickey_encoded_len,
|
||||
ssh2_curve_type curve);
|
||||
|
||||
int ssh2_ecdsa_new_priv_from_file(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase);
|
||||
int ssh2_ecdsa_new_priv_from_blob(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
int ssh2_ecdsa_new_priv(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
|
||||
int ssh2_ecdsa_sign(ssh2_ecdsa_ctx *ec_ctx, LIBSSH2_SESSION *session,
|
||||
const unsigned char *hash, size_t hash_len,
|
||||
@@ -246,14 +237,11 @@ int ssh2_ed25519_new_public(ssh2_ed25519_ctx **ed_ctx,
|
||||
const unsigned char *raw_pub_key,
|
||||
const size_t key_len);
|
||||
|
||||
int ssh2_ed25519_new_priv_from_file(ssh2_ed25519_ctx **ed_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase);
|
||||
int ssh2_ed25519_new_priv_from_blob(ssh2_ed25519_ctx **ed_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
int ssh2_ed25519_new_priv(ssh2_ed25519_ctx **ed_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase);
|
||||
|
||||
int ssh2_ed25519_sign(ssh2_ed25519_ctx *ed_ctx, LIBSSH2_SESSION *session,
|
||||
uint8_t **out_sig, size_t *out_sig_len,
|
||||
@@ -284,26 +272,22 @@ int ssh2_cipher_crypt(ssh2_cipher_ctx *ctx, SSH2_CIPHER_T(algo),
|
||||
void ssh2_cipher_dtor(ssh2_cipher_ctx *ctx);
|
||||
#endif
|
||||
|
||||
int ssh2_pub_privkey_file(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *passphrase);
|
||||
int ssh2_pub_privkey(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase);
|
||||
|
||||
int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase);
|
||||
|
||||
int ssh2_sk_pubkey_blob(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
int *algorithm, unsigned char *flags,
|
||||
const char **application,
|
||||
const unsigned char **key_handle, size_t *handle_len,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase);
|
||||
int ssh2_sk_pubkey(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
int *algorithm, unsigned char *flags,
|
||||
const char **application,
|
||||
const unsigned char **key_handle, size_t *handle_len,
|
||||
const char *privatekey,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase);
|
||||
|
||||
#ifndef ssh2_bn_ctx
|
||||
#define ssh2_bn_ctx int
|
||||
|
||||
@@ -137,22 +137,15 @@ static int hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION *session,
|
||||
void **abstract)
|
||||
{
|
||||
ssh2_rsa_ctx *rsa;
|
||||
int rc;
|
||||
|
||||
if(*abstract) {
|
||||
hostkey_method_ssh_rsa_dtor(session, abstract);
|
||||
*abstract = NULL;
|
||||
}
|
||||
|
||||
if(privkeyfile)
|
||||
rc = ssh2_rsa_new_priv_from_file(&rsa, session,
|
||||
privkeyfile,
|
||||
passphrase);
|
||||
else
|
||||
rc = ssh2_rsa_new_priv_from_blob(&rsa, session,
|
||||
privkeyblob, privkeyblob_len,
|
||||
passphrase);
|
||||
if(rc)
|
||||
if(ssh2_rsa_new_priv(&rsa, session,
|
||||
privkeyfile, privkeyblob, privkeyblob_len,
|
||||
passphrase))
|
||||
return -1;
|
||||
|
||||
*abstract = rsa;
|
||||
@@ -495,22 +488,15 @@ static int hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION *session,
|
||||
void **abstract)
|
||||
{
|
||||
ssh2_dsa_ctx *dsa;
|
||||
int rc;
|
||||
|
||||
if(*abstract) {
|
||||
hostkey_method_ssh_dss_dtor(session, abstract);
|
||||
*abstract = NULL;
|
||||
}
|
||||
|
||||
if(privkeyfile)
|
||||
rc = ssh2_dsa_new_priv_from_file(&dsa, session,
|
||||
privkeyfile,
|
||||
passphrase);
|
||||
else
|
||||
rc = ssh2_dsa_new_priv_from_blob(&dsa, session,
|
||||
privkeyblob, privkeyblob_len,
|
||||
passphrase);
|
||||
if(rc)
|
||||
if(ssh2_dsa_new_priv(&dsa, session,
|
||||
privkeyfile, privkeyblob, privkeyblob_len,
|
||||
passphrase))
|
||||
return -1;
|
||||
|
||||
*abstract = dsa;
|
||||
@@ -702,22 +688,15 @@ static int hostkey_method_ssh_ecdsa_initPEM(LIBSSH2_SESSION *session,
|
||||
void **abstract)
|
||||
{
|
||||
ssh2_ecdsa_ctx *ec_ctx = NULL;
|
||||
int rc;
|
||||
|
||||
if(abstract && *abstract) {
|
||||
hostkey_method_ssh_ecdsa_dtor(session, abstract);
|
||||
*abstract = NULL;
|
||||
}
|
||||
|
||||
if(privkeyfile)
|
||||
rc = ssh2_ecdsa_new_priv_from_file(&ec_ctx, session,
|
||||
privkeyfile,
|
||||
passphrase);
|
||||
else
|
||||
rc = ssh2_ecdsa_new_priv_from_blob(&ec_ctx, session,
|
||||
privkeyblob, privkeyblob_len,
|
||||
passphrase);
|
||||
if(rc)
|
||||
if(ssh2_ecdsa_new_priv(&ec_ctx, session,
|
||||
privkeyfile, privkeyblob, privkeyblob_len,
|
||||
passphrase))
|
||||
return -1;
|
||||
|
||||
if(abstract)
|
||||
@@ -1017,22 +996,15 @@ static int hostkey_method_ssh_ed25519_initPEM(LIBSSH2_SESSION *session,
|
||||
void **abstract)
|
||||
{
|
||||
ssh2_ed25519_ctx *ed_ctx = NULL;
|
||||
int rc;
|
||||
|
||||
if(*abstract) {
|
||||
hostkey_method_ssh_ed25519_dtor(session, abstract);
|
||||
*abstract = NULL;
|
||||
}
|
||||
|
||||
if(privkeyfile)
|
||||
rc = ssh2_ed25519_new_priv_from_file(&ed_ctx, session,
|
||||
privkeyfile,
|
||||
passphrase);
|
||||
else
|
||||
rc = ssh2_ed25519_new_priv_from_blob(&ed_ctx, session,
|
||||
privkeyblob, privkeyblob_len,
|
||||
passphrase);
|
||||
if(rc)
|
||||
if(ssh2_ed25519_new_priv(&ed_ctx, session,
|
||||
privkeyfile, privkeyblob, privkeyblob_len,
|
||||
passphrase))
|
||||
return -1;
|
||||
|
||||
*abstract = ed_ctx;
|
||||
|
||||
125
src/libgcrypt.c
125
src/libgcrypt.c
@@ -238,25 +238,11 @@ int ssh2_dsa_new(ssh2_dsa_ctx **dsa,
|
||||
#endif
|
||||
|
||||
#if LIBSSH2_RSA
|
||||
int ssh2_rsa_new_priv_from_blob(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
(void)rsa;
|
||||
(void)blob;
|
||||
(void)blob_len;
|
||||
(void)passphrase;
|
||||
|
||||
return ssh2_err(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
||||
"Unable to extract private key from memory: "
|
||||
"Method unimplemented in libgcrypt backend");
|
||||
}
|
||||
|
||||
int ssh2_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
int ssh2_rsa_new_priv(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned char *data, *save_data;
|
||||
@@ -265,13 +251,19 @@ int ssh2_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
unsigned char *n, *e, *d, *p, *q, *e1, *e2, *coeff;
|
||||
unsigned int nlen, elen, dlen, plen, qlen, e1len, e2len, coefflen;
|
||||
|
||||
fp = ssh2_fopen(filename, "rb");
|
||||
if(!fp)
|
||||
return -1;
|
||||
|
||||
ret = ssh2_pem_parse_FILE(session, PEM_RSA_HEADER, PEM_RSA_FOOTER,
|
||||
fp, passphrase, &data, &datalen);
|
||||
fclose(fp);
|
||||
if(filename) {
|
||||
fp = ssh2_fopen(filename, "rb");
|
||||
if(!fp)
|
||||
return -1;
|
||||
ret = ssh2_pem_parse_FILE(session, PEM_RSA_HEADER, PEM_RSA_FOOTER,
|
||||
fp, passphrase,
|
||||
&data, &datalen);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
ret = ssh2_pem_parse_blob(session, PEM_RSA_HEADER, PEM_RSA_FOOTER,
|
||||
blob, blob_len, passphrase,
|
||||
&data, &datalen);
|
||||
if(ret)
|
||||
return -1;
|
||||
|
||||
@@ -352,25 +344,11 @@ fail:
|
||||
#endif
|
||||
|
||||
#if LIBSSH2_DSA
|
||||
int ssh2_dsa_new_priv_from_blob(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
(void)dsa;
|
||||
(void)blob;
|
||||
(void)blob_len;
|
||||
(void)passphrase;
|
||||
|
||||
return ssh2_err(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
||||
"Unable to extract private key from memory: "
|
||||
"Method unimplemented in libgcrypt backend");
|
||||
}
|
||||
|
||||
int ssh2_dsa_new_priv_from_file(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
int ssh2_dsa_new_priv(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned char *data, *save_data;
|
||||
@@ -379,13 +357,20 @@ int ssh2_dsa_new_priv_from_file(ssh2_dsa_ctx **dsa,
|
||||
unsigned char *p, *q, *g, *y, *x;
|
||||
unsigned int plen, qlen, glen, ylen, xlen;
|
||||
|
||||
fp = ssh2_fopen(filename, "rb");
|
||||
if(!fp)
|
||||
return -1;
|
||||
if(filename) {
|
||||
fp = ssh2_fopen(filename, "rb");
|
||||
if(!fp)
|
||||
return -1;
|
||||
|
||||
ret = ssh2_pem_parse_FILE(session, PEM_DSA_HEADER, PEM_DSA_FOOTER,
|
||||
fp, passphrase, &data, &datalen);
|
||||
fclose(fp);
|
||||
ret = ssh2_pem_parse_FILE(session, PEM_DSA_HEADER, PEM_DSA_FOOTER,
|
||||
fp, passphrase,
|
||||
&data, &datalen);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
ret = ssh2_pem_parse_blob(session, PEM_DSA_HEADER, PEM_DSA_FOOTER,
|
||||
blob, blob_len, passphrase,
|
||||
&data, &datalen);
|
||||
if(ret)
|
||||
return -1;
|
||||
|
||||
@@ -696,41 +681,25 @@ int ssh2_cipher_crypt(ssh2_cipher_ctx *ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
(void)method;
|
||||
(void)method_len;
|
||||
(void)pubkeydata;
|
||||
(void)pubkeydata_len;
|
||||
(void)privkeyblob;
|
||||
(void)privkeyblob_len;
|
||||
(void)passphrase;
|
||||
|
||||
return ssh2_err(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
||||
"Unable to extract public key from private key in "
|
||||
"memory: Method unimplemented in libgcrypt backend");
|
||||
}
|
||||
|
||||
int ssh2_pub_privkey_file(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *passphrase)
|
||||
int ssh2_pub_privkey(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
(void)method;
|
||||
(void)method_len;
|
||||
(void)pubkeydata;
|
||||
(void)pubkeydata_len;
|
||||
(void)privatekey;
|
||||
(void)privkeyblob;
|
||||
(void)privkeyblob_len;
|
||||
(void)passphrase;
|
||||
|
||||
return ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key from private key "
|
||||
"file: Method unimplemented in libgcrypt backend");
|
||||
return ssh2_err(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
||||
"Unable to extract public key from private key: "
|
||||
"Method unimplemented in libgcrypt backend");
|
||||
}
|
||||
|
||||
void ssh2_dh_init(ssh2_dh_ctx *dhctx)
|
||||
|
||||
274
src/mbedtls.c
274
src/mbedtls.c
@@ -354,14 +354,16 @@ int ssh2_rsa_new(ssh2_rsa_ctx **rsa,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssh2_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
int ssh2_rsa_new_priv(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
int ret;
|
||||
mbedtls_pk_context pkey;
|
||||
mbedtls_rsa_context *pk_rsa;
|
||||
unsigned char *data_nullterm = NULL;
|
||||
|
||||
(void)session;
|
||||
|
||||
@@ -370,61 +372,35 @@ int ssh2_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
return -1;
|
||||
|
||||
mbedtls_rsa_init(*rsa);
|
||||
|
||||
if(!filename) {
|
||||
/* mbedtls checks in "mbedtls/pkparse.c:1184"
|
||||
if "key[keylen - 1] != '\0'"
|
||||
private-key from memory fails if the last byte is not a null byte */
|
||||
data_nullterm = mbedtls_calloc(blob_len + 1, 1);
|
||||
if(!data_nullterm) {
|
||||
ssh2_rsa_free(*rsa);
|
||||
*rsa = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data_nullterm, blob, blob_len);
|
||||
data_nullterm[blob_len] = 0;
|
||||
}
|
||||
|
||||
mbedtls_pk_init(&pkey);
|
||||
|
||||
ret = mbedtls_pk_parse_keyfile(&pkey, filename, passphrase,
|
||||
if(!filename) {
|
||||
ret = mbedtls_pk_parse_key(&pkey, data_nullterm, blob_len + 1,
|
||||
(const unsigned char *)passphrase,
|
||||
passphrase ? strlen(passphrase) : 0,
|
||||
mbedtls_ctr_drbg_random, &mbed_ctr_drbg);
|
||||
if(ret || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) {
|
||||
mbedtls_pk_free(&pkey);
|
||||
ssh2_rsa_free(*rsa);
|
||||
*rsa = NULL;
|
||||
return -1;
|
||||
mbed_zero_free(data_nullterm, blob_len + 1);
|
||||
}
|
||||
|
||||
pk_rsa = mbedtls_pk_rsa(pkey);
|
||||
mbedtls_rsa_copy(*rsa, pk_rsa);
|
||||
mbedtls_pk_free(&pkey);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ssh2_rsa_new_priv_from_blob(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
int ret;
|
||||
mbedtls_pk_context pkey;
|
||||
mbedtls_rsa_context *pk_rsa;
|
||||
unsigned char *data_nullterm;
|
||||
|
||||
(void)session;
|
||||
|
||||
*rsa = mbedtls_calloc(1, sizeof(ssh2_rsa_ctx));
|
||||
if(!*rsa)
|
||||
return -1;
|
||||
|
||||
mbedtls_rsa_init(*rsa);
|
||||
|
||||
/* mbedtls checks in "mbedtls/pkparse.c:1184" if "key[keylen - 1] != '\0'"
|
||||
private-key from memory fails if the last byte is not a null byte */
|
||||
data_nullterm = mbedtls_calloc(blob_len + 1, 1);
|
||||
if(!data_nullterm) {
|
||||
ssh2_rsa_free(*rsa);
|
||||
*rsa = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data_nullterm, blob, blob_len);
|
||||
data_nullterm[blob_len] = 0;
|
||||
|
||||
mbedtls_pk_init(&pkey);
|
||||
|
||||
ret = mbedtls_pk_parse_key(&pkey, data_nullterm, blob_len + 1,
|
||||
(const unsigned char *)passphrase,
|
||||
passphrase ? strlen(passphrase) : 0,
|
||||
mbedtls_ctr_drbg_random, &mbed_ctr_drbg);
|
||||
mbed_zero_free(data_nullterm, blob_len + 1);
|
||||
else
|
||||
ret = mbedtls_pk_parse_keyfile(&pkey, filename, passphrase,
|
||||
mbedtls_ctr_drbg_random,
|
||||
&mbed_ctr_drbg);
|
||||
|
||||
if(ret || mbedtls_pk_get_type(&pkey) != MBEDTLS_PK_RSA) {
|
||||
mbedtls_pk_free(&pkey);
|
||||
@@ -645,61 +621,43 @@ static int mbed_pub_priv_key(LIBSSH2_SESSION *session,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssh2_pub_privkey_file(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *passphrase)
|
||||
int ssh2_pub_privkey(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
mbedtls_pk_context pkey;
|
||||
char buf[1024];
|
||||
int ret;
|
||||
unsigned char *data_nullterm = NULL;
|
||||
|
||||
mbedtls_pk_init(&pkey);
|
||||
ret = mbedtls_pk_parse_keyfile(&pkey, privatekey, passphrase,
|
||||
mbedtls_ctr_drbg_random, &mbed_ctr_drbg);
|
||||
if(ret) {
|
||||
mbedtls_strerror(ret, (char *)buf, sizeof(buf));
|
||||
mbedtls_pk_free(&pkey);
|
||||
return ssh2_err_flags(session, LIBSSH2_ERROR_FILE, buf,
|
||||
SSH2_ERR_FLAG_DUP);
|
||||
if(!privatekey) {
|
||||
/* mbedtls checks in "mbedtls/pkparse.c:1184"
|
||||
if "key[keylen - 1] != '\0'"
|
||||
private-key from memory fails if the last byte is not a null byte */
|
||||
data_nullterm = mbedtls_calloc(privkeyblob_len + 1, 1);
|
||||
if(!data_nullterm)
|
||||
return -1;
|
||||
|
||||
memcpy(data_nullterm, privkeyblob, privkeyblob_len);
|
||||
data_nullterm[privkeyblob_len] = 0;
|
||||
}
|
||||
|
||||
ret = mbed_pub_priv_key(session, method, method_len,
|
||||
pubkeydata, pubkeydata_len, &pkey);
|
||||
|
||||
mbedtls_pk_free(&pkey);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
mbedtls_pk_context pkey;
|
||||
char buf[1024];
|
||||
int ret;
|
||||
unsigned char *data_nullterm;
|
||||
|
||||
/* mbedtls checks in "mbedtls/pkparse.c:1184" if "key[keylen - 1] != '\0'"
|
||||
private-key from memory fails if the last byte is not a null byte */
|
||||
data_nullterm = mbedtls_calloc(privkeyblob_len + 1, 1);
|
||||
if(!data_nullterm)
|
||||
return -1;
|
||||
|
||||
memcpy(data_nullterm, privkeyblob, privkeyblob_len);
|
||||
data_nullterm[privkeyblob_len] = 0;
|
||||
|
||||
mbedtls_pk_init(&pkey);
|
||||
|
||||
ret = mbedtls_pk_parse_key(&pkey, data_nullterm, privkeyblob_len + 1,
|
||||
(const unsigned char *)passphrase,
|
||||
passphrase ? strlen(passphrase) : 0,
|
||||
mbedtls_ctr_drbg_random, &mbed_ctr_drbg);
|
||||
mbed_zero_free(data_nullterm, privkeyblob_len + 1);
|
||||
if(!privatekey) {
|
||||
ret = mbedtls_pk_parse_key(&pkey, data_nullterm, privkeyblob_len + 1,
|
||||
(const unsigned char *)passphrase,
|
||||
passphrase ? strlen(passphrase) : 0,
|
||||
mbedtls_ctr_drbg_random, &mbed_ctr_drbg);
|
||||
mbed_zero_free(data_nullterm, privkeyblob_len + 1);
|
||||
}
|
||||
else
|
||||
ret = mbedtls_pk_parse_keyfile(&pkey, privatekey, passphrase,
|
||||
mbedtls_ctr_drbg_random,
|
||||
&mbed_ctr_drbg);
|
||||
|
||||
if(ret) {
|
||||
mbedtls_strerror(ret, (char *)buf, sizeof(buf));
|
||||
@@ -997,10 +955,11 @@ cleanup:
|
||||
}
|
||||
|
||||
static int mbed_parse_eckey(ssh2_ecdsa_ctx **ctx, mbedtls_pk_context *pkey,
|
||||
const unsigned char *data, size_t data_len,
|
||||
const char *data, size_t data_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
if(mbedtls_pk_parse_key(pkey, data, data_len,
|
||||
if(mbedtls_pk_parse_key(pkey,
|
||||
(const unsigned char *)data, data_len,
|
||||
(const unsigned char *)passphrase,
|
||||
passphrase ? strlen(passphrase) : 0,
|
||||
mbedtls_ctr_drbg_random, &mbed_ctr_drbg))
|
||||
@@ -1062,8 +1021,7 @@ static int mbed_ecdsa_curve_type_from_name(const char *name,
|
||||
|
||||
static int mbed_parse_openssh_key(ssh2_ecdsa_ctx **ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const unsigned char *data,
|
||||
size_t data_len,
|
||||
const char *data, size_t data_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
ssh2_curve_type type;
|
||||
@@ -1072,8 +1030,7 @@ static int mbed_parse_openssh_key(ssh2_ecdsa_ctx **ctx,
|
||||
size_t curvelen, exponentlen, pointlen;
|
||||
unsigned char *curve, *exponent, *point_buf;
|
||||
|
||||
if(ssh2_openssh_pem_parse_blob(session,
|
||||
(const char *)data, data_len,
|
||||
if(ssh2_openssh_pem_parse_blob(session, data, data_len,
|
||||
passphrase, &decrypted))
|
||||
goto failed;
|
||||
|
||||
@@ -1131,39 +1088,49 @@ cleanup:
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new private key given a file path and password
|
||||
* Creates a new private key given a file/blob and password
|
||||
*/
|
||||
int ssh2_ecdsa_new_priv_from_file(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
int ssh2_ecdsa_new_priv(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
mbedtls_pk_context pkey;
|
||||
unsigned char *data = NULL;
|
||||
char *data = NULL;
|
||||
size_t data_len = 0;
|
||||
FILE *fp = NULL;
|
||||
long file_size;
|
||||
|
||||
mbedtls_pk_init(&pkey);
|
||||
|
||||
fp = ssh2_fopen(filename, "rb");
|
||||
if(!fp)
|
||||
goto cleanup;
|
||||
if(fseek(fp, 0, SEEK_END))
|
||||
goto cleanup;
|
||||
file_size = ftell(fp);
|
||||
if(file_size < 0 || file_size > (1024 * 1024))
|
||||
goto cleanup;
|
||||
if(fseek(fp, 0, SEEK_SET))
|
||||
goto cleanup;
|
||||
data_len = (size_t)file_size;
|
||||
if(data_len == 0)
|
||||
goto cleanup;
|
||||
data = SSH2_ALLOC(session, data_len + 1);
|
||||
if(!data)
|
||||
goto cleanup;
|
||||
if(fread(data, 1, data_len, fp) != data_len)
|
||||
goto cleanup;
|
||||
if(filename) {
|
||||
long file_size;
|
||||
fp = ssh2_fopen(filename, "rb");
|
||||
if(!fp)
|
||||
goto cleanup;
|
||||
if(fseek(fp, 0, SEEK_END))
|
||||
goto cleanup;
|
||||
file_size = ftell(fp);
|
||||
if(file_size < 0 || file_size > (1024 * 1024))
|
||||
goto cleanup;
|
||||
if(fseek(fp, 0, SEEK_SET))
|
||||
goto cleanup;
|
||||
data_len = (size_t)file_size;
|
||||
if(data_len == 0)
|
||||
goto cleanup;
|
||||
data = mbedtls_calloc(1, data_len + 1);
|
||||
if(!data)
|
||||
goto cleanup;
|
||||
if(fread(data, 1, data_len, fp) != data_len)
|
||||
goto cleanup;
|
||||
}
|
||||
else {
|
||||
data_len = blob_len;
|
||||
data = mbedtls_calloc(1, data_len + 1);
|
||||
if(!data)
|
||||
goto cleanup;
|
||||
memcpy(data, blob, blob_len);
|
||||
}
|
||||
|
||||
data[data_len] = 0; /* for mbedtls_pk_parse_key() */
|
||||
if(mbed_parse_eckey(ec_ctx, &pkey, data, data_len + 1, passphrase) == 0)
|
||||
@@ -1175,54 +1142,13 @@ cleanup:
|
||||
|
||||
if(fp)
|
||||
fclose(fp);
|
||||
if(data) {
|
||||
ssh2_explicit_zero(data, data_len + 1);
|
||||
SSH2_FREE(session, data);
|
||||
}
|
||||
mbed_zero_free(data, data_len + 1);
|
||||
|
||||
mbedtls_pk_free(&pkey);
|
||||
|
||||
return *ec_ctx ? 0 : -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new private key given a file data and password
|
||||
*/
|
||||
int ssh2_ecdsa_new_priv_from_blob(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
unsigned char *data_nullterm;
|
||||
mbedtls_pk_context pkey;
|
||||
|
||||
(void)session;
|
||||
|
||||
mbedtls_pk_init(&pkey);
|
||||
|
||||
data_nullterm = mbedtls_calloc(1, blob_len + 1);
|
||||
if(!data_nullterm)
|
||||
goto cleanup;
|
||||
|
||||
memcpy(data_nullterm, blob, blob_len);
|
||||
data_nullterm[blob_len] = 0;
|
||||
|
||||
if(mbed_parse_eckey(ec_ctx, &pkey, data_nullterm, blob_len + 1,
|
||||
passphrase) == 0)
|
||||
goto cleanup;
|
||||
|
||||
mbed_parse_openssh_key(ec_ctx, session, data_nullterm, blob_len + 1,
|
||||
passphrase);
|
||||
|
||||
cleanup:
|
||||
|
||||
mbedtls_pk_free(&pkey);
|
||||
|
||||
mbed_zero_free(data_nullterm, blob_len + 1);
|
||||
|
||||
return *ec_ctx ? 0 : -1;
|
||||
}
|
||||
|
||||
static unsigned char *mbed_write_bn(unsigned char *buf,
|
||||
const mbedtls_mpi *bn, size_t bn_size)
|
||||
{
|
||||
|
||||
20
src/misc.c
20
src/misc.c
@@ -999,14 +999,15 @@ int ssh2_timingsafe_bcmp(const void *b1, const void *b2, size_t n)
|
||||
}
|
||||
|
||||
#ifndef LIBSSH2_KEY_SK
|
||||
int ssh2_sk_pubkey_blob(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
int *algorithm, unsigned char *flags,
|
||||
const char **application,
|
||||
const unsigned char **key_handle, size_t *handle_len,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
int ssh2_sk_pubkey(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
int *algorithm, unsigned char *flags,
|
||||
const char **application,
|
||||
const unsigned char **key_handle, size_t *handle_len,
|
||||
const char *privatekey,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
(void)method;
|
||||
(void)method_len;
|
||||
@@ -1017,12 +1018,13 @@ int ssh2_sk_pubkey_blob(LIBSSH2_SESSION *session,
|
||||
(void)application;
|
||||
(void)key_handle;
|
||||
(void)handle_len;
|
||||
(void)privatekey;
|
||||
(void)privkeyblob;
|
||||
(void)privkeyblob_len;
|
||||
(void)passphrase;
|
||||
|
||||
return ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public SK key from private key file: "
|
||||
"Unable to extract public SK key from private key: "
|
||||
"Method unimplemented in "
|
||||
SSH2_CRYPTO_ENGINE_NAME " backend");
|
||||
}
|
||||
|
||||
505
src/openssl.c
505
src/openssl.c
@@ -1049,34 +1049,6 @@ static int ossl_passphrase_cb(char *buf, int size, int rwflag,
|
||||
#endif /* LIBSSH2_RSA || LIBSSH2_DSA || LIBSSH2_ECDSA || LIBSSH2_ED25519 */
|
||||
|
||||
#if LIBSSH2_RSA
|
||||
int ssh2_rsa_new_priv_from_blob(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
int rc = 0;
|
||||
BIO *bp;
|
||||
|
||||
OSSL_INIT_IF_NEEDED();
|
||||
|
||||
bp = BIO_new_mem_buf(blob, (int)blob_len);
|
||||
if(bp)
|
||||
#ifdef USE_OPENSSL_3
|
||||
*rsa = PEM_read_bio_PrivateKey(bp, NULL, ossl_passphrase_cb,
|
||||
SSH2_UNCONST(passphrase));
|
||||
#else
|
||||
*rsa = PEM_read_bio_RSAPrivateKey(bp, NULL, ossl_passphrase_cb,
|
||||
SSH2_UNCONST(passphrase));
|
||||
#endif
|
||||
BIO_free(bp);
|
||||
|
||||
if(!*rsa)
|
||||
rc = ossl_key_from_openssh_blob(session, (void **)rsa, "ssh-rsa",
|
||||
NULL, NULL, NULL, NULL,
|
||||
blob, blob_len, passphrase);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static unsigned char *ossl_rsa_to_pubkey(LIBSSH2_SESSION *session,
|
||||
ssh2_rsa_ctx *rsa, size_t *key_len)
|
||||
{
|
||||
@@ -1373,7 +1345,7 @@ static int ossl_rsa_openssh_priv_new(ssh2_rsa_ctx **rsa,
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
rc = ssh2_get_string(decrypted, &buf, NULL);
|
||||
if(rc || !buf) {
|
||||
ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
@@ -1396,17 +1368,23 @@ cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ssh2_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
int ssh2_rsa_new_priv(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
int rc = 0;
|
||||
BIO *bp;
|
||||
|
||||
OSSL_INIT_IF_NEEDED();
|
||||
|
||||
bp = BIO_new_file(filename, "r");
|
||||
*rsa = NULL;
|
||||
|
||||
if(filename)
|
||||
bp = BIO_new_file(filename, "r");
|
||||
else
|
||||
bp = BIO_new_mem_buf(blob, (int)blob_len);
|
||||
if(bp)
|
||||
#ifdef USE_OPENSSL_3
|
||||
*rsa = PEM_read_bio_PrivateKey(bp, NULL, ossl_passphrase_cb,
|
||||
@@ -1417,42 +1395,20 @@ int ssh2_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
#endif
|
||||
BIO_free(bp);
|
||||
|
||||
if(!*rsa)
|
||||
rc = ossl_rsa_openssh_priv_new(rsa, session, filename, passphrase);
|
||||
if(!*rsa) {
|
||||
if(filename)
|
||||
rc = ossl_rsa_openssh_priv_new(rsa, session, filename, passphrase);
|
||||
else
|
||||
rc = ossl_key_from_openssh_blob(session, (void **)rsa, "ssh-rsa",
|
||||
NULL, NULL, NULL, NULL,
|
||||
blob, blob_len, passphrase);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LIBSSH2_DSA
|
||||
int ssh2_dsa_new_priv_from_blob(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
int rc = 0;
|
||||
BIO *bp;
|
||||
|
||||
OSSL_INIT_IF_NEEDED();
|
||||
|
||||
bp = BIO_new_mem_buf(blob, (int)blob_len);
|
||||
if(bp)
|
||||
#ifdef USE_OPENSSL_3
|
||||
*dsa = PEM_read_bio_PrivateKey(bp, NULL, ossl_passphrase_cb,
|
||||
SSH2_UNCONST(passphrase));
|
||||
#else
|
||||
*dsa = PEM_read_bio_DSAPrivateKey(bp, NULL, ossl_passphrase_cb,
|
||||
SSH2_UNCONST(passphrase));
|
||||
#endif
|
||||
BIO_free(bp);
|
||||
|
||||
if(!*dsa)
|
||||
rc = ossl_key_from_openssh_blob(session, (void **)dsa, "ssh-dsa",
|
||||
NULL, NULL, NULL, NULL,
|
||||
blob, blob_len, passphrase);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static unsigned char *ossl_dsa_to_pubkey(LIBSSH2_SESSION *session,
|
||||
ssh2_dsa_ctx *dsa, size_t *key_len)
|
||||
{
|
||||
@@ -1682,7 +1638,7 @@ static int ossl_dsa_openssh_priv_new(ssh2_dsa_ctx **dsa,
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
rc = ssh2_get_string(decrypted, &buf, NULL);
|
||||
if(rc || !buf) {
|
||||
ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
@@ -1705,17 +1661,23 @@ cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ssh2_dsa_new_priv_from_file(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
int ssh2_dsa_new_priv(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
int rc = 0;
|
||||
BIO *bp;
|
||||
|
||||
OSSL_INIT_IF_NEEDED();
|
||||
|
||||
bp = BIO_new_file(filename, "r");
|
||||
*dsa = NULL;
|
||||
|
||||
if(filename)
|
||||
bp = BIO_new_file(filename, "r");
|
||||
else
|
||||
bp = BIO_new_mem_buf(blob, (int)blob_len);
|
||||
if(bp)
|
||||
#ifdef USE_OPENSSL_3
|
||||
*dsa = PEM_read_bio_PrivateKey(bp, NULL, ossl_passphrase_cb,
|
||||
@@ -1726,43 +1688,19 @@ int ssh2_dsa_new_priv_from_file(ssh2_dsa_ctx **dsa,
|
||||
#endif
|
||||
BIO_free(bp);
|
||||
|
||||
if(!*dsa)
|
||||
rc = ossl_dsa_openssh_priv_new(dsa, session, filename, passphrase);
|
||||
if(!*dsa) {
|
||||
if(filename)
|
||||
rc = ossl_dsa_openssh_priv_new(dsa, session, filename, passphrase);
|
||||
else
|
||||
rc = ossl_key_from_openssh_blob(session, (void **)dsa, "ssh-dsa",
|
||||
NULL, NULL, NULL, NULL,
|
||||
blob, blob_len, passphrase);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif /* LIBSSH2_DSA */
|
||||
|
||||
#if LIBSSH2_ECDSA
|
||||
int ssh2_ecdsa_new_priv_from_blob(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
int rc = 0;
|
||||
BIO *bp;
|
||||
|
||||
OSSL_INIT_IF_NEEDED();
|
||||
|
||||
bp = BIO_new_mem_buf(blob, (int)blob_len);
|
||||
if(bp)
|
||||
#ifdef USE_OPENSSL_3
|
||||
*ec_ctx = PEM_read_bio_PrivateKey(bp, NULL, ossl_passphrase_cb,
|
||||
SSH2_UNCONST(passphrase));
|
||||
#else
|
||||
*ec_ctx = PEM_read_bio_ECPrivateKey(bp, NULL, ossl_passphrase_cb,
|
||||
SSH2_UNCONST(passphrase));
|
||||
#endif
|
||||
BIO_free(bp);
|
||||
|
||||
if(!*ec_ctx)
|
||||
rc = ossl_key_from_openssh_blob(session, (void **)ec_ctx, "ssh-ecdsa",
|
||||
NULL, NULL, NULL, NULL,
|
||||
blob, blob_len, passphrase);
|
||||
return rc;
|
||||
}
|
||||
#endif /* LIBSSH2_ECDSA */
|
||||
|
||||
#if LIBSSH2_ED25519
|
||||
|
||||
int ssh2_curve25519_new(LIBSSH2_SESSION *session,
|
||||
@@ -2164,15 +2102,12 @@ clean_exit:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ssh2_ed25519_new_priv_from_file(ssh2_ed25519_ctx **ed_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
int ssh2_ed25519_new_priv(ssh2_ed25519_ctx **ed_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
int rc;
|
||||
FILE *fp;
|
||||
unsigned char *buf;
|
||||
struct string_buf *decrypted = NULL;
|
||||
ssh2_ed25519_ctx *ctx = NULL;
|
||||
|
||||
if(!session)
|
||||
@@ -2180,78 +2115,81 @@ int ssh2_ed25519_new_priv_from_file(ssh2_ed25519_ctx **ed_ctx,
|
||||
|
||||
OSSL_INIT_IF_NEEDED();
|
||||
|
||||
fp = ssh2_fopen(filename, "r");
|
||||
if(!fp) {
|
||||
ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to open ED25519 private key file");
|
||||
return -1;
|
||||
}
|
||||
if(filename) {
|
||||
int rc;
|
||||
FILE *fp;
|
||||
unsigned char *buf;
|
||||
struct string_buf *decrypted = NULL;
|
||||
|
||||
rc = ssh2_openssh_pem_parse_FILE(session, fp, passphrase, &decrypted);
|
||||
fclose(fp);
|
||||
if(rc)
|
||||
return rc;
|
||||
fp = ssh2_fopen(filename, "r");
|
||||
if(!fp) {
|
||||
ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to open ED25519 private key file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
rc = ssh2_get_string(decrypted, &buf, NULL);
|
||||
if(rc || !buf) {
|
||||
ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
"Public key type in decrypted key data not found");
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
rc = ssh2_openssh_pem_parse_FILE(session, fp, passphrase, &decrypted);
|
||||
fclose(fp);
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
if(!strcmp("ssh-ed25519", (const char *)buf))
|
||||
rc = ossl_ed25519_openssh_priv_to_pubkey(session, decrypted,
|
||||
NULL, NULL, NULL, NULL, &ctx);
|
||||
else
|
||||
rc = -1;
|
||||
/* We have a new key file, now try and parse it using supported
|
||||
types */
|
||||
rc = ssh2_get_string(decrypted, &buf, NULL);
|
||||
if(rc || !buf) {
|
||||
ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
"Public key type in decrypted key data not found");
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if(rc == 0) {
|
||||
if(ed_ctx)
|
||||
*ed_ctx = ctx;
|
||||
else if(ctx)
|
||||
ssh2_ed25519_free(ctx);
|
||||
}
|
||||
if(!strcmp("ssh-ed25519", (const char *)buf))
|
||||
rc = ossl_ed25519_openssh_priv_to_pubkey(session, decrypted,
|
||||
NULL, NULL, NULL, NULL,
|
||||
&ctx);
|
||||
else
|
||||
rc = -1;
|
||||
|
||||
if(rc == 0) {
|
||||
if(ed_ctx)
|
||||
*ed_ctx = ctx;
|
||||
else if(ctx)
|
||||
ssh2_ed25519_free(ctx);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
if(decrypted)
|
||||
ssh2_string_buf_free(session, decrypted);
|
||||
if(decrypted)
|
||||
ssh2_string_buf_free(session, decrypted);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ssh2_ed25519_new_priv_from_blob(ssh2_ed25519_ctx **ed_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
ssh2_ed25519_ctx *ctx = NULL;
|
||||
BIO *bp;
|
||||
|
||||
OSSL_INIT_IF_NEEDED();
|
||||
|
||||
bp = BIO_new_mem_buf(blob, (int)blob_len);
|
||||
if(bp) {
|
||||
ctx = PEM_read_bio_PrivateKey(bp, NULL, ossl_passphrase_cb,
|
||||
SSH2_UNCONST(passphrase));
|
||||
BIO_free(bp);
|
||||
if(ctx) {
|
||||
if(EVP_PKEY_id(ctx) != EVP_PKEY_ED25519) {
|
||||
ssh2_ed25519_free(ctx);
|
||||
return ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
"Private key is not an ED25519 key");
|
||||
}
|
||||
|
||||
*ed_ctx = ctx;
|
||||
return 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
else {
|
||||
BIO *bp = BIO_new_mem_buf(blob, (int)blob_len);
|
||||
if(bp) {
|
||||
ctx = PEM_read_bio_PrivateKey(bp, NULL, ossl_passphrase_cb,
|
||||
SSH2_UNCONST(passphrase));
|
||||
BIO_free(bp);
|
||||
if(ctx) {
|
||||
if(EVP_PKEY_id(ctx) != EVP_PKEY_ED25519) {
|
||||
ssh2_ed25519_free(ctx);
|
||||
return ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
"Private key is not an ED25519 key");
|
||||
}
|
||||
|
||||
return ossl_key_from_openssh_blob(session, (void **)ed_ctx, "ssh-ed25519",
|
||||
NULL, NULL, NULL, NULL,
|
||||
blob, blob_len, passphrase);
|
||||
if(ed_ctx)
|
||||
*ed_ctx = ctx;
|
||||
else
|
||||
ssh2_ed25519_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ossl_key_from_openssh_blob(session,
|
||||
(void **)ed_ctx, "ssh-ed25519",
|
||||
NULL, NULL, NULL, NULL,
|
||||
blob, blob_len, passphrase);
|
||||
}
|
||||
}
|
||||
|
||||
int ssh2_ed25519_new_public(ssh2_ed25519_ctx **ed_ctx,
|
||||
@@ -3140,7 +3078,7 @@ static int ossl_ecdsa_openssh_priv_new(ssh2_ecdsa_ctx **ec_ctx,
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
rc = ssh2_get_string(decrypted, &buf, NULL);
|
||||
if(rc || !buf) {
|
||||
ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
@@ -3165,17 +3103,23 @@ cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ssh2_ecdsa_new_priv_from_file(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
int ssh2_ecdsa_new_priv(ssh2_ecdsa_ctx **ec_ctx,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
int rc = 0;
|
||||
BIO *bp;
|
||||
|
||||
OSSL_INIT_IF_NEEDED();
|
||||
|
||||
bp = BIO_new_file(filename, "r");
|
||||
*ec_ctx = NULL;
|
||||
|
||||
if(filename)
|
||||
bp = BIO_new_file(filename, "r");
|
||||
else
|
||||
bp = BIO_new_mem_buf(blob, (int)blob_len);
|
||||
if(bp)
|
||||
#ifdef USE_OPENSSL_3
|
||||
*ec_ctx = PEM_read_bio_PrivateKey(bp, NULL, ossl_passphrase_cb,
|
||||
@@ -3186,9 +3130,16 @@ int ssh2_ecdsa_new_priv_from_file(ssh2_ecdsa_ctx **ec_ctx,
|
||||
#endif
|
||||
BIO_free(bp);
|
||||
|
||||
if(!*ec_ctx)
|
||||
rc = ossl_ecdsa_openssh_priv_new(ec_ctx, session, filename,
|
||||
passphrase);
|
||||
if(!*ec_ctx) {
|
||||
if(filename)
|
||||
rc = ossl_ecdsa_openssh_priv_new(ec_ctx, session, filename,
|
||||
passphrase);
|
||||
else
|
||||
rc = ossl_key_from_openssh_blob(session,
|
||||
(void **)ec_ctx, "ssh-ecdsa",
|
||||
NULL, NULL, NULL, NULL,
|
||||
blob, blob_len, passphrase);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3659,14 +3610,13 @@ static int ossl_key_from_openssh_file(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
rc = ssh2_openssh_pem_parse_FILE(session, fp, passphrase, &decrypted);
|
||||
|
||||
fclose(fp);
|
||||
if(rc) {
|
||||
ssh2_err(session, LIBSSH2_ERROR_FILE, "Not an OpenSSH key file");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
rc = ssh2_get_string(decrypted, &buf, NULL);
|
||||
if(rc || !buf) {
|
||||
ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
@@ -3723,82 +3673,6 @@ cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ssh2_pub_privkey_file(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *passphrase)
|
||||
{
|
||||
BIO *bp;
|
||||
EVP_PKEY *pk;
|
||||
int pktype;
|
||||
int rc;
|
||||
|
||||
ssh2_deb((session, LIBSSH2_TRACE_AUTH,
|
||||
"Computing public key from private key file: %s", privatekey));
|
||||
|
||||
bp = BIO_new_file(privatekey, "r");
|
||||
if(!bp)
|
||||
return ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key from private key file: "
|
||||
"Unable to open private key file");
|
||||
|
||||
(void)BIO_reset(bp);
|
||||
pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, SSH2_UNCONST(passphrase));
|
||||
BIO_free(bp);
|
||||
|
||||
if(!pk) {
|
||||
/* Try OpenSSH format */
|
||||
rc = ossl_key_from_openssh_file(session, method, method_len,
|
||||
pubkeydata, pubkeydata_len,
|
||||
privatekey, passphrase);
|
||||
if(rc)
|
||||
return ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key "
|
||||
"from private key file: "
|
||||
"Wrong passphrase or invalid/unrecognized "
|
||||
"private key file format");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pktype = EVP_PKEY_id(pk);
|
||||
|
||||
switch(pktype) {
|
||||
#if LIBSSH2_ED25519
|
||||
case EVP_PKEY_ED25519:
|
||||
rc = ossl_ed25519_evp_to_pubkey(session, method, method_len,
|
||||
pubkeydata, pubkeydata_len, pk);
|
||||
break;
|
||||
#endif /* LIBSSH2_ED25519 */
|
||||
#if LIBSSH2_RSA
|
||||
case EVP_PKEY_RSA:
|
||||
rc = ossl_rsa_evp_to_pubkey(session, method, method_len,
|
||||
pubkeydata, pubkeydata_len, pk);
|
||||
break;
|
||||
#endif /* LIBSSH2_RSA */
|
||||
#if LIBSSH2_DSA
|
||||
case EVP_PKEY_DSA:
|
||||
rc = ossl_dsa_evp_to_pubkey(session, method, method_len,
|
||||
pubkeydata, pubkeydata_len, pk);
|
||||
break;
|
||||
#endif /* LIBSSH2_DSA */
|
||||
#if LIBSSH2_ECDSA
|
||||
case EVP_PKEY_EC:
|
||||
rc = ossl_ecdsa_evp_to_pubkey(session, method, method_len,
|
||||
pubkeydata, pubkeydata_len, 0, pk);
|
||||
break;
|
||||
#endif /* LIBSSH2_ECDSA */
|
||||
default:
|
||||
rc = ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key from private key file: "
|
||||
"Unsupported private key file format");
|
||||
break;
|
||||
}
|
||||
|
||||
EVP_PKEY_free(pk);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ossl_key_from_openssh_blob(LIBSSH2_SESSION *session,
|
||||
void **key_ctx,
|
||||
const char *want_method,
|
||||
@@ -3827,14 +3701,13 @@ static int ossl_key_from_openssh_blob(LIBSSH2_SESSION *session,
|
||||
|
||||
OSSL_INIT_IF_NEEDED();
|
||||
|
||||
rc = ssh2_openssh_pem_parse_blob(session,
|
||||
privkeyblob, privkeyblob_len,
|
||||
rc = ssh2_openssh_pem_parse_blob(session, privkeyblob, privkeyblob_len,
|
||||
passphrase,
|
||||
&decrypted);
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
rc = ssh2_get_string(decrypted, &buf, NULL);
|
||||
if(rc || !buf) {
|
||||
rc = ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
@@ -3899,8 +3772,8 @@ static int ossl_key_from_openssh_blob(LIBSSH2_SESSION *session,
|
||||
|
||||
if(rc == LIBSSH2_ERROR_FILE)
|
||||
rc = ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key from private key file: "
|
||||
"invalid/unrecognized private key file format");
|
||||
"Unable to extract public key from private key: "
|
||||
"invalid/unrecognized private key format");
|
||||
|
||||
cleanup:
|
||||
|
||||
@@ -3910,14 +3783,15 @@ cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ssh2_sk_pubkey_blob(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
int *algorithm, unsigned char *flags,
|
||||
const char **application,
|
||||
const unsigned char **key_handle, size_t *handle_len,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
int ssh2_sk_pubkey(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
int *algorithm, unsigned char *flags,
|
||||
const char **application,
|
||||
const unsigned char **key_handle, size_t *handle_len,
|
||||
const char *privatekey,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
int rc;
|
||||
unsigned char *buf = NULL;
|
||||
@@ -3931,14 +3805,22 @@ int ssh2_sk_pubkey_blob(LIBSSH2_SESSION *session,
|
||||
|
||||
OSSL_INIT_IF_NEEDED();
|
||||
|
||||
rc = ssh2_openssh_pem_parse_blob(session,
|
||||
privkeyblob, privkeyblob_len,
|
||||
passphrase,
|
||||
&decrypted);
|
||||
if(privatekey) {
|
||||
FILE *fp = ssh2_fopen(privatekey, "rb");
|
||||
if(!fp)
|
||||
return ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Opening the private key failed");
|
||||
rc = ssh2_openssh_pem_parse_FILE(session, fp, passphrase, &decrypted);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
rc = ssh2_openssh_pem_parse_blob(session, privkeyblob, privkeyblob_len,
|
||||
passphrase,
|
||||
&decrypted);
|
||||
if(rc)
|
||||
return rc;
|
||||
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
/* We have a new key file, now try and parse it using supported types */
|
||||
rc = ssh2_get_string(decrypted, &buf, NULL);
|
||||
if(rc || !buf) {
|
||||
rc = ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
@@ -3985,8 +3867,8 @@ int ssh2_sk_pubkey_blob(LIBSSH2_SESSION *session,
|
||||
|
||||
if(rc == LIBSSH2_ERROR_FILE)
|
||||
rc = ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key from private key file: "
|
||||
"invalid/unrecognized private key file format");
|
||||
"Unable to extract public key from private key: "
|
||||
"invalid/unrecognized private key format");
|
||||
|
||||
cleanup:
|
||||
|
||||
@@ -4000,12 +3882,12 @@ cleanup:
|
||||
#define HAVE_SSLERROR_BAD_DECRYPT
|
||||
#endif
|
||||
|
||||
int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privkeyblob,
|
||||
size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
int ssh2_pub_privkey(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
int rc;
|
||||
BIO *bp;
|
||||
@@ -4015,13 +3897,29 @@ int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
unsigned long sslError;
|
||||
#endif
|
||||
|
||||
ssh2_deb((session, LIBSSH2_TRACE_AUTH,
|
||||
"Computing public key from private key."));
|
||||
OSSL_INIT_IF_NEEDED();
|
||||
|
||||
if(privatekey) {
|
||||
ssh2_deb((session, LIBSSH2_TRACE_AUTH,
|
||||
"Computing public key from private key file: %s",
|
||||
privatekey));
|
||||
|
||||
bp = BIO_new_file(privatekey, "r");
|
||||
if(!bp)
|
||||
return ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to open private key file");
|
||||
}
|
||||
else {
|
||||
ssh2_deb((session, LIBSSH2_TRACE_AUTH,
|
||||
"Computing public key from private key."));
|
||||
|
||||
bp = BIO_new_mem_buf(privkeyblob, (int)privkeyblob_len);
|
||||
if(!bp)
|
||||
return ssh2_err(session, LIBSSH2_ERROR_ALLOC,
|
||||
"Unable to allocate memory when computing "
|
||||
"public key");
|
||||
}
|
||||
|
||||
bp = BIO_new_mem_buf(privkeyblob, (int)privkeyblob_len);
|
||||
if(!bp)
|
||||
return ssh2_err(session, LIBSSH2_ERROR_ALLOC,
|
||||
"Unable to allocate memory when computing public key");
|
||||
(void)BIO_reset(bp);
|
||||
pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, SSH2_UNCONST(passphrase));
|
||||
#ifdef HAVE_SSLERROR_BAD_DECRYPT
|
||||
@@ -4031,11 +3929,18 @@ int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
|
||||
if(!pk) {
|
||||
/* Try OpenSSH format */
|
||||
rc = ossl_key_from_openssh_blob(session, NULL, NULL,
|
||||
method, method_len,
|
||||
pubkeydata, pubkeydata_len,
|
||||
privkeyblob, privkeyblob_len,
|
||||
passphrase);
|
||||
if(privatekey)
|
||||
rc = ossl_key_from_openssh_file(session,
|
||||
method, method_len,
|
||||
pubkeydata, pubkeydata_len,
|
||||
privatekey,
|
||||
passphrase);
|
||||
else
|
||||
rc = ossl_key_from_openssh_blob(session, NULL, NULL,
|
||||
method, method_len,
|
||||
pubkeydata, pubkeydata_len,
|
||||
privkeyblob, privkeyblob_len,
|
||||
passphrase);
|
||||
if(rc == 0)
|
||||
return 0;
|
||||
|
||||
@@ -4048,8 +3953,8 @@ int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
"Wrong passphrase for private key");
|
||||
#endif
|
||||
return ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key from private key file: "
|
||||
"Unsupported private key file format");
|
||||
"Unable to extract public key from private key: "
|
||||
"Unsupported private key format");
|
||||
}
|
||||
|
||||
pktype = EVP_PKEY_id(pk);
|
||||
@@ -4081,8 +3986,8 @@ int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
#endif /* LIBSSH2_ECDSA */
|
||||
default:
|
||||
rc = ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key from private key file: "
|
||||
"Unsupported private key file format");
|
||||
"Unable to extract public key from private key: "
|
||||
"Unsupported private key format");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
# define LIBSSH2_3DES 1
|
||||
#endif
|
||||
|
||||
#define LIBSSH2_KEY_SK /* implements ssh2_sk_pubkey_blob() */
|
||||
#define LIBSSH2_KEY_SK /* implements ssh2_sk_pubkey() */
|
||||
|
||||
#include "crypto_config.h"
|
||||
|
||||
|
||||
251
src/os400qc3.c
251
src/os400qc3.c
@@ -2073,34 +2073,14 @@ static int load_rsa_private_file(LIBSSH2_SESSION *session,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssh2_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
static int os400_pub_privkey_file(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata,
|
||||
size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *passphrase)
|
||||
{
|
||||
ssh2_rsa_ctx *ctx = init_crypto_ctx(NULL);
|
||||
int ret;
|
||||
|
||||
if(!ctx)
|
||||
return -1;
|
||||
ret = load_rsa_private_file(session, filename, passphrase,
|
||||
rsapkcs1privkey, rsapkcs8privkey,
|
||||
(void *)ctx);
|
||||
if(ret) {
|
||||
ssh2_os400qc3_crypto_dtor(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
*rsa = ctx;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssh2_pub_privkey_file(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *passphrase)
|
||||
{
|
||||
struct loadpubkeydata p;
|
||||
struct loadpubkeydata p = { 0 };
|
||||
int ret;
|
||||
|
||||
*method = NULL;
|
||||
@@ -2134,91 +2114,19 @@ int ssh2_pub_privkey_file(LIBSSH2_SESSION *session,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssh2_rsa_new_priv_from_blob(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
static int os400_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata,
|
||||
size_t *pubkeydata_len,
|
||||
const char *privkeyblob,
|
||||
size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
ssh2_rsa_ctx *ctx = init_crypto_ctx(NULL);
|
||||
struct loadpubkeydata p = { 0 };
|
||||
unsigned char *data = NULL;
|
||||
size_t datalen = 0;
|
||||
int ret;
|
||||
|
||||
if(!ctx)
|
||||
return -1;
|
||||
|
||||
/* Try with "ENCRYPTED PRIVATE KEY" PEM armor.
|
||||
--> PKCS#8 EncryptedPrivateKeyInfo */
|
||||
ret = ssh2_pem_parse_blob(session,
|
||||
beginencprivkeyhdr, endencprivkeyhdr,
|
||||
blob, blob_len,
|
||||
passphrase,
|
||||
&data, &datalen);
|
||||
|
||||
/* Try with "PRIVATE KEY" PEM armor.
|
||||
--> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */
|
||||
if(ret)
|
||||
ret = ssh2_pem_parse_blob(session,
|
||||
beginprivkeyhdr, endprivkeyhdr,
|
||||
blob, blob_len,
|
||||
passphrase,
|
||||
&data, &datalen);
|
||||
|
||||
if(!ret) {
|
||||
/* Process PKCS#8. */
|
||||
ret = rsapkcs8privkey(session,
|
||||
data, datalen, passphrase, (void *)&ctx);
|
||||
}
|
||||
else {
|
||||
/* Try with "RSA PRIVATE KEY" PEM armor.
|
||||
--> PKCS#1 RSAPrivateKey */
|
||||
ret = ssh2_pem_parse_blob(session,
|
||||
beginrsaprivkeyhdr, endrsaprivkeyhdr,
|
||||
blob, blob_len,
|
||||
passphrase,
|
||||
&data, &datalen);
|
||||
if(!ret)
|
||||
ret = rsapkcs1privkey(session,
|
||||
data, datalen, passphrase, (void *)&ctx);
|
||||
}
|
||||
|
||||
if(ret) {
|
||||
/* Try as PKCS#8 DER data.
|
||||
--> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */
|
||||
ret = rsapkcs8privkey(session, blob, blob_len,
|
||||
passphrase, (void *)&ctx);
|
||||
|
||||
/* Try as PKCS#1 DER data.
|
||||
--> PKCS#1 RSAPrivateKey */
|
||||
if(ret)
|
||||
ret = rsapkcs1privkey(session, blob, blob_len,
|
||||
passphrase, (void *)&ctx);
|
||||
}
|
||||
|
||||
if(data)
|
||||
SSH2_FREE(session, data);
|
||||
|
||||
if(ret) {
|
||||
ssh2_os400qc3_crypto_dtor(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
*rsa = ctx;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
struct loadpubkeydata p;
|
||||
unsigned char *data = NULL;
|
||||
size_t datalen = 0;
|
||||
const char *meth;
|
||||
int ret;
|
||||
|
||||
*method = NULL;
|
||||
*method_len = 0;
|
||||
*pubkeydata = NULL;
|
||||
@@ -2297,6 +2205,135 @@ int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: merge the two callees into one. */
|
||||
int ssh2_pub_privkey(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
if(privatekey)
|
||||
return os400_pub_privkey_file(session, method, method_len,
|
||||
pubkeydata, pubkeydata_len,
|
||||
privatekey,
|
||||
passphrase);
|
||||
else
|
||||
return os400_pub_privkey_blob(session, method, method_len,
|
||||
pubkeydata, pubkeydata_len,
|
||||
privkeyblob, privkeyblob_len,
|
||||
passphrase);
|
||||
}
|
||||
|
||||
static int os400_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
{
|
||||
ssh2_rsa_ctx *ctx = init_crypto_ctx(NULL);
|
||||
int ret;
|
||||
|
||||
if(!ctx)
|
||||
return -1;
|
||||
ret = load_rsa_private_file(session, filename, passphrase,
|
||||
rsapkcs1privkey, rsapkcs8privkey,
|
||||
(void *)ctx);
|
||||
if(ret) {
|
||||
ssh2_os400qc3_crypto_dtor(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
*rsa = ctx;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int os400_rsa_new_priv_from_blob(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
ssh2_rsa_ctx *ctx = init_crypto_ctx(NULL);
|
||||
unsigned char *data = NULL;
|
||||
size_t datalen = 0;
|
||||
int ret;
|
||||
|
||||
if(!ctx)
|
||||
return -1;
|
||||
|
||||
/* Try with "ENCRYPTED PRIVATE KEY" PEM armor.
|
||||
--> PKCS#8 EncryptedPrivateKeyInfo */
|
||||
ret = ssh2_pem_parse_blob(session,
|
||||
beginencprivkeyhdr, endencprivkeyhdr,
|
||||
blob, blob_len,
|
||||
passphrase,
|
||||
&data, &datalen);
|
||||
|
||||
/* Try with "PRIVATE KEY" PEM armor.
|
||||
--> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */
|
||||
if(ret)
|
||||
ret = ssh2_pem_parse_blob(session,
|
||||
beginprivkeyhdr, endprivkeyhdr,
|
||||
blob, blob_len,
|
||||
passphrase,
|
||||
&data, &datalen);
|
||||
|
||||
if(!ret) {
|
||||
/* Process PKCS#8. */
|
||||
ret = rsapkcs8privkey(session,
|
||||
data, datalen, passphrase, (void *)&ctx);
|
||||
}
|
||||
else {
|
||||
/* Try with "RSA PRIVATE KEY" PEM armor.
|
||||
--> PKCS#1 RSAPrivateKey */
|
||||
ret = ssh2_pem_parse_blob(session,
|
||||
beginrsaprivkeyhdr, endrsaprivkeyhdr,
|
||||
blob, blob_len,
|
||||
passphrase,
|
||||
&data, &datalen);
|
||||
if(!ret)
|
||||
ret = rsapkcs1privkey(session,
|
||||
data, datalen, passphrase, (void *)&ctx);
|
||||
}
|
||||
|
||||
if(ret) {
|
||||
/* Try as PKCS#8 DER data.
|
||||
--> PKCS#8 PrivateKeyInfo or EncryptedPrivateKeyInfo */
|
||||
ret = rsapkcs8privkey(session, blob, blob_len,
|
||||
passphrase, (void *)&ctx);
|
||||
|
||||
/* Try as PKCS#1 DER data.
|
||||
--> PKCS#1 RSAPrivateKey */
|
||||
if(ret)
|
||||
ret = rsapkcs1privkey(session, blob, blob_len,
|
||||
passphrase, (void *)&ctx);
|
||||
}
|
||||
|
||||
if(data)
|
||||
SSH2_FREE(session, data);
|
||||
|
||||
if(ret) {
|
||||
ssh2_os400qc3_crypto_dtor(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
*rsa = ctx;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: merge the two callees into one. */
|
||||
int ssh2_rsa_new_priv(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
if(filename)
|
||||
return os400_rsa_new_priv_from_file(rsa, session,
|
||||
filename, passphrase);
|
||||
else
|
||||
return os400_rsa_new_priv_from_blob(rsa, session,
|
||||
blob, blob_len, passphrase);
|
||||
}
|
||||
|
||||
int ssh2_rsa_sha2_verify(ssh2_rsa_ctx *rsa, size_t hash_len,
|
||||
const unsigned char *sig, size_t sig_len,
|
||||
const unsigned char *m, size_t m_len)
|
||||
|
||||
@@ -918,11 +918,11 @@ static int userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
|
||||
&pubkeydata, &pubkeydata_len,
|
||||
publickey, NULL, 0);
|
||||
else /* Compute public key from private key. */
|
||||
rc = ssh2_pub_privkey_file(session,
|
||||
&session->userauth_host_method,
|
||||
&session->userauth_host_method_len,
|
||||
&pubkeydata, &pubkeydata_len,
|
||||
privatekey, passphrase);
|
||||
rc = ssh2_pub_privkey(session,
|
||||
&session->userauth_host_method,
|
||||
&session->userauth_host_method_len,
|
||||
&pubkeydata, &pubkeydata_len,
|
||||
privatekey, NULL, 0, passphrase);
|
||||
|
||||
if(rc)
|
||||
return rc; /* low-level functions called ssh2_err() */
|
||||
@@ -1786,26 +1786,20 @@ static int userauth_publickey(LIBSSH2_SESSION *session,
|
||||
privkey_info.passphrase = passphrase;
|
||||
|
||||
if(session->userauth_pblc_state == ssh2_NB_state_idle) {
|
||||
if(pubkeyfile || (pubkeyblob_len && pubkeyblob))
|
||||
if(pubkeyfile || (pubkeyblob && pubkeyblob_len))
|
||||
rc = userauth_read_pubkey(session,
|
||||
&session->userauth_pblc_method,
|
||||
&session->userauth_pblc_method_len,
|
||||
&pubkeydata, &pubkeydata_len,
|
||||
pubkeyfile, pubkeyblob, pubkeyblob_len);
|
||||
/* Compute public key from private key. */
|
||||
else if(privkeyfile)
|
||||
rc = ssh2_pub_privkey_file(session,
|
||||
&session->userauth_pblc_method,
|
||||
&session->userauth_pblc_method_len,
|
||||
&pubkeydata, &pubkeydata_len,
|
||||
privkeyfile, passphrase);
|
||||
else if(privkeyblob_len && privkeyblob)
|
||||
rc = ssh2_pub_privkey_blob(session,
|
||||
&session->userauth_pblc_method,
|
||||
&session->userauth_pblc_method_len,
|
||||
&pubkeydata, &pubkeydata_len,
|
||||
privkeyblob, privkeyblob_len,
|
||||
passphrase);
|
||||
else if(privkeyfile || (privkeyblob && privkeyblob_len))
|
||||
rc = ssh2_pub_privkey(session,
|
||||
&session->userauth_pblc_method,
|
||||
&session->userauth_pblc_method_len,
|
||||
&pubkeydata, &pubkeydata_len,
|
||||
privkeyfile, privkeyblob, privkeyblob_len,
|
||||
passphrase);
|
||||
else
|
||||
return ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Invalid data in public and private key.");
|
||||
@@ -2198,18 +2192,18 @@ int libssh2_userauth_publickey_sk(
|
||||
|
||||
if(privkeyblob_len && privkeyblob) {
|
||||
|
||||
if(ssh2_sk_pubkey_blob(session,
|
||||
&tmp_method,
|
||||
&tmp_method_len,
|
||||
&tmp_publickeydata,
|
||||
&tmp_publickeydata_len,
|
||||
&sk_info.algorithm,
|
||||
&sk_info.flags,
|
||||
&sk_info.application,
|
||||
&sk_info.key_handle,
|
||||
&sk_info.handle_len,
|
||||
privkeyblob, privkeyblob_len,
|
||||
passphrase))
|
||||
if(ssh2_sk_pubkey(session,
|
||||
&tmp_method,
|
||||
&tmp_method_len,
|
||||
&tmp_publickeydata,
|
||||
&tmp_publickeydata_len,
|
||||
&sk_info.algorithm,
|
||||
&sk_info.flags,
|
||||
&sk_info.application,
|
||||
&sk_info.key_handle,
|
||||
&sk_info.handle_len,
|
||||
NULL, privkeyblob, privkeyblob_len,
|
||||
passphrase))
|
||||
return ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Unable to extract public key from private key.");
|
||||
else if(publickeydata_len == 0 || !publickeydata) {
|
||||
|
||||
270
src/wincng.c
270
src/wincng.c
@@ -899,80 +899,59 @@ static int wcng_key_sha_verify(struct wcng_key_ctx *ctx, ULONG hash_len,
|
||||
return BCRYPT_SUCCESS(ret) ? 0 : -1;
|
||||
}
|
||||
|
||||
static int wcng_load_priv_from_file(LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase,
|
||||
unsigned char **ppbEncoded,
|
||||
size_t *pcbEncoded,
|
||||
int tryLoadRSA, int tryLoadDSA)
|
||||
static int wcng_load_priv(LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *privkeyblob,
|
||||
size_t privkeyblob_len,
|
||||
const char *passphrase,
|
||||
unsigned char **ppbEncoded,
|
||||
size_t *pcbEncoded,
|
||||
int tryLoadRSA, int tryLoadDSA)
|
||||
{
|
||||
int ret = -1;
|
||||
FILE *fp;
|
||||
unsigned char *data = NULL;
|
||||
size_t datalen = 0;
|
||||
FILE *fp = NULL;
|
||||
|
||||
fp = ssh2_fopen(filename, "rb");
|
||||
if(!fp)
|
||||
return -1;
|
||||
|
||||
#if LIBSSH2_RSA
|
||||
if(ret && tryLoadRSA)
|
||||
ret = ssh2_pem_parse_FILE(session, PEM_RSA_HEADER, PEM_RSA_FOOTER,
|
||||
fp, passphrase,
|
||||
&data, &datalen);
|
||||
#else
|
||||
(void)tryLoadRSA;
|
||||
#endif
|
||||
|
||||
#if LIBSSH2_DSA
|
||||
if(ret && tryLoadDSA)
|
||||
ret = ssh2_pem_parse_FILE(session, PEM_DSA_HEADER, PEM_DSA_FOOTER,
|
||||
fp, passphrase,
|
||||
&data, &datalen);
|
||||
#else
|
||||
(void)tryLoadDSA;
|
||||
#endif
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if(!ret) {
|
||||
*ppbEncoded = data;
|
||||
*pcbEncoded = datalen;
|
||||
if(filename) {
|
||||
fp = ssh2_fopen(filename, "rb");
|
||||
if(!fp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wcng_load_priv_from_blob(LIBSSH2_SESSION *session,
|
||||
const char *privkeyblob,
|
||||
size_t privkeyblob_len,
|
||||
const char *passphrase,
|
||||
unsigned char **ppbEncoded,
|
||||
size_t *pcbEncoded,
|
||||
int tryLoadRSA, int tryLoadDSA)
|
||||
{
|
||||
unsigned char *data = NULL;
|
||||
size_t datalen = 0;
|
||||
int ret = -1;
|
||||
|
||||
#if LIBSSH2_RSA
|
||||
if(ret && tryLoadRSA)
|
||||
ret = ssh2_pem_parse_blob(session, PEM_RSA_HEADER, PEM_RSA_FOOTER,
|
||||
privkeyblob, privkeyblob_len, passphrase,
|
||||
&data, &datalen);
|
||||
if(ret && tryLoadRSA) {
|
||||
if(filename)
|
||||
ret = ssh2_pem_parse_FILE(session, PEM_RSA_HEADER, PEM_RSA_FOOTER,
|
||||
fp, passphrase,
|
||||
&data, &datalen);
|
||||
else
|
||||
ret = ssh2_pem_parse_blob(session, PEM_RSA_HEADER, PEM_RSA_FOOTER,
|
||||
privkeyblob, privkeyblob_len, passphrase,
|
||||
&data, &datalen);
|
||||
}
|
||||
#else
|
||||
(void)tryLoadRSA;
|
||||
#endif
|
||||
|
||||
#if LIBSSH2_DSA
|
||||
if(ret && tryLoadDSA)
|
||||
ret = ssh2_pem_parse_blob(session, PEM_DSA_HEADER, PEM_DSA_FOOTER,
|
||||
privkeyblob, privkeyblob_len, passphrase,
|
||||
&data, &datalen);
|
||||
if(ret && tryLoadDSA) {
|
||||
if(filename)
|
||||
ret = ssh2_pem_parse_FILE(session, PEM_DSA_HEADER, PEM_DSA_FOOTER,
|
||||
fp, passphrase,
|
||||
&data, &datalen);
|
||||
else
|
||||
ret = ssh2_pem_parse_blob(session, PEM_DSA_HEADER, PEM_DSA_FOOTER,
|
||||
privkeyblob, privkeyblob_len, passphrase,
|
||||
&data, &datalen);
|
||||
}
|
||||
#else
|
||||
(void)tryLoadDSA;
|
||||
#endif
|
||||
|
||||
if(fp)
|
||||
fclose(fp);
|
||||
|
||||
if(!ret) {
|
||||
*ppbEncoded = data;
|
||||
*pcbEncoded = datalen;
|
||||
@@ -1330,35 +1309,17 @@ static int wcng_rsa_new_private_parse(ssh2_rsa_ctx **rsa,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ssh2_rsa_new_priv_from_file(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
int ssh2_rsa_new_priv(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
unsigned char *pbEncoded;
|
||||
size_t cbEncoded;
|
||||
int ret;
|
||||
|
||||
ret = wcng_load_priv_from_file(session, filename, passphrase,
|
||||
&pbEncoded, &cbEncoded, 1, 0);
|
||||
if(ret)
|
||||
return -1;
|
||||
|
||||
return wcng_rsa_new_private_parse(rsa, session, pbEncoded, cbEncoded);
|
||||
}
|
||||
|
||||
int ssh2_rsa_new_priv_from_blob(ssh2_rsa_ctx **rsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
unsigned char *pbEncoded;
|
||||
size_t cbEncoded;
|
||||
int ret;
|
||||
|
||||
ret = wcng_load_priv_from_blob(session, blob, blob_len, passphrase,
|
||||
&pbEncoded, &cbEncoded, 1, 0);
|
||||
if(ret)
|
||||
if(wcng_load_priv(session, filename, blob, blob_len, passphrase,
|
||||
&pbEncoded, &cbEncoded, 1, 0))
|
||||
return -1;
|
||||
|
||||
return wcng_rsa_new_private_parse(rsa, session, pbEncoded, cbEncoded);
|
||||
@@ -1617,35 +1578,17 @@ static int wcng_dsa_new_private_parse(ssh2_dsa_ctx **dsa,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssh2_dsa_new_priv_from_file(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *passphrase)
|
||||
int ssh2_dsa_new_priv(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *filename,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
unsigned char *pbEncoded;
|
||||
size_t cbEncoded;
|
||||
int ret;
|
||||
|
||||
ret = wcng_load_priv_from_file(session, filename, passphrase,
|
||||
&pbEncoded, &cbEncoded, 0, 1);
|
||||
if(ret)
|
||||
return -1;
|
||||
|
||||
return wcng_dsa_new_private_parse(dsa, session, pbEncoded, cbEncoded);
|
||||
}
|
||||
|
||||
int ssh2_dsa_new_priv_from_blob(ssh2_dsa_ctx **dsa,
|
||||
LIBSSH2_SESSION *session,
|
||||
const char *blob, size_t blob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
unsigned char *pbEncoded;
|
||||
size_t cbEncoded;
|
||||
int ret;
|
||||
|
||||
ret = wcng_load_priv_from_blob(session, blob, blob_len, passphrase,
|
||||
&pbEncoded, &cbEncoded, 0, 1);
|
||||
if(ret)
|
||||
if(wcng_load_priv(session, filename, blob, blob_len, passphrase,
|
||||
&pbEncoded, &cbEncoded, 0, 1))
|
||||
return -1;
|
||||
|
||||
return wcng_dsa_new_private_parse(dsa, session, pbEncoded, cbEncoded);
|
||||
@@ -2517,32 +2460,41 @@ cleanup:
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new private key given a file path and password
|
||||
* Creates a new private key given a file or blob and password.
|
||||
* ECDSA private key files use the decoding defined in PROTOCOL.key
|
||||
* in the OpenSSH source tree.
|
||||
*/
|
||||
int ssh2_ecdsa_new_priv_from_file(OUT ssh2_ecdsa_ctx **ec_ctx,
|
||||
IN LIBSSH2_SESSION *session,
|
||||
IN const char *filename,
|
||||
IN const char *passphrase)
|
||||
int ssh2_ecdsa_new_priv(OUT ssh2_ecdsa_ctx **ec_ctx,
|
||||
IN LIBSSH2_SESSION *session,
|
||||
IN const char *filename,
|
||||
IN const char *blob, IN size_t blob_len,
|
||||
IN const char *passphrase)
|
||||
{
|
||||
int result;
|
||||
|
||||
FILE *fp = NULL;
|
||||
struct string_buf *decrypted = NULL;
|
||||
FILE *fp = NULL;
|
||||
|
||||
/* Validate parameters */
|
||||
if(!ec_ctx || !session || !filename)
|
||||
if(!ec_ctx || !session || (!filename && !blob))
|
||||
return LIBSSH2_ERROR_INVAL;
|
||||
|
||||
*ec_ctx = NULL;
|
||||
|
||||
fp = ssh2_fopen(filename, "rb");
|
||||
if(!fp) {
|
||||
result = ssh2_err(session, LIBSSH2_ERROR_INVAL,
|
||||
"Opening the private key file failed");
|
||||
goto cleanup;
|
||||
}
|
||||
if(filename) {
|
||||
fp = ssh2_fopen(filename, "rb");
|
||||
if(!fp) {
|
||||
result = ssh2_err(session, LIBSSH2_ERROR_FILE,
|
||||
"Opening the private key file failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = ssh2_openssh_pem_parse_FILE(session, fp,
|
||||
passphrase, &decrypted);
|
||||
}
|
||||
else
|
||||
result = ssh2_openssh_pem_parse_blob(session, blob, blob_len,
|
||||
passphrase, &decrypted);
|
||||
|
||||
result = ssh2_openssh_pem_parse_FILE(session, fp, passphrase, &decrypted);
|
||||
if(result)
|
||||
goto cleanup;
|
||||
|
||||
@@ -2559,40 +2511,6 @@ cleanup:
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new private key given a file data and password.
|
||||
* ECDSA private key files use the decoding defined in PROTOCOL.key
|
||||
* in the OpenSSH source tree.
|
||||
*/
|
||||
int ssh2_ecdsa_new_priv_from_blob(OUT ssh2_ecdsa_ctx **ec_ctx,
|
||||
IN LIBSSH2_SESSION *session,
|
||||
IN const char *blob, IN size_t blob_len,
|
||||
IN const char *passphrase)
|
||||
{
|
||||
int result;
|
||||
struct string_buf *decrypted = NULL;
|
||||
|
||||
/* Validate parameters */
|
||||
if(!ec_ctx || !session || !blob)
|
||||
return LIBSSH2_ERROR_INVAL;
|
||||
|
||||
*ec_ctx = NULL;
|
||||
|
||||
result = ssh2_openssh_pem_parse_blob(session, blob, blob_len,
|
||||
passphrase, &decrypted);
|
||||
if(result)
|
||||
goto cleanup;
|
||||
|
||||
result = wcng_ecdsa_new_private_parse(ec_ctx, session,
|
||||
decrypted->data, decrypted->len);
|
||||
|
||||
cleanup:
|
||||
if(decrypted)
|
||||
ssh2_string_buf_free(session, decrypted);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes the ECDSA signature of a previously-hashed message
|
||||
*/
|
||||
@@ -2833,41 +2751,19 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ssh2_pub_privkey_file(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *passphrase)
|
||||
int ssh2_pub_privkey(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privatekey,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
unsigned char *pbEncoded;
|
||||
size_t cbEncoded;
|
||||
int ret;
|
||||
|
||||
ret = wcng_load_priv_from_file(session,
|
||||
privatekey, passphrase,
|
||||
&pbEncoded, &cbEncoded, 1, 1);
|
||||
if(ret)
|
||||
return -1;
|
||||
|
||||
return wcng_pub_privkey_file_parse(session, method, method_len,
|
||||
pubkeydata, pubkeydata_len,
|
||||
pbEncoded, cbEncoded);
|
||||
}
|
||||
|
||||
int ssh2_pub_privkey_blob(LIBSSH2_SESSION *session,
|
||||
char **method, size_t *method_len,
|
||||
unsigned char **pubkeydata, size_t *pubkeydata_len,
|
||||
const char *privkeyblob, size_t privkeyblob_len,
|
||||
const char *passphrase)
|
||||
{
|
||||
unsigned char *pbEncoded;
|
||||
size_t cbEncoded;
|
||||
int ret;
|
||||
|
||||
ret = wcng_load_priv_from_blob(session,
|
||||
privkeyblob, privkeyblob_len, passphrase,
|
||||
&pbEncoded, &cbEncoded, 1, 1);
|
||||
if(ret)
|
||||
if(wcng_load_priv(session,
|
||||
privatekey, privkeyblob, privkeyblob_len, passphrase,
|
||||
&pbEncoded, &cbEncoded, 1, 1))
|
||||
return -1;
|
||||
|
||||
return wcng_pub_privkey_file_parse(session, method, method_len,
|
||||
|
||||
Reference in New Issue
Block a user