1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 #include <openssl/evp.h>
17 #include <openssl/rsa.h>
18 
19 #include "error/s2n_errno.h"
20 
21 #include "stuffer/s2n_stuffer.h"
22 
23 #include "crypto/s2n_hash.h"
24 #include "crypto/s2n_rsa_pss.h"
25 #include "crypto/s2n_rsa_signing.h"
26 #include "crypto/s2n_pkey.h"
27 
28 #include "utils/s2n_blob.h"
29 #include "utils/s2n_safety.h"
30 
31 static int s2n_hash_alg_to_NID[] = {
32     [S2N_HASH_MD5_SHA1] = NID_md5_sha1,
33     [S2N_HASH_SHA1]     = NID_sha1,
34     [S2N_HASH_SHA224]   = NID_sha224,
35     [S2N_HASH_SHA256]   = NID_sha256,
36     [S2N_HASH_SHA384]   = NID_sha384,
37     [S2N_HASH_SHA512]   = NID_sha512 };
38 
s2n_hash_NID_type(s2n_hash_algorithm alg,int * out)39 int s2n_hash_NID_type(s2n_hash_algorithm alg, int *out)
40 {
41     switch(alg) {
42     case S2N_HASH_MD5_SHA1:
43     case S2N_HASH_SHA1:
44     case S2N_HASH_SHA224:
45     case S2N_HASH_SHA256:
46     case S2N_HASH_SHA384:
47     case S2N_HASH_SHA512:
48         *out = s2n_hash_alg_to_NID[alg];
49         break;
50     default:
51         POSIX_BAIL(S2N_ERR_HASH_INVALID_ALGORITHM);
52     }
53     return 0;
54 }
55 
s2n_rsa_pkcs1v15_sign_digest(const struct s2n_pkey * priv,s2n_hash_algorithm hash_alg,struct s2n_blob * digest,struct s2n_blob * signature)56 int s2n_rsa_pkcs1v15_sign_digest(const struct s2n_pkey *priv, s2n_hash_algorithm hash_alg,
57         struct s2n_blob *digest, struct s2n_blob *signature)
58 {
59     POSIX_ENSURE_REF(priv);
60     POSIX_ENSURE_REF(digest);
61     POSIX_ENSURE_REF(signature);
62 
63     int NID_type = 0;
64     POSIX_GUARD(s2n_hash_NID_type(hash_alg, &NID_type));
65 
66     const s2n_rsa_private_key *key = &priv->key.rsa_key;
67 
68     unsigned int signature_size = signature->size;
69     POSIX_GUARD_OSSL(RSA_sign(NID_type, digest->data, digest->size, signature->data, &signature_size, key->rsa), S2N_ERR_SIGN);
70     POSIX_ENSURE(signature_size <= signature->size, S2N_ERR_SIZE_MISMATCH);
71     signature->size = signature_size;
72 
73     return S2N_SUCCESS;
74 }
75 
s2n_rsa_pkcs1v15_sign(const struct s2n_pkey * priv,struct s2n_hash_state * digest,struct s2n_blob * signature)76 int s2n_rsa_pkcs1v15_sign(const struct s2n_pkey *priv, struct s2n_hash_state *digest, struct s2n_blob *signature)
77 {
78     POSIX_ENSURE_REF(digest);
79 
80     uint8_t digest_length = 0;
81     POSIX_GUARD(s2n_hash_digest_size(digest->alg, &digest_length));
82     POSIX_ENSURE_LTE(digest_length, S2N_MAX_DIGEST_LEN);
83 
84     uint8_t digest_out[S2N_MAX_DIGEST_LEN] = { 0 };
85     POSIX_GUARD(s2n_hash_digest(digest, digest_out, digest_length));
86 
87     struct s2n_blob digest_blob = { 0 };
88     POSIX_GUARD(s2n_blob_init(&digest_blob, digest_out, digest_length));
89     POSIX_GUARD(s2n_rsa_pkcs1v15_sign_digest(priv, digest->alg, &digest_blob, signature));
90 
91     return S2N_SUCCESS;
92 }
93 
s2n_rsa_pkcs1v15_verify(const struct s2n_pkey * pub,struct s2n_hash_state * digest,struct s2n_blob * signature)94 int s2n_rsa_pkcs1v15_verify(const struct s2n_pkey *pub, struct s2n_hash_state *digest, struct s2n_blob *signature)
95 {
96     uint8_t digest_length;
97     int digest_NID_type;
98     POSIX_GUARD(s2n_hash_digest_size(digest->alg, &digest_length));
99     POSIX_GUARD(s2n_hash_NID_type(digest->alg, &digest_NID_type));
100     POSIX_ENSURE_LTE(digest_length, S2N_MAX_DIGEST_LEN);
101 
102     const s2n_rsa_public_key *key = &pub->key.rsa_key;
103 
104     uint8_t digest_out[S2N_MAX_DIGEST_LEN];
105     POSIX_GUARD(s2n_hash_digest(digest, digest_out, digest_length));
106 
107     POSIX_GUARD_OSSL(RSA_verify(digest_NID_type, digest_out, digest_length, signature->data, signature->size, key->rsa), S2N_ERR_VERIFY_SIGNATURE);
108 
109     return 0;
110 }
111 
112 /* this function returns whether RSA PSS signing is supported */
s2n_is_rsa_pss_signing_supported()113 int s2n_is_rsa_pss_signing_supported()
114 {
115     return RSA_PSS_SIGNING_SUPPORTED;
116 }
117 
118 #if RSA_PSS_SIGNING_SUPPORTED
119 
s2n_hash_alg_to_evp_alg(s2n_hash_algorithm alg)120 const EVP_MD* s2n_hash_alg_to_evp_alg(s2n_hash_algorithm alg)
121 {
122     switch (alg) {
123         case S2N_HASH_MD5_SHA1:
124             return EVP_md5_sha1();
125         case S2N_HASH_SHA1:
126             return EVP_sha1();
127         case S2N_HASH_SHA224:
128             return EVP_sha224();
129         case S2N_HASH_SHA256:
130             return EVP_sha256();
131         case S2N_HASH_SHA384:
132             return EVP_sha384();
133         case S2N_HASH_SHA512:
134             return EVP_sha512();
135         default:
136             return NULL;
137     }
138 }
139 
140 /* On some versions of OpenSSL, "EVP_PKEY_CTX_set_signature_md()" is just a macro that casts digest_alg to "void*",
141  * which fails to compile when the "-Werror=cast-qual" compiler flag is enabled. So we work around this OpenSSL
142  * issue by turning off this compiler check for this one function with a cast through. */
s2n_evp_pkey_ctx_set_rsa_signature_digest(EVP_PKEY_CTX * ctx,const EVP_MD * digest_alg)143 static int s2n_evp_pkey_ctx_set_rsa_signature_digest(EVP_PKEY_CTX *ctx, const EVP_MD* digest_alg)
144 {
145     POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_signature_md(ctx,(EVP_MD*) (uintptr_t) digest_alg), S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
146     POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, (EVP_MD*) (uintptr_t) digest_alg), S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
147     return 0;
148 }
149 
s2n_evp_pkey_ctx_free(EVP_PKEY_CTX ** ctx)150 static void s2n_evp_pkey_ctx_free(EVP_PKEY_CTX **ctx)
151 {
152     EVP_PKEY_CTX_free(*ctx);
153 }
154 
s2n_rsa_pss_sign_digest(const struct s2n_pkey * priv,s2n_hash_algorithm hash_alg,struct s2n_blob * digest_in,struct s2n_blob * signature_out)155 int s2n_rsa_pss_sign_digest(const struct s2n_pkey *priv, s2n_hash_algorithm hash_alg,
156         struct s2n_blob *digest_in, struct s2n_blob *signature_out)
157 {
158     POSIX_ENSURE_REF(priv);
159     POSIX_ENSURE_REF(digest_in);
160     POSIX_ENSURE_REF(signature_out);
161 
162     const EVP_MD* digest_alg = s2n_hash_alg_to_evp_alg(hash_alg);
163     POSIX_ENSURE_REF(digest_alg);
164 
165     /* For more info see: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_sign.html */
166     DEFER_CLEANUP(EVP_PKEY_CTX *ctx  = EVP_PKEY_CTX_new(priv->pkey, NULL), s2n_evp_pkey_ctx_free);
167     POSIX_ENSURE_REF(ctx);
168 
169     size_t signature_len = signature_out->size;
170     POSIX_GUARD_OSSL(EVP_PKEY_sign_init(ctx), S2N_ERR_SIGN);
171     POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING), S2N_ERR_SIGN);
172     POSIX_GUARD(s2n_evp_pkey_ctx_set_rsa_signature_digest(ctx, digest_alg));
173     POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, RSA_PSS_SALTLEN_DIGEST), S2N_ERR_SIGN);
174 
175     /* Calling EVP_PKEY_sign() with NULL will only update the signature_len parameter so users can validate sizes. */
176     POSIX_GUARD_OSSL(EVP_PKEY_sign(ctx, NULL, &signature_len, digest_in->data, digest_in->size), S2N_ERR_SIGN);
177     POSIX_ENSURE(signature_len <= signature_out->size, S2N_ERR_SIZE_MISMATCH);
178 
179     /* Actually sign the digest */
180     POSIX_GUARD_OSSL(EVP_PKEY_sign(ctx, signature_out->data, &signature_len, digest_in->data, digest_in->size), S2N_ERR_SIGN);
181     signature_out->size = signature_len;
182 
183     return S2N_SUCCESS;
184 }
185 
s2n_rsa_pss_sign(const struct s2n_pkey * priv,struct s2n_hash_state * digest,struct s2n_blob * signature_out)186 int s2n_rsa_pss_sign(const struct s2n_pkey *priv, struct s2n_hash_state *digest, struct s2n_blob *signature_out)
187 {
188     POSIX_ENSURE_REF(digest);
189 
190     uint8_t digest_length = 0;
191     uint8_t digest_data[S2N_MAX_DIGEST_LEN] = { 0 };
192     POSIX_GUARD(s2n_hash_digest_size(digest->alg, &digest_length));
193     POSIX_GUARD(s2n_hash_digest(digest, digest_data, digest_length));
194 
195     struct s2n_blob digest_blob = { 0 };
196     POSIX_GUARD(s2n_blob_init(&digest_blob, digest_data, digest_length));
197     POSIX_GUARD(s2n_rsa_pss_sign_digest(priv, digest->alg, &digest_blob, signature_out));
198 
199     return S2N_SUCCESS;
200 }
201 
s2n_rsa_pss_verify(const struct s2n_pkey * pub,struct s2n_hash_state * digest,struct s2n_blob * signature_in)202 int s2n_rsa_pss_verify(const struct s2n_pkey *pub, struct s2n_hash_state *digest, struct s2n_blob *signature_in)
203 {
204     POSIX_ENSURE_REF(pub);
205 
206     uint8_t digest_length;
207     uint8_t digest_data[S2N_MAX_DIGEST_LEN];
208     POSIX_GUARD(s2n_hash_digest_size(digest->alg, &digest_length));
209     POSIX_GUARD(s2n_hash_digest(digest, digest_data, digest_length));
210     const EVP_MD* digest_alg = s2n_hash_alg_to_evp_alg(digest->alg);
211     POSIX_ENSURE_REF(digest_alg);
212 
213     /* For more info see: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_verify.html */
214     DEFER_CLEANUP(EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pub->pkey, NULL), s2n_evp_pkey_ctx_free);
215     POSIX_ENSURE_REF(ctx);
216 
217     POSIX_GUARD_OSSL(EVP_PKEY_verify_init(ctx), S2N_ERR_VERIFY_SIGNATURE);
218     POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING), S2N_ERR_SIGN);
219     POSIX_GUARD(s2n_evp_pkey_ctx_set_rsa_signature_digest(ctx, digest_alg));
220     POSIX_GUARD_OSSL(EVP_PKEY_verify(ctx, signature_in->data, signature_in->size, digest_data, digest_length), S2N_ERR_VERIFY_SIGNATURE);
221 
222     return 0;
223 }
224 
225 #else
226 
s2n_rsa_pss_sign_digest(const struct s2n_pkey * priv,s2n_hash_algorithm hash_alg,struct s2n_blob * digest_in,struct s2n_blob * signature_out)227 int s2n_rsa_pss_sign_digest(const struct s2n_pkey *priv, s2n_hash_algorithm hash_alg,
228         struct s2n_blob *digest_in, struct s2n_blob *signature_out)
229 {
230     POSIX_BAIL(S2N_RSA_PSS_NOT_SUPPORTED);
231 }
232 
s2n_rsa_pss_sign(const struct s2n_pkey * priv,struct s2n_hash_state * digest,struct s2n_blob * signature_out)233 int s2n_rsa_pss_sign(const struct s2n_pkey *priv, struct s2n_hash_state *digest, struct s2n_blob *signature_out)
234 {
235     POSIX_BAIL(S2N_RSA_PSS_NOT_SUPPORTED);
236 }
237 
s2n_rsa_pss_verify(const struct s2n_pkey * pub,struct s2n_hash_state * digest,struct s2n_blob * signature_in)238 int s2n_rsa_pss_verify(const struct s2n_pkey *pub, struct s2n_hash_state *digest, struct s2n_blob *signature_in)
239 {
240     POSIX_BAIL(S2N_RSA_PSS_NOT_SUPPORTED);
241 }
242 
243 #endif
244