2 * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 #include "wolfssl_common.h"
27 #include "wolfssl_rsa_public_key.h"
28 #include "wolfssl_util.h"
30 #include <utils/debug.h>
31 #include <asn1/asn1.h>
32 #include <crypto/hashers/hasher.h>
33 #include <credentials/keys/signature_params.h>
35 #include <wolfssl/wolfcrypt/rsa.h>
36 #include <wolfssl/wolfcrypt/asn.h>
38 typedef struct private_wolfssl_rsa_public_key_t private_wolfssl_rsa_public_key_t
;
43 struct private_wolfssl_rsa_public_key_t
{
48 wolfssl_rsa_public_key_t
public;
51 * RSA key object from wolfSSL.
56 * Random number generator to use with RSA operations.
67 * Verify RSA signature
69 static bool verify_signature(private_wolfssl_rsa_public_key_t
*this,
70 chunk_t data
, chunk_t signature
)
73 int len
= wc_RsaEncryptSize(&this->rsa
);
77 if (signature
.len
> len
)
79 signature
= chunk_skip(signature
, signature
.len
- len
);
82 padded
= chunk_copy_pad(chunk_alloca(len
), signature
, 0x00);
84 len
= wc_RsaSSL_VerifyInline(padded
.ptr
, len
, &p
, &this->rsa
);
87 success
= chunk_equals_const(data
, chunk_create(p
, len
));
93 * Verification of an EMSA PKCS1 signature described in PKCS#1
95 static bool verify_emsa_pkcs1_signature(private_wolfssl_rsa_public_key_t
*this,
96 enum wc_HashType hash
, chunk_t data
,
99 chunk_t dgst
, digestInfo
;
100 bool success
= FALSE
;
103 if (wolfssl_hash_chunk(hash
, data
, &dgst
))
105 digestInfo
= chunk_alloc(MAX_DER_DIGEST_SZ
);
106 len
= wc_EncodeSignature(digestInfo
.ptr
, dgst
.ptr
, dgst
.len
,
107 wc_HashGetOID(hash
));
110 digestInfo
.len
= len
;
111 success
= verify_signature(this, digestInfo
, signature
);
113 chunk_free(&digestInfo
);
121 * Verification of an EMSA PSS signature described in PKCS#1
123 static bool verify_emsa_pss_signature(private_wolfssl_rsa_public_key_t
*this,
124 rsa_pss_params_t
*params
, chunk_t data
,
127 chunk_t dgst
, padded
;
128 enum wc_HashType hash
;
131 bool success
= FALSE
;
133 if (!wolfssl_hash2type(params
->hash
, &hash
))
137 if (!wolfssl_hash2mgf1(params
->mgf1_hash
, &mgf
))
141 if (!wolfssl_hash_chunk(hash
, data
, &dgst
))
145 len
= wc_RsaEncryptSize(&this->rsa
);
146 if (signature
.len
> len
)
148 signature
= chunk_skip(signature
, signature
.len
- len
);
150 padded
= chunk_copy_pad(chunk_alloca(len
), signature
, 0x00);
152 len
= wc_RsaPSS_VerifyInline_ex(padded
.ptr
, len
, &p
, hash
, mgf
,
153 params
->salt_len
, &this->rsa
);
156 success
= wc_RsaPSS_CheckPadding_ex(dgst
.ptr
, dgst
.len
, p
, len
, hash
,
157 params
->salt_len
, mp_count_bits(&this->rsa
.n
)) == 0;
164 METHOD(public_key_t
, get_type
, key_type_t
,
165 private_wolfssl_rsa_public_key_t
*this)
170 METHOD(public_key_t
, verify
, bool,
171 private_wolfssl_rsa_public_key_t
*this, signature_scheme_t scheme
,
172 void *params
, chunk_t data
, chunk_t signature
)
176 case SIGN_RSA_EMSA_PKCS1_NULL
:
177 return verify_signature(this, data
, signature
);
178 case SIGN_RSA_EMSA_PKCS1_SHA2_224
:
179 return verify_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA224
, data
,
181 case SIGN_RSA_EMSA_PKCS1_SHA2_256
:
182 return verify_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA256
, data
,
184 case SIGN_RSA_EMSA_PKCS1_SHA2_384
:
185 return verify_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA384
, data
,
187 case SIGN_RSA_EMSA_PKCS1_SHA2_512
:
188 return verify_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA512
, data
,
190 case SIGN_RSA_EMSA_PKCS1_SHA3_224
:
191 return verify_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA3_224
, data
,
193 case SIGN_RSA_EMSA_PKCS1_SHA3_256
:
194 return verify_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA3_256
, data
,
196 case SIGN_RSA_EMSA_PKCS1_SHA3_384
:
197 return verify_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA3_384
, data
,
199 case SIGN_RSA_EMSA_PKCS1_SHA3_512
:
200 return verify_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA3_512
, data
,
202 case SIGN_RSA_EMSA_PKCS1_SHA1
:
203 return verify_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA
, data
,
205 case SIGN_RSA_EMSA_PKCS1_MD5
:
206 return verify_emsa_pkcs1_signature(this, WC_HASH_TYPE_MD5
, data
,
209 case SIGN_RSA_EMSA_PSS
:
210 return verify_emsa_pss_signature(this, params
, data
, signature
);
213 DBG1(DBG_LIB
, "signature scheme %N not supported via wolfssl",
214 signature_scheme_names
, scheme
);
219 METHOD(public_key_t
, encrypt
, bool,
220 private_wolfssl_rsa_public_key_t
*this, encryption_scheme_t scheme
,
221 chunk_t plain
, chunk_t
*crypto
)
223 int padding
, mgf
, len
;
224 enum wc_HashType hash
;
228 case ENCRYPT_RSA_PKCS1
:
229 padding
= WC_RSA_PKCSV15_PAD
;
230 hash
= WC_HASH_TYPE_NONE
;
233 #ifndef WC_NO_RSA_OAEP
235 case ENCRYPT_RSA_OAEP_SHA1
:
236 padding
= WC_RSA_OAEP_PAD
;
237 hash
= WC_HASH_TYPE_SHA
;
241 #ifdef WOLFSSL_SHA224
242 case ENCRYPT_RSA_OAEP_SHA224
:
243 padding
= WC_RSA_OAEP_PAD
;
244 hash
= WC_HASH_TYPE_SHA224
;
249 case ENCRYPT_RSA_OAEP_SHA256
:
250 padding
= WC_RSA_OAEP_PAD
;
251 hash
= WC_HASH_TYPE_SHA256
;
255 #ifdef WOLFSSL_SHA384
256 case ENCRYPT_RSA_OAEP_SHA384
:
257 padding
= WC_RSA_OAEP_PAD
;
258 hash
= WC_HASH_TYPE_SHA384
;
262 #ifdef WOLFSSL_SHA512
263 case ENCRYPT_RSA_OAEP_SHA512
:
264 padding
= WC_RSA_OAEP_PAD
;
265 hash
= WC_HASH_TYPE_SHA512
;
271 DBG1(DBG_LIB
, "decryption scheme %N not supported via wolfssl",
272 encryption_scheme_names
, scheme
);
275 len
= wc_RsaEncryptSize(&this->rsa
);
276 *crypto
= chunk_alloc(len
);
277 len
= wc_RsaPublicEncrypt_ex(plain
.ptr
, plain
.len
, crypto
->ptr
, len
,
278 &this->rsa
, &this->rng
, padding
, hash
, mgf
,
282 DBG1(DBG_LIB
, "RSA encryption failed");
290 METHOD(public_key_t
, get_keysize
, int,
291 private_wolfssl_rsa_public_key_t
*this)
293 return wc_RsaEncryptSize(&this->rsa
) * 8;
297 * Encode the given public key as ASN.1 DER with algorithm identifier
299 bool wolfssl_rsa_encode_public(RsaKey
*rsa
, chunk_t
*encoding
)
303 len
= wc_RsaEncryptSize(rsa
) * 2 + 4 * MAX_SEQ_SZ
+ MAX_ALGO_SZ
;
304 *encoding
= chunk_alloc(len
);
305 len
= wc_RsaKeyToPublicDer(rsa
, encoding
->ptr
, len
);
308 chunk_free(encoding
);
316 * Calculate fingerprint from a RSA key, also used in rsa private key.
318 bool wolfssl_rsa_fingerprint(RsaKey
*rsa
, cred_encoding_type_t type
,
323 bool success
= FALSE
;
325 if (lib
->encoding
->get_cache(lib
->encoding
, type
, rsa
, fp
))
331 case KEYID_PUBKEY_SHA1
:
333 chunk_t n
= chunk_empty
, e
= chunk_empty
;
335 if (wolfssl_mp2chunk(&rsa
->n
, &n
) &&
336 wolfssl_mp2chunk(&rsa
->e
, &e
))
338 key
= asn1_wrap(ASN1_SEQUENCE
, "mm",
339 asn1_integer("m", n
),
340 asn1_integer("m", e
));
350 case KEYID_PUBKEY_INFO_SHA1
:
351 if (!wolfssl_rsa_encode_public(rsa
, &key
))
360 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
361 if (!hasher
|| !hasher
->allocate_hash(hasher
, key
, fp
))
363 DBG1(DBG_LIB
, "SHA1 not supported, fingerprinting failed");
367 lib
->encoding
->cache(lib
->encoding
, type
, rsa
, *fp
);
375 METHOD(public_key_t
, get_fingerprint
, bool,
376 private_wolfssl_rsa_public_key_t
*this, cred_encoding_type_t type
,
377 chunk_t
*fingerprint
)
379 return wolfssl_rsa_fingerprint(&this->rsa
, type
, fingerprint
);
382 METHOD(public_key_t
, get_encoding
, bool,
383 private_wolfssl_rsa_public_key_t
*this, cred_encoding_type_t type
,
386 chunk_t n
= chunk_empty
, e
= chunk_empty
;
387 bool success
= FALSE
;
389 if (type
== PUBKEY_SPKI_ASN1_DER
)
391 return wolfssl_rsa_encode_public(&this->rsa
, encoding
);
394 if (wolfssl_mp2chunk(&this->rsa
.n
, &n
) &&
395 wolfssl_mp2chunk(&this->rsa
.e
, &e
))
397 success
= lib
->encoding
->encode(lib
->encoding
, type
, NULL
, encoding
,
398 CRED_PART_RSA_MODULUS
, n
,
399 CRED_PART_RSA_PUB_EXP
, e
, CRED_PART_END
);
406 METHOD(public_key_t
, get_ref
, public_key_t
*,
407 private_wolfssl_rsa_public_key_t
*this)
410 return &this->public.key
;
413 METHOD(public_key_t
, destroy
, void,
414 private_wolfssl_rsa_public_key_t
*this)
416 if (ref_put(&this->ref
))
418 lib
->encoding
->clear_cache(lib
->encoding
, &this->rsa
);
419 wc_FreeRsaKey(&this->rsa
);
420 wc_FreeRng(&this->rng
);
426 * Generic private constructor
428 static private_wolfssl_rsa_public_key_t
*create_empty()
430 private_wolfssl_rsa_public_key_t
*this;
435 .get_type
= _get_type
,
438 .equals
= public_key_equals
,
439 .get_keysize
= _get_keysize
,
440 .get_fingerprint
= _get_fingerprint
,
441 .has_fingerprint
= public_key_has_fingerprint
,
442 .get_encoding
= _get_encoding
,
450 if (wc_InitRng(&this->rng
) != 0)
452 DBG1(DBG_LIB
, "init RNG failed, rsa public key load failed");
456 if (wc_InitRsaKey(&this->rsa
, NULL
) != 0)
458 DBG1(DBG_LIB
, "init RSA failed, rsa public key load failed");
459 wc_FreeRng(&this->rng
);
467 * Described in header
469 wolfssl_rsa_public_key_t
*wolfssl_rsa_public_key_load(key_type_t type
,
472 private_wolfssl_rsa_public_key_t
*this;
476 n
= e
= blob
= chunk_empty
;
479 switch (va_arg(args
, builder_part_t
))
481 case BUILD_BLOB_ASN1_DER
:
482 blob
= va_arg(args
, chunk_t
);
484 case BUILD_RSA_MODULUS
:
485 n
= va_arg(args
, chunk_t
);
487 case BUILD_RSA_PUB_EXP
:
488 e
= va_arg(args
, chunk_t
);
498 this = create_empty();
511 if (wc_RsaPublicKeyDecode(blob
.ptr
, &idx
, &this->rsa
,
522 return &this->public;
524 else if (n
.ptr
&& e
.ptr
&& type
== KEY_RSA
)
526 if (wc_RsaPublicKeyDecodeRaw(n
.ptr
, n
.len
, e
.ptr
, e
.len
,
532 return &this->public;