mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-22 06:38:37 -05:00
cmdgen: add a --dump option.
Also spelled '-O text', this takes a public or private key as input, and produces on standard output a dump of all the actual numbers involved in the key: the exponent and modulus for RSA, the p,q,g,y parameters for DSA, the affine x and y coordinates of the public elliptic curve point for ECC keys, and all the extra bits and pieces in the private keys too. Partly I expect this to be useful to me for debugging: I've had to paste key files a few too many times through base64 decoders and hex dump tools, then manually decode SSH marshalling and paste the result into the Python REPL to get an integer object. Now I should be able to get _straight_ to text I can paste into Python. But also, it's a way that other applications can use the key generator: if you need to generate, say, an RSA key in some format I don't support (I've recently heard of an XML-based one, for example), then you can run 'puttygen -t rsa --dump' and have it print the elements of a freshly generated keypair on standard output, and then all you have to do is understand the output format.
This commit is contained in:
parent
96f1fb9456
commit
c18e5dc8fb
2
Recipe
2
Recipe
@ -400,7 +400,7 @@ testcrypt : [UT] testcrypt SSHCRYPTO sshprng sshprime sshpubk marshal utils
|
|||||||
testcrypt : [C] testcrypt SSHCRYPTO sshprng sshprime sshpubk marshal utils
|
testcrypt : [C] testcrypt SSHCRYPTO sshprng sshprime sshpubk marshal utils
|
||||||
+ memory tree234 winmiscs KEYGEN
|
+ memory tree234 winmiscs KEYGEN
|
||||||
testsc : [UT] testsc SSHCRYPTO marshal utils memory tree234 wildcard
|
testsc : [UT] testsc SSHCRYPTO marshal utils memory tree234 wildcard
|
||||||
+ sshmac uxutils
|
+ sshmac uxutils sshpubk
|
||||||
testzlib : [UT] testzlib sshzlib utils marshal memory
|
testzlib : [UT] testzlib sshzlib utils marshal memory
|
||||||
|
|
||||||
uppity : [UT] uxserver SSHSERVER UXMISC uxsignal uxnoise uxgss uxnogtk
|
uppity : [UT] uxserver SSHSERVER UXMISC uxsignal uxnoise uxgss uxnogtk
|
||||||
|
77
cmdgen.c
77
cmdgen.c
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "putty.h"
|
#include "putty.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
|
#include "mpint.h"
|
||||||
|
|
||||||
struct progress {
|
struct progress {
|
||||||
int phase, current;
|
int phase, current;
|
||||||
@ -97,6 +98,8 @@ void help(void)
|
|||||||
" public RFC 4716 / ssh.com public key\n"
|
" public RFC 4716 / ssh.com public key\n"
|
||||||
" public-openssh OpenSSH public key\n"
|
" public-openssh OpenSSH public key\n"
|
||||||
" fingerprint output the key fingerprint\n"
|
" fingerprint output the key fingerprint\n"
|
||||||
|
" text output the key components as "
|
||||||
|
"'name=0x####'\n"
|
||||||
" -o specify output file\n"
|
" -o specify output file\n"
|
||||||
" -l equivalent to `-O fingerprint'\n"
|
" -l equivalent to `-O fingerprint'\n"
|
||||||
" -L equivalent to `-O public-openssh'\n"
|
" -L equivalent to `-O public-openssh'\n"
|
||||||
@ -166,7 +169,7 @@ int main(int argc, char **argv)
|
|||||||
enum { NOKEYGEN, RSA1, RSA2, DSA, ECDSA, ED25519 } keytype = NOKEYGEN;
|
enum { NOKEYGEN, RSA1, RSA2, DSA, ECDSA, ED25519 } keytype = NOKEYGEN;
|
||||||
char *outfile = NULL, *outfiletmp = NULL;
|
char *outfile = NULL, *outfiletmp = NULL;
|
||||||
enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH_AUTO,
|
enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH_AUTO,
|
||||||
OPENSSH_NEW, SSHCOM } outtype = PRIVATE;
|
OPENSSH_NEW, SSHCOM, TEXT } outtype = PRIVATE;
|
||||||
int bits = -1;
|
int bits = -1;
|
||||||
const char *comment = NULL;
|
const char *comment = NULL;
|
||||||
char *origcomment = NULL;
|
char *origcomment = NULL;
|
||||||
@ -287,6 +290,8 @@ int main(int argc, char **argv)
|
|||||||
} else {
|
} else {
|
||||||
random_device = val;
|
random_device = val;
|
||||||
}
|
}
|
||||||
|
} else if (!strcmp(opt, "-dump")) {
|
||||||
|
outtype = TEXT;
|
||||||
} else {
|
} else {
|
||||||
errs = true;
|
errs = true;
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -389,6 +394,8 @@ int main(int argc, char **argv)
|
|||||||
outtype = OPENSSH_NEW, sshver = 2;
|
outtype = OPENSSH_NEW, sshver = 2;
|
||||||
else if (!strcmp(p, "private-sshcom"))
|
else if (!strcmp(p, "private-sshcom"))
|
||||||
outtype = SSHCOM, sshver = 2;
|
outtype = SSHCOM, sshver = 2;
|
||||||
|
else if (!strcmp(p, "text"))
|
||||||
|
outtype = TEXT;
|
||||||
else {
|
else {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"puttygen: unknown output type `%s'\n", p);
|
"puttygen: unknown output type `%s'\n", p);
|
||||||
@ -498,7 +505,7 @@ int main(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
if (keytype != NOKEYGEN &&
|
if (keytype != NOKEYGEN &&
|
||||||
(outtype != PRIVATE && outtype != OPENSSH_AUTO &&
|
(outtype != PRIVATE && outtype != OPENSSH_AUTO &&
|
||||||
outtype != OPENSSH_NEW && outtype != SSHCOM)) {
|
outtype != OPENSSH_NEW && outtype != SSHCOM && outtype != TEXT)) {
|
||||||
fprintf(stderr, "puttygen: this would generate a new key but "
|
fprintf(stderr, "puttygen: this would generate a new key but "
|
||||||
"discard the private part\n");
|
"discard the private part\n");
|
||||||
RETURN(1);
|
RETURN(1);
|
||||||
@ -867,8 +874,13 @@ int main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Prompt for a new passphrase if we have been asked to, or if
|
* Prompt for a new passphrase if we have been asked to, or if
|
||||||
* we have just generated a key.
|
* we have just generated a key.
|
||||||
|
*
|
||||||
|
* In the latter case, an exception is if we're producing text
|
||||||
|
* output, because that output format doesn't support encryption
|
||||||
|
* in any case.
|
||||||
*/
|
*/
|
||||||
if (!new_passphrase && (change_passphrase || keytype != NOKEYGEN)) {
|
if (!new_passphrase && (change_passphrase ||
|
||||||
|
(keytype != NOKEYGEN && outtype != TEXT))) {
|
||||||
prompts_t *p = new_prompts();
|
prompts_t *p = new_prompts();
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -1039,6 +1051,65 @@ int main(int argc, char **argv)
|
|||||||
RETURN(1); /* rename failed */
|
RETURN(1); /* rename failed */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TEXT: {
|
||||||
|
key_components *kc;
|
||||||
|
if (sshver == 1) {
|
||||||
|
assert(ssh1key);
|
||||||
|
kc = rsa_components(ssh1key);
|
||||||
|
} else {
|
||||||
|
if (ssh2key) {
|
||||||
|
kc = ssh_key_components(ssh2key->key);
|
||||||
|
} else {
|
||||||
|
assert(ssh2blob);
|
||||||
|
|
||||||
|
BinarySource src[1];
|
||||||
|
BinarySource_BARE_INIT_PL(src, ptrlen_from_strbuf(ssh2blob));
|
||||||
|
ptrlen algname = get_string(src);
|
||||||
|
const ssh_keyalg *alg = find_pubkey_alg_len(algname);
|
||||||
|
if (!alg) {
|
||||||
|
fprintf(stderr, "puttygen: cannot extract key components "
|
||||||
|
"from public key of unknown type '%.*s'\n",
|
||||||
|
PTRLEN_PRINTF(algname));
|
||||||
|
RETURN(1);
|
||||||
|
}
|
||||||
|
ssh_key *sk = ssh_key_new_pub(
|
||||||
|
alg, ptrlen_from_strbuf(ssh2blob));
|
||||||
|
kc = ssh_key_components(sk);
|
||||||
|
ssh_key_free(sk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fp;
|
||||||
|
if (outfile) {
|
||||||
|
fp = f_open(outfilename, "w", false);
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "unable to open output file\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fp = stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < kc->ncomponents; i++) {
|
||||||
|
if (kc->components[i].is_mp_int) {
|
||||||
|
char *hex = mp_get_hex(kc->components[i].mp);
|
||||||
|
fprintf(fp, "%s=0x%s\n", kc->components[i].name, hex);
|
||||||
|
smemclr(hex, strlen(hex));
|
||||||
|
sfree(hex);
|
||||||
|
} else {
|
||||||
|
fprintf(fp, "%s=\"", kc->components[i].name);
|
||||||
|
write_c_string_literal(fp, ptrlen_from_asciz(
|
||||||
|
kc->components[i].text));
|
||||||
|
fputs("\"\n", fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outfile)
|
||||||
|
fclose(fp);
|
||||||
|
key_components_free(kc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
3
misc.h
3
misc.h
@ -215,6 +215,9 @@ bool smemeq(const void *av, const void *bv, size_t len);
|
|||||||
* been removed. */
|
* been removed. */
|
||||||
size_t encode_utf8(void *output, unsigned long ch);
|
size_t encode_utf8(void *output, unsigned long ch);
|
||||||
|
|
||||||
|
/* Write a string out in C string-literal format. */
|
||||||
|
void write_c_string_literal(FILE *fp, ptrlen str);
|
||||||
|
|
||||||
char *buildinfo(const char *newline);
|
char *buildinfo(const char *newline);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
22
ssh.h
22
ssh.h
@ -528,6 +528,24 @@ struct eddsa_key {
|
|||||||
WeierstrassPoint *ecdsa_public(mp_int *private_key, const ssh_keyalg *alg);
|
WeierstrassPoint *ecdsa_public(mp_int *private_key, const ssh_keyalg *alg);
|
||||||
EdwardsPoint *eddsa_public(mp_int *private_key, const ssh_keyalg *alg);
|
EdwardsPoint *eddsa_public(mp_int *private_key, const ssh_keyalg *alg);
|
||||||
|
|
||||||
|
typedef struct key_components {
|
||||||
|
size_t ncomponents, componentsize;
|
||||||
|
struct {
|
||||||
|
char *name;
|
||||||
|
bool is_mp_int;
|
||||||
|
union {
|
||||||
|
char *text;
|
||||||
|
mp_int *mp;
|
||||||
|
};
|
||||||
|
} *components;
|
||||||
|
} key_components;
|
||||||
|
key_components *key_components_new(void);
|
||||||
|
void key_components_add_text(key_components *kc,
|
||||||
|
const char *name, const char *value);
|
||||||
|
void key_components_add_mp(key_components *kc,
|
||||||
|
const char *name, mp_int *value);
|
||||||
|
void key_components_free(key_components *kc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SSH-1 never quite decided which order to store the two components
|
* SSH-1 never quite decided which order to store the two components
|
||||||
* of an RSA key. During connection setup, the server sends its host
|
* of an RSA key. During connection setup, the server sends its host
|
||||||
@ -554,6 +572,7 @@ int rsa_ssh1_public_blob_len(ptrlen data);
|
|||||||
void rsa_ssh1_private_blob_agent(BinarySink *bs, RSAKey *key);
|
void rsa_ssh1_private_blob_agent(BinarySink *bs, RSAKey *key);
|
||||||
void freersapriv(RSAKey *key);
|
void freersapriv(RSAKey *key);
|
||||||
void freersakey(RSAKey *key);
|
void freersakey(RSAKey *key);
|
||||||
|
key_components *rsa_components(RSAKey *key);
|
||||||
|
|
||||||
uint32_t crc32_rfc1662(ptrlen data);
|
uint32_t crc32_rfc1662(ptrlen data);
|
||||||
uint32_t crc32_ssh1(ptrlen data);
|
uint32_t crc32_ssh1(ptrlen data);
|
||||||
@ -801,6 +820,7 @@ struct ssh_keyalg {
|
|||||||
void (*private_blob)(ssh_key *key, BinarySink *);
|
void (*private_blob)(ssh_key *key, BinarySink *);
|
||||||
void (*openssh_blob) (ssh_key *key, BinarySink *);
|
void (*openssh_blob) (ssh_key *key, BinarySink *);
|
||||||
char *(*cache_str) (ssh_key *key);
|
char *(*cache_str) (ssh_key *key);
|
||||||
|
key_components *(*components) (ssh_key *key);
|
||||||
|
|
||||||
/* 'Class methods' that don't deal with an ssh_key at all */
|
/* 'Class methods' that don't deal with an ssh_key at all */
|
||||||
int (*pubkey_bits) (const ssh_keyalg *self, ptrlen blob);
|
int (*pubkey_bits) (const ssh_keyalg *self, ptrlen blob);
|
||||||
@ -837,6 +857,8 @@ static inline void ssh_key_openssh_blob(ssh_key *key, BinarySink *bs)
|
|||||||
{ key->vt->openssh_blob(key, bs); }
|
{ key->vt->openssh_blob(key, bs); }
|
||||||
static inline char *ssh_key_cache_str(ssh_key *key)
|
static inline char *ssh_key_cache_str(ssh_key *key)
|
||||||
{ return key->vt->cache_str(key); }
|
{ return key->vt->cache_str(key); }
|
||||||
|
static inline key_components *ssh_key_components(ssh_key *key)
|
||||||
|
{ return key->vt->components(key); }
|
||||||
static inline int ssh_key_public_bits(const ssh_keyalg *self, ptrlen blob)
|
static inline int ssh_key_public_bits(const ssh_keyalg *self, ptrlen blob)
|
||||||
{ return self->pubkey_bits(self, blob); }
|
{ return self->pubkey_bits(self, blob); }
|
||||||
static inline const ssh_keyalg *ssh_key_alg(ssh_key *key)
|
static inline const ssh_keyalg *ssh_key_alg(ssh_key *key)
|
||||||
|
18
sshdss.c
18
sshdss.c
@ -83,6 +83,23 @@ static char *dss_cache_str(ssh_key *key)
|
|||||||
return strbuf_to_str(sb);
|
return strbuf_to_str(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static key_components *dss_components(ssh_key *key)
|
||||||
|
{
|
||||||
|
struct dss_key *dss = container_of(key, struct dss_key, sshk);
|
||||||
|
key_components *kc = key_components_new();
|
||||||
|
|
||||||
|
key_components_add_text(kc, "key_type", "DSA");
|
||||||
|
assert(dss->p);
|
||||||
|
key_components_add_mp(kc, "p", dss->p);
|
||||||
|
key_components_add_mp(kc, "q", dss->q);
|
||||||
|
key_components_add_mp(kc, "g", dss->g);
|
||||||
|
key_components_add_mp(kc, "public_y", dss->y);
|
||||||
|
if (dss->x)
|
||||||
|
key_components_add_mp(kc, "private_x", dss->x);
|
||||||
|
|
||||||
|
return kc;
|
||||||
|
}
|
||||||
|
|
||||||
static char *dss_invalid(ssh_key *key, unsigned flags)
|
static char *dss_invalid(ssh_key *key, unsigned flags)
|
||||||
{
|
{
|
||||||
/* No validity criterion will stop us from using a DSA key at all */
|
/* No validity criterion will stop us from using a DSA key at all */
|
||||||
@ -478,6 +495,7 @@ const ssh_keyalg ssh_dss = {
|
|||||||
dss_private_blob,
|
dss_private_blob,
|
||||||
dss_openssh_blob,
|
dss_openssh_blob,
|
||||||
dss_cache_str,
|
dss_cache_str,
|
||||||
|
dss_components,
|
||||||
|
|
||||||
dss_pubkey_bits,
|
dss_pubkey_bits,
|
||||||
|
|
||||||
|
46
sshecc.c
46
sshecc.c
@ -640,6 +640,27 @@ static char *ecdsa_cache_str(ssh_key *key)
|
|||||||
return toret;
|
return toret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static key_components *ecdsa_components(ssh_key *key)
|
||||||
|
{
|
||||||
|
struct ecdsa_key *ek = container_of(key, struct ecdsa_key, sshk);
|
||||||
|
key_components *kc = key_components_new();
|
||||||
|
|
||||||
|
key_components_add_text(kc, "key_type", "ECDSA");
|
||||||
|
key_components_add_text(kc, "curve_name", ek->curve->textname);
|
||||||
|
|
||||||
|
mp_int *x, *y;
|
||||||
|
ecc_weierstrass_get_affine(ek->publicKey, &x, &y);
|
||||||
|
key_components_add_mp(kc, "public_affine_x", x);
|
||||||
|
key_components_add_mp(kc, "public_affine_y", y);
|
||||||
|
mp_free(x);
|
||||||
|
mp_free(y);
|
||||||
|
|
||||||
|
if (ek->privateKey)
|
||||||
|
key_components_add_mp(kc, "private_exponent", ek->privateKey);
|
||||||
|
|
||||||
|
return kc;
|
||||||
|
}
|
||||||
|
|
||||||
static char *eddsa_cache_str(ssh_key *key)
|
static char *eddsa_cache_str(ssh_key *key)
|
||||||
{
|
{
|
||||||
struct eddsa_key *ek = container_of(key, struct eddsa_key, sshk);
|
struct eddsa_key *ek = container_of(key, struct eddsa_key, sshk);
|
||||||
@ -652,6 +673,27 @@ static char *eddsa_cache_str(ssh_key *key)
|
|||||||
return toret;
|
return toret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static key_components *eddsa_components(ssh_key *key)
|
||||||
|
{
|
||||||
|
struct eddsa_key *ek = container_of(key, struct eddsa_key, sshk);
|
||||||
|
key_components *kc = key_components_new();
|
||||||
|
|
||||||
|
key_components_add_text(kc, "key_type", "EdDSA");
|
||||||
|
key_components_add_text(kc, "curve_name", ek->curve->textname);
|
||||||
|
|
||||||
|
mp_int *x, *y;
|
||||||
|
ecc_edwards_get_affine(ek->publicKey, &x, &y);
|
||||||
|
key_components_add_mp(kc, "affine_x", x);
|
||||||
|
key_components_add_mp(kc, "affine_y", y);
|
||||||
|
mp_free(x);
|
||||||
|
mp_free(y);
|
||||||
|
|
||||||
|
if (ek->privateKey)
|
||||||
|
key_components_add_mp(kc, "private_exponent", ek->privateKey);
|
||||||
|
|
||||||
|
return kc;
|
||||||
|
}
|
||||||
|
|
||||||
static void ecdsa_public_blob(ssh_key *key, BinarySink *bs)
|
static void ecdsa_public_blob(ssh_key *key, BinarySink *bs)
|
||||||
{
|
{
|
||||||
struct ecdsa_key *ek = container_of(key, struct ecdsa_key, sshk);
|
struct ecdsa_key *ek = container_of(key, struct ecdsa_key, sshk);
|
||||||
@ -1141,6 +1183,7 @@ const ssh_keyalg ssh_ecdsa_ed25519 = {
|
|||||||
eddsa_private_blob,
|
eddsa_private_blob,
|
||||||
eddsa_openssh_blob,
|
eddsa_openssh_blob,
|
||||||
eddsa_cache_str,
|
eddsa_cache_str,
|
||||||
|
eddsa_components,
|
||||||
|
|
||||||
ec_shared_pubkey_bits,
|
ec_shared_pubkey_bits,
|
||||||
|
|
||||||
@ -1171,6 +1214,7 @@ const ssh_keyalg ssh_ecdsa_nistp256 = {
|
|||||||
ecdsa_private_blob,
|
ecdsa_private_blob,
|
||||||
ecdsa_openssh_blob,
|
ecdsa_openssh_blob,
|
||||||
ecdsa_cache_str,
|
ecdsa_cache_str,
|
||||||
|
ecdsa_components,
|
||||||
|
|
||||||
ec_shared_pubkey_bits,
|
ec_shared_pubkey_bits,
|
||||||
|
|
||||||
@ -1201,6 +1245,7 @@ const ssh_keyalg ssh_ecdsa_nistp384 = {
|
|||||||
ecdsa_private_blob,
|
ecdsa_private_blob,
|
||||||
ecdsa_openssh_blob,
|
ecdsa_openssh_blob,
|
||||||
ecdsa_cache_str,
|
ecdsa_cache_str,
|
||||||
|
ecdsa_components,
|
||||||
|
|
||||||
ec_shared_pubkey_bits,
|
ec_shared_pubkey_bits,
|
||||||
|
|
||||||
@ -1231,6 +1276,7 @@ const ssh_keyalg ssh_ecdsa_nistp521 = {
|
|||||||
ecdsa_private_blob,
|
ecdsa_private_blob,
|
||||||
ecdsa_openssh_blob,
|
ecdsa_openssh_blob,
|
||||||
ecdsa_cache_str,
|
ecdsa_cache_str,
|
||||||
|
ecdsa_components,
|
||||||
|
|
||||||
ec_shared_pubkey_bits,
|
ec_shared_pubkey_bits,
|
||||||
|
|
||||||
|
44
sshpubk.c
44
sshpubk.c
@ -1730,3 +1730,47 @@ const char *key_type_to_str(int type)
|
|||||||
unreachable("bad key type in key_type_to_str");
|
unreachable("bad key type in key_type_to_str");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
key_components *key_components_new(void)
|
||||||
|
{
|
||||||
|
key_components *kc = snew(key_components);
|
||||||
|
kc->ncomponents = 0;
|
||||||
|
kc->componentsize = 0;
|
||||||
|
kc->components = NULL;
|
||||||
|
return kc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void key_components_add_text(key_components *kc,
|
||||||
|
const char *name, const char *value)
|
||||||
|
{
|
||||||
|
sgrowarray(kc->components, kc->componentsize, kc->ncomponents);
|
||||||
|
size_t n = kc->ncomponents++;
|
||||||
|
kc->components[n].name = dupstr(name);
|
||||||
|
kc->components[n].is_mp_int = false;
|
||||||
|
kc->components[n].text = dupstr(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void key_components_add_mp(key_components *kc,
|
||||||
|
const char *name, mp_int *value)
|
||||||
|
{
|
||||||
|
sgrowarray(kc->components, kc->componentsize, kc->ncomponents);
|
||||||
|
size_t n = kc->ncomponents++;
|
||||||
|
kc->components[n].name = dupstr(name);
|
||||||
|
kc->components[n].is_mp_int = true;
|
||||||
|
kc->components[n].mp = mp_copy(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void key_components_free(key_components *kc)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < kc->ncomponents; i++) {
|
||||||
|
sfree(kc->components[i].name);
|
||||||
|
if (kc->components[i].is_mp_int) {
|
||||||
|
mp_free(kc->components[i].mp);
|
||||||
|
} else {
|
||||||
|
smemclr(kc->components[i].text, strlen(kc->components[i].text));
|
||||||
|
sfree(kc->components[i].text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sfree(kc->components);
|
||||||
|
sfree(kc);
|
||||||
|
}
|
||||||
|
22
sshrsa.c
22
sshrsa.c
@ -43,6 +43,21 @@ void BinarySource_get_rsa_ssh1_priv(
|
|||||||
rsa->private_exponent = get_mp_ssh1(src);
|
rsa->private_exponent = get_mp_ssh1(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
key_components *rsa_components(RSAKey *rsa)
|
||||||
|
{
|
||||||
|
key_components *kc = key_components_new();
|
||||||
|
key_components_add_text(kc, "key_type", "RSA");
|
||||||
|
key_components_add_mp(kc, "public_modulus", rsa->modulus);
|
||||||
|
key_components_add_mp(kc, "public_exponent", rsa->exponent);
|
||||||
|
if (rsa->private_exponent) {
|
||||||
|
key_components_add_mp(kc, "private_exponent", rsa->private_exponent);
|
||||||
|
key_components_add_mp(kc, "private_p", rsa->p);
|
||||||
|
key_components_add_mp(kc, "private_q", rsa->q);
|
||||||
|
key_components_add_mp(kc, "private_inverse_q_mod_p", rsa->iqmp);
|
||||||
|
}
|
||||||
|
return kc;
|
||||||
|
}
|
||||||
|
|
||||||
RSAKey *BinarySource_get_rsa_ssh1_priv_agent(BinarySource *src)
|
RSAKey *BinarySource_get_rsa_ssh1_priv_agent(BinarySource *src)
|
||||||
{
|
{
|
||||||
RSAKey *rsa = snew(RSAKey);
|
RSAKey *rsa = snew(RSAKey);
|
||||||
@ -484,6 +499,12 @@ static char *rsa2_cache_str(ssh_key *key)
|
|||||||
return rsastr_fmt(rsa);
|
return rsastr_fmt(rsa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static key_components *rsa2_components(ssh_key *key)
|
||||||
|
{
|
||||||
|
RSAKey *rsa = container_of(key, RSAKey, sshk);
|
||||||
|
return rsa_components(rsa);
|
||||||
|
}
|
||||||
|
|
||||||
static void rsa2_public_blob(ssh_key *key, BinarySink *bs)
|
static void rsa2_public_blob(ssh_key *key, BinarySink *bs)
|
||||||
{
|
{
|
||||||
RSAKey *rsa = container_of(key, RSAKey, sshk);
|
RSAKey *rsa = container_of(key, RSAKey, sshk);
|
||||||
@ -808,6 +829,7 @@ const ssh_keyalg ssh_rsa = {
|
|||||||
rsa2_private_blob,
|
rsa2_private_blob,
|
||||||
rsa2_openssh_blob,
|
rsa2_openssh_blob,
|
||||||
rsa2_cache_str,
|
rsa2_cache_str,
|
||||||
|
rsa2_components,
|
||||||
|
|
||||||
rsa2_pubkey_bits,
|
rsa2_pubkey_bits,
|
||||||
|
|
||||||
|
@ -163,17 +163,41 @@ def make_argword(arg, argtype, fnname, argindex, to_preserve):
|
|||||||
"Can't convert {}() argument {:d} to {} (value was {!r})".format(
|
"Can't convert {}() argument {:d} to {} (value was {!r})".format(
|
||||||
fnname, argindex, typename, arg))
|
fnname, argindex, typename, arg))
|
||||||
|
|
||||||
|
def unpack_string(identifier):
|
||||||
|
retwords = childprocess.funcall("getstring", [identifier])
|
||||||
|
childprocess.funcall("free", [identifier])
|
||||||
|
return re.sub(b"%[0-9A-F][0-9A-F]",
|
||||||
|
lambda m: valbytes([int(m.group(0)[1:], 16)]),
|
||||||
|
retwords[0])
|
||||||
|
|
||||||
|
def unpack_mp(identifier):
|
||||||
|
retwords = childprocess.funcall("mp_dump", [identifier])
|
||||||
|
childprocess.funcall("free", [identifier])
|
||||||
|
return int(retwords[0], 16)
|
||||||
|
|
||||||
def make_retval(rettype, word, unpack_strings):
|
def make_retval(rettype, word, unpack_strings):
|
||||||
if rettype.startswith("opt_"):
|
if rettype.startswith("opt_"):
|
||||||
if word == b"NULL":
|
if word == b"NULL":
|
||||||
return None
|
return None
|
||||||
rettype = rettype[4:]
|
rettype = rettype[4:]
|
||||||
if rettype == "val_string" and unpack_strings:
|
if rettype == "val_string" and unpack_strings:
|
||||||
retwords = childprocess.funcall("getstring", [word])
|
return unpack_string(word)
|
||||||
|
if rettype == "val_keycomponents":
|
||||||
|
kc = {}
|
||||||
|
retwords = childprocess.funcall("key_components_count", [word])
|
||||||
|
for i in range(int(retwords[0], 0)):
|
||||||
|
args = [word, "{:d}".format(i)]
|
||||||
|
retwords = childprocess.funcall("key_components_nth_name", args)
|
||||||
|
kc_key = unpack_string(retwords[0])
|
||||||
|
retwords = childprocess.funcall("key_components_nth_str", args)
|
||||||
|
if retwords[0] != b"NULL":
|
||||||
|
kc_value = unpack_string(retwords[0]).decode("ASCII")
|
||||||
|
else:
|
||||||
|
retwords = childprocess.funcall("key_components_nth_mp", args)
|
||||||
|
kc_value = unpack_mp(retwords[0])
|
||||||
|
kc[kc_key.decode("ASCII")] = kc_value
|
||||||
childprocess.funcall("free", [word])
|
childprocess.funcall("free", [word])
|
||||||
return re.sub(b"%[0-9A-F][0-9A-F]",
|
return kc
|
||||||
lambda m: valbytes([int(m.group(0)[1:], 16)]),
|
|
||||||
retwords[0])
|
|
||||||
if rettype.startswith("val_"):
|
if rettype.startswith("val_"):
|
||||||
return Value(rettype, word)
|
return Value(rettype, word)
|
||||||
elif rettype == "int" or rettype == "uint":
|
elif rettype == "int" or rettype == "uint":
|
||||||
|
22
testcrypt.c
22
testcrypt.c
@ -87,6 +87,7 @@ uint64_t prng_reseed_time_ms(void)
|
|||||||
X(rsakex, RSAKey *, ssh_rsakex_freekey(v)) \
|
X(rsakex, RSAKey *, ssh_rsakex_freekey(v)) \
|
||||||
X(rsa, RSAKey *, rsa_free(v)) \
|
X(rsa, RSAKey *, rsa_free(v)) \
|
||||||
X(prng, prng *, prng_free(v)) \
|
X(prng, prng *, prng_free(v)) \
|
||||||
|
X(keycomponents, key_components *, key_components_free(v)) \
|
||||||
/* end of list */
|
/* end of list */
|
||||||
|
|
||||||
typedef struct Value Value;
|
typedef struct Value Value;
|
||||||
@ -576,6 +577,7 @@ static void return_val_string_asciz(strbuf *out, char *s)
|
|||||||
|
|
||||||
NULLABLE_RETURN_WRAPPER(val_string, strbuf *)
|
NULLABLE_RETURN_WRAPPER(val_string, strbuf *)
|
||||||
NULLABLE_RETURN_WRAPPER(val_string_asciz, char *)
|
NULLABLE_RETURN_WRAPPER(val_string_asciz, char *)
|
||||||
|
NULLABLE_RETURN_WRAPPER(val_string_asciz_const, const char *)
|
||||||
NULLABLE_RETURN_WRAPPER(val_cipher, ssh_cipher *)
|
NULLABLE_RETURN_WRAPPER(val_cipher, ssh_cipher *)
|
||||||
NULLABLE_RETURN_WRAPPER(val_hash, ssh_hash *)
|
NULLABLE_RETURN_WRAPPER(val_hash, ssh_hash *)
|
||||||
NULLABLE_RETURN_WRAPPER(val_key, ssh_key *)
|
NULLABLE_RETURN_WRAPPER(val_key, ssh_key *)
|
||||||
@ -1077,6 +1079,25 @@ ssh_key *eddsa_generate_wrapper(int bits)
|
|||||||
}
|
}
|
||||||
#define eddsa_generate eddsa_generate_wrapper
|
#define eddsa_generate eddsa_generate_wrapper
|
||||||
|
|
||||||
|
size_t key_components_count(key_components *kc) { return kc->ncomponents; }
|
||||||
|
const char *key_components_nth_name(key_components *kc, size_t n)
|
||||||
|
{
|
||||||
|
return (n >= kc->ncomponents ? NULL :
|
||||||
|
kc->components[n].name);
|
||||||
|
}
|
||||||
|
const char *key_components_nth_str(key_components *kc, size_t n)
|
||||||
|
{
|
||||||
|
return (n >= kc->ncomponents ? NULL :
|
||||||
|
kc->components[n].is_mp_int ? NULL :
|
||||||
|
kc->components[n].text);
|
||||||
|
}
|
||||||
|
mp_int *key_components_nth_mp(key_components *kc, size_t n)
|
||||||
|
{
|
||||||
|
return (n >= kc->ncomponents ? NULL :
|
||||||
|
!kc->components[n].is_mp_int ? NULL :
|
||||||
|
mp_copy(kc->components[n].mp));
|
||||||
|
}
|
||||||
|
|
||||||
#define VALTYPE_TYPEDEF(n,t,f) \
|
#define VALTYPE_TYPEDEF(n,t,f) \
|
||||||
typedef t TD_val_##n; \
|
typedef t TD_val_##n; \
|
||||||
typedef t *TD_out_val_##n;
|
typedef t *TD_out_val_##n;
|
||||||
@ -1113,6 +1134,7 @@ typedef const ssh_cipheralg *TD_cipheralg;
|
|||||||
typedef const ssh_kex *TD_dh_group;
|
typedef const ssh_kex *TD_dh_group;
|
||||||
typedef const ssh_kex *TD_ecdh_alg;
|
typedef const ssh_kex *TD_ecdh_alg;
|
||||||
typedef RsaSsh1Order TD_rsaorder;
|
typedef RsaSsh1Order TD_rsaorder;
|
||||||
|
typedef key_components *TD_keycomponents;
|
||||||
|
|
||||||
#define FUNC0(rettype, function) \
|
#define FUNC0(rettype, function) \
|
||||||
static void handle_##function(BinarySource *in, strbuf *out) { \
|
static void handle_##function(BinarySource *in, strbuf *out) { \
|
||||||
|
@ -157,8 +157,17 @@ FUNC2(void, ssh_key_public_blob, val_key, out_val_string_binarysink)
|
|||||||
FUNC2(void, ssh_key_private_blob, val_key, out_val_string_binarysink)
|
FUNC2(void, ssh_key_private_blob, val_key, out_val_string_binarysink)
|
||||||
FUNC2(void, ssh_key_openssh_blob, val_key, out_val_string_binarysink)
|
FUNC2(void, ssh_key_openssh_blob, val_key, out_val_string_binarysink)
|
||||||
FUNC1(val_string_asciz, ssh_key_cache_str, val_key)
|
FUNC1(val_string_asciz, ssh_key_cache_str, val_key)
|
||||||
|
FUNC1(val_keycomponents, ssh_key_components, val_key)
|
||||||
FUNC2(uint, ssh_key_public_bits, keyalg, val_string_ptrlen)
|
FUNC2(uint, ssh_key_public_bits, keyalg, val_string_ptrlen)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Accessors to retrieve the innards of a 'key_components'.
|
||||||
|
*/
|
||||||
|
FUNC1(uint, key_components_count, val_keycomponents)
|
||||||
|
FUNC2(opt_val_string_asciz_const, key_components_nth_name, val_keycomponents, uint)
|
||||||
|
FUNC2(opt_val_string_asciz_const, key_components_nth_str, val_keycomponents, uint)
|
||||||
|
FUNC2(opt_val_mpint, key_components_nth_mp, val_keycomponents, uint)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The ssh_cipher abstraction. The in-place encrypt and decrypt
|
* The ssh_cipher abstraction. The in-place encrypt and decrypt
|
||||||
* functions are wrapped to replace them with versions that take one
|
* functions are wrapped to replace them with versions that take one
|
||||||
|
4
testsc.c
4
testsc.c
@ -93,6 +93,10 @@ static NORETURN PRINTF_LIKE(1, 2) void fatal_error(const char *p, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void out_of_memory(void) { fatal_error("out of memory"); }
|
void out_of_memory(void) { fatal_error("out of memory"); }
|
||||||
|
FILE *f_open(const Filename *filename, char const *mode, bool is_private)
|
||||||
|
{ unreachable("this is a stub needed to link, and should never be called"); }
|
||||||
|
void old_keyfile_warning(void)
|
||||||
|
{ unreachable("this is a stub needed to link, and should never be called"); }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A simple deterministic PRNG, without any of the Fortuna
|
* A simple deterministic PRNG, without any of the Fortuna
|
||||||
|
24
utils.c
24
utils.c
@ -1049,3 +1049,27 @@ size_t encode_utf8(void *output, unsigned long ch)
|
|||||||
}
|
}
|
||||||
return p - start;
|
return p - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_c_string_literal(FILE *fp, ptrlen str)
|
||||||
|
{
|
||||||
|
for (const char *p = str.ptr; p < (const char *)str.ptr + str.len; p++) {
|
||||||
|
char c = *p;
|
||||||
|
|
||||||
|
if (c == '\n')
|
||||||
|
fputs("\\n", fp);
|
||||||
|
else if (c == '\r')
|
||||||
|
fputs("\\r", fp);
|
||||||
|
else if (c == '\t')
|
||||||
|
fputs("\\t", fp);
|
||||||
|
else if (c == '\b')
|
||||||
|
fputs("\\b", fp);
|
||||||
|
else if (c == '\\')
|
||||||
|
fputs("\\\\", fp);
|
||||||
|
else if (c == '"')
|
||||||
|
fputs("\\\"", fp);
|
||||||
|
else if (c >= 32 && c <= 126)
|
||||||
|
fputc(c, fp);
|
||||||
|
else
|
||||||
|
fprintf(fp, "\\%03o", (unsigned char)c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user