Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1/* RSA asymmetric public-key algorithm [RFC3447]
  2 *
  3 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
  4 * Written by David Howells (dhowells@redhat.com)
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU General Public Licence
  8 * as published by the Free Software Foundation; either version
  9 * 2 of the Licence, or (at your option) any later version.
 10 */
 11
 12#define pr_fmt(fmt) "RSA: "fmt
 13#include <linux/module.h>
 14#include <linux/kernel.h>
 15#include <linux/slab.h>
 16#include <crypto/algapi.h>
 17#include "public_key.h"
 18
 19MODULE_LICENSE("GPL");
 20MODULE_DESCRIPTION("RSA Public Key Algorithm");
 21
 22#define kenter(FMT, ...) \
 23	pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
 24#define kleave(FMT, ...) \
 25	pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
 26
 27/*
 28 * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
 29 */
 30static const u8 RSA_digest_info_MD5[] = {
 31	0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
 32	0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */
 33	0x05, 0x00, 0x04, 0x10
 34};
 35
 36static const u8 RSA_digest_info_SHA1[] = {
 37	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
 38	0x2B, 0x0E, 0x03, 0x02, 0x1A,
 39	0x05, 0x00, 0x04, 0x14
 40};
 41
 42static const u8 RSA_digest_info_RIPE_MD_160[] = {
 43	0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
 44	0x2B, 0x24, 0x03, 0x02, 0x01,
 45	0x05, 0x00, 0x04, 0x14
 46};
 47
 48static const u8 RSA_digest_info_SHA224[] = {
 49	0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
 50	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
 51	0x05, 0x00, 0x04, 0x1C
 52};
 53
 54static const u8 RSA_digest_info_SHA256[] = {
 55	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
 56	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
 57	0x05, 0x00, 0x04, 0x20
 58};
 59
 60static const u8 RSA_digest_info_SHA384[] = {
 61	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
 62	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
 63	0x05, 0x00, 0x04, 0x30
 64};
 65
 66static const u8 RSA_digest_info_SHA512[] = {
 67	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
 68	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
 69	0x05, 0x00, 0x04, 0x40
 70};
 71
 72static const struct {
 73	const u8 *data;
 74	size_t size;
 75} RSA_ASN1_templates[PKEY_HASH__LAST] = {
 76#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
 77	[HASH_ALGO_MD5]		= _(MD5),
 78	[HASH_ALGO_SHA1]	= _(SHA1),
 79	[HASH_ALGO_RIPE_MD_160]	= _(RIPE_MD_160),
 80	[HASH_ALGO_SHA256]	= _(SHA256),
 81	[HASH_ALGO_SHA384]	= _(SHA384),
 82	[HASH_ALGO_SHA512]	= _(SHA512),
 83	[HASH_ALGO_SHA224]	= _(SHA224),
 84#undef _
 85};
 86
 87/*
 88 * RSAVP1() function [RFC3447 sec 5.2.2]
 89 */
 90static int RSAVP1(const struct public_key *key, MPI s, MPI *_m)
 91{
 92	MPI m;
 93	int ret;
 94
 95	/* (1) Validate 0 <= s < n */
 96	if (mpi_cmp_ui(s, 0) < 0) {
 97		kleave(" = -EBADMSG [s < 0]");
 98		return -EBADMSG;
 99	}
100	if (mpi_cmp(s, key->rsa.n) >= 0) {
101		kleave(" = -EBADMSG [s >= n]");
102		return -EBADMSG;
103	}
104
105	m = mpi_alloc(0);
106	if (!m)
107		return -ENOMEM;
108
109	/* (2) m = s^e mod n */
110	ret = mpi_powm(m, s, key->rsa.e, key->rsa.n);
111	if (ret < 0) {
112		mpi_free(m);
113		return ret;
114	}
115
116	*_m = m;
117	return 0;
118}
119
120/*
121 * Integer to Octet String conversion [RFC3447 sec 4.1]
122 */
123static int RSA_I2OSP(MPI x, size_t xLen, u8 **_X)
124{
125	unsigned X_size, x_size;
126	int X_sign;
127	u8 *X;
128
129	/* Make sure the string is the right length.  The number should begin
130	 * with { 0x00, 0x01, ... } so we have to account for 15 leading zero
131	 * bits not being reported by MPI.
132	 */
133	x_size = mpi_get_nbits(x);
134	pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8);
135	if (x_size != xLen * 8 - 15)
136		return -ERANGE;
137
138	X = mpi_get_buffer(x, &X_size, &X_sign);
139	if (!X)
140		return -ENOMEM;
141	if (X_sign < 0) {
142		kfree(X);
143		return -EBADMSG;
144	}
145	if (X_size != xLen - 1) {
146		kfree(X);
147		return -EBADMSG;
148	}
149
150	*_X = X;
151	return 0;
152}
153
154/*
155 * Perform the RSA signature verification.
156 * @H: Value of hash of data and metadata
157 * @EM: The computed signature value
158 * @k: The size of EM (EM[0] is an invalid location but should hold 0x00)
159 * @hash_size: The size of H
160 * @asn1_template: The DigestInfo ASN.1 template
161 * @asn1_size: Size of asm1_template[]
162 */
163static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
164		      const u8 *asn1_template, size_t asn1_size)
165{
166	unsigned PS_end, T_offset, i;
167
168	kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size);
169
170	if (k < 2 + 1 + asn1_size + hash_size)
171		return -EBADMSG;
172
173	/* Decode the EMSA-PKCS1-v1_5 */
174	if (EM[1] != 0x01) {
175		kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]);
176		return -EBADMSG;
177	}
178
179	T_offset = k - (asn1_size + hash_size);
180	PS_end = T_offset - 1;
181	if (EM[PS_end] != 0x00) {
182		kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]);
183		return -EBADMSG;
184	}
185
186	for (i = 2; i < PS_end; i++) {
187		if (EM[i] != 0xff) {
188			kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]);
189			return -EBADMSG;
190		}
191	}
192
193	if (crypto_memneq(asn1_template, EM + T_offset, asn1_size) != 0) {
194		kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]");
195		return -EBADMSG;
196	}
197
198	if (crypto_memneq(H, EM + T_offset + asn1_size, hash_size) != 0) {
199		kleave(" = -EKEYREJECTED [EM[T] hash mismatch]");
200		return -EKEYREJECTED;
201	}
202
203	kleave(" = 0");
204	return 0;
205}
206
207/*
208 * Perform the verification step [RFC3447 sec 8.2.2].
209 */
210static int RSA_verify_signature(const struct public_key *key,
211				const struct public_key_signature *sig)
212{
213	size_t tsize;
214	int ret;
215
216	/* Variables as per RFC3447 sec 8.2.2 */
217	const u8 *H = sig->digest;
218	u8 *EM = NULL;
219	MPI m = NULL;
220	size_t k;
221
222	kenter("");
223
224	if (!RSA_ASN1_templates[sig->pkey_hash_algo].data)
225		return -ENOTSUPP;
226
227	/* (1) Check the signature size against the public key modulus size */
228	k = mpi_get_nbits(key->rsa.n);
229	tsize = mpi_get_nbits(sig->rsa.s);
230
231	/* According to RFC 4880 sec 3.2, length of MPI is computed starting
232	 * from most significant bit.  So the RFC 3447 sec 8.2.2 size check
233	 * must be relaxed to conform with shorter signatures - so we fail here
234	 * only if signature length is longer than modulus size.
235	 */
236	pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize);
237	if (k < tsize) {
238		ret = -EBADMSG;
239		goto error;
240	}
241
242	/* Round up and convert to octets */
243	k = (k + 7) / 8;
244
245	/* (2b) Apply the RSAVP1 verification primitive to the public key */
246	ret = RSAVP1(key, sig->rsa.s, &m);
247	if (ret < 0)
248		goto error;
249
250	/* (2c) Convert the message representative (m) to an encoded message
251	 *      (EM) of length k octets.
252	 *
253	 *      NOTE!  The leading zero byte is suppressed by MPI, so we pass a
254	 *      pointer to the _preceding_ byte to RSA_verify()!
255	 */
256	ret = RSA_I2OSP(m, k, &EM);
257	if (ret < 0)
258		goto error;
259
260	ret = RSA_verify(H, EM - 1, k, sig->digest_size,
261			 RSA_ASN1_templates[sig->pkey_hash_algo].data,
262			 RSA_ASN1_templates[sig->pkey_hash_algo].size);
263
264error:
265	kfree(EM);
266	mpi_free(m);
267	kleave(" = %d", ret);
268	return ret;
269}
270
271const struct public_key_algorithm RSA_public_key_algorithm = {
272	.name		= "RSA",
273	.n_pub_mpi	= 2,
274	.n_sec_mpi	= 3,
275	.n_sig_mpi	= 1,
276	.verify_signature = RSA_verify_signature,
277};
278EXPORT_SYMBOL_GPL(RSA_public_key_algorithm);