From d9f54f439c98aed8b974f55acd468bdae424683f Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Tue, 12 Jul 2016 19:54:19 +0200 Subject: [PATCH] crypto: Remove support for ASN public keys. These have been deprecated for some years in favor of ssh keys generated with ssh-keygen(1). Removing support for the deprecated format allows to get rid of quite some ugly ASN parsing code. Private ASN keys, however, still need to be parsed in case libgcrypt is employed as the crypto API. So the parser in find_privkey_bignum_offset() needs to stay. --- crypt.c | 27 ++++-------- gcrypt.c | 123 +------------------------------------------------------ 2 files changed, 11 insertions(+), 139 deletions(-) diff --git a/crypt.c b/crypt.c index c15768a3..34b78798 100644 --- a/crypt.c +++ b/crypt.c @@ -61,7 +61,7 @@ void init_random_seed_or_die(void) 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; @@ -69,23 +69,18 @@ static EVP_PKEY *load_key(const char *file, int private) 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) @@ -170,12 +165,8 @@ int get_public_key(const char *key_file, struct asymmetric_key **result) 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; @@ -225,7 +216,7 @@ int priv_decrypt(const char *key_file, unsigned char *outbuf, 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; diff --git a/gcrypt.c b/gcrypt.c index 8bbc82f3..1ae7cfb0 100644 --- a/gcrypt.c +++ b/gcrypt.c @@ -301,64 +301,6 @@ static inline int get_long_form_num_length_bytes(unsigned char c) 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 @@ -539,65 +481,6 @@ free_blob: 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; @@ -673,10 +556,8 @@ int get_public_key(const char *key_file, struct asymmetric_key **result) 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; -- 2.30.2