18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PKCS #1 (RSA Encryption)
350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
1250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#include "crypto/crypto.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsa.h"
1450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt#include "asn1.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pkcs1.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   const u8 *in, size_t inlen,
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   u8 *out, size_t *outlen)
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t ps_len;
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * PKCS #1 v1.5, 8.1:
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EB = 00 || BT || PS || 00 || D
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * BT = 00 or 01 for private-key operation; 02 for public-key operation
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * PS = k-3-||D||; at least eight octets
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * k = length of modulus in octets (modlen)
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "lengths (modlen=%lu outlen=%lu inlen=%lu)",
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   __func__, (unsigned long) modlen,
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) *outlen,
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   (unsigned long) inlen);
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = out;
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = 0x00;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = block_type; /* BT */
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ps_len = modlen - inlen - 3;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (block_type) {
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 0:
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(pos, 0x00, ps_len);
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ps_len;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 1:
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(pos, 0xff, ps_len);
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += ps_len;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case 2:
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (os_get_random(pos, ps_len) < 0) {
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "random data for PS", __func__);
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (ps_len--) {
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (*pos == 0x00)
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				*pos = 0x01;
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos++;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%d", __func__, block_type);
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*pos++ = 0x00;
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(pos, in, inlen); /* D */
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint pkcs1_encrypt(int block_type, struct crypto_rsa_key *key,
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  int use_private, const u8 *in, size_t inlen,
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  u8 *out, size_t *outlen)
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t modlen;
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	modlen = crypto_rsa_get_modulus_len(key);
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    out, outlen) < 0)
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private);
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key,
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  const u8 *in, size_t inlen,
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  u8 *out, size_t *outlen)
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int res;
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos, *end;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = crypto_rsa_exptmod(in, inlen, out, outlen, key, 1);
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res)
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return res;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (*outlen < 2 || out[0] != 0 || out[1] != 2)
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Skip PS (pseudorandom non-zero octets) */
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = out + 2;
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	end = out + *outlen;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (*pos && pos < end)
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos++;
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos == end)
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
11850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (pos - out - 2 < 8) {
11950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
12050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_INFO, "LibTomCrypt: Too short padding");
12150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
12250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos++;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*outlen -= pos - out;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Strip PKCS #1 header */
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memmove(out, pos, *outlen);
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint pkcs1_decrypt_public_key(struct crypto_rsa_key *key,
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     const u8 *crypt, size_t crypt_len,
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     u8 *plain, size_t *plain_len)
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = *plain_len;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, key, 0) < 0)
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * PKCS #1 v1.5, 8.1:
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 *
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * EB = 00 || BT || PS || 00 || D
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * BT = 00 or 01
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01)
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * k = length of modulus in octets
15250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 *
15350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * Based on 10.1.3, "The block type shall be 01" for a signature.
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 3 + 8 + 16 /* min hash len */ ||
15750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	    plain[0] != 0x00 || plain[1] != 0x01) {
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "structure");
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos = plain + 3;
16450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	/* BT = 01 */
16550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (plain[2] != 0xff) {
16650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
16750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   "PS (BT=01)");
16850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	while (pos < plain + len && *pos == 0xff)
17150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		pos++;
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos - plain - 2 < 8) {
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "padding");
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "structure (2)");
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pos++;
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len -= pos - plain;
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Strip PKCS #1 header */
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memmove(plain, pos, len);
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	*plain_len = len;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
19450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
19550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
19650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidtint pkcs1_v15_sig_ver(struct crypto_public_key *pk,
19750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		      const u8 *s, size_t s_len,
19850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		      const struct asn1_oid *hash_alg,
19950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		      const u8 *hash, size_t hash_len)
20050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt{
20150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	int res;
20250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	u8 *decrypted;
20350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	size_t decrypted_len;
20450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	const u8 *pos, *end, *next, *da_end;
20550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	struct asn1_hdr hdr;
20650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	struct asn1_oid oid;
20750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
20850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	decrypted = os_malloc(s_len);
20950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (decrypted == NULL)
21050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
21150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	decrypted_len = s_len;
21250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	res = crypto_public_key_decrypt_pkcs1(pk, s, s_len, decrypted,
21350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt					      &decrypted_len);
21450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (res < 0) {
21550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_INFO, "PKCS #1: RSA decrypt failed");
21650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		os_free(decrypted);
21750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
21850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
21950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "Decrypted(S)", decrypted, decrypted_len);
22050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
22150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	/*
22250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * PKCS #1 v1.5, 10.1.2:
22350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 *
22450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * DigestInfo ::= SEQUENCE {
22550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 *     digestAlgorithm DigestAlgorithmIdentifier,
22650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 *     digest Digest
22750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * }
22850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 *
22950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
23050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 *
23150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * Digest ::= OCTET STRING
23250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 *
23350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 */
23450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (asn1_get_next(decrypted, decrypted_len, &hdr) < 0 ||
23550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
23650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	    hdr.tag != ASN1_TAG_SEQUENCE) {
23750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_DEBUG,
23850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   "PKCS #1: Expected SEQUENCE (DigestInfo) - found class %d tag 0x%x",
23950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   hdr.class, hdr.tag);
24050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		os_free(decrypted);
24150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
24250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
24350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
24450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	pos = hdr.payload;
24550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	end = pos + hdr.length;
24650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
24750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	/*
24850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * X.509:
24950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * AlgorithmIdentifier ::= SEQUENCE {
25050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 *     algorithm            OBJECT IDENTIFIER,
25150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 *     parameters           ANY DEFINED BY algorithm OPTIONAL
25250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 * }
25350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	 */
25450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
25550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
25650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
25750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	    hdr.tag != ASN1_TAG_SEQUENCE) {
25850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_DEBUG,
25950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   "PKCS #1: Expected SEQUENCE (AlgorithmIdentifier) - found class %d tag 0x%x",
26050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   hdr.class, hdr.tag);
26150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		os_free(decrypted);
26250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
26350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
26450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	da_end = hdr.payload + hdr.length;
26550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
26650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) {
26750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_DEBUG,
26850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   "PKCS #1: Failed to parse digestAlgorithm");
26950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		os_free(decrypted);
27050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
27150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
27250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
27350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (!asn1_oid_equal(&oid, hash_alg)) {
27450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		char txt[100], txt2[100];
27550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		asn1_oid_to_str(&oid, txt, sizeof(txt));
27650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		asn1_oid_to_str(hash_alg, txt2, sizeof(txt2));
27750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_DEBUG,
27850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   "PKCS #1: Hash alg OID mismatch: was %s, expected %s",
27950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   txt, txt2);
28050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		os_free(decrypted);
28150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
28250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
28350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
28450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	/* Digest ::= OCTET STRING */
28550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	pos = da_end;
28650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	end = decrypted + decrypted_len;
28750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
28850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
28950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
29050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	    hdr.tag != ASN1_TAG_OCTETSTRING) {
29150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_DEBUG,
29250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   "PKCS #1: Expected OCTETSTRING (Digest) - found class %d tag 0x%x",
29350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   hdr.class, hdr.tag);
29450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		os_free(decrypted);
29550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
29650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
29750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "PKCS #1: Decrypted Digest",
29850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		    hdr.payload, hdr.length);
29950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
30050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (hdr.length != hash_len ||
301c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt	    os_memcmp_const(hdr.payload, hash, hdr.length) != 0) {
30250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_INFO, "PKCS #1: Digest value does not match calculated hash");
30350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		os_free(decrypted);
30450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
30550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
30650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
30750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	os_free(decrypted);
30850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
30950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	if (hdr.payload + hdr.length != end) {
31050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_printf(MSG_INFO,
31150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			   "PKCS #1: Extra data after signature - reject");
31250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
31350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "PKCS #1: Extra data",
31450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			    hdr.payload + hdr.length,
31550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt			    end - hdr.payload - hdr.length);
31650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt		return -1;
31750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	}
31850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt
31950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt	return 0;
32050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt}
321