123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- /*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * A copy of the License is located at
- *
- * http://aws.amazon.com/apache2.0
- *
- * or in the "license" file accompanying this file. This file is distributed
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
- #include "crypto/s2n_rsa.h"
- #include <openssl/evp.h>
- #include <openssl/rsa.h>
- #include <stdint.h>
- #include "crypto/s2n_drbg.h"
- #include "crypto/s2n_evp_signing.h"
- #include "crypto/s2n_hash.h"
- #include "crypto/s2n_pkey.h"
- #include "crypto/s2n_rsa_signing.h"
- #include "error/s2n_errno.h"
- #include "stuffer/s2n_stuffer.h"
- #include "utils/s2n_blob.h"
- #include "utils/s2n_compiler.h"
- #include "utils/s2n_random.h"
- #include "utils/s2n_result.h"
- #include "utils/s2n_safety.h"
- RSA *s2n_unsafe_rsa_get_non_const(const struct s2n_rsa_key *rsa_key)
- {
- PTR_ENSURE_REF(rsa_key);
- #ifdef S2N_DIAGNOSTICS_PUSH_SUPPORTED
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wcast-qual"
- #endif
- RSA *out_rsa_key = (RSA *) rsa_key->rsa;
- #ifdef S2N_DIAGNOSTICS_POP_SUPPORTED
- #pragma GCC diagnostic pop
- #endif
- return out_rsa_key;
- }
- static S2N_RESULT s2n_rsa_modulus_check(const RSA *rsa)
- {
- /* RSA was made opaque starting in Openssl 1.1.0 */
- #if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)
- const BIGNUM *n = NULL;
- /* RSA still owns the memory for n */
- RSA_get0_key(rsa, &n, NULL, NULL);
- RESULT_ENSURE_REF(n);
- #else
- RESULT_ENSURE_REF(rsa->n);
- #endif
- return S2N_RESULT_OK;
- }
- static S2N_RESULT s2n_rsa_encrypted_size(const struct s2n_pkey *pkey, uint32_t *size_out)
- {
- RESULT_ENSURE_REF(pkey);
- RESULT_ENSURE_REF(size_out);
- const struct s2n_rsa_key *rsa_key = &pkey->key.rsa_key;
- RESULT_ENSURE_REF(rsa_key->rsa);
- RESULT_GUARD(s2n_rsa_modulus_check(rsa_key->rsa));
- const int size = RSA_size(rsa_key->rsa);
- RESULT_GUARD_POSIX(size);
- *size_out = size;
- return S2N_RESULT_OK;
- }
- static int s2n_rsa_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig_alg, struct s2n_hash_state *digest,
- struct s2n_blob *signature)
- {
- switch (sig_alg) {
- case S2N_SIGNATURE_RSA:
- return s2n_rsa_pkcs1v15_sign(priv, digest, signature);
- case S2N_SIGNATURE_RSA_PSS_RSAE:
- return s2n_rsa_pss_sign(priv, digest, signature);
- default:
- POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
- }
- return S2N_SUCCESS;
- }
- static int s2n_rsa_verify(const struct s2n_pkey *pub, s2n_signature_algorithm sig_alg, struct s2n_hash_state *digest,
- struct s2n_blob *signature)
- {
- switch (sig_alg) {
- case S2N_SIGNATURE_RSA:
- return s2n_rsa_pkcs1v15_verify(pub, digest, signature);
- case S2N_SIGNATURE_RSA_PSS_RSAE:
- return s2n_rsa_pss_verify(pub, digest, signature);
- default:
- POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
- }
- return S2N_SUCCESS;
- }
- static int s2n_rsa_encrypt(const struct s2n_pkey *pub, struct s2n_blob *in, struct s2n_blob *out)
- {
- uint32_t size = 0;
- POSIX_GUARD_RESULT(s2n_rsa_encrypted_size(pub, &size));
- S2N_ERROR_IF(out->size < size, S2N_ERR_NOMEM);
- const s2n_rsa_public_key *pub_key = &pub->key.rsa_key;
- /* Safety: RSA_public_encrypt does not mutate the key */
- int r = RSA_public_encrypt(in->size, (unsigned char *) in->data, (unsigned char *) out->data,
- s2n_unsafe_rsa_get_non_const(pub_key), RSA_PKCS1_PADDING);
- POSIX_ENSURE((int64_t) r == (int64_t) out->size, S2N_ERR_SIZE_MISMATCH);
- return 0;
- }
- static int s2n_rsa_decrypt(const struct s2n_pkey *priv, struct s2n_blob *in, struct s2n_blob *out)
- {
- unsigned char intermediate[4096];
- uint32_t expected_size = 0;
- POSIX_GUARD_RESULT(s2n_rsa_encrypted_size(priv, &expected_size));
- S2N_ERROR_IF(expected_size > sizeof(intermediate), S2N_ERR_NOMEM);
- S2N_ERROR_IF(out->size > sizeof(intermediate), S2N_ERR_NOMEM);
- POSIX_GUARD_RESULT(s2n_get_public_random_data(out));
- const s2n_rsa_private_key *priv_key = &priv->key.rsa_key;
- /* Safety: RSA_private_decrypt does not mutate the key */
- int r = RSA_private_decrypt(in->size, (unsigned char *) in->data, intermediate,
- s2n_unsafe_rsa_get_non_const(priv_key), RSA_NO_PADDING);
- POSIX_ENSURE((int64_t) r == (int64_t) expected_size, S2N_ERR_SIZE_MISMATCH);
- s2n_constant_time_pkcs1_unpad_or_dont(out->data, intermediate, r, out->size);
- return 0;
- }
- static int s2n_rsa_keys_match(const struct s2n_pkey *pub, const struct s2n_pkey *priv)
- {
- uint8_t plain_inpad[36] = { 1 }, plain_outpad[36] = { 0 }, encpad[8192];
- struct s2n_blob plain_in = { 0 }, plain_out = { 0 }, enc = { 0 };
- plain_in.data = plain_inpad;
- plain_in.size = sizeof(plain_inpad);
- enc.data = encpad;
- POSIX_GUARD_RESULT(s2n_rsa_encrypted_size(pub, &enc.size));
- POSIX_ENSURE_LTE(enc.size, sizeof(encpad));
- POSIX_GUARD(s2n_rsa_encrypt(pub, &plain_in, &enc));
- plain_out.data = plain_outpad;
- plain_out.size = sizeof(plain_outpad);
- POSIX_GUARD(s2n_rsa_decrypt(priv, &enc, &plain_out));
- S2N_ERROR_IF(memcmp(plain_in.data, plain_out.data, plain_in.size), S2N_ERR_KEY_MISMATCH);
- return 0;
- }
- static int s2n_rsa_key_free(struct s2n_pkey *pkey)
- {
- POSIX_ENSURE_REF(pkey);
- struct s2n_rsa_key *rsa_key = &pkey->key.rsa_key;
- if (rsa_key->rsa == NULL) {
- return S2N_SUCCESS;
- }
- /* Safety: freeing the key owned by this object */
- RSA_free(s2n_unsafe_rsa_get_non_const(rsa_key));
- rsa_key->rsa = NULL;
- return S2N_SUCCESS;
- }
- static int s2n_rsa_check_key_exists(const struct s2n_pkey *pkey)
- {
- const struct s2n_rsa_key *rsa_key = &pkey->key.rsa_key;
- POSIX_ENSURE_REF(rsa_key->rsa);
- return 0;
- }
- int s2n_evp_pkey_to_rsa_public_key(s2n_rsa_public_key *rsa_key, EVP_PKEY *evp_public_key)
- {
- const RSA *rsa = EVP_PKEY_get1_RSA(evp_public_key);
- S2N_ERROR_IF(rsa == NULL, S2N_ERR_DECODE_CERTIFICATE);
- rsa_key->rsa = rsa;
- return 0;
- }
- int s2n_evp_pkey_to_rsa_private_key(s2n_rsa_private_key *rsa_key, EVP_PKEY *evp_private_key)
- {
- const RSA *rsa = EVP_PKEY_get1_RSA(evp_private_key);
- S2N_ERROR_IF(rsa == NULL, S2N_ERR_DECODE_PRIVATE_KEY);
- rsa_key->rsa = rsa;
- return 0;
- }
- int s2n_rsa_pkey_init(struct s2n_pkey *pkey)
- {
- pkey->size = &s2n_rsa_encrypted_size;
- pkey->sign = &s2n_rsa_sign;
- pkey->verify = &s2n_rsa_verify;
- pkey->encrypt = &s2n_rsa_encrypt;
- pkey->decrypt = &s2n_rsa_decrypt;
- pkey->match = &s2n_rsa_keys_match;
- pkey->free = &s2n_rsa_key_free;
- pkey->check_key = &s2n_rsa_check_key_exists;
- POSIX_GUARD_RESULT(s2n_evp_signing_set_pkey_overrides(pkey));
- return 0;
- }
|