mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 09:27:59 +00: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
|
||||
+ memory tree234 winmiscs KEYGEN
|
||||
testsc : [UT] testsc SSHCRYPTO marshal utils memory tree234 wildcard
|
||||
+ sshmac uxutils
|
||||
+ sshmac uxutils sshpubk
|
||||
testzlib : [UT] testzlib sshzlib utils marshal memory
|
||||
|
||||
uppity : [UT] uxserver SSHSERVER UXMISC uxsignal uxnoise uxgss uxnogtk
|
||||
|
77
cmdgen.c
77
cmdgen.c
@ -13,6 +13,7 @@
|
||||
|
||||
#include "putty.h"
|
||||
#include "ssh.h"
|
||||
#include "mpint.h"
|
||||
|
||||
struct progress {
|
||||
int phase, current;
|
||||
@ -97,6 +98,8 @@ void help(void)
|
||||
" public RFC 4716 / ssh.com public key\n"
|
||||
" public-openssh OpenSSH public key\n"
|
||||
" fingerprint output the key fingerprint\n"
|
||||
" text output the key components as "
|
||||
"'name=0x####'\n"
|
||||
" -o specify output file\n"
|
||||
" -l equivalent to `-O fingerprint'\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;
|
||||
char *outfile = NULL, *outfiletmp = NULL;
|
||||
enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH_AUTO,
|
||||
OPENSSH_NEW, SSHCOM } outtype = PRIVATE;
|
||||
OPENSSH_NEW, SSHCOM, TEXT } outtype = PRIVATE;
|
||||
int bits = -1;
|
||||
const char *comment = NULL;
|
||||
char *origcomment = NULL;
|
||||
@ -287,6 +290,8 @@ int main(int argc, char **argv)
|
||||
} else {
|
||||
random_device = val;
|
||||
}
|
||||
} else if (!strcmp(opt, "-dump")) {
|
||||
outtype = TEXT;
|
||||
} else {
|
||||
errs = true;
|
||||
fprintf(stderr,
|
||||
@ -389,6 +394,8 @@ int main(int argc, char **argv)
|
||||
outtype = OPENSSH_NEW, sshver = 2;
|
||||
else if (!strcmp(p, "private-sshcom"))
|
||||
outtype = SSHCOM, sshver = 2;
|
||||
else if (!strcmp(p, "text"))
|
||||
outtype = TEXT;
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"puttygen: unknown output type `%s'\n", p);
|
||||
@ -498,7 +505,7 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
if (keytype != NOKEYGEN &&
|
||||
(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 "
|
||||
"discard the private part\n");
|
||||
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
|
||||
* 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();
|
||||
int ret;
|
||||
|
||||
@ -1039,6 +1051,65 @@ int main(int argc, char **argv)
|
||||
RETURN(1); /* rename failed */
|
||||
}
|
||||
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:
|
||||
|
3
misc.h
3
misc.h
@ -215,6 +215,9 @@ bool smemeq(const void *av, const void *bv, size_t len);
|
||||
* been removed. */
|
||||
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);
|
||||
|
||||
/*
|
||||
|
22
ssh.h
22
ssh.h
@ -528,6 +528,24 @@ struct eddsa_key {
|
||||
WeierstrassPoint *ecdsa_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
|
||||
* 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 freersapriv(RSAKey *key);
|
||||
void freersakey(RSAKey *key);
|
||||
key_components *rsa_components(RSAKey *key);
|
||||
|
||||
uint32_t crc32_rfc1662(ptrlen data);
|
||||
uint32_t crc32_ssh1(ptrlen data);
|
||||
@ -801,6 +820,7 @@ struct ssh_keyalg {
|
||||
void (*private_blob)(ssh_key *key, BinarySink *);
|
||||
void (*openssh_blob) (ssh_key *key, BinarySink *);
|
||||
char *(*cache_str) (ssh_key *key);
|
||||
key_components *(*components) (ssh_key *key);
|
||||
|
||||
/* 'Class methods' that don't deal with an ssh_key at all */
|
||||
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); }
|
||||
static inline char *ssh_key_cache_str(ssh_key *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)
|
||||
{ return self->pubkey_bits(self, blob); }
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* 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_openssh_blob,
|
||||
dss_cache_str,
|
||||
dss_components,
|
||||
|
||||
dss_pubkey_bits,
|
||||
|
||||
|
46
sshecc.c
46
sshecc.c
@ -640,6 +640,27 @@ static char *ecdsa_cache_str(ssh_key *key)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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_openssh_blob,
|
||||
eddsa_cache_str,
|
||||
eddsa_components,
|
||||
|
||||
ec_shared_pubkey_bits,
|
||||
|
||||
@ -1171,6 +1214,7 @@ const ssh_keyalg ssh_ecdsa_nistp256 = {
|
||||
ecdsa_private_blob,
|
||||
ecdsa_openssh_blob,
|
||||
ecdsa_cache_str,
|
||||
ecdsa_components,
|
||||
|
||||
ec_shared_pubkey_bits,
|
||||
|
||||
@ -1201,6 +1245,7 @@ const ssh_keyalg ssh_ecdsa_nistp384 = {
|
||||
ecdsa_private_blob,
|
||||
ecdsa_openssh_blob,
|
||||
ecdsa_cache_str,
|
||||
ecdsa_components,
|
||||
|
||||
ec_shared_pubkey_bits,
|
||||
|
||||
@ -1231,6 +1276,7 @@ const ssh_keyalg ssh_ecdsa_nistp521 = {
|
||||
ecdsa_private_blob,
|
||||
ecdsa_openssh_blob,
|
||||
ecdsa_cache_str,
|
||||
ecdsa_components,
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 *rsa = snew(RSAKey);
|
||||
@ -484,6 +499,12 @@ static char *rsa2_cache_str(ssh_key *key)
|
||||
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)
|
||||
{
|
||||
RSAKey *rsa = container_of(key, RSAKey, sshk);
|
||||
@ -808,6 +829,7 @@ const ssh_keyalg ssh_rsa = {
|
||||
rsa2_private_blob,
|
||||
rsa2_openssh_blob,
|
||||
rsa2_cache_str,
|
||||
rsa2_components,
|
||||
|
||||
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(
|
||||
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):
|
||||
if rettype.startswith("opt_"):
|
||||
if word == b"NULL":
|
||||
return None
|
||||
rettype = rettype[4:]
|
||||
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])
|
||||
return re.sub(b"%[0-9A-F][0-9A-F]",
|
||||
lambda m: valbytes([int(m.group(0)[1:], 16)]),
|
||||
retwords[0])
|
||||
return kc
|
||||
if rettype.startswith("val_"):
|
||||
return Value(rettype, word)
|
||||
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(rsa, RSAKey *, rsa_free(v)) \
|
||||
X(prng, prng *, prng_free(v)) \
|
||||
X(keycomponents, key_components *, key_components_free(v)) \
|
||||
/* end of list */
|
||||
|
||||
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_asciz, char *)
|
||||
NULLABLE_RETURN_WRAPPER(val_string_asciz_const, const char *)
|
||||
NULLABLE_RETURN_WRAPPER(val_cipher, ssh_cipher *)
|
||||
NULLABLE_RETURN_WRAPPER(val_hash, ssh_hash *)
|
||||
NULLABLE_RETURN_WRAPPER(val_key, ssh_key *)
|
||||
@ -1077,6 +1079,25 @@ ssh_key *eddsa_generate_wrapper(int bits)
|
||||
}
|
||||
#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) \
|
||||
typedef t TD_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_ecdh_alg;
|
||||
typedef RsaSsh1Order TD_rsaorder;
|
||||
typedef key_components *TD_keycomponents;
|
||||
|
||||
#define FUNC0(rettype, function) \
|
||||
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_openssh_blob, val_key, out_val_string_binarysink)
|
||||
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)
|
||||
|
||||
/*
|
||||
* 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
|
||||
* 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"); }
|
||||
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
|
||||
|
24
utils.c
24
utils.c
@ -1049,3 +1049,27 @@ size_t encode_utf8(void *output, unsigned long ch)
|
||||
}
|
||||
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…
Reference in New Issue
Block a user