Latest KEYS code return error if hexadecimal string length id odd. Fix it. Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com> Signed-off-by: David Howells <dhowells@redhat.com>
		
			
				
	
	
		
			105 lines
		
	
	
	
		
			2.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
	
		
			2.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (C) 2013 Intel Corporation
 | 
						|
 *
 | 
						|
 * Author:
 | 
						|
 * Dmitry Kasatkin <dmitry.kasatkin@intel.com>
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or modify
 | 
						|
 * it under the terms of the GNU General Public License as published by
 | 
						|
 * the Free Software Foundation, version 2 of the License.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 | 
						|
 | 
						|
#include <linux/err.h>
 | 
						|
#include <linux/ratelimit.h>
 | 
						|
#include <linux/key-type.h>
 | 
						|
#include <crypto/public_key.h>
 | 
						|
#include <keys/asymmetric-type.h>
 | 
						|
 | 
						|
#include "integrity.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * Request an asymmetric key.
 | 
						|
 */
 | 
						|
static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
 | 
						|
{
 | 
						|
	struct key *key;
 | 
						|
	char name[12];
 | 
						|
 | 
						|
	sprintf(name, "id:%08x", keyid);
 | 
						|
 | 
						|
	pr_debug("key search: \"%s\"\n", name);
 | 
						|
 | 
						|
	if (keyring) {
 | 
						|
		/* search in specific keyring */
 | 
						|
		key_ref_t kref;
 | 
						|
		kref = keyring_search(make_key_ref(keyring, 1),
 | 
						|
				      &key_type_asymmetric, name);
 | 
						|
		if (IS_ERR(kref))
 | 
						|
			key = ERR_CAST(kref);
 | 
						|
		else
 | 
						|
			key = key_ref_to_ptr(kref);
 | 
						|
	} else {
 | 
						|
		key = request_key(&key_type_asymmetric, name, NULL);
 | 
						|
	}
 | 
						|
 | 
						|
	if (IS_ERR(key)) {
 | 
						|
		pr_err_ratelimited("Request for unknown key '%s' err %ld\n",
 | 
						|
				   name, PTR_ERR(key));
 | 
						|
		switch (PTR_ERR(key)) {
 | 
						|
			/* Hide some search errors */
 | 
						|
		case -EACCES:
 | 
						|
		case -ENOTDIR:
 | 
						|
		case -EAGAIN:
 | 
						|
			return ERR_PTR(-ENOKEY);
 | 
						|
		default:
 | 
						|
			return key;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	pr_debug("%s() = 0 [%x]\n", __func__, key_serial(key));
 | 
						|
 | 
						|
	return key;
 | 
						|
}
 | 
						|
 | 
						|
int asymmetric_verify(struct key *keyring, const char *sig,
 | 
						|
		      int siglen, const char *data, int datalen)
 | 
						|
{
 | 
						|
	struct public_key_signature pks;
 | 
						|
	struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
 | 
						|
	struct key *key;
 | 
						|
	int ret = -ENOMEM;
 | 
						|
 | 
						|
	if (siglen <= sizeof(*hdr))
 | 
						|
		return -EBADMSG;
 | 
						|
 | 
						|
	siglen -= sizeof(*hdr);
 | 
						|
 | 
						|
	if (siglen != __be16_to_cpu(hdr->sig_size))
 | 
						|
		return -EBADMSG;
 | 
						|
 | 
						|
	if (hdr->hash_algo >= PKEY_HASH__LAST)
 | 
						|
		return -ENOPKG;
 | 
						|
 | 
						|
	key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid));
 | 
						|
	if (IS_ERR(key))
 | 
						|
		return PTR_ERR(key);
 | 
						|
 | 
						|
	memset(&pks, 0, sizeof(pks));
 | 
						|
 | 
						|
	pks.pkey_hash_algo = hdr->hash_algo;
 | 
						|
	pks.digest = (u8 *)data;
 | 
						|
	pks.digest_size = datalen;
 | 
						|
	pks.nr_mpi = 1;
 | 
						|
	pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen);
 | 
						|
 | 
						|
	if (pks.rsa.s)
 | 
						|
		ret = verify_signature(key, &pks);
 | 
						|
 | 
						|
	mpi_free(pks.rsa.s);
 | 
						|
	key_put(key);
 | 
						|
	pr_debug("%s() = %d\n", __func__, ret);
 | 
						|
	return ret;
 | 
						|
}
 |