CryptX
view release on metacpan or search on metacpan
src/ltc/misc/pem/pem_ssh.c view on Meta::CPAN
* there was no comment inside the SSH key.
*/
if (*comment == NULL && elements[ake_comment].p) {
*comment = XMALLOC(elements[ake_comment].len + 1);
if (*comment == NULL) {
return CRYPT_MEM;
}
XMEMCPY(*comment, elements[ake_comment].p, elements[ake_comment].len);
(*comment)[elements[ake_comment].len] = '\0';
}
*len = r - line;
return CRYPT_OK;
}
}
return CRYPT_PK_INVALID_TYPE;
}
static int s_read_authorized_keys(const void *buf, unsigned long len, ssh_authorized_key_cb cb, void *ctx)
{
char *s;
int err;
unsigned long clen = len;
ltc_pka_key *key = XCALLOC(1, sizeof(*key));
char *comment = NULL;
void *cpy = XMALLOC(len);
if (key == NULL || cpy == NULL) {
if (cpy)
XFREE(cpy);
if (key)
XFREE(key);
return CRYPT_MEM;
}
XMEMCPY(cpy, buf, len);
s = cpy;
while (clen && (err = s_parse_line(s, &clen, key, &comment)) == CRYPT_OK) {
if (cb(key, comment, ctx)) {
break;
}
s += clen;
len -= clen;
clen = len;
key = XCALLOC(1, sizeof(*key));
if (key == NULL) {
err = CRYPT_MEM;
break;
}
if (comment) {
XFREE(comment);
comment = NULL;
}
}
if (comment)
XFREE(comment);
if (cpy)
XFREE(cpy);
if (key)
XFREE(key);
return err;
}
static int s_decrypt_private_keys(unsigned char *in, unsigned long *inlen,
unsigned char *tag, unsigned long taglen,
struct kdf_options *opts)
{
int err, cipher;
unsigned long symkey_len, iv_len;
unsigned char symkey[MAXBLOCKSIZE], *iv, iv_[8] = { 0 };
enum cipher_mode mode = opts->cipher->mode & cm_modes;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != NULL);
LTC_ARGCHK(opts != NULL);
if (mode != cm_stream) {
cipher = find_cipher(opts->cipher->algo);
if (cipher == -1) {
return CRYPT_INVALID_CIPHER;
}
iv = symkey + opts->cipher->keylen;
iv_len = mode == cm_gcm ? 12 : cipher_descriptor[cipher].block_length;
symkey_len = opts->cipher->keylen + iv_len;
} else {
iv = iv_;
iv_len = sizeof(iv_);
symkey_len = 64;
}
if (sizeof(symkey) < symkey_len) {
return CRYPT_OVERFLOW;
}
if ((err = bcrypt_pbkdf_openbsd(opts->pw.pw, opts->pw.l, opts->salt, opts->saltlen,
opts->num_rounds, find_hash("sha512"), symkey, &symkey_len)) != CRYPT_OK) {
return err;
}
err = pem_decrypt(in, inlen,
symkey, opts->cipher->keylen,
iv, iv_len,
tag, taglen,
opts->cipher, LTC_PAD_SSH);
zeromem(symkey, sizeof(symkey));
return err;
}
static int s_decode_header(unsigned char *in, unsigned long *inlen, struct kdf_options *opts)
{
int err;
unsigned char ciphername[64], kdfname[64], kdfoptions[128], pubkey1[2048];
unsigned long ciphernamelen = sizeof(ciphername), kdfnamelen = sizeof(kdfname);
unsigned long kdfoptionslen = sizeof(kdfoptions), pubkey1len = sizeof(pubkey1);
ulong32 num_keys;
unsigned long i;
void *magic = strstr((const char*)in, "openssh-key-v1");
unsigned long slen = XSTRLEN("openssh-key-v1");
unsigned char *start = &in[slen + 1];
unsigned long len = *inlen - slen - 1;
if (magic == NULL || magic != in) {
src/ltc/misc/pem/pem_ssh.c view on Meta::CPAN
},
};
static const unsigned long pem_openssh_num = LTC_ARRAY_SIZE(pem_openssh);
static int s_decode_openssh(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_ctx)
{
unsigned char *pem = NULL, *p, *privkey = NULL, *tag;
unsigned long n, w = 0, l, privkey_len, taglen;
int err;
struct pem_headers hdr;
struct kdf_options opts = { 0 };
XMEMSET(k, 0, sizeof(*k));
for (n = 0; n < pem_openssh_num; ++n) {
hdr.id = &pem_openssh[n];
err = pem_read((void**)&pem, &w, &hdr, g);
if (err == CRYPT_OK) {
break;
} else if (err != CRYPT_UNKNOWN_PEM) {
goto cleanup;
}
hdr.id = NULL;
}
/* id not found */
if (hdr.id == NULL) {
goto cleanup;
}
p = pem;
l = w;
if (hdr.id->flags != pf_public) {
if ((err = s_decode_header(pem, &w, &opts)) != CRYPT_OK) {
goto cleanup;
}
p = pem + w;
l -= w;
w = l;
privkey_len = l;
privkey = XMALLOC(privkey_len);
if (privkey == NULL) {
return CRYPT_MEM;
}
if ((err = ssh_decode_sequence_multi(p, &w,
LTC_SSHDATA_STRING, privkey, &privkey_len,
LTC_SSHDATA_EOL, LTC_NULL)) != CRYPT_OK) {
goto cleanup;
}
if (XSTRCMP(opts.name, "none") != 0) {
if ((pw_ctx == NULL) || (pw_ctx->callback == NULL)) {
err = CRYPT_PW_CTX_MISSING;
goto cleanup;
}
if (pw_ctx->callback(&opts.pw.pw, &opts.pw.l, pw_ctx->userdata)) {
err = CRYPT_ERROR;
goto cleanup;
}
tag = p + w;
taglen = l - w;
w = privkey_len;
if ((err = s_decrypt_private_keys(privkey, &privkey_len,
tag, taglen,
&opts)) != CRYPT_OK) {
goto cleanup;
}
zeromem(opts.pw.pw, opts.pw.l);
}
p = privkey;
w = privkey_len;
}
if ((err = s_decode_key(p, &w, k, NULL, hdr.id->flags)) != CRYPT_OK) {
goto cleanup;
}
cleanup:
password_free(&opts.pw, pw_ctx);
if (privkey) {
zeromem(privkey, privkey_len);
XFREE(privkey);
}
if (pem) {
XFREE(pem);
}
return err;
}
#ifndef LTC_NO_FILE
int pem_decode_openssh_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_ctx)
{
LTC_ARGCHK(f != NULL);
LTC_ARGCHK(k != NULL);
{
struct get_char g = pem_get_char_init_filehandle(f);
return s_decode_openssh(&g, k, pw_ctx);
}
}
int ssh_read_authorized_keys_filehandle(FILE *f, ssh_authorized_key_cb cb, void *ctx)
{
size_t tot_data;
void *buf;
int err;
LTC_ARGCHK(f != NULL);
LTC_ARGCHK(cb != NULL);
if (fseek(f, 0, SEEK_END) == -1)
return CRYPT_ERROR;
tot_data = ftell(f);
if (fseek(f, 0, SEEK_SET) == -1)
return CRYPT_ERROR;
buf = XMALLOC(tot_data);
if (buf == NULL) {
return CRYPT_MEM;
}
if (fread(buf, 1, tot_data, f) != tot_data) {
err = CRYPT_ERROR;
} else {
err = s_read_authorized_keys(buf, tot_data, cb, ctx);
}
( run in 2.298 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )