diff --git a/import.c b/import.c index 41c06a9a..28e70b8a 100644 --- a/import.c +++ b/import.c @@ -1075,7 +1075,7 @@ static bool openssh_pem_write( fprintf(fp, "%02X", iv[i]); fprintf(fp, "\n\n"); } - base64_encode(fp, outblob->u, outblob->len, 64); + base64_encode_fp(fp, ptrlen_from_strbuf(outblob), 64); fputs(footer, fp); fclose(fp); ret = true; @@ -1606,7 +1606,7 @@ static bool openssh_new_write( if (!fp) goto error; fputs("-----BEGIN OPENSSH PRIVATE KEY-----\n", fp); - base64_encode(fp, cblob->u, cblob->len, 64); + base64_encode_fp(fp, ptrlen_from_strbuf(cblob), 64); fputs("-----END OPENSSH PRIVATE KEY-----\n", fp); fclose(fp); ret = true; @@ -2308,7 +2308,7 @@ static bool sshcom_write( } fprintf(fp, "%s\"\n", c); } - base64_encode(fp, outblob->u, outblob->len, 70); + base64_encode_fp(fp, ptrlen_from_strbuf(outblob), 70); fputs("---- END SSH2 ENCRYPTED PRIVATE KEY ----\n", fp); fclose(fp); ret = true; diff --git a/misc.h b/misc.h index a2dee9ac..eeed80c1 100644 --- a/misc.h +++ b/misc.h @@ -108,6 +108,12 @@ bool strendswith(const char *s, const char *t); void base64_encode_atom(const unsigned char *data, int n, char *out); int base64_decode_atom(const char *atom, unsigned char *out); +void base64_decode_bs(BinarySink *bs, ptrlen data); +void base64_decode_fp(FILE *fp, ptrlen data); +strbuf *base64_decode_sb(ptrlen data); +void base64_encode_bs(BinarySink *bs, ptrlen data, int cpl); +void base64_encode_fp(FILE *fp, ptrlen data, int cpl); +strbuf *base64_encode_sb(ptrlen data, int cpl); struct bufchain_granule; struct bufchain_tag { diff --git a/ssh.h b/ssh.h index b703945f..3465c196 100644 --- a/ssh.h +++ b/ssh.h @@ -1290,11 +1290,7 @@ static inline bool is_base64_char(char c) c == '+' || c == '/' || c == '='); } -extern int base64_decode_atom(const char *atom, unsigned char *out); extern int base64_lines(int datalen); -extern void base64_encode_atom(const unsigned char *data, int n, char *out); -extern void base64_encode(FILE *fp, const unsigned char *data, int datalen, - int cpl); /* ppk_load_* can return this as an error */ extern ssh2_userkey ssh2_wrong_passphrase; diff --git a/sshpubk.c b/sshpubk.c index 4b332778..2755df0f 100644 --- a/sshpubk.c +++ b/sshpubk.c @@ -1391,37 +1391,6 @@ int base64_lines(int datalen) return (datalen + 47) / 48; } -static void base64_encode_s(BinarySink *bs, const unsigned char *data, - int datalen, int cpl) -{ - int linelen = 0; - char out[4]; - int n, i; - - while (datalen > 0) { - n = (datalen < 3 ? datalen : 3); - base64_encode_atom(data, n, out); - data += n; - datalen -= n; - for (i = 0; i < 4; i++) { - if (linelen >= cpl) { - linelen = 0; - put_byte(bs, '\n'); - } - put_byte(bs, out[i]); - linelen++; - } - } - put_byte(bs, '\n'); -} - -void base64_encode(FILE *fp, const unsigned char *data, int datalen, int cpl) -{ - stdio_sink ss; - stdio_sink_init(&ss, fp); - base64_encode_s(BinarySink_UPCAST(&ss), data, datalen, cpl); -} - const ppk_save_parameters ppk_save_default_parameters = { .fmt_version = 3, @@ -1566,7 +1535,7 @@ strbuf *ppk_save_sb(ssh2_userkey *key, const char *passphrase, put_fmt(out, "Encryption: %s\n", cipherstr); put_fmt(out, "Comment: %s\n", key->comment); put_fmt(out, "Public-Lines: %d\n", base64_lines(pub_blob->len)); - base64_encode_s(BinarySink_UPCAST(out), pub_blob->u, pub_blob->len, 64); + base64_encode_bs(BinarySink_UPCAST(out), ptrlen_from_strbuf(pub_blob), 64); if (params.fmt_version == 3 && ciphertype->keylen != 0) { put_fmt(out, "Key-Derivation: %s\n", params.argon2_flavour == Argon2d ? "Argon2d" : @@ -1582,8 +1551,8 @@ strbuf *ppk_save_sb(ssh2_userkey *key, const char *passphrase, put_fmt(out, "\n"); } put_fmt(out, "Private-Lines: %d\n", base64_lines(priv_encrypted_len)); - base64_encode_s(BinarySink_UPCAST(out), - priv_blob_encrypted, priv_encrypted_len, 64); + base64_encode_bs(BinarySink_UPCAST(out), + make_ptrlen(priv_blob_encrypted, priv_encrypted_len), 64); put_fmt(out, "Private-MAC: "); for (i = 0; i < macalg->len; i++) put_fmt(out, "%02x", priv_mac[i]); diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 9e995e04..74ce4d54 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -2,7 +2,9 @@ add_sources_from_current_dir(utils antispoof.c backend_socket_log.c base64_decode_atom.c + base64_decode.c base64_encode_atom.c + base64_encode.c bufchain.c buildinfo.c burnstr.c diff --git a/utils/base64_decode.c b/utils/base64_decode.c new file mode 100644 index 00000000..4f00f196 --- /dev/null +++ b/utils/base64_decode.c @@ -0,0 +1,37 @@ +#include "misc.h" + +void base64_decode_bs(BinarySink *bs, ptrlen input) +{ + BinarySource src[1]; + BinarySource_BARE_INIT_PL(src, input); + + while (get_avail(src)) { + char b64atom[4]; + unsigned char binatom[3]; + + for (size_t i = 0; i < 4 ;) { + char c = get_byte(src); + if (get_err(src)) + c = '='; + if (c == '\n' || c == '\r') + continue; + b64atom[i++] = c; + } + + put_data(bs, binatom, base64_decode_atom(b64atom, binatom)); + } +} + +void base64_decode_fp(FILE *fp, ptrlen input) +{ + stdio_sink ss; + stdio_sink_init(&ss, fp); + base64_decode_bs(BinarySink_UPCAST(&ss), input); +} + +strbuf *base64_decode_sb(ptrlen input) +{ + strbuf *sb = strbuf_new_nm(); + base64_decode_bs(BinarySink_UPCAST(sb), input); + return sb; +} diff --git a/utils/base64_encode.c b/utils/base64_encode.c new file mode 100644 index 00000000..3db85571 --- /dev/null +++ b/utils/base64_encode.c @@ -0,0 +1,40 @@ +#include "misc.h" + +void base64_encode_bs(BinarySink *bs, ptrlen input, int cpl) +{ + BinarySource src[1]; + BinarySource_BARE_INIT_PL(src, input); + int linelen = 0; + + while (get_avail(src)) { + size_t n = get_avail(src) < 3 ? get_avail(src) : 3; + ptrlen binatom = get_data(src, n); + + char b64atom[4]; + base64_encode_atom(binatom.ptr, binatom.len, b64atom); + for (size_t i = 0; i < 4; i++) { + if (cpl > 0 && linelen >= cpl) { + linelen = 0; + put_byte(bs, '\n'); + } + put_byte(bs, b64atom[i]); + linelen++; + } + } + if (cpl > 0) + put_byte(bs, '\n'); +} + +void base64_encode_fp(FILE *fp, ptrlen input, int cpl) +{ + stdio_sink ss; + stdio_sink_init(&ss, fp); + base64_encode_bs(BinarySink_UPCAST(&ss), input, cpl); +} + +strbuf *base64_encode_sb(ptrlen input, int cpl) +{ + strbuf *sb = strbuf_new_nm(); + base64_encode_bs(BinarySink_UPCAST(sb), input, cpl); + return sb; +}