aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/s2n/crypto/s2n_evp_signing.c
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.ru>2022-05-10 22:16:03 +0300
committerthegeorg <thegeorg@yandex-team.ru>2022-05-10 22:16:03 +0300
commit09c71d918d4d0b0ebf67e1ab41aa90ddf587a3f2 (patch)
treedd44d2cb68e2845c2d4c367b66893f3e043a6e8e /contrib/restricted/aws/s2n/crypto/s2n_evp_signing.c
parent5eb4a8a2d487411924e1d1b27c454223dcf35005 (diff)
downloadydb-09c71d918d4d0b0ebf67e1ab41aa90ddf587a3f2.tar.gz
Update contrib/restricted/aws/s2n to 1.3.12
ref:f8279d764b4c00974a63543a1364c91e2b81b7a6
Diffstat (limited to 'contrib/restricted/aws/s2n/crypto/s2n_evp_signing.c')
-rw-r--r--contrib/restricted/aws/s2n/crypto/s2n_evp_signing.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/contrib/restricted/aws/s2n/crypto/s2n_evp_signing.c b/contrib/restricted/aws/s2n/crypto/s2n_evp_signing.c
new file mode 100644
index 0000000000..147840c2dd
--- /dev/null
+++ b/contrib/restricted/aws/s2n/crypto/s2n_evp_signing.c
@@ -0,0 +1,154 @@
+/*
+ * 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 "error/s2n_errno.h"
+
+#include "crypto/s2n_evp.h"
+#include "crypto/s2n_evp_signing.h"
+#include "crypto/s2n_pkey.h"
+#include "crypto/s2n_rsa_pss.h"
+
+#include "utils/s2n_safety.h"
+
+/*
+ * FIPS 140-3 requires that we don't pass raw digest bytes to the libcrypto signing methods.
+ * In order to do that, we need to use signing methods that both calculate the digest and
+ * perform the signature.
+ */
+
+static S2N_RESULT s2n_evp_md_ctx_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx)
+{
+#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX
+ EVP_MD_CTX_set_pkey_ctx(ctx, pctx);
+ return S2N_RESULT_OK;
+#else
+ RESULT_BAIL(S2N_ERR_UNIMPLEMENTED);
+#endif
+}
+
+static S2N_RESULT s2n_evp_pkey_set_rsa_pss_saltlen(EVP_PKEY_CTX *pctx)
+{
+#if RSA_PSS_SIGNING_SUPPORTED
+ RESULT_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST), S2N_ERR_PKEY_CTX_INIT);
+ return S2N_RESULT_OK;
+#else
+ RESULT_BAIL(S2N_ERR_UNIMPLEMENTED);
+#endif
+}
+
+bool s2n_evp_signing_supported()
+{
+#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX
+ /* We can only use EVP signing if the hash state has an EVP_MD_CTX
+ * that we can pass to the EVP signing methods.
+ */
+ return s2n_hash_evp_fully_supported();
+#else
+ return false;
+#endif
+}
+
+/* If using EVP signing, override the sign and verify pkey methods.
+ * The EVP methods can handle all pkey types / signature algorithms.
+ */
+S2N_RESULT s2n_evp_signing_set_pkey_overrides(struct s2n_pkey *pkey)
+{
+ if (s2n_evp_signing_supported()) {
+ RESULT_ENSURE_REF(pkey);
+ pkey->sign = &s2n_evp_sign;
+ pkey->verify = &s2n_evp_verify;
+ }
+ return S2N_RESULT_OK;
+}
+
+static S2N_RESULT s2n_evp_signing_validate_hash_alg(s2n_signature_algorithm sig_alg, s2n_hash_algorithm hash_alg)
+{
+ switch(hash_alg) {
+ case S2N_HASH_NONE:
+ case S2N_HASH_MD5:
+ /* MD5 alone is never supported */
+ RESULT_BAIL(S2N_ERR_HASH_INVALID_ALGORITHM);
+ break;
+ case S2N_HASH_MD5_SHA1:
+ /* Only RSA supports MD5+SHA1.
+ * This should not be a problem, as we only allow MD5+SHA1 when
+ * falling back to TLS1.0 or 1.1, which only support RSA.
+ */
+ RESULT_ENSURE(sig_alg == S2N_SIGNATURE_RSA, S2N_ERR_HASH_INVALID_ALGORITHM);
+ break;
+ default:
+ break;
+ }
+ /* Hash algorithm must be recognized and supported by EVP_MD */
+ RESULT_ENSURE(s2n_hash_alg_to_evp_md(hash_alg) != NULL, S2N_ERR_HASH_INVALID_ALGORITHM);
+ return S2N_RESULT_OK;
+}
+
+int s2n_evp_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig_alg,
+ struct s2n_hash_state *hash_state, struct s2n_blob *signature)
+{
+ POSIX_ENSURE_REF(priv);
+ POSIX_ENSURE_REF(hash_state);
+ POSIX_ENSURE_REF(signature);
+ POSIX_ENSURE(s2n_evp_signing_supported(), S2N_ERR_HASH_NOT_READY);
+ POSIX_GUARD_RESULT(s2n_evp_signing_validate_hash_alg(sig_alg, hash_state->alg));
+
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(priv->pkey, NULL);
+ POSIX_ENSURE_REF(pctx);
+ POSIX_GUARD_OSSL(EVP_PKEY_sign_init(pctx), S2N_ERR_PKEY_CTX_INIT);
+ POSIX_GUARD_OSSL(S2N_EVP_PKEY_CTX_set_signature_md(pctx, s2n_hash_alg_to_evp_md(hash_state->alg)), S2N_ERR_PKEY_CTX_INIT);
+
+ if (sig_alg == S2N_SIGNATURE_RSA_PSS_RSAE || sig_alg == S2N_SIGNATURE_RSA_PSS_PSS) {
+ POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING), S2N_ERR_PKEY_CTX_INIT);
+ POSIX_GUARD_RESULT(s2n_evp_pkey_set_rsa_pss_saltlen(pctx));
+ }
+
+ EVP_MD_CTX *ctx = hash_state->digest.high_level.evp.ctx;
+ POSIX_ENSURE_REF(ctx);
+ POSIX_GUARD_RESULT(s2n_evp_md_ctx_set_pkey_ctx(ctx, pctx));
+
+ size_t signature_size = signature->size;
+ POSIX_GUARD_OSSL(EVP_DigestSignFinal(ctx, signature->data, &signature_size), S2N_ERR_SIGN);
+ POSIX_ENSURE(signature_size <= signature->size, S2N_ERR_SIZE_MISMATCH);
+ signature->size = signature_size;
+ return S2N_SUCCESS;
+}
+
+int s2n_evp_verify(const struct s2n_pkey *pub, s2n_signature_algorithm sig_alg,
+ struct s2n_hash_state *hash_state, struct s2n_blob *signature)
+{
+ POSIX_ENSURE_REF(pub);
+ POSIX_ENSURE_REF(hash_state);
+ POSIX_ENSURE_REF(signature);
+ POSIX_ENSURE(s2n_evp_signing_supported(), S2N_ERR_HASH_NOT_READY);
+ POSIX_GUARD_RESULT(s2n_evp_signing_validate_hash_alg(sig_alg, hash_state->alg));
+
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pub->pkey, NULL);
+ POSIX_ENSURE_REF(pctx);
+ POSIX_GUARD_OSSL(EVP_PKEY_verify_init(pctx), S2N_ERR_PKEY_CTX_INIT);
+ POSIX_GUARD_OSSL(S2N_EVP_PKEY_CTX_set_signature_md(pctx, s2n_hash_alg_to_evp_md(hash_state->alg)), S2N_ERR_PKEY_CTX_INIT);
+
+ if (sig_alg == S2N_SIGNATURE_RSA_PSS_RSAE || sig_alg == S2N_SIGNATURE_RSA_PSS_PSS) {
+ POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING), S2N_ERR_PKEY_CTX_INIT);
+ POSIX_GUARD_RESULT(s2n_evp_pkey_set_rsa_pss_saltlen(pctx));
+ }
+
+ EVP_MD_CTX *ctx = hash_state->digest.high_level.evp.ctx;
+ POSIX_ENSURE_REF(ctx);
+ POSIX_GUARD_RESULT(s2n_evp_md_ctx_set_pkey_ctx(ctx, pctx));
+
+ POSIX_GUARD_OSSL(EVP_DigestVerifyFinal(ctx, signature->data, signature->size), S2N_ERR_VERIFY_SIGNATURE);
+ return S2N_SUCCESS;
+}