]>
git.ipfire.org Git - thirdparty/hostap.git/blob - src/tls/pkcs1.c
2 * PKCS #1 (RSA Encryption)
3 * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "crypto/crypto.h"
18 static int pkcs1_generate_encryption_block(u8 block_type
, size_t modlen
,
19 const u8
*in
, size_t inlen
,
20 u8
*out
, size_t *outlen
)
28 * EB = 00 || BT || PS || 00 || D
29 * BT = 00 or 01 for private-key operation; 02 for public-key operation
30 * PS = k-3-||D||; at least eight octets
31 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
32 * k = length of modulus in octets (modlen)
35 if (modlen
< 12 || modlen
> *outlen
|| inlen
> modlen
- 11) {
36 wpa_printf(MSG_DEBUG
, "PKCS #1: %s - Invalid buffer "
37 "lengths (modlen=%lu outlen=%lu inlen=%lu)",
38 __func__
, (unsigned long) modlen
,
39 (unsigned long) *outlen
,
40 (unsigned long) inlen
);
46 *pos
++ = block_type
; /* BT */
47 ps_len
= modlen
- inlen
- 3;
50 os_memset(pos
, 0x00, ps_len
);
54 os_memset(pos
, 0xff, ps_len
);
58 if (os_get_random(pos
, ps_len
) < 0) {
59 wpa_printf(MSG_DEBUG
, "PKCS #1: %s - Failed to get "
60 "random data for PS", __func__
);
70 wpa_printf(MSG_DEBUG
, "PKCS #1: %s - Unsupported block type "
71 "%d", __func__
, block_type
);
75 os_memcpy(pos
, in
, inlen
); /* D */
81 int pkcs1_encrypt(int block_type
, struct crypto_rsa_key
*key
,
82 int use_private
, const u8
*in
, size_t inlen
,
83 u8
*out
, size_t *outlen
)
87 modlen
= crypto_rsa_get_modulus_len(key
);
89 if (pkcs1_generate_encryption_block(block_type
, modlen
, in
, inlen
,
93 return crypto_rsa_exptmod(out
, modlen
, out
, outlen
, key
, use_private
);
97 int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key
*key
,
98 const u8
*in
, size_t inlen
,
99 u8
*out
, size_t *outlen
)
104 res
= crypto_rsa_exptmod(in
, inlen
, out
, outlen
, key
, 1);
108 if (*outlen
< 2 || out
[0] != 0 || out
[1] != 2)
111 /* Skip PS (pseudorandom non-zero octets) */
114 while (*pos
&& pos
< end
)
118 if (pos
- out
- 2 < 8) {
119 /* PKCS #1 v1.5, 8.1: At least eight octets long PS */
120 wpa_printf(MSG_INFO
, "LibTomCrypt: Too short padding");
125 *outlen
-= pos
- out
;
127 /* Strip PKCS #1 header */
128 os_memmove(out
, pos
, *outlen
);
134 int pkcs1_decrypt_public_key(struct crypto_rsa_key
*key
,
135 const u8
*crypt
, size_t crypt_len
,
136 u8
*plain
, size_t *plain_len
)
142 if (crypto_rsa_exptmod(crypt
, crypt_len
, plain
, &len
, key
, 0) < 0)
148 * EB = 00 || BT || PS || 00 || D
150 * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01)
151 * k = length of modulus in octets
153 * Based on 10.1.3, "The block type shall be 01" for a signature.
156 if (len
< 3 + 8 + 16 /* min hash len */ ||
157 plain
[0] != 0x00 || plain
[1] != 0x01) {
158 wpa_printf(MSG_INFO
, "LibTomCrypt: Invalid signature EB "
165 if (plain
[2] != 0xff) {
166 wpa_printf(MSG_INFO
, "LibTomCrypt: Invalid signature "
170 while (pos
< plain
+ len
&& *pos
== 0xff)
173 if (pos
- plain
- 2 < 8) {
174 /* PKCS #1 v1.5, 8.1: At least eight octets long PS */
175 wpa_printf(MSG_INFO
, "LibTomCrypt: Too short signature "
180 if (pos
+ 16 /* min hash len */ >= plain
+ len
|| *pos
!= 0x00) {
181 wpa_printf(MSG_INFO
, "LibTomCrypt: Invalid signature EB "
188 /* Strip PKCS #1 header */
189 os_memmove(plain
, pos
, len
);
196 int pkcs1_v15_sig_ver(struct crypto_public_key
*pk
,
197 const u8
*s
, size_t s_len
,
198 const struct asn1_oid
*hash_alg
,
199 const u8
*hash
, size_t hash_len
)
203 size_t decrypted_len
;
204 const u8
*pos
, *end
, *next
, *da_end
;
208 decrypted
= os_malloc(s_len
);
209 if (decrypted
== NULL
)
211 decrypted_len
= s_len
;
212 res
= crypto_public_key_decrypt_pkcs1(pk
, s
, s_len
, decrypted
,
215 wpa_printf(MSG_INFO
, "PKCS #1: RSA decrypt failed");
219 wpa_hexdump(MSG_DEBUG
, "Decrypted(S)", decrypted
, decrypted_len
);
222 * PKCS #1 v1.5, 10.1.2:
224 * DigestInfo ::= SEQUENCE {
225 * digestAlgorithm DigestAlgorithmIdentifier,
229 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
231 * Digest ::= OCTET STRING
234 if (asn1_get_next(decrypted
, decrypted_len
, &hdr
) < 0 ||
235 hdr
.class != ASN1_CLASS_UNIVERSAL
||
236 hdr
.tag
!= ASN1_TAG_SEQUENCE
) {
237 wpa_printf(MSG_DEBUG
,
238 "PKCS #1: Expected SEQUENCE (DigestInfo) - found class %d tag 0x%x",
245 end
= pos
+ hdr
.length
;
249 * AlgorithmIdentifier ::= SEQUENCE {
250 * algorithm OBJECT IDENTIFIER,
251 * parameters ANY DEFINED BY algorithm OPTIONAL
255 if (asn1_get_next(pos
, end
- pos
, &hdr
) < 0 ||
256 hdr
.class != ASN1_CLASS_UNIVERSAL
||
257 hdr
.tag
!= ASN1_TAG_SEQUENCE
) {
258 wpa_printf(MSG_DEBUG
,
259 "PKCS #1: Expected SEQUENCE (AlgorithmIdentifier) - found class %d tag 0x%x",
264 da_end
= hdr
.payload
+ hdr
.length
;
266 if (asn1_get_oid(hdr
.payload
, hdr
.length
, &oid
, &next
)) {
267 wpa_printf(MSG_DEBUG
,
268 "PKCS #1: Failed to parse digestAlgorithm");
273 if (!asn1_oid_equal(&oid
, hash_alg
)) {
274 char txt
[100], txt2
[100];
275 asn1_oid_to_str(&oid
, txt
, sizeof(txt
));
276 asn1_oid_to_str(hash_alg
, txt2
, sizeof(txt2
));
277 wpa_printf(MSG_DEBUG
,
278 "PKCS #1: Hash alg OID mismatch: was %s, expected %s",
284 /* Digest ::= OCTET STRING */
286 end
= decrypted
+ decrypted_len
;
288 if (asn1_get_next(pos
, end
- pos
, &hdr
) < 0 ||
289 hdr
.class != ASN1_CLASS_UNIVERSAL
||
290 hdr
.tag
!= ASN1_TAG_OCTETSTRING
) {
291 wpa_printf(MSG_DEBUG
,
292 "PKCS #1: Expected OCTETSTRING (Digest) - found class %d tag 0x%x",
297 wpa_hexdump(MSG_MSGDUMP
, "PKCS #1: Decrypted Digest",
298 hdr
.payload
, hdr
.length
);
300 if (hdr
.length
!= hash_len
||
301 os_memcmp_const(hdr
.payload
, hash
, hdr
.length
) != 0) {
302 wpa_printf(MSG_INFO
, "PKCS #1: Digest value does not match calculated hash");
309 if (hdr
.payload
+ hdr
.length
!= end
) {
311 "PKCS #1: Extra data after signature - reject");
313 wpa_hexdump(MSG_DEBUG
, "PKCS #1: Extra data",
314 hdr
.payload
+ hdr
.length
,
315 end
- hdr
.payload
- hdr
.length
);