xref: /aosp_15_r20/system/keymaster/km_openssl/rsa_operation.cpp (revision 789431f29546679ab5188a97751fb38e3018d44d)
1*789431f2SAndroid Build Coastguard Worker /*
2*789431f2SAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
3*789431f2SAndroid Build Coastguard Worker  *
4*789431f2SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*789431f2SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*789431f2SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*789431f2SAndroid Build Coastguard Worker  *
8*789431f2SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*789431f2SAndroid Build Coastguard Worker  *
10*789431f2SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*789431f2SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*789431f2SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*789431f2SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*789431f2SAndroid Build Coastguard Worker  * limitations under the License.
15*789431f2SAndroid Build Coastguard Worker  */
16*789431f2SAndroid Build Coastguard Worker 
17*789431f2SAndroid Build Coastguard Worker #include <keymaster/km_openssl/rsa_operation.h>
18*789431f2SAndroid Build Coastguard Worker 
19*789431f2SAndroid Build Coastguard Worker #include <utility>
20*789431f2SAndroid Build Coastguard Worker 
21*789431f2SAndroid Build Coastguard Worker #include <limits.h>
22*789431f2SAndroid Build Coastguard Worker 
23*789431f2SAndroid Build Coastguard Worker #include <openssl/err.h>
24*789431f2SAndroid Build Coastguard Worker 
25*789431f2SAndroid Build Coastguard Worker #include <keymaster/km_openssl/openssl_err.h>
26*789431f2SAndroid Build Coastguard Worker #include <keymaster/km_openssl/openssl_utils.h>
27*789431f2SAndroid Build Coastguard Worker #include <keymaster/km_openssl/rsa_key.h>
28*789431f2SAndroid Build Coastguard Worker #include <keymaster/logger.h>
29*789431f2SAndroid Build Coastguard Worker 
30*789431f2SAndroid Build Coastguard Worker namespace keymaster {
31*789431f2SAndroid Build Coastguard Worker 
32*789431f2SAndroid Build Coastguard Worker const size_t kPssOverhead = 2;
33*789431f2SAndroid Build Coastguard Worker 
34*789431f2SAndroid Build Coastguard Worker // Overhead for PKCS#1 v1.5 signature padding of undigested messages.  Digested messages have
35*789431f2SAndroid Build Coastguard Worker // additional overhead, for the digest algorithmIdentifier required by PKCS#1.
36*789431f2SAndroid Build Coastguard Worker const size_t kPkcs1UndigestedSignaturePaddingOverhead = 11;
37*789431f2SAndroid Build Coastguard Worker 
38*789431f2SAndroid Build Coastguard Worker /* static */
GetRsaKey(const Key & key,keymaster_error_t * error)39*789431f2SAndroid Build Coastguard Worker EVP_PKEY* RsaOperationFactory::GetRsaKey(const Key& key, keymaster_error_t* error) {
40*789431f2SAndroid Build Coastguard Worker     const RsaKey& rsa_key = static_cast<const RsaKey&>(key);
41*789431f2SAndroid Build Coastguard Worker     if (!rsa_key.key()) {
42*789431f2SAndroid Build Coastguard Worker         *error = KM_ERROR_UNKNOWN_ERROR;
43*789431f2SAndroid Build Coastguard Worker         return nullptr;
44*789431f2SAndroid Build Coastguard Worker     }
45*789431f2SAndroid Build Coastguard Worker 
46*789431f2SAndroid Build Coastguard Worker     EVP_PKEY_Ptr pkey(rsa_key.InternalToEvp());
47*789431f2SAndroid Build Coastguard Worker     if (pkey.get() == nullptr) {
48*789431f2SAndroid Build Coastguard Worker         *error = KM_ERROR_UNKNOWN_ERROR;
49*789431f2SAndroid Build Coastguard Worker         return nullptr;
50*789431f2SAndroid Build Coastguard Worker     }
51*789431f2SAndroid Build Coastguard Worker     return pkey.release();
52*789431f2SAndroid Build Coastguard Worker }
53*789431f2SAndroid Build Coastguard Worker 
54*789431f2SAndroid Build Coastguard Worker static const keymaster_digest_t supported_digests[] = {
55*789431f2SAndroid Build Coastguard Worker     KM_DIGEST_NONE,      KM_DIGEST_MD5,       KM_DIGEST_SHA1,     KM_DIGEST_SHA_2_224,
56*789431f2SAndroid Build Coastguard Worker     KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
57*789431f2SAndroid Build Coastguard Worker 
SupportedDigests(size_t * digest_count) const58*789431f2SAndroid Build Coastguard Worker const keymaster_digest_t* RsaOperationFactory::SupportedDigests(size_t* digest_count) const {
59*789431f2SAndroid Build Coastguard Worker     *digest_count = array_length(supported_digests);
60*789431f2SAndroid Build Coastguard Worker     return supported_digests;
61*789431f2SAndroid Build Coastguard Worker }
62*789431f2SAndroid Build Coastguard Worker 
CreateRsaOperation(Key && key,const AuthorizationSet & begin_params,keymaster_error_t * error)63*789431f2SAndroid Build Coastguard Worker RsaOperation* RsaOperationFactory::CreateRsaOperation(Key&& key,
64*789431f2SAndroid Build Coastguard Worker                                                       const AuthorizationSet& begin_params,
65*789431f2SAndroid Build Coastguard Worker                                                       keymaster_error_t* error) {
66*789431f2SAndroid Build Coastguard Worker     keymaster_padding_t padding;
67*789431f2SAndroid Build Coastguard Worker     if (!GetAndValidatePadding(begin_params, key, &padding, error)) return nullptr;
68*789431f2SAndroid Build Coastguard Worker 
69*789431f2SAndroid Build Coastguard Worker     bool require_digest = (purpose() == KM_PURPOSE_SIGN || purpose() == KM_PURPOSE_VERIFY ||
70*789431f2SAndroid Build Coastguard Worker                            padding == KM_PAD_RSA_OAEP);
71*789431f2SAndroid Build Coastguard Worker 
72*789431f2SAndroid Build Coastguard Worker     keymaster_digest_t digest = KM_DIGEST_NONE;
73*789431f2SAndroid Build Coastguard Worker 
74*789431f2SAndroid Build Coastguard Worker     if (require_digest && !GetAndValidateDigest(begin_params, key, &digest, error, true)) {
75*789431f2SAndroid Build Coastguard Worker         return nullptr;
76*789431f2SAndroid Build Coastguard Worker     }
77*789431f2SAndroid Build Coastguard Worker 
78*789431f2SAndroid Build Coastguard Worker     UniquePtr<EVP_PKEY, EVP_PKEY_Delete> rsa(GetRsaKey(key, error));
79*789431f2SAndroid Build Coastguard Worker     if (!rsa.get()) return nullptr;
80*789431f2SAndroid Build Coastguard Worker 
81*789431f2SAndroid Build Coastguard Worker     RsaOperation* op = InstantiateOperation(key.hw_enforced_move(), key.sw_enforced_move(), digest,
82*789431f2SAndroid Build Coastguard Worker                                             padding, rsa.release());
83*789431f2SAndroid Build Coastguard Worker     if (!op) *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
84*789431f2SAndroid Build Coastguard Worker     return op;
85*789431f2SAndroid Build Coastguard Worker }
86*789431f2SAndroid Build Coastguard Worker 
87*789431f2SAndroid Build Coastguard Worker static const keymaster_padding_t supported_sig_padding[] = {KM_PAD_NONE, KM_PAD_RSA_PKCS1_1_5_SIGN,
88*789431f2SAndroid Build Coastguard Worker                                                             KM_PAD_RSA_PSS};
89*789431f2SAndroid Build Coastguard Worker const keymaster_padding_t*
SupportedPaddingModes(size_t * padding_mode_count) const90*789431f2SAndroid Build Coastguard Worker RsaDigestingOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
91*789431f2SAndroid Build Coastguard Worker     *padding_mode_count = array_length(supported_sig_padding);
92*789431f2SAndroid Build Coastguard Worker     return supported_sig_padding;
93*789431f2SAndroid Build Coastguard Worker }
94*789431f2SAndroid Build Coastguard Worker 
CreateRsaOperation(Key && key,const AuthorizationSet & begin_params,keymaster_error_t * error)95*789431f2SAndroid Build Coastguard Worker RsaOperation* RsaCryptingOperationFactory::CreateRsaOperation(Key&& key,
96*789431f2SAndroid Build Coastguard Worker                                                               const AuthorizationSet& begin_params,
97*789431f2SAndroid Build Coastguard Worker                                                               keymaster_error_t* error) {
98*789431f2SAndroid Build Coastguard Worker     keymaster_digest_t mgf_digest = KM_DIGEST_NONE;
99*789431f2SAndroid Build Coastguard Worker     key.authorizations().GetTagValue(TAG_RSA_OAEP_MGF_DIGEST, &mgf_digest);
100*789431f2SAndroid Build Coastguard Worker     *error = GetAndValidateMgfDigest(begin_params, key, &mgf_digest);
101*789431f2SAndroid Build Coastguard Worker     if (*error != KM_ERROR_OK) return nullptr;
102*789431f2SAndroid Build Coastguard Worker     UniquePtr<RsaOperation> op(
103*789431f2SAndroid Build Coastguard Worker         RsaOperationFactory::CreateRsaOperation(std::move(key), begin_params, error));
104*789431f2SAndroid Build Coastguard Worker     if (op.get()) {
105*789431f2SAndroid Build Coastguard Worker         switch (op->padding()) {
106*789431f2SAndroid Build Coastguard Worker         case KM_PAD_NONE:
107*789431f2SAndroid Build Coastguard Worker         case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
108*789431f2SAndroid Build Coastguard Worker             if (op->digest() != KM_DIGEST_NONE) {
109*789431f2SAndroid Build Coastguard Worker                 *error = KM_ERROR_INCOMPATIBLE_DIGEST;
110*789431f2SAndroid Build Coastguard Worker                 return nullptr;
111*789431f2SAndroid Build Coastguard Worker             }
112*789431f2SAndroid Build Coastguard Worker             break;
113*789431f2SAndroid Build Coastguard Worker 
114*789431f2SAndroid Build Coastguard Worker         case KM_PAD_RSA_OAEP:
115*789431f2SAndroid Build Coastguard Worker             if (op->digest() == KM_DIGEST_NONE) {
116*789431f2SAndroid Build Coastguard Worker                 *error = KM_ERROR_INCOMPATIBLE_DIGEST;
117*789431f2SAndroid Build Coastguard Worker                 return nullptr;
118*789431f2SAndroid Build Coastguard Worker             }
119*789431f2SAndroid Build Coastguard Worker             static_cast<RsaCryptOperation*>(op.get())->setOaepMgfDigest(mgf_digest);
120*789431f2SAndroid Build Coastguard Worker             break;
121*789431f2SAndroid Build Coastguard Worker 
122*789431f2SAndroid Build Coastguard Worker         default:
123*789431f2SAndroid Build Coastguard Worker             *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
124*789431f2SAndroid Build Coastguard Worker             return nullptr;
125*789431f2SAndroid Build Coastguard Worker         }
126*789431f2SAndroid Build Coastguard Worker     }
127*789431f2SAndroid Build Coastguard Worker     return op.release();
128*789431f2SAndroid Build Coastguard Worker }
129*789431f2SAndroid Build Coastguard Worker 
GetAndValidateMgfDigest(const AuthorizationSet & begin_params,const Key & key,keymaster_digest_t * digest) const130*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaCryptingOperationFactory::GetAndValidateMgfDigest(
131*789431f2SAndroid Build Coastguard Worker     const AuthorizationSet& begin_params, const Key& key, keymaster_digest_t* digest) const {
132*789431f2SAndroid Build Coastguard Worker     *digest = KM_DIGEST_SHA1;
133*789431f2SAndroid Build Coastguard Worker     if (!begin_params.Contains(TAG_PADDING, KM_PAD_RSA_OAEP)) {
134*789431f2SAndroid Build Coastguard Worker         *digest = KM_DIGEST_NONE;
135*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_OK;
136*789431f2SAndroid Build Coastguard Worker     }
137*789431f2SAndroid Build Coastguard Worker     // If begin params does not specify any mgf digest
138*789431f2SAndroid Build Coastguard Worker     if (!begin_params.GetTagValue(TAG_RSA_OAEP_MGF_DIGEST, digest)) {
139*789431f2SAndroid Build Coastguard Worker         // And the authorizations has MGF Digest tag specified.
140*789431f2SAndroid Build Coastguard Worker         if (key.authorizations().GetTagCount(TAG_RSA_OAEP_MGF_DIGEST) > 0) {
141*789431f2SAndroid Build Coastguard Worker             // And key authorizations does not contain SHA1 for Mgf digest.
142*789431f2SAndroid Build Coastguard Worker             if (!key.authorizations().Contains(TAG_RSA_OAEP_MGF_DIGEST, KM_DIGEST_SHA1)) {
143*789431f2SAndroid Build Coastguard Worker                 // Then it is an error.
144*789431f2SAndroid Build Coastguard Worker                 LOG_E("%zu MGF digests specified in begin params and SHA1 not authorized",
145*789431f2SAndroid Build Coastguard Worker                       begin_params.GetTagCount(TAG_RSA_OAEP_MGF_DIGEST));
146*789431f2SAndroid Build Coastguard Worker                 return KM_ERROR_UNSUPPORTED_MGF_DIGEST;
147*789431f2SAndroid Build Coastguard Worker             }
148*789431f2SAndroid Build Coastguard Worker         }
149*789431f2SAndroid Build Coastguard Worker     } else if (!supported(*digest) || (*digest == KM_DIGEST_NONE)) {
150*789431f2SAndroid Build Coastguard Worker         LOG_E("MGF Digest %d not supported", *digest);
151*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_UNSUPPORTED_MGF_DIGEST;
152*789431f2SAndroid Build Coastguard Worker     } else if (!key.authorizations().Contains(TAG_RSA_OAEP_MGF_DIGEST, *digest)) {
153*789431f2SAndroid Build Coastguard Worker         LOG_E("MGF Digest %d was specified, but not authorized by key", *digest);
154*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_INCOMPATIBLE_MGF_DIGEST;
155*789431f2SAndroid Build Coastguard Worker     }
156*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
157*789431f2SAndroid Build Coastguard Worker }
158*789431f2SAndroid Build Coastguard Worker 
159*789431f2SAndroid Build Coastguard Worker static const keymaster_padding_t supported_crypt_padding[] = {KM_PAD_NONE, KM_PAD_RSA_OAEP,
160*789431f2SAndroid Build Coastguard Worker                                                               KM_PAD_RSA_PKCS1_1_5_ENCRYPT};
161*789431f2SAndroid Build Coastguard Worker const keymaster_padding_t*
SupportedPaddingModes(size_t * padding_mode_count) const162*789431f2SAndroid Build Coastguard Worker RsaCryptingOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
163*789431f2SAndroid Build Coastguard Worker     *padding_mode_count = array_length(supported_crypt_padding);
164*789431f2SAndroid Build Coastguard Worker     return supported_crypt_padding;
165*789431f2SAndroid Build Coastguard Worker }
166*789431f2SAndroid Build Coastguard Worker 
~RsaOperation()167*789431f2SAndroid Build Coastguard Worker RsaOperation::~RsaOperation() {
168*789431f2SAndroid Build Coastguard Worker     if (rsa_key_ != nullptr) EVP_PKEY_free(rsa_key_);
169*789431f2SAndroid Build Coastguard Worker }
170*789431f2SAndroid Build Coastguard Worker 
Begin(const AuthorizationSet &,AuthorizationSet *)171*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaOperation::Begin(const AuthorizationSet& /* input_params */,
172*789431f2SAndroid Build Coastguard Worker                                       AuthorizationSet* /* output_params */) {
173*789431f2SAndroid Build Coastguard Worker     auto rc = GenerateRandom(reinterpret_cast<uint8_t*>(&operation_handle_),
174*789431f2SAndroid Build Coastguard Worker                              (size_t)sizeof(operation_handle_));
175*789431f2SAndroid Build Coastguard Worker     if (rc != KM_ERROR_OK) return rc;
176*789431f2SAndroid Build Coastguard Worker 
177*789431f2SAndroid Build Coastguard Worker     return InitDigest();
178*789431f2SAndroid Build Coastguard Worker }
179*789431f2SAndroid Build Coastguard Worker 
Update(const AuthorizationSet &,const Buffer & input,AuthorizationSet *,Buffer *,size_t * input_consumed)180*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaOperation::Update(const AuthorizationSet& /* additional_params */,
181*789431f2SAndroid Build Coastguard Worker                                        const Buffer& input, AuthorizationSet* /* output_params */,
182*789431f2SAndroid Build Coastguard Worker                                        Buffer* /* output */, size_t* input_consumed) {
183*789431f2SAndroid Build Coastguard Worker     assert(input_consumed);
184*789431f2SAndroid Build Coastguard Worker     switch (purpose()) {
185*789431f2SAndroid Build Coastguard Worker     default:
186*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_UNIMPLEMENTED;
187*789431f2SAndroid Build Coastguard Worker     case KM_PURPOSE_SIGN:
188*789431f2SAndroid Build Coastguard Worker     case KM_PURPOSE_VERIFY:
189*789431f2SAndroid Build Coastguard Worker     case KM_PURPOSE_ENCRYPT:
190*789431f2SAndroid Build Coastguard Worker     case KM_PURPOSE_DECRYPT:
191*789431f2SAndroid Build Coastguard Worker         return StoreData(input, input_consumed);
192*789431f2SAndroid Build Coastguard Worker     }
193*789431f2SAndroid Build Coastguard Worker }
194*789431f2SAndroid Build Coastguard Worker 
StoreData(const Buffer & input,size_t * input_consumed)195*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaOperation::StoreData(const Buffer& input, size_t* input_consumed) {
196*789431f2SAndroid Build Coastguard Worker     assert(input_consumed);
197*789431f2SAndroid Build Coastguard Worker 
198*789431f2SAndroid Build Coastguard Worker     if (!data_.reserve(EVP_PKEY_size(rsa_key_))) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
199*789431f2SAndroid Build Coastguard Worker     // If the write fails, it's because input length exceeds key size.
200*789431f2SAndroid Build Coastguard Worker     if (!data_.write(input.peek_read(), input.available_read())) {
201*789431f2SAndroid Build Coastguard Worker         LOG_E("Input too long: cannot operate on %zu bytes of data with %u-byte RSA key",
202*789431f2SAndroid Build Coastguard Worker               input.available_read() + data_.available_read(), EVP_PKEY_size(rsa_key_));
203*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_INVALID_INPUT_LENGTH;
204*789431f2SAndroid Build Coastguard Worker     }
205*789431f2SAndroid Build Coastguard Worker 
206*789431f2SAndroid Build Coastguard Worker     *input_consumed = input.available_read();
207*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
208*789431f2SAndroid Build Coastguard Worker }
209*789431f2SAndroid Build Coastguard Worker 
SetRsaPaddingInEvpContext(EVP_PKEY_CTX * pkey_ctx,bool signing)210*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaOperation::SetRsaPaddingInEvpContext(EVP_PKEY_CTX* pkey_ctx, bool signing) {
211*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error;
212*789431f2SAndroid Build Coastguard Worker     int openssl_padding = GetOpensslPadding(&error);
213*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
214*789431f2SAndroid Build Coastguard Worker 
215*789431f2SAndroid Build Coastguard Worker     if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, openssl_padding) <= 0)
216*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
217*789431f2SAndroid Build Coastguard Worker 
218*789431f2SAndroid Build Coastguard Worker     if (signing && openssl_padding == RSA_PKCS1_PSS_PADDING) {
219*789431f2SAndroid Build Coastguard Worker         // Also need to set the length of the salt used in the padding generation.  We set it equal
220*789431f2SAndroid Build Coastguard Worker         // to the length of the selected digest.
221*789431f2SAndroid Build Coastguard Worker         assert(digest_algorithm_);
222*789431f2SAndroid Build Coastguard Worker         if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, EVP_MD_size(digest_algorithm_)) <= 0)
223*789431f2SAndroid Build Coastguard Worker             return TranslateLastOpenSslError();
224*789431f2SAndroid Build Coastguard Worker     }
225*789431f2SAndroid Build Coastguard Worker 
226*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
227*789431f2SAndroid Build Coastguard Worker }
228*789431f2SAndroid Build Coastguard Worker 
InitDigest()229*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaOperation::InitDigest() {
230*789431f2SAndroid Build Coastguard Worker     if (digest_ == KM_DIGEST_NONE) {
231*789431f2SAndroid Build Coastguard Worker         if (require_digest()) return KM_ERROR_INCOMPATIBLE_DIGEST;
232*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_OK;
233*789431f2SAndroid Build Coastguard Worker     }
234*789431f2SAndroid Build Coastguard Worker     digest_algorithm_ = KmDigestToEvpDigest(digest_);
235*789431f2SAndroid Build Coastguard Worker     if (digest_algorithm_ == nullptr) {
236*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_UNSUPPORTED_DIGEST;
237*789431f2SAndroid Build Coastguard Worker     }
238*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
239*789431f2SAndroid Build Coastguard Worker }
240*789431f2SAndroid Build Coastguard Worker 
RsaDigestingOperation(AuthorizationSet && hw_enforced,AuthorizationSet && sw_enforced,keymaster_purpose_t purpose,keymaster_digest_t digest,keymaster_padding_t padding,EVP_PKEY * key)241*789431f2SAndroid Build Coastguard Worker RsaDigestingOperation::RsaDigestingOperation(AuthorizationSet&& hw_enforced,
242*789431f2SAndroid Build Coastguard Worker                                              AuthorizationSet&& sw_enforced,
243*789431f2SAndroid Build Coastguard Worker                                              keymaster_purpose_t purpose, keymaster_digest_t digest,
244*789431f2SAndroid Build Coastguard Worker                                              keymaster_padding_t padding, EVP_PKEY* key)
245*789431f2SAndroid Build Coastguard Worker     : RsaOperation(std::move(hw_enforced), std::move(sw_enforced), purpose, digest, padding, key) {
246*789431f2SAndroid Build Coastguard Worker     EVP_MD_CTX_init(&digest_ctx_);
247*789431f2SAndroid Build Coastguard Worker }
~RsaDigestingOperation()248*789431f2SAndroid Build Coastguard Worker RsaDigestingOperation::~RsaDigestingOperation() {
249*789431f2SAndroid Build Coastguard Worker     EVP_MD_CTX_cleanup(&digest_ctx_);
250*789431f2SAndroid Build Coastguard Worker }
251*789431f2SAndroid Build Coastguard Worker 
GetOpensslPadding(keymaster_error_t * error)252*789431f2SAndroid Build Coastguard Worker int RsaDigestingOperation::GetOpensslPadding(keymaster_error_t* error) {
253*789431f2SAndroid Build Coastguard Worker     *error = KM_ERROR_OK;
254*789431f2SAndroid Build Coastguard Worker     switch (padding_) {
255*789431f2SAndroid Build Coastguard Worker     case KM_PAD_NONE:
256*789431f2SAndroid Build Coastguard Worker         return RSA_NO_PADDING;
257*789431f2SAndroid Build Coastguard Worker     case KM_PAD_RSA_PKCS1_1_5_SIGN:
258*789431f2SAndroid Build Coastguard Worker         return RSA_PKCS1_PADDING;
259*789431f2SAndroid Build Coastguard Worker     case KM_PAD_RSA_PSS:
260*789431f2SAndroid Build Coastguard Worker         if (digest_ == KM_DIGEST_NONE) {
261*789431f2SAndroid Build Coastguard Worker             *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
262*789431f2SAndroid Build Coastguard Worker             return -1;
263*789431f2SAndroid Build Coastguard Worker         }
264*789431f2SAndroid Build Coastguard Worker         if (EVP_MD_size(digest_algorithm_) * 2 + kPssOverhead > (size_t)EVP_PKEY_size(rsa_key_)) {
265*789431f2SAndroid Build Coastguard Worker             LOG_E("Input too long: %zu-byte digest cannot be used with %d-byte RSA key in PSS "
266*789431f2SAndroid Build Coastguard Worker                   "padding mode",
267*789431f2SAndroid Build Coastguard Worker                   EVP_MD_size(digest_algorithm_), EVP_PKEY_size(rsa_key_));
268*789431f2SAndroid Build Coastguard Worker             *error = KM_ERROR_INCOMPATIBLE_DIGEST;
269*789431f2SAndroid Build Coastguard Worker             return -1;
270*789431f2SAndroid Build Coastguard Worker         }
271*789431f2SAndroid Build Coastguard Worker         return RSA_PKCS1_PSS_PADDING;
272*789431f2SAndroid Build Coastguard Worker     default:
273*789431f2SAndroid Build Coastguard Worker         return -1;
274*789431f2SAndroid Build Coastguard Worker     }
275*789431f2SAndroid Build Coastguard Worker }
276*789431f2SAndroid Build Coastguard Worker 
Begin(const AuthorizationSet & input_params,AuthorizationSet * output_params)277*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaSignOperation::Begin(const AuthorizationSet& input_params,
278*789431f2SAndroid Build Coastguard Worker                                           AuthorizationSet* output_params) {
279*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error = RsaDigestingOperation::Begin(input_params, output_params);
280*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
281*789431f2SAndroid Build Coastguard Worker 
282*789431f2SAndroid Build Coastguard Worker     if (digest_ == KM_DIGEST_NONE) return KM_ERROR_OK;
283*789431f2SAndroid Build Coastguard Worker 
284*789431f2SAndroid Build Coastguard Worker     EVP_PKEY_CTX* pkey_ctx;
285*789431f2SAndroid Build Coastguard Worker     if (EVP_DigestSignInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr /* engine */,
286*789431f2SAndroid Build Coastguard Worker                            rsa_key_) != 1)
287*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
288*789431f2SAndroid Build Coastguard Worker     return SetRsaPaddingInEvpContext(pkey_ctx, true /* signing */);
289*789431f2SAndroid Build Coastguard Worker }
290*789431f2SAndroid Build Coastguard Worker 
Update(const AuthorizationSet & additional_params,const Buffer & input,AuthorizationSet * output_params,Buffer * output,size_t * input_consumed)291*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaSignOperation::Update(const AuthorizationSet& additional_params,
292*789431f2SAndroid Build Coastguard Worker                                            const Buffer& input, AuthorizationSet* output_params,
293*789431f2SAndroid Build Coastguard Worker                                            Buffer* output, size_t* input_consumed) {
294*789431f2SAndroid Build Coastguard Worker     if (digest_ == KM_DIGEST_NONE)
295*789431f2SAndroid Build Coastguard Worker         // Just buffer the data.
296*789431f2SAndroid Build Coastguard Worker         return RsaOperation::Update(additional_params, input, output_params, output,
297*789431f2SAndroid Build Coastguard Worker                                     input_consumed);
298*789431f2SAndroid Build Coastguard Worker 
299*789431f2SAndroid Build Coastguard Worker     if (EVP_DigestSignUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
300*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
301*789431f2SAndroid Build Coastguard Worker     *input_consumed = input.available_read();
302*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
303*789431f2SAndroid Build Coastguard Worker }
304*789431f2SAndroid Build Coastguard Worker 
Finish(const AuthorizationSet & additional_params,const Buffer & input,const Buffer &,AuthorizationSet *,Buffer * output)305*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaSignOperation::Finish(const AuthorizationSet& additional_params,
306*789431f2SAndroid Build Coastguard Worker                                            const Buffer& input, const Buffer& /* signature */,
307*789431f2SAndroid Build Coastguard Worker                                            AuthorizationSet* /* output_params */, Buffer* output) {
308*789431f2SAndroid Build Coastguard Worker     assert(output);
309*789431f2SAndroid Build Coastguard Worker 
310*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error = UpdateForFinish(additional_params, input);
311*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
312*789431f2SAndroid Build Coastguard Worker 
313*789431f2SAndroid Build Coastguard Worker     if (digest_ == KM_DIGEST_NONE)
314*789431f2SAndroid Build Coastguard Worker         return SignUndigested(output);
315*789431f2SAndroid Build Coastguard Worker     else
316*789431f2SAndroid Build Coastguard Worker         return SignDigested(output);
317*789431f2SAndroid Build Coastguard Worker }
318*789431f2SAndroid Build Coastguard Worker 
zero_pad_left(UniquePtr<uint8_t[]> * dest,size_t padded_len,Buffer & src)319*789431f2SAndroid Build Coastguard Worker static keymaster_error_t zero_pad_left(UniquePtr<uint8_t[]>* dest, size_t padded_len, Buffer& src) {
320*789431f2SAndroid Build Coastguard Worker     assert(padded_len > src.available_read());
321*789431f2SAndroid Build Coastguard Worker 
322*789431f2SAndroid Build Coastguard Worker     dest->reset(new (std::nothrow) uint8_t[padded_len]);
323*789431f2SAndroid Build Coastguard Worker     if (!dest->get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
324*789431f2SAndroid Build Coastguard Worker 
325*789431f2SAndroid Build Coastguard Worker     size_t padding_len = padded_len - src.available_read();
326*789431f2SAndroid Build Coastguard Worker     memset(dest->get(), 0, padding_len);
327*789431f2SAndroid Build Coastguard Worker     if (!src.read(dest->get() + padding_len, src.available_read())) return KM_ERROR_UNKNOWN_ERROR;
328*789431f2SAndroid Build Coastguard Worker 
329*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
330*789431f2SAndroid Build Coastguard Worker }
331*789431f2SAndroid Build Coastguard Worker 
SignUndigested(Buffer * output)332*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaSignOperation::SignUndigested(Buffer* output) {
333*789431f2SAndroid Build Coastguard Worker     UniquePtr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(rsa_key_)));
334*789431f2SAndroid Build Coastguard Worker     if (!rsa.get()) return TranslateLastOpenSslError();
335*789431f2SAndroid Build Coastguard Worker 
336*789431f2SAndroid Build Coastguard Worker     if (!output->Reinitialize(RSA_size(rsa.get()))) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
337*789431f2SAndroid Build Coastguard Worker 
338*789431f2SAndroid Build Coastguard Worker     size_t key_len = EVP_PKEY_size(rsa_key_);
339*789431f2SAndroid Build Coastguard Worker     int bytes_encrypted;
340*789431f2SAndroid Build Coastguard Worker     switch (padding_) {
341*789431f2SAndroid Build Coastguard Worker     case KM_PAD_NONE: {
342*789431f2SAndroid Build Coastguard Worker         const uint8_t* to_encrypt = data_.peek_read();
343*789431f2SAndroid Build Coastguard Worker         UniquePtr<uint8_t[]> zero_padded;
344*789431f2SAndroid Build Coastguard Worker         if (data_.available_read() > key_len) {
345*789431f2SAndroid Build Coastguard Worker             return KM_ERROR_INVALID_INPUT_LENGTH;
346*789431f2SAndroid Build Coastguard Worker         } else if (data_.available_read() < key_len) {
347*789431f2SAndroid Build Coastguard Worker             keymaster_error_t error = zero_pad_left(&zero_padded, key_len, data_);
348*789431f2SAndroid Build Coastguard Worker             if (error != KM_ERROR_OK) return error;
349*789431f2SAndroid Build Coastguard Worker             to_encrypt = zero_padded.get();
350*789431f2SAndroid Build Coastguard Worker         }
351*789431f2SAndroid Build Coastguard Worker         bytes_encrypted = RSA_private_encrypt(key_len, to_encrypt, output->peek_write(), rsa.get(),
352*789431f2SAndroid Build Coastguard Worker                                               RSA_NO_PADDING);
353*789431f2SAndroid Build Coastguard Worker         break;
354*789431f2SAndroid Build Coastguard Worker     }
355*789431f2SAndroid Build Coastguard Worker     case KM_PAD_RSA_PKCS1_1_5_SIGN:
356*789431f2SAndroid Build Coastguard Worker         // Does PKCS1 padding without digesting even make sense?  Dunno.  We'll support it.
357*789431f2SAndroid Build Coastguard Worker         if (data_.available_read() + kPkcs1UndigestedSignaturePaddingOverhead > key_len) {
358*789431f2SAndroid Build Coastguard Worker             LOG_E("Input too long: cannot sign %zu-byte message with PKCS1 padding with %u-bit key",
359*789431f2SAndroid Build Coastguard Worker                   data_.available_read(), EVP_PKEY_size(rsa_key_) * 8);
360*789431f2SAndroid Build Coastguard Worker             return KM_ERROR_INVALID_INPUT_LENGTH;
361*789431f2SAndroid Build Coastguard Worker         }
362*789431f2SAndroid Build Coastguard Worker         bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
363*789431f2SAndroid Build Coastguard Worker                                               output->peek_write(), rsa.get(), RSA_PKCS1_PADDING);
364*789431f2SAndroid Build Coastguard Worker         break;
365*789431f2SAndroid Build Coastguard Worker 
366*789431f2SAndroid Build Coastguard Worker     default:
367*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_UNSUPPORTED_PADDING_MODE;
368*789431f2SAndroid Build Coastguard Worker     }
369*789431f2SAndroid Build Coastguard Worker 
370*789431f2SAndroid Build Coastguard Worker     if (bytes_encrypted <= 0) return TranslateLastOpenSslError();
371*789431f2SAndroid Build Coastguard Worker     if (!output->advance_write(bytes_encrypted)) return KM_ERROR_UNKNOWN_ERROR;
372*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
373*789431f2SAndroid Build Coastguard Worker }
374*789431f2SAndroid Build Coastguard Worker 
SignDigested(Buffer * output)375*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaSignOperation::SignDigested(Buffer* output) {
376*789431f2SAndroid Build Coastguard Worker     size_t siglen;
377*789431f2SAndroid Build Coastguard Worker     if (EVP_DigestSignFinal(&digest_ctx_, nullptr /* signature */, &siglen) != 1)
378*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
379*789431f2SAndroid Build Coastguard Worker 
380*789431f2SAndroid Build Coastguard Worker     if (!output->Reinitialize(siglen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
381*789431f2SAndroid Build Coastguard Worker 
382*789431f2SAndroid Build Coastguard Worker     if (EVP_DigestSignFinal(&digest_ctx_, output->peek_write(), &siglen) <= 0)
383*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
384*789431f2SAndroid Build Coastguard Worker     if (!output->advance_write(siglen)) return KM_ERROR_UNKNOWN_ERROR;
385*789431f2SAndroid Build Coastguard Worker 
386*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
387*789431f2SAndroid Build Coastguard Worker }
388*789431f2SAndroid Build Coastguard Worker 
Begin(const AuthorizationSet & input_params,AuthorizationSet * output_params)389*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaVerifyOperation::Begin(const AuthorizationSet& input_params,
390*789431f2SAndroid Build Coastguard Worker                                             AuthorizationSet* output_params) {
391*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error = RsaDigestingOperation::Begin(input_params, output_params);
392*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
393*789431f2SAndroid Build Coastguard Worker 
394*789431f2SAndroid Build Coastguard Worker     if (digest_ == KM_DIGEST_NONE) return KM_ERROR_OK;
395*789431f2SAndroid Build Coastguard Worker 
396*789431f2SAndroid Build Coastguard Worker     EVP_PKEY_CTX* pkey_ctx;
397*789431f2SAndroid Build Coastguard Worker     if (EVP_DigestVerifyInit(&digest_ctx_, &pkey_ctx, digest_algorithm_, nullptr, rsa_key_) != 1)
398*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
399*789431f2SAndroid Build Coastguard Worker     return SetRsaPaddingInEvpContext(pkey_ctx, false /* signing */);
400*789431f2SAndroid Build Coastguard Worker }
401*789431f2SAndroid Build Coastguard Worker 
Update(const AuthorizationSet & additional_params,const Buffer & input,AuthorizationSet * output_params,Buffer * output,size_t * input_consumed)402*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaVerifyOperation::Update(const AuthorizationSet& additional_params,
403*789431f2SAndroid Build Coastguard Worker                                              const Buffer& input, AuthorizationSet* output_params,
404*789431f2SAndroid Build Coastguard Worker                                              Buffer* output, size_t* input_consumed) {
405*789431f2SAndroid Build Coastguard Worker     if (digest_ == KM_DIGEST_NONE)
406*789431f2SAndroid Build Coastguard Worker         // Just buffer the data.
407*789431f2SAndroid Build Coastguard Worker         return RsaOperation::Update(additional_params, input, output_params, output,
408*789431f2SAndroid Build Coastguard Worker                                     input_consumed);
409*789431f2SAndroid Build Coastguard Worker 
410*789431f2SAndroid Build Coastguard Worker     if (EVP_DigestVerifyUpdate(&digest_ctx_, input.peek_read(), input.available_read()) != 1)
411*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
412*789431f2SAndroid Build Coastguard Worker     *input_consumed = input.available_read();
413*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
414*789431f2SAndroid Build Coastguard Worker }
415*789431f2SAndroid Build Coastguard Worker 
Finish(const AuthorizationSet & additional_params,const Buffer & input,const Buffer & signature,AuthorizationSet *,Buffer *)416*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaVerifyOperation::Finish(const AuthorizationSet& additional_params,
417*789431f2SAndroid Build Coastguard Worker                                              const Buffer& input, const Buffer& signature,
418*789431f2SAndroid Build Coastguard Worker                                              AuthorizationSet* /* output_params */,
419*789431f2SAndroid Build Coastguard Worker                                              Buffer* /* output */) {
420*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error = UpdateForFinish(additional_params, input);
421*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
422*789431f2SAndroid Build Coastguard Worker 
423*789431f2SAndroid Build Coastguard Worker     if (digest_ == KM_DIGEST_NONE)
424*789431f2SAndroid Build Coastguard Worker         return VerifyUndigested(signature);
425*789431f2SAndroid Build Coastguard Worker     else
426*789431f2SAndroid Build Coastguard Worker         return VerifyDigested(signature);
427*789431f2SAndroid Build Coastguard Worker }
428*789431f2SAndroid Build Coastguard Worker 
VerifyUndigested(const Buffer & signature)429*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaVerifyOperation::VerifyUndigested(const Buffer& signature) {
430*789431f2SAndroid Build Coastguard Worker     UniquePtr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(rsa_key_)));
431*789431f2SAndroid Build Coastguard Worker     if (!rsa.get()) return KM_ERROR_UNKNOWN_ERROR;
432*789431f2SAndroid Build Coastguard Worker 
433*789431f2SAndroid Build Coastguard Worker     size_t key_len = RSA_size(rsa.get());
434*789431f2SAndroid Build Coastguard Worker     int openssl_padding;
435*789431f2SAndroid Build Coastguard Worker     switch (padding_) {
436*789431f2SAndroid Build Coastguard Worker     case KM_PAD_NONE:
437*789431f2SAndroid Build Coastguard Worker         if (data_.available_read() > key_len) return KM_ERROR_INVALID_INPUT_LENGTH;
438*789431f2SAndroid Build Coastguard Worker         if (key_len != signature.available_read()) return KM_ERROR_VERIFICATION_FAILED;
439*789431f2SAndroid Build Coastguard Worker         openssl_padding = RSA_NO_PADDING;
440*789431f2SAndroid Build Coastguard Worker         break;
441*789431f2SAndroid Build Coastguard Worker     case KM_PAD_RSA_PKCS1_1_5_SIGN:
442*789431f2SAndroid Build Coastguard Worker         if (data_.available_read() + kPkcs1UndigestedSignaturePaddingOverhead > key_len) {
443*789431f2SAndroid Build Coastguard Worker             LOG_E("Input too long: cannot verify %zu-byte message with PKCS1 padding + %zu-bit key",
444*789431f2SAndroid Build Coastguard Worker                   data_.available_read(), key_len * 8);
445*789431f2SAndroid Build Coastguard Worker             return KM_ERROR_INVALID_INPUT_LENGTH;
446*789431f2SAndroid Build Coastguard Worker         }
447*789431f2SAndroid Build Coastguard Worker         openssl_padding = RSA_PKCS1_PADDING;
448*789431f2SAndroid Build Coastguard Worker         break;
449*789431f2SAndroid Build Coastguard Worker     default:
450*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_UNSUPPORTED_PADDING_MODE;
451*789431f2SAndroid Build Coastguard Worker     }
452*789431f2SAndroid Build Coastguard Worker 
453*789431f2SAndroid Build Coastguard Worker     UniquePtr<uint8_t[]> decrypted_data(new (std::nothrow) uint8_t[key_len]);
454*789431f2SAndroid Build Coastguard Worker     if (!decrypted_data.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
455*789431f2SAndroid Build Coastguard Worker     int bytes_decrypted = RSA_public_decrypt(signature.available_read(), signature.peek_read(),
456*789431f2SAndroid Build Coastguard Worker                                              decrypted_data.get(), rsa.get(), openssl_padding);
457*789431f2SAndroid Build Coastguard Worker     if (bytes_decrypted < 0) return KM_ERROR_VERIFICATION_FAILED;
458*789431f2SAndroid Build Coastguard Worker 
459*789431f2SAndroid Build Coastguard Worker     const uint8_t* compare_pos = decrypted_data.get();
460*789431f2SAndroid Build Coastguard Worker     size_t bytes_to_compare = bytes_decrypted;
461*789431f2SAndroid Build Coastguard Worker     uint8_t zero_check_result = 0;
462*789431f2SAndroid Build Coastguard Worker     if (padding_ == KM_PAD_NONE && data_.available_read() < bytes_to_compare) {
463*789431f2SAndroid Build Coastguard Worker         // If the data is short, for "unpadded" signing we zero-pad to the left.  So during
464*789431f2SAndroid Build Coastguard Worker         // verification we should have zeros on the left of the decrypted data.  Do a constant-time
465*789431f2SAndroid Build Coastguard Worker         // check.
466*789431f2SAndroid Build Coastguard Worker         const uint8_t* zero_end = compare_pos + bytes_to_compare - data_.available_read();
467*789431f2SAndroid Build Coastguard Worker         while (compare_pos < zero_end)
468*789431f2SAndroid Build Coastguard Worker             zero_check_result |= *compare_pos++;
469*789431f2SAndroid Build Coastguard Worker         bytes_to_compare = data_.available_read();
470*789431f2SAndroid Build Coastguard Worker     }
471*789431f2SAndroid Build Coastguard Worker     if (memcmp_s(compare_pos, data_.peek_read(), bytes_to_compare) != 0 || zero_check_result != 0)
472*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_VERIFICATION_FAILED;
473*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
474*789431f2SAndroid Build Coastguard Worker }
475*789431f2SAndroid Build Coastguard Worker 
VerifyDigested(const Buffer & signature)476*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaVerifyOperation::VerifyDigested(const Buffer& signature) {
477*789431f2SAndroid Build Coastguard Worker     if (!EVP_DigestVerifyFinal(&digest_ctx_, signature.peek_read(), signature.available_read()))
478*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_VERIFICATION_FAILED;
479*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
480*789431f2SAndroid Build Coastguard Worker }
481*789431f2SAndroid Build Coastguard Worker 
SetOaepDigestIfRequired(EVP_PKEY_CTX * pkey_ctx)482*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaCryptOperation::SetOaepDigestIfRequired(EVP_PKEY_CTX* pkey_ctx) {
483*789431f2SAndroid Build Coastguard Worker     if (padding() != KM_PAD_RSA_OAEP) return KM_ERROR_OK;
484*789431f2SAndroid Build Coastguard Worker 
485*789431f2SAndroid Build Coastguard Worker     assert(digest_algorithm_ != nullptr);
486*789431f2SAndroid Build Coastguard Worker     if (!EVP_PKEY_CTX_set_rsa_oaep_md(pkey_ctx, digest_algorithm_)) {
487*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
488*789431f2SAndroid Build Coastguard Worker     }
489*789431f2SAndroid Build Coastguard Worker     assert(mgf_digest_algorithm_ != nullptr);
490*789431f2SAndroid Build Coastguard Worker     // MGF1 MD is always SHA1.
491*789431f2SAndroid Build Coastguard Worker     if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf_digest_algorithm_)) {
492*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
493*789431f2SAndroid Build Coastguard Worker     }
494*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
495*789431f2SAndroid Build Coastguard Worker }
496*789431f2SAndroid Build Coastguard Worker 
Begin(const AuthorizationSet & input_params,AuthorizationSet * output_params)497*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaCryptOperation::Begin(const AuthorizationSet& input_params,
498*789431f2SAndroid Build Coastguard Worker                                            AuthorizationSet* output_params) {
499*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error = RsaOperation::Begin(input_params, output_params);
500*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
501*789431f2SAndroid Build Coastguard Worker     return InitMgfDigest();
502*789431f2SAndroid Build Coastguard Worker }
503*789431f2SAndroid Build Coastguard Worker 
GetOpensslPadding(keymaster_error_t * error)504*789431f2SAndroid Build Coastguard Worker int RsaCryptOperation::GetOpensslPadding(keymaster_error_t* error) {
505*789431f2SAndroid Build Coastguard Worker     *error = KM_ERROR_OK;
506*789431f2SAndroid Build Coastguard Worker     switch (padding_) {
507*789431f2SAndroid Build Coastguard Worker     case KM_PAD_NONE:
508*789431f2SAndroid Build Coastguard Worker         return RSA_NO_PADDING;
509*789431f2SAndroid Build Coastguard Worker     case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
510*789431f2SAndroid Build Coastguard Worker         return RSA_PKCS1_PADDING;
511*789431f2SAndroid Build Coastguard Worker     case KM_PAD_RSA_OAEP:
512*789431f2SAndroid Build Coastguard Worker         return RSA_PKCS1_OAEP_PADDING;
513*789431f2SAndroid Build Coastguard Worker     default:
514*789431f2SAndroid Build Coastguard Worker         return -1;
515*789431f2SAndroid Build Coastguard Worker     }
516*789431f2SAndroid Build Coastguard Worker }
517*789431f2SAndroid Build Coastguard Worker 
InitMgfDigest()518*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaCryptOperation::InitMgfDigest() {
519*789431f2SAndroid Build Coastguard Worker     if (mgf_digest_ == KM_DIGEST_NONE) {
520*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_OK;
521*789431f2SAndroid Build Coastguard Worker     }
522*789431f2SAndroid Build Coastguard Worker     mgf_digest_algorithm_ = KmDigestToEvpDigest(mgf_digest_);
523*789431f2SAndroid Build Coastguard Worker     if (mgf_digest_algorithm_ == nullptr) {
524*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_UNSUPPORTED_DIGEST;
525*789431f2SAndroid Build Coastguard Worker     }
526*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
527*789431f2SAndroid Build Coastguard Worker }
528*789431f2SAndroid Build Coastguard Worker 
Finish(const AuthorizationSet & additional_params,const Buffer & input,const Buffer &,AuthorizationSet *,Buffer * output)529*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaEncryptOperation::Finish(const AuthorizationSet& additional_params,
530*789431f2SAndroid Build Coastguard Worker                                               const Buffer& input, const Buffer& /* signature */,
531*789431f2SAndroid Build Coastguard Worker                                               AuthorizationSet* /* output_params */,
532*789431f2SAndroid Build Coastguard Worker                                               Buffer* output) {
533*789431f2SAndroid Build Coastguard Worker     if (!output) return KM_ERROR_OUTPUT_PARAMETER_NULL;
534*789431f2SAndroid Build Coastguard Worker 
535*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error = UpdateForFinish(additional_params, input);
536*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
537*789431f2SAndroid Build Coastguard Worker 
538*789431f2SAndroid Build Coastguard Worker     EVP_PKEY_CTX_Ptr ctx(EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
539*789431f2SAndroid Build Coastguard Worker     if (!ctx.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
540*789431f2SAndroid Build Coastguard Worker 
541*789431f2SAndroid Build Coastguard Worker     if (EVP_PKEY_encrypt_init(ctx.get()) <= 0) return TranslateLastOpenSslError();
542*789431f2SAndroid Build Coastguard Worker 
543*789431f2SAndroid Build Coastguard Worker     error = SetRsaPaddingInEvpContext(ctx.get(), false /* signing */);
544*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
545*789431f2SAndroid Build Coastguard Worker     error = SetOaepDigestIfRequired(ctx.get());
546*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
547*789431f2SAndroid Build Coastguard Worker 
548*789431f2SAndroid Build Coastguard Worker     size_t outlen;
549*789431f2SAndroid Build Coastguard Worker     if (EVP_PKEY_encrypt(ctx.get(), nullptr /* out */, &outlen, data_.peek_read(),
550*789431f2SAndroid Build Coastguard Worker                          data_.available_read()) <= 0)
551*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
552*789431f2SAndroid Build Coastguard Worker 
553*789431f2SAndroid Build Coastguard Worker     if (!output->Reinitialize(outlen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
554*789431f2SAndroid Build Coastguard Worker 
555*789431f2SAndroid Build Coastguard Worker     const uint8_t* to_encrypt = data_.peek_read();
556*789431f2SAndroid Build Coastguard Worker     size_t to_encrypt_len = data_.available_read();
557*789431f2SAndroid Build Coastguard Worker     UniquePtr<uint8_t[]> zero_padded;
558*789431f2SAndroid Build Coastguard Worker     if (padding_ == KM_PAD_NONE && to_encrypt_len < outlen) {
559*789431f2SAndroid Build Coastguard Worker         keymaster_error_t error = zero_pad_left(&zero_padded, outlen, data_);
560*789431f2SAndroid Build Coastguard Worker         if (error != KM_ERROR_OK) return error;
561*789431f2SAndroid Build Coastguard Worker         to_encrypt = zero_padded.get();
562*789431f2SAndroid Build Coastguard Worker         to_encrypt_len = outlen;
563*789431f2SAndroid Build Coastguard Worker     }
564*789431f2SAndroid Build Coastguard Worker 
565*789431f2SAndroid Build Coastguard Worker     if (EVP_PKEY_encrypt(ctx.get(), output->peek_write(), &outlen, to_encrypt, to_encrypt_len) <= 0)
566*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
567*789431f2SAndroid Build Coastguard Worker     if (!output->advance_write(outlen)) return KM_ERROR_UNKNOWN_ERROR;
568*789431f2SAndroid Build Coastguard Worker 
569*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
570*789431f2SAndroid Build Coastguard Worker }
571*789431f2SAndroid Build Coastguard Worker 
Finish(const AuthorizationSet & additional_params,const Buffer & input,const Buffer &,AuthorizationSet *,Buffer * output)572*789431f2SAndroid Build Coastguard Worker keymaster_error_t RsaDecryptOperation::Finish(const AuthorizationSet& additional_params,
573*789431f2SAndroid Build Coastguard Worker                                               const Buffer& input, const Buffer& /* signature */,
574*789431f2SAndroid Build Coastguard Worker                                               AuthorizationSet* /* output_params */,
575*789431f2SAndroid Build Coastguard Worker                                               Buffer* output) {
576*789431f2SAndroid Build Coastguard Worker     if (!output) return KM_ERROR_OUTPUT_PARAMETER_NULL;
577*789431f2SAndroid Build Coastguard Worker 
578*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error = UpdateForFinish(additional_params, input);
579*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
580*789431f2SAndroid Build Coastguard Worker 
581*789431f2SAndroid Build Coastguard Worker     EVP_PKEY_CTX_Ptr ctx(EVP_PKEY_CTX_new(rsa_key_, nullptr /* engine */));
582*789431f2SAndroid Build Coastguard Worker     if (!ctx.get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
583*789431f2SAndroid Build Coastguard Worker 
584*789431f2SAndroid Build Coastguard Worker     if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) return TranslateLastOpenSslError();
585*789431f2SAndroid Build Coastguard Worker 
586*789431f2SAndroid Build Coastguard Worker     error = SetRsaPaddingInEvpContext(ctx.get(), false /* signing */);
587*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
588*789431f2SAndroid Build Coastguard Worker     error = SetOaepDigestIfRequired(ctx.get());
589*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
590*789431f2SAndroid Build Coastguard Worker 
591*789431f2SAndroid Build Coastguard Worker     size_t outlen;
592*789431f2SAndroid Build Coastguard Worker     if (EVP_PKEY_decrypt(ctx.get(), nullptr /* out */, &outlen, data_.peek_read(),
593*789431f2SAndroid Build Coastguard Worker                          data_.available_read()) <= 0)
594*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
595*789431f2SAndroid Build Coastguard Worker 
596*789431f2SAndroid Build Coastguard Worker     if (!output->Reinitialize(outlen)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
597*789431f2SAndroid Build Coastguard Worker 
598*789431f2SAndroid Build Coastguard Worker     const uint8_t* to_decrypt = data_.peek_read();
599*789431f2SAndroid Build Coastguard Worker     size_t to_decrypt_len = data_.available_read();
600*789431f2SAndroid Build Coastguard Worker     UniquePtr<uint8_t[]> zero_padded;
601*789431f2SAndroid Build Coastguard Worker     if (padding_ == KM_PAD_NONE && to_decrypt_len < outlen) {
602*789431f2SAndroid Build Coastguard Worker         keymaster_error_t error = zero_pad_left(&zero_padded, outlen, data_);
603*789431f2SAndroid Build Coastguard Worker         if (error != KM_ERROR_OK) return error;
604*789431f2SAndroid Build Coastguard Worker         to_decrypt = zero_padded.get();
605*789431f2SAndroid Build Coastguard Worker         to_decrypt_len = outlen;
606*789431f2SAndroid Build Coastguard Worker     }
607*789431f2SAndroid Build Coastguard Worker 
608*789431f2SAndroid Build Coastguard Worker     if (EVP_PKEY_decrypt(ctx.get(), output->peek_write(), &outlen, to_decrypt, to_decrypt_len) <= 0)
609*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
610*789431f2SAndroid Build Coastguard Worker     if (!output->advance_write(outlen)) return KM_ERROR_UNKNOWN_ERROR;
611*789431f2SAndroid Build Coastguard Worker 
612*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
613*789431f2SAndroid Build Coastguard Worker }
614*789431f2SAndroid Build Coastguard Worker 
615*789431f2SAndroid Build Coastguard Worker }  // namespace keymaster
616