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 )