srandom(seed);
}
-static EVP_PKEY *load_key(const char *file, int private)
+static EVP_PKEY *load_key(const char *file)
{
BIO *key;
EVP_PKEY *pkey = NULL;
key = BIO_new(BIO_s_file());
if (!key)
return NULL;
- if (BIO_read_filename(key, file) > 0) {
- if (private == LOAD_PRIVATE_KEY)
- pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL);
- else
- pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL);
- }
+ if (BIO_read_filename(key, file) > 0)
+ pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL);
BIO_free(key);
return pkey;
}
-static int get_openssl_key(const char *key_file, RSA **rsa, int private)
+static int get_private_key(const char *key_file, RSA **rsa)
{
- EVP_PKEY *key = load_key(key_file, private);
+ EVP_PKEY *key = load_key(key_file);
if (!key)
- return (private == LOAD_PRIVATE_KEY)? -E_PRIVATE_KEY
- : -E_PUBLIC_KEY;
+ return -E_PRIVATE_KEY;
*rsa = EVP_PKEY_get1_RSA(key);
EVP_PKEY_free(key);
if (!*rsa)
goto out;
ret = is_ssh_rsa_key(map, map_size);
if (!ret) {
- ret = para_munmap(map, map_size);
- map = NULL;
- if (ret < 0)
- goto out;
- ret = get_openssl_key(key_file, &key->rsa, LOAD_PUBLIC_KEY);
- goto out;
+ para_munmap(map, map_size);
+ return -E_SSH_PARSE;
}
cp = map + ret;
encoded_size = map_size - ret;
if (inlen < 0)
return -E_RSA;
priv = para_malloc(sizeof(*priv));
- ret = get_openssl_key(key_file, &priv->rsa, LOAD_PRIVATE_KEY);
+ ret = get_private_key(key_file, &priv->rsa);
if (ret < 0) {
free(priv);
return ret;
return c & 0x7f;
}
-static int find_pubkey_bignum_offset(const unsigned char *data, int len)
-{
- const unsigned char *p = data, *end = data + len;
-
- /* the whole thing starts with one sequence */
- if (*p != ASN1_TYPE_SEQUENCE)
- return -E_ASN1_PARSE;
- p++;
- if (p >= end)
- return -E_ASN1_PARSE;
- if (is_short_form(*p))
- p++;
- else
- p += 1 + get_long_form_num_length_bytes(*p);
- if (p >= end)
- return -E_ASN1_PARSE;
- /* another sequence containing the object id, skip it */
- if (*p != ASN1_TYPE_SEQUENCE)
- return -E_ASN1_PARSE;
- p++;
- if (p >= end)
- return -E_ASN1_PARSE;
- if (!is_short_form(*p))
- return -E_ASN1_PARSE;
- p += 1 + get_short_form_length(*p);
- if (p >= end)
- return -E_ASN1_PARSE;
- /* all numbers are wrapped in a bit string object that follows */
- if (*p != ASN1_TYPE_BIT_STRING)
- return -E_ASN1_PARSE;
- p++;
- if (p >= end)
- return -E_ASN1_PARSE;
- if (is_short_form(*p))
- p++;
- else
- p += 1 + get_long_form_num_length_bytes(*p);
- p++; /* skip number of unused bits in the bit string */
- if (p >= end)
- return -E_ASN1_PARSE;
-
- /* next, we have a sequence of two integers (n and e) */
- if (*p != ASN1_TYPE_SEQUENCE)
- return -E_ASN1_PARSE;
- p++;
- if (p >= end)
- return -E_ASN1_PARSE;
- if (is_short_form(*p))
- p++;
- else
- p += 1 + get_long_form_num_length_bytes(*p);
- if (p >= end)
- return -E_ASN1_PARSE;
- if (*p != ASN1_TYPE_INTEGER)
- return -E_ASN1_PARSE;
- return p - data;
-}
-
/*
* Returns: Number of bytes scanned. This may differ from the value returned via
* bn_bytes because the latter does not include the ASN.1 prefix and a leading
return ret;
}
-/** Public keys start with this header. */
-#define PUBLIC_KEY_HEADER "-----BEGIN PUBLIC KEY-----"
-/** Public keys end with this footer. */
-#define PUBLIC_KEY_FOOTER "-----END PUBLIC KEY-----"
-
-static int get_asn_public_key(const char *key_file, struct asymmetric_key **result)
-{
- gcry_mpi_t n = NULL, e = NULL;
- unsigned char *blob, *cp, *end;
- int blob_size, ret, n_size;
- gcry_error_t gret;
- size_t erroff;
- gcry_sexp_t sexp;
- struct asymmetric_key *key;
-
- ret = decode_key(key_file, PUBLIC_KEY_HEADER, PUBLIC_KEY_FOOTER,
- &blob);
- if (ret < 0)
- return ret;
- blob_size = ret;
- end = blob + blob_size;
- ret = find_pubkey_bignum_offset(blob, blob_size);
- if (ret < 0)
- goto free_blob;
- PARA_DEBUG_LOG("decoding public RSA params at offset %d\n", ret);
- cp = blob + ret;
-
- ret = read_bignum(cp, end, &n, &n_size);
- if (ret < 0)
- goto free_blob;
- cp += ret;
-
- ret = read_bignum(cp, end, &e, NULL);
- if (ret < 0)
- goto release_n;
-
- gret = gcry_sexp_build(&sexp, &erroff, RSA_PUBKEY_SEXP, n, e);
- if (gret) {
- PARA_ERROR_LOG("offset %zu: %s\n", erroff,
- gcry_strerror(gcry_err_code(gret)));
- ret = -E_SEXP_BUILD;
- goto release_e;
- }
- key = para_malloc(sizeof(*key));
- key->sexp = sexp;
- key->num_bytes = n_size;
- *result = key;
- ret = n_size;
- PARA_INFO_LOG("successfully read %d bit asn public key\n", n_size * 8);
-
-release_e:
- gcry_mpi_release(e);
-release_n:
- gcry_mpi_release(n);
-free_blob:
- free(blob);
- return ret;
-}
-
static int get_ssh_public_key(unsigned char *data, int size, gcry_sexp_t *result)
{
int ret;
return ret;
ret = is_ssh_rsa_key(map, map_size);
if (!ret) {
- ret = para_munmap(map, map_size);
- if (ret < 0)
- return ret;
- return get_asn_public_key(key_file, result);
+ para_munmap(map, map_size);
+ return -E_SSH_PARSE;
}
start = map + ret;
end = map + map_size;