xref: /aosp_15_r20/external/boringssl/src/ssl/ssl_privkey.cc (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
1*8fb009dcSAndroid Build Coastguard Worker /* Copyright (C) 1995-1998 Eric Young ([email protected])
2*8fb009dcSAndroid Build Coastguard Worker  * All rights reserved.
3*8fb009dcSAndroid Build Coastguard Worker  *
4*8fb009dcSAndroid Build Coastguard Worker  * This package is an SSL implementation written
5*8fb009dcSAndroid Build Coastguard Worker  * by Eric Young ([email protected]).
6*8fb009dcSAndroid Build Coastguard Worker  * The implementation was written so as to conform with Netscapes SSL.
7*8fb009dcSAndroid Build Coastguard Worker  *
8*8fb009dcSAndroid Build Coastguard Worker  * This library is free for commercial and non-commercial use as long as
9*8fb009dcSAndroid Build Coastguard Worker  * the following conditions are aheared to.  The following conditions
10*8fb009dcSAndroid Build Coastguard Worker  * apply to all code found in this distribution, be it the RC4, RSA,
11*8fb009dcSAndroid Build Coastguard Worker  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12*8fb009dcSAndroid Build Coastguard Worker  * included with this distribution is covered by the same copyright terms
13*8fb009dcSAndroid Build Coastguard Worker  * except that the holder is Tim Hudson ([email protected]).
14*8fb009dcSAndroid Build Coastguard Worker  *
15*8fb009dcSAndroid Build Coastguard Worker  * Copyright remains Eric Young's, and as such any Copyright notices in
16*8fb009dcSAndroid Build Coastguard Worker  * the code are not to be removed.
17*8fb009dcSAndroid Build Coastguard Worker  * If this package is used in a product, Eric Young should be given attribution
18*8fb009dcSAndroid Build Coastguard Worker  * as the author of the parts of the library used.
19*8fb009dcSAndroid Build Coastguard Worker  * This can be in the form of a textual message at program startup or
20*8fb009dcSAndroid Build Coastguard Worker  * in documentation (online or textual) provided with the package.
21*8fb009dcSAndroid Build Coastguard Worker  *
22*8fb009dcSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
23*8fb009dcSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
24*8fb009dcSAndroid Build Coastguard Worker  * are met:
25*8fb009dcSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the copyright
26*8fb009dcSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
27*8fb009dcSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
28*8fb009dcSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
29*8fb009dcSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
30*8fb009dcSAndroid Build Coastguard Worker  * 3. All advertising materials mentioning features or use of this software
31*8fb009dcSAndroid Build Coastguard Worker  *    must display the following acknowledgement:
32*8fb009dcSAndroid Build Coastguard Worker  *    "This product includes cryptographic software written by
33*8fb009dcSAndroid Build Coastguard Worker  *     Eric Young ([email protected])"
34*8fb009dcSAndroid Build Coastguard Worker  *    The word 'cryptographic' can be left out if the rouines from the library
35*8fb009dcSAndroid Build Coastguard Worker  *    being used are not cryptographic related :-).
36*8fb009dcSAndroid Build Coastguard Worker  * 4. If you include any Windows specific code (or a derivative thereof) from
37*8fb009dcSAndroid Build Coastguard Worker  *    the apps directory (application code) you must include an acknowledgement:
38*8fb009dcSAndroid Build Coastguard Worker  *    "This product includes software written by Tim Hudson ([email protected])"
39*8fb009dcSAndroid Build Coastguard Worker  *
40*8fb009dcSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41*8fb009dcSAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42*8fb009dcSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43*8fb009dcSAndroid Build Coastguard Worker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44*8fb009dcSAndroid Build Coastguard Worker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45*8fb009dcSAndroid Build Coastguard Worker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46*8fb009dcSAndroid Build Coastguard Worker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47*8fb009dcSAndroid Build Coastguard Worker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48*8fb009dcSAndroid Build Coastguard Worker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49*8fb009dcSAndroid Build Coastguard Worker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50*8fb009dcSAndroid Build Coastguard Worker  * SUCH DAMAGE.
51*8fb009dcSAndroid Build Coastguard Worker  *
52*8fb009dcSAndroid Build Coastguard Worker  * The licence and distribution terms for any publically available version or
53*8fb009dcSAndroid Build Coastguard Worker  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54*8fb009dcSAndroid Build Coastguard Worker  * copied and put under another distribution licence
55*8fb009dcSAndroid Build Coastguard Worker  * [including the GNU Public Licence.] */
56*8fb009dcSAndroid Build Coastguard Worker 
57*8fb009dcSAndroid Build Coastguard Worker #include <openssl/ssl.h>
58*8fb009dcSAndroid Build Coastguard Worker 
59*8fb009dcSAndroid Build Coastguard Worker #include <assert.h>
60*8fb009dcSAndroid Build Coastguard Worker #include <limits.h>
61*8fb009dcSAndroid Build Coastguard Worker 
62*8fb009dcSAndroid Build Coastguard Worker #include <algorithm>
63*8fb009dcSAndroid Build Coastguard Worker 
64*8fb009dcSAndroid Build Coastguard Worker #include <openssl/ec.h>
65*8fb009dcSAndroid Build Coastguard Worker #include <openssl/ec_key.h>
66*8fb009dcSAndroid Build Coastguard Worker #include <openssl/err.h>
67*8fb009dcSAndroid Build Coastguard Worker #include <openssl/evp.h>
68*8fb009dcSAndroid Build Coastguard Worker #include <openssl/mem.h>
69*8fb009dcSAndroid Build Coastguard Worker #include <openssl/span.h>
70*8fb009dcSAndroid Build Coastguard Worker 
71*8fb009dcSAndroid Build Coastguard Worker #include "internal.h"
72*8fb009dcSAndroid Build Coastguard Worker #include "../crypto/internal.h"
73*8fb009dcSAndroid Build Coastguard Worker 
74*8fb009dcSAndroid Build Coastguard Worker 
75*8fb009dcSAndroid Build Coastguard Worker BSSL_NAMESPACE_BEGIN
76*8fb009dcSAndroid Build Coastguard Worker 
ssl_is_key_type_supported(int key_type)77*8fb009dcSAndroid Build Coastguard Worker bool ssl_is_key_type_supported(int key_type) {
78*8fb009dcSAndroid Build Coastguard Worker   return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC ||
79*8fb009dcSAndroid Build Coastguard Worker          key_type == EVP_PKEY_ED25519;
80*8fb009dcSAndroid Build Coastguard Worker }
81*8fb009dcSAndroid Build Coastguard Worker 
82*8fb009dcSAndroid Build Coastguard Worker typedef struct {
83*8fb009dcSAndroid Build Coastguard Worker   uint16_t sigalg;
84*8fb009dcSAndroid Build Coastguard Worker   int pkey_type;
85*8fb009dcSAndroid Build Coastguard Worker   int curve;
86*8fb009dcSAndroid Build Coastguard Worker   const EVP_MD *(*digest_func)(void);
87*8fb009dcSAndroid Build Coastguard Worker   bool is_rsa_pss;
88*8fb009dcSAndroid Build Coastguard Worker   bool tls12_ok;
89*8fb009dcSAndroid Build Coastguard Worker   bool tls13_ok;
90*8fb009dcSAndroid Build Coastguard Worker   bool client_only;
91*8fb009dcSAndroid Build Coastguard Worker } SSL_SIGNATURE_ALGORITHM;
92*8fb009dcSAndroid Build Coastguard Worker 
93*8fb009dcSAndroid Build Coastguard Worker static const SSL_SIGNATURE_ALGORITHM kSignatureAlgorithms[] = {
94*8fb009dcSAndroid Build Coastguard Worker     // PKCS#1 v1.5 code points are only allowed in TLS 1.2.
95*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_MD5_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_md5_sha1,
96*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
97*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
98*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_sha1,
99*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
100*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
101*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256,
102*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
103*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
104*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384,
105*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
106*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
107*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512,
108*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
109*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
110*8fb009dcSAndroid Build Coastguard Worker 
111*8fb009dcSAndroid Build Coastguard Worker     // Legacy PKCS#1 v1.5 code points are only allowed in TLS 1.3 and
112*8fb009dcSAndroid Build Coastguard Worker     // client-only. See draft-ietf-tls-tls13-pkcs1-00.
113*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_SHA256_LEGACY, EVP_PKEY_RSA, NID_undef, &EVP_sha256,
114*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/false, /*tls12_ok=*/false, /*tls13_ok=*/true,
115*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/true},
116*8fb009dcSAndroid Build Coastguard Worker 
117*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PSS_RSAE_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256,
118*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true,
119*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
120*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PSS_RSAE_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384,
121*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true,
122*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
123*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PSS_RSAE_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512,
124*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true,
125*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
126*8fb009dcSAndroid Build Coastguard Worker 
127*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_ECDSA_SHA1, EVP_PKEY_EC, NID_undef, &EVP_sha1,
128*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
129*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
130*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_ECDSA_SECP256R1_SHA256, EVP_PKEY_EC, NID_X9_62_prime256v1,
131*8fb009dcSAndroid Build Coastguard Worker      &EVP_sha256, /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true,
132*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
133*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_ECDSA_SECP384R1_SHA384, EVP_PKEY_EC, NID_secp384r1, &EVP_sha384,
134*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true,
135*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
136*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_ECDSA_SECP521R1_SHA512, EVP_PKEY_EC, NID_secp521r1, &EVP_sha512,
137*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true,
138*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
139*8fb009dcSAndroid Build Coastguard Worker 
140*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_ED25519, EVP_PKEY_ED25519, NID_undef, nullptr,
141*8fb009dcSAndroid Build Coastguard Worker      /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true,
142*8fb009dcSAndroid Build Coastguard Worker      /*client_only=*/false},
143*8fb009dcSAndroid Build Coastguard Worker };
144*8fb009dcSAndroid Build Coastguard Worker 
get_signature_algorithm(uint16_t sigalg)145*8fb009dcSAndroid Build Coastguard Worker static const SSL_SIGNATURE_ALGORITHM *get_signature_algorithm(uint16_t sigalg) {
146*8fb009dcSAndroid Build Coastguard Worker   for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kSignatureAlgorithms); i++) {
147*8fb009dcSAndroid Build Coastguard Worker     if (kSignatureAlgorithms[i].sigalg == sigalg) {
148*8fb009dcSAndroid Build Coastguard Worker       return &kSignatureAlgorithms[i];
149*8fb009dcSAndroid Build Coastguard Worker     }
150*8fb009dcSAndroid Build Coastguard Worker   }
151*8fb009dcSAndroid Build Coastguard Worker   return NULL;
152*8fb009dcSAndroid Build Coastguard Worker }
153*8fb009dcSAndroid Build Coastguard Worker 
ssl_pkey_supports_algorithm(const SSL * ssl,EVP_PKEY * pkey,uint16_t sigalg,bool is_verify)154*8fb009dcSAndroid Build Coastguard Worker bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
155*8fb009dcSAndroid Build Coastguard Worker                                  uint16_t sigalg, bool is_verify) {
156*8fb009dcSAndroid Build Coastguard Worker   const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
157*8fb009dcSAndroid Build Coastguard Worker   if (alg == NULL || EVP_PKEY_id(pkey) != alg->pkey_type) {
158*8fb009dcSAndroid Build Coastguard Worker     return false;
159*8fb009dcSAndroid Build Coastguard Worker   }
160*8fb009dcSAndroid Build Coastguard Worker 
161*8fb009dcSAndroid Build Coastguard Worker   // Ensure the RSA key is large enough for the hash. RSASSA-PSS requires that
162*8fb009dcSAndroid Build Coastguard Worker   // emLen be at least hLen + sLen + 2. Both hLen and sLen are the size of the
163*8fb009dcSAndroid Build Coastguard Worker   // hash in TLS. Reasonable RSA key sizes are large enough for the largest
164*8fb009dcSAndroid Build Coastguard Worker   // defined RSASSA-PSS algorithm, but 1024-bit RSA is slightly too small for
165*8fb009dcSAndroid Build Coastguard Worker   // SHA-512. 1024-bit RSA is sometimes used for test credentials, so check the
166*8fb009dcSAndroid Build Coastguard Worker   // size so that we can fall back to another algorithm in that case.
167*8fb009dcSAndroid Build Coastguard Worker   if (alg->is_rsa_pss &&
168*8fb009dcSAndroid Build Coastguard Worker       (size_t)EVP_PKEY_size(pkey) < 2 * EVP_MD_size(alg->digest_func()) + 2) {
169*8fb009dcSAndroid Build Coastguard Worker     return false;
170*8fb009dcSAndroid Build Coastguard Worker   }
171*8fb009dcSAndroid Build Coastguard Worker 
172*8fb009dcSAndroid Build Coastguard Worker   if (ssl_protocol_version(ssl) < TLS1_2_VERSION) {
173*8fb009dcSAndroid Build Coastguard Worker     // TLS 1.0 and 1.1 do not negotiate algorithms and always sign one of two
174*8fb009dcSAndroid Build Coastguard Worker     // hardcoded algorithms.
175*8fb009dcSAndroid Build Coastguard Worker     return sigalg == SSL_SIGN_RSA_PKCS1_MD5_SHA1 ||
176*8fb009dcSAndroid Build Coastguard Worker            sigalg == SSL_SIGN_ECDSA_SHA1;
177*8fb009dcSAndroid Build Coastguard Worker   }
178*8fb009dcSAndroid Build Coastguard Worker 
179*8fb009dcSAndroid Build Coastguard Worker   // |SSL_SIGN_RSA_PKCS1_MD5_SHA1| is not a real SignatureScheme for TLS 1.2 and
180*8fb009dcSAndroid Build Coastguard Worker   // higher. It is an internal value we use to represent TLS 1.0/1.1's MD5/SHA1
181*8fb009dcSAndroid Build Coastguard Worker   // concatenation.
182*8fb009dcSAndroid Build Coastguard Worker   if (sigalg == SSL_SIGN_RSA_PKCS1_MD5_SHA1) {
183*8fb009dcSAndroid Build Coastguard Worker     return false;
184*8fb009dcSAndroid Build Coastguard Worker   }
185*8fb009dcSAndroid Build Coastguard Worker 
186*8fb009dcSAndroid Build Coastguard Worker   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
187*8fb009dcSAndroid Build Coastguard Worker     if (!alg->tls13_ok) {
188*8fb009dcSAndroid Build Coastguard Worker       return false;
189*8fb009dcSAndroid Build Coastguard Worker     }
190*8fb009dcSAndroid Build Coastguard Worker 
191*8fb009dcSAndroid Build Coastguard Worker     bool is_client_sign = ssl->server == is_verify;
192*8fb009dcSAndroid Build Coastguard Worker     if (alg->client_only && !is_client_sign) {
193*8fb009dcSAndroid Build Coastguard Worker       return false;
194*8fb009dcSAndroid Build Coastguard Worker     }
195*8fb009dcSAndroid Build Coastguard Worker 
196*8fb009dcSAndroid Build Coastguard Worker     // EC keys have a curve requirement.
197*8fb009dcSAndroid Build Coastguard Worker     if (alg->pkey_type == EVP_PKEY_EC &&
198*8fb009dcSAndroid Build Coastguard Worker         (alg->curve == NID_undef ||
199*8fb009dcSAndroid Build Coastguard Worker          EC_GROUP_get_curve_name(
200*8fb009dcSAndroid Build Coastguard Worker              EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey))) != alg->curve)) {
201*8fb009dcSAndroid Build Coastguard Worker       return false;
202*8fb009dcSAndroid Build Coastguard Worker     }
203*8fb009dcSAndroid Build Coastguard Worker   } else if (!alg->tls12_ok) {
204*8fb009dcSAndroid Build Coastguard Worker     return false;
205*8fb009dcSAndroid Build Coastguard Worker   }
206*8fb009dcSAndroid Build Coastguard Worker 
207*8fb009dcSAndroid Build Coastguard Worker   return true;
208*8fb009dcSAndroid Build Coastguard Worker }
209*8fb009dcSAndroid Build Coastguard Worker 
setup_ctx(SSL * ssl,EVP_MD_CTX * ctx,EVP_PKEY * pkey,uint16_t sigalg,bool is_verify)210*8fb009dcSAndroid Build Coastguard Worker static bool setup_ctx(SSL *ssl, EVP_MD_CTX *ctx, EVP_PKEY *pkey,
211*8fb009dcSAndroid Build Coastguard Worker                       uint16_t sigalg, bool is_verify) {
212*8fb009dcSAndroid Build Coastguard Worker   if (!ssl_pkey_supports_algorithm(ssl, pkey, sigalg, is_verify)) {
213*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
214*8fb009dcSAndroid Build Coastguard Worker     return false;
215*8fb009dcSAndroid Build Coastguard Worker   }
216*8fb009dcSAndroid Build Coastguard Worker 
217*8fb009dcSAndroid Build Coastguard Worker   const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
218*8fb009dcSAndroid Build Coastguard Worker   const EVP_MD *digest = alg->digest_func != NULL ? alg->digest_func() : NULL;
219*8fb009dcSAndroid Build Coastguard Worker   EVP_PKEY_CTX *pctx;
220*8fb009dcSAndroid Build Coastguard Worker   if (is_verify) {
221*8fb009dcSAndroid Build Coastguard Worker     if (!EVP_DigestVerifyInit(ctx, &pctx, digest, NULL, pkey)) {
222*8fb009dcSAndroid Build Coastguard Worker       return false;
223*8fb009dcSAndroid Build Coastguard Worker     }
224*8fb009dcSAndroid Build Coastguard Worker   } else if (!EVP_DigestSignInit(ctx, &pctx, digest, NULL, pkey)) {
225*8fb009dcSAndroid Build Coastguard Worker     return false;
226*8fb009dcSAndroid Build Coastguard Worker   }
227*8fb009dcSAndroid Build Coastguard Worker 
228*8fb009dcSAndroid Build Coastguard Worker   if (alg->is_rsa_pss) {
229*8fb009dcSAndroid Build Coastguard Worker     if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
230*8fb009dcSAndroid Build Coastguard Worker         !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */)) {
231*8fb009dcSAndroid Build Coastguard Worker       return false;
232*8fb009dcSAndroid Build Coastguard Worker     }
233*8fb009dcSAndroid Build Coastguard Worker   }
234*8fb009dcSAndroid Build Coastguard Worker 
235*8fb009dcSAndroid Build Coastguard Worker   return true;
236*8fb009dcSAndroid Build Coastguard Worker }
237*8fb009dcSAndroid Build Coastguard Worker 
ssl_private_key_sign(SSL_HANDSHAKE * hs,uint8_t * out,size_t * out_len,size_t max_out,uint16_t sigalg,Span<const uint8_t> in)238*8fb009dcSAndroid Build Coastguard Worker enum ssl_private_key_result_t ssl_private_key_sign(
239*8fb009dcSAndroid Build Coastguard Worker     SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
240*8fb009dcSAndroid Build Coastguard Worker     uint16_t sigalg, Span<const uint8_t> in) {
241*8fb009dcSAndroid Build Coastguard Worker   SSL *const ssl = hs->ssl;
242*8fb009dcSAndroid Build Coastguard Worker   const SSL_CREDENTIAL *const cred = hs->credential.get();
243*8fb009dcSAndroid Build Coastguard Worker   SSL_HANDSHAKE_HINTS *const hints = hs->hints.get();
244*8fb009dcSAndroid Build Coastguard Worker   Array<uint8_t> spki;
245*8fb009dcSAndroid Build Coastguard Worker   if (hints) {
246*8fb009dcSAndroid Build Coastguard Worker     ScopedCBB spki_cbb;
247*8fb009dcSAndroid Build Coastguard Worker     if (!CBB_init(spki_cbb.get(), 64) ||
248*8fb009dcSAndroid Build Coastguard Worker         !EVP_marshal_public_key(spki_cbb.get(), cred->pubkey.get()) ||
249*8fb009dcSAndroid Build Coastguard Worker         !CBBFinishArray(spki_cbb.get(), &spki)) {
250*8fb009dcSAndroid Build Coastguard Worker       ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
251*8fb009dcSAndroid Build Coastguard Worker       return ssl_private_key_failure;
252*8fb009dcSAndroid Build Coastguard Worker     }
253*8fb009dcSAndroid Build Coastguard Worker   }
254*8fb009dcSAndroid Build Coastguard Worker 
255*8fb009dcSAndroid Build Coastguard Worker   // Replay the signature from handshake hints if available.
256*8fb009dcSAndroid Build Coastguard Worker   if (hints && !hs->hints_requested &&         //
257*8fb009dcSAndroid Build Coastguard Worker       sigalg == hints->signature_algorithm &&  //
258*8fb009dcSAndroid Build Coastguard Worker       in == hints->signature_input &&
259*8fb009dcSAndroid Build Coastguard Worker       MakeConstSpan(spki) == hints->signature_spki &&
260*8fb009dcSAndroid Build Coastguard Worker       !hints->signature.empty() &&  //
261*8fb009dcSAndroid Build Coastguard Worker       hints->signature.size() <= max_out) {
262*8fb009dcSAndroid Build Coastguard Worker     // Signature algorithm and input both match. Reuse the signature from hints.
263*8fb009dcSAndroid Build Coastguard Worker     *out_len = hints->signature.size();
264*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_memcpy(out, hints->signature.data(), hints->signature.size());
265*8fb009dcSAndroid Build Coastguard Worker     return ssl_private_key_success;
266*8fb009dcSAndroid Build Coastguard Worker   }
267*8fb009dcSAndroid Build Coastguard Worker 
268*8fb009dcSAndroid Build Coastguard Worker   const SSL_PRIVATE_KEY_METHOD *key_method = cred->key_method;
269*8fb009dcSAndroid Build Coastguard Worker   EVP_PKEY *privkey = cred->privkey.get();
270*8fb009dcSAndroid Build Coastguard Worker   assert(!hs->can_release_private_key);
271*8fb009dcSAndroid Build Coastguard Worker 
272*8fb009dcSAndroid Build Coastguard Worker   if (key_method != NULL) {
273*8fb009dcSAndroid Build Coastguard Worker     enum ssl_private_key_result_t ret;
274*8fb009dcSAndroid Build Coastguard Worker     if (hs->pending_private_key_op) {
275*8fb009dcSAndroid Build Coastguard Worker       ret = key_method->complete(ssl, out, out_len, max_out);
276*8fb009dcSAndroid Build Coastguard Worker     } else {
277*8fb009dcSAndroid Build Coastguard Worker       ret = key_method->sign(ssl, out, out_len, max_out, sigalg, in.data(),
278*8fb009dcSAndroid Build Coastguard Worker                              in.size());
279*8fb009dcSAndroid Build Coastguard Worker     }
280*8fb009dcSAndroid Build Coastguard Worker     if (ret == ssl_private_key_failure) {
281*8fb009dcSAndroid Build Coastguard Worker       OPENSSL_PUT_ERROR(SSL, SSL_R_PRIVATE_KEY_OPERATION_FAILED);
282*8fb009dcSAndroid Build Coastguard Worker     }
283*8fb009dcSAndroid Build Coastguard Worker     hs->pending_private_key_op = ret == ssl_private_key_retry;
284*8fb009dcSAndroid Build Coastguard Worker     if (ret != ssl_private_key_success) {
285*8fb009dcSAndroid Build Coastguard Worker       return ret;
286*8fb009dcSAndroid Build Coastguard Worker     }
287*8fb009dcSAndroid Build Coastguard Worker   } else {
288*8fb009dcSAndroid Build Coastguard Worker     *out_len = max_out;
289*8fb009dcSAndroid Build Coastguard Worker     ScopedEVP_MD_CTX ctx;
290*8fb009dcSAndroid Build Coastguard Worker     if (!setup_ctx(ssl, ctx.get(), privkey, sigalg, false /* sign */) ||
291*8fb009dcSAndroid Build Coastguard Worker         !EVP_DigestSign(ctx.get(), out, out_len, in.data(), in.size())) {
292*8fb009dcSAndroid Build Coastguard Worker       return ssl_private_key_failure;
293*8fb009dcSAndroid Build Coastguard Worker     }
294*8fb009dcSAndroid Build Coastguard Worker   }
295*8fb009dcSAndroid Build Coastguard Worker 
296*8fb009dcSAndroid Build Coastguard Worker   // Save the hint if applicable.
297*8fb009dcSAndroid Build Coastguard Worker   if (hints && hs->hints_requested) {
298*8fb009dcSAndroid Build Coastguard Worker     hints->signature_algorithm = sigalg;
299*8fb009dcSAndroid Build Coastguard Worker     hints->signature_spki = std::move(spki);
300*8fb009dcSAndroid Build Coastguard Worker     if (!hints->signature_input.CopyFrom(in) ||
301*8fb009dcSAndroid Build Coastguard Worker         !hints->signature.CopyFrom(MakeConstSpan(out, *out_len))) {
302*8fb009dcSAndroid Build Coastguard Worker       return ssl_private_key_failure;
303*8fb009dcSAndroid Build Coastguard Worker     }
304*8fb009dcSAndroid Build Coastguard Worker   }
305*8fb009dcSAndroid Build Coastguard Worker   return ssl_private_key_success;
306*8fb009dcSAndroid Build Coastguard Worker }
307*8fb009dcSAndroid Build Coastguard Worker 
ssl_public_key_verify(SSL * ssl,Span<const uint8_t> signature,uint16_t sigalg,EVP_PKEY * pkey,Span<const uint8_t> in)308*8fb009dcSAndroid Build Coastguard Worker bool ssl_public_key_verify(SSL *ssl, Span<const uint8_t> signature,
309*8fb009dcSAndroid Build Coastguard Worker                            uint16_t sigalg, EVP_PKEY *pkey,
310*8fb009dcSAndroid Build Coastguard Worker                            Span<const uint8_t> in) {
311*8fb009dcSAndroid Build Coastguard Worker   ScopedEVP_MD_CTX ctx;
312*8fb009dcSAndroid Build Coastguard Worker   if (!setup_ctx(ssl, ctx.get(), pkey, sigalg, true /* verify */)) {
313*8fb009dcSAndroid Build Coastguard Worker     return false;
314*8fb009dcSAndroid Build Coastguard Worker   }
315*8fb009dcSAndroid Build Coastguard Worker   bool ok = EVP_DigestVerify(ctx.get(), signature.data(), signature.size(),
316*8fb009dcSAndroid Build Coastguard Worker                              in.data(), in.size());
317*8fb009dcSAndroid Build Coastguard Worker #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
318*8fb009dcSAndroid Build Coastguard Worker   ok = true;
319*8fb009dcSAndroid Build Coastguard Worker   ERR_clear_error();
320*8fb009dcSAndroid Build Coastguard Worker #endif
321*8fb009dcSAndroid Build Coastguard Worker   return ok;
322*8fb009dcSAndroid Build Coastguard Worker }
323*8fb009dcSAndroid Build Coastguard Worker 
ssl_private_key_decrypt(SSL_HANDSHAKE * hs,uint8_t * out,size_t * out_len,size_t max_out,Span<const uint8_t> in)324*8fb009dcSAndroid Build Coastguard Worker enum ssl_private_key_result_t ssl_private_key_decrypt(SSL_HANDSHAKE *hs,
325*8fb009dcSAndroid Build Coastguard Worker                                                       uint8_t *out,
326*8fb009dcSAndroid Build Coastguard Worker                                                       size_t *out_len,
327*8fb009dcSAndroid Build Coastguard Worker                                                       size_t max_out,
328*8fb009dcSAndroid Build Coastguard Worker                                                       Span<const uint8_t> in) {
329*8fb009dcSAndroid Build Coastguard Worker   SSL *const ssl = hs->ssl;
330*8fb009dcSAndroid Build Coastguard Worker   const SSL_CREDENTIAL *const cred = hs->credential.get();
331*8fb009dcSAndroid Build Coastguard Worker   assert(!hs->can_release_private_key);
332*8fb009dcSAndroid Build Coastguard Worker   if (cred->key_method != NULL) {
333*8fb009dcSAndroid Build Coastguard Worker     enum ssl_private_key_result_t ret;
334*8fb009dcSAndroid Build Coastguard Worker     if (hs->pending_private_key_op) {
335*8fb009dcSAndroid Build Coastguard Worker       ret = cred->key_method->complete(ssl, out, out_len, max_out);
336*8fb009dcSAndroid Build Coastguard Worker     } else {
337*8fb009dcSAndroid Build Coastguard Worker       ret = cred->key_method->decrypt(ssl, out, out_len, max_out, in.data(),
338*8fb009dcSAndroid Build Coastguard Worker                                       in.size());
339*8fb009dcSAndroid Build Coastguard Worker     }
340*8fb009dcSAndroid Build Coastguard Worker     if (ret == ssl_private_key_failure) {
341*8fb009dcSAndroid Build Coastguard Worker       OPENSSL_PUT_ERROR(SSL, SSL_R_PRIVATE_KEY_OPERATION_FAILED);
342*8fb009dcSAndroid Build Coastguard Worker     }
343*8fb009dcSAndroid Build Coastguard Worker     hs->pending_private_key_op = ret == ssl_private_key_retry;
344*8fb009dcSAndroid Build Coastguard Worker     return ret;
345*8fb009dcSAndroid Build Coastguard Worker   }
346*8fb009dcSAndroid Build Coastguard Worker 
347*8fb009dcSAndroid Build Coastguard Worker   RSA *rsa = EVP_PKEY_get0_RSA(cred->privkey.get());
348*8fb009dcSAndroid Build Coastguard Worker   if (rsa == NULL) {
349*8fb009dcSAndroid Build Coastguard Worker     // Decrypt operations are only supported for RSA keys.
350*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
351*8fb009dcSAndroid Build Coastguard Worker     return ssl_private_key_failure;
352*8fb009dcSAndroid Build Coastguard Worker   }
353*8fb009dcSAndroid Build Coastguard Worker 
354*8fb009dcSAndroid Build Coastguard Worker   // Decrypt with no padding. PKCS#1 padding will be removed as part of the
355*8fb009dcSAndroid Build Coastguard Worker   // timing-sensitive code by the caller.
356*8fb009dcSAndroid Build Coastguard Worker   if (!RSA_decrypt(rsa, out_len, out, max_out, in.data(), in.size(),
357*8fb009dcSAndroid Build Coastguard Worker                    RSA_NO_PADDING)) {
358*8fb009dcSAndroid Build Coastguard Worker     return ssl_private_key_failure;
359*8fb009dcSAndroid Build Coastguard Worker   }
360*8fb009dcSAndroid Build Coastguard Worker   return ssl_private_key_success;
361*8fb009dcSAndroid Build Coastguard Worker }
362*8fb009dcSAndroid Build Coastguard Worker 
363*8fb009dcSAndroid Build Coastguard Worker BSSL_NAMESPACE_END
364*8fb009dcSAndroid Build Coastguard Worker 
365*8fb009dcSAndroid Build Coastguard Worker using namespace bssl;
366*8fb009dcSAndroid Build Coastguard Worker 
SSL_use_RSAPrivateKey(SSL * ssl,RSA * rsa)367*8fb009dcSAndroid Build Coastguard Worker int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
368*8fb009dcSAndroid Build Coastguard Worker   if (rsa == NULL || ssl->config == NULL) {
369*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
370*8fb009dcSAndroid Build Coastguard Worker     return 0;
371*8fb009dcSAndroid Build Coastguard Worker   }
372*8fb009dcSAndroid Build Coastguard Worker 
373*8fb009dcSAndroid Build Coastguard Worker   UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
374*8fb009dcSAndroid Build Coastguard Worker   if (!pkey ||
375*8fb009dcSAndroid Build Coastguard Worker       !EVP_PKEY_set1_RSA(pkey.get(), rsa)) {
376*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
377*8fb009dcSAndroid Build Coastguard Worker     return 0;
378*8fb009dcSAndroid Build Coastguard Worker   }
379*8fb009dcSAndroid Build Coastguard Worker 
380*8fb009dcSAndroid Build Coastguard Worker   return SSL_use_PrivateKey(ssl, pkey.get());
381*8fb009dcSAndroid Build Coastguard Worker }
382*8fb009dcSAndroid Build Coastguard Worker 
SSL_use_RSAPrivateKey_ASN1(SSL * ssl,const uint8_t * der,size_t der_len)383*8fb009dcSAndroid Build Coastguard Worker int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
384*8fb009dcSAndroid Build Coastguard Worker   UniquePtr<RSA> rsa(RSA_private_key_from_bytes(der, der_len));
385*8fb009dcSAndroid Build Coastguard Worker   if (!rsa) {
386*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
387*8fb009dcSAndroid Build Coastguard Worker     return 0;
388*8fb009dcSAndroid Build Coastguard Worker   }
389*8fb009dcSAndroid Build Coastguard Worker 
390*8fb009dcSAndroid Build Coastguard Worker   return SSL_use_RSAPrivateKey(ssl, rsa.get());
391*8fb009dcSAndroid Build Coastguard Worker }
392*8fb009dcSAndroid Build Coastguard Worker 
SSL_use_PrivateKey(SSL * ssl,EVP_PKEY * pkey)393*8fb009dcSAndroid Build Coastguard Worker int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
394*8fb009dcSAndroid Build Coastguard Worker   if (pkey == NULL || ssl->config == NULL) {
395*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
396*8fb009dcSAndroid Build Coastguard Worker     return 0;
397*8fb009dcSAndroid Build Coastguard Worker   }
398*8fb009dcSAndroid Build Coastguard Worker 
399*8fb009dcSAndroid Build Coastguard Worker   return SSL_CREDENTIAL_set1_private_key(
400*8fb009dcSAndroid Build Coastguard Worker       ssl->config->cert->default_credential.get(), pkey);
401*8fb009dcSAndroid Build Coastguard Worker }
402*8fb009dcSAndroid Build Coastguard Worker 
SSL_use_PrivateKey_ASN1(int type,SSL * ssl,const uint8_t * der,size_t der_len)403*8fb009dcSAndroid Build Coastguard Worker int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der,
404*8fb009dcSAndroid Build Coastguard Worker                             size_t der_len) {
405*8fb009dcSAndroid Build Coastguard Worker   if (der_len > LONG_MAX) {
406*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
407*8fb009dcSAndroid Build Coastguard Worker     return 0;
408*8fb009dcSAndroid Build Coastguard Worker   }
409*8fb009dcSAndroid Build Coastguard Worker 
410*8fb009dcSAndroid Build Coastguard Worker   const uint8_t *p = der;
411*8fb009dcSAndroid Build Coastguard Worker   UniquePtr<EVP_PKEY> pkey(d2i_PrivateKey(type, NULL, &p, (long)der_len));
412*8fb009dcSAndroid Build Coastguard Worker   if (!pkey || p != der + der_len) {
413*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
414*8fb009dcSAndroid Build Coastguard Worker     return 0;
415*8fb009dcSAndroid Build Coastguard Worker   }
416*8fb009dcSAndroid Build Coastguard Worker 
417*8fb009dcSAndroid Build Coastguard Worker   return SSL_use_PrivateKey(ssl, pkey.get());
418*8fb009dcSAndroid Build Coastguard Worker }
419*8fb009dcSAndroid Build Coastguard Worker 
SSL_CTX_use_RSAPrivateKey(SSL_CTX * ctx,RSA * rsa)420*8fb009dcSAndroid Build Coastguard Worker int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
421*8fb009dcSAndroid Build Coastguard Worker   if (rsa == NULL) {
422*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
423*8fb009dcSAndroid Build Coastguard Worker     return 0;
424*8fb009dcSAndroid Build Coastguard Worker   }
425*8fb009dcSAndroid Build Coastguard Worker 
426*8fb009dcSAndroid Build Coastguard Worker   UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
427*8fb009dcSAndroid Build Coastguard Worker   if (!pkey ||
428*8fb009dcSAndroid Build Coastguard Worker       !EVP_PKEY_set1_RSA(pkey.get(), rsa)) {
429*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
430*8fb009dcSAndroid Build Coastguard Worker     return 0;
431*8fb009dcSAndroid Build Coastguard Worker   }
432*8fb009dcSAndroid Build Coastguard Worker 
433*8fb009dcSAndroid Build Coastguard Worker   return SSL_CTX_use_PrivateKey(ctx, pkey.get());
434*8fb009dcSAndroid Build Coastguard Worker }
435*8fb009dcSAndroid Build Coastguard Worker 
SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX * ctx,const uint8_t * der,size_t der_len)436*8fb009dcSAndroid Build Coastguard Worker int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der,
437*8fb009dcSAndroid Build Coastguard Worker                                    size_t der_len) {
438*8fb009dcSAndroid Build Coastguard Worker   UniquePtr<RSA> rsa(RSA_private_key_from_bytes(der, der_len));
439*8fb009dcSAndroid Build Coastguard Worker   if (!rsa) {
440*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
441*8fb009dcSAndroid Build Coastguard Worker     return 0;
442*8fb009dcSAndroid Build Coastguard Worker   }
443*8fb009dcSAndroid Build Coastguard Worker 
444*8fb009dcSAndroid Build Coastguard Worker   return SSL_CTX_use_RSAPrivateKey(ctx, rsa.get());
445*8fb009dcSAndroid Build Coastguard Worker }
446*8fb009dcSAndroid Build Coastguard Worker 
SSL_CTX_use_PrivateKey(SSL_CTX * ctx,EVP_PKEY * pkey)447*8fb009dcSAndroid Build Coastguard Worker int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) {
448*8fb009dcSAndroid Build Coastguard Worker   if (pkey == NULL) {
449*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
450*8fb009dcSAndroid Build Coastguard Worker     return 0;
451*8fb009dcSAndroid Build Coastguard Worker   }
452*8fb009dcSAndroid Build Coastguard Worker 
453*8fb009dcSAndroid Build Coastguard Worker   return SSL_CREDENTIAL_set1_private_key(ctx->cert->default_credential.get(),
454*8fb009dcSAndroid Build Coastguard Worker                                          pkey);
455*8fb009dcSAndroid Build Coastguard Worker }
456*8fb009dcSAndroid Build Coastguard Worker 
SSL_CTX_use_PrivateKey_ASN1(int type,SSL_CTX * ctx,const uint8_t * der,size_t der_len)457*8fb009dcSAndroid Build Coastguard Worker int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *der,
458*8fb009dcSAndroid Build Coastguard Worker                                 size_t der_len) {
459*8fb009dcSAndroid Build Coastguard Worker   if (der_len > LONG_MAX) {
460*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
461*8fb009dcSAndroid Build Coastguard Worker     return 0;
462*8fb009dcSAndroid Build Coastguard Worker   }
463*8fb009dcSAndroid Build Coastguard Worker 
464*8fb009dcSAndroid Build Coastguard Worker   const uint8_t *p = der;
465*8fb009dcSAndroid Build Coastguard Worker   UniquePtr<EVP_PKEY> pkey(d2i_PrivateKey(type, NULL, &p, (long)der_len));
466*8fb009dcSAndroid Build Coastguard Worker   if (!pkey || p != der + der_len) {
467*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
468*8fb009dcSAndroid Build Coastguard Worker     return 0;
469*8fb009dcSAndroid Build Coastguard Worker   }
470*8fb009dcSAndroid Build Coastguard Worker 
471*8fb009dcSAndroid Build Coastguard Worker   return SSL_CTX_use_PrivateKey(ctx, pkey.get());
472*8fb009dcSAndroid Build Coastguard Worker }
473*8fb009dcSAndroid Build Coastguard Worker 
SSL_set_private_key_method(SSL * ssl,const SSL_PRIVATE_KEY_METHOD * key_method)474*8fb009dcSAndroid Build Coastguard Worker void SSL_set_private_key_method(SSL *ssl,
475*8fb009dcSAndroid Build Coastguard Worker                                 const SSL_PRIVATE_KEY_METHOD *key_method) {
476*8fb009dcSAndroid Build Coastguard Worker   if (!ssl->config) {
477*8fb009dcSAndroid Build Coastguard Worker     return;
478*8fb009dcSAndroid Build Coastguard Worker   }
479*8fb009dcSAndroid Build Coastguard Worker   BSSL_CHECK(SSL_CREDENTIAL_set_private_key_method(
480*8fb009dcSAndroid Build Coastguard Worker       ssl->config->cert->default_credential.get(), key_method));
481*8fb009dcSAndroid Build Coastguard Worker }
482*8fb009dcSAndroid Build Coastguard Worker 
SSL_CTX_set_private_key_method(SSL_CTX * ctx,const SSL_PRIVATE_KEY_METHOD * key_method)483*8fb009dcSAndroid Build Coastguard Worker void SSL_CTX_set_private_key_method(SSL_CTX *ctx,
484*8fb009dcSAndroid Build Coastguard Worker                                     const SSL_PRIVATE_KEY_METHOD *key_method) {
485*8fb009dcSAndroid Build Coastguard Worker   BSSL_CHECK(SSL_CREDENTIAL_set_private_key_method(
486*8fb009dcSAndroid Build Coastguard Worker       ctx->cert->default_credential.get(), key_method));
487*8fb009dcSAndroid Build Coastguard Worker }
488*8fb009dcSAndroid Build Coastguard Worker 
489*8fb009dcSAndroid Build Coastguard Worker static constexpr size_t kMaxSignatureAlgorithmNameLen = 24;
490*8fb009dcSAndroid Build Coastguard Worker 
491*8fb009dcSAndroid Build Coastguard Worker struct SignatureAlgorithmName {
492*8fb009dcSAndroid Build Coastguard Worker   uint16_t signature_algorithm;
493*8fb009dcSAndroid Build Coastguard Worker   const char name[kMaxSignatureAlgorithmNameLen];
494*8fb009dcSAndroid Build Coastguard Worker };
495*8fb009dcSAndroid Build Coastguard Worker 
496*8fb009dcSAndroid Build Coastguard Worker // This was "constexpr" rather than "const", but that triggered a bug in MSVC
497*8fb009dcSAndroid Build Coastguard Worker // where it didn't pad the strings to the correct length.
498*8fb009dcSAndroid Build Coastguard Worker static const SignatureAlgorithmName kSignatureAlgorithmNames[] = {
499*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_MD5_SHA1, "rsa_pkcs1_md5_sha1"},
500*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_SHA1, "rsa_pkcs1_sha1"},
501*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_SHA256, "rsa_pkcs1_sha256"},
502*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_SHA256_LEGACY, "rsa_pkcs1_sha256_legacy"},
503*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_SHA384, "rsa_pkcs1_sha384"},
504*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PKCS1_SHA512, "rsa_pkcs1_sha512"},
505*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_ECDSA_SHA1, "ecdsa_sha1"},
506*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_ECDSA_SECP256R1_SHA256, "ecdsa_secp256r1_sha256"},
507*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_ECDSA_SECP384R1_SHA384, "ecdsa_secp384r1_sha384"},
508*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_ECDSA_SECP521R1_SHA512, "ecdsa_secp521r1_sha512"},
509*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PSS_RSAE_SHA256, "rsa_pss_rsae_sha256"},
510*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PSS_RSAE_SHA384, "rsa_pss_rsae_sha384"},
511*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_RSA_PSS_RSAE_SHA512, "rsa_pss_rsae_sha512"},
512*8fb009dcSAndroid Build Coastguard Worker     {SSL_SIGN_ED25519, "ed25519"},
513*8fb009dcSAndroid Build Coastguard Worker };
514*8fb009dcSAndroid Build Coastguard Worker 
SSL_get_signature_algorithm_name(uint16_t sigalg,int include_curve)515*8fb009dcSAndroid Build Coastguard Worker const char *SSL_get_signature_algorithm_name(uint16_t sigalg,
516*8fb009dcSAndroid Build Coastguard Worker                                              int include_curve) {
517*8fb009dcSAndroid Build Coastguard Worker   if (!include_curve) {
518*8fb009dcSAndroid Build Coastguard Worker     switch (sigalg) {
519*8fb009dcSAndroid Build Coastguard Worker       case SSL_SIGN_ECDSA_SECP256R1_SHA256:
520*8fb009dcSAndroid Build Coastguard Worker         return "ecdsa_sha256";
521*8fb009dcSAndroid Build Coastguard Worker       case SSL_SIGN_ECDSA_SECP384R1_SHA384:
522*8fb009dcSAndroid Build Coastguard Worker         return "ecdsa_sha384";
523*8fb009dcSAndroid Build Coastguard Worker       case SSL_SIGN_ECDSA_SECP521R1_SHA512:
524*8fb009dcSAndroid Build Coastguard Worker         return "ecdsa_sha512";
525*8fb009dcSAndroid Build Coastguard Worker         // If adding more here, also update
526*8fb009dcSAndroid Build Coastguard Worker         // |SSL_get_all_signature_algorithm_names|.
527*8fb009dcSAndroid Build Coastguard Worker     }
528*8fb009dcSAndroid Build Coastguard Worker   }
529*8fb009dcSAndroid Build Coastguard Worker 
530*8fb009dcSAndroid Build Coastguard Worker   for (const auto &candidate : kSignatureAlgorithmNames) {
531*8fb009dcSAndroid Build Coastguard Worker     if (candidate.signature_algorithm == sigalg) {
532*8fb009dcSAndroid Build Coastguard Worker       return candidate.name;
533*8fb009dcSAndroid Build Coastguard Worker     }
534*8fb009dcSAndroid Build Coastguard Worker   }
535*8fb009dcSAndroid Build Coastguard Worker 
536*8fb009dcSAndroid Build Coastguard Worker   return NULL;
537*8fb009dcSAndroid Build Coastguard Worker }
538*8fb009dcSAndroid Build Coastguard Worker 
SSL_get_all_signature_algorithm_names(const char ** out,size_t max_out)539*8fb009dcSAndroid Build Coastguard Worker size_t SSL_get_all_signature_algorithm_names(const char **out, size_t max_out) {
540*8fb009dcSAndroid Build Coastguard Worker   const char *kPredefinedNames[] = {"ecdsa_sha256", "ecdsa_sha384",
541*8fb009dcSAndroid Build Coastguard Worker                                     "ecdsa_sha512"};
542*8fb009dcSAndroid Build Coastguard Worker   return GetAllNames(out, max_out, MakeConstSpan(kPredefinedNames),
543*8fb009dcSAndroid Build Coastguard Worker                      &SignatureAlgorithmName::name,
544*8fb009dcSAndroid Build Coastguard Worker                      MakeConstSpan(kSignatureAlgorithmNames));
545*8fb009dcSAndroid Build Coastguard Worker }
546*8fb009dcSAndroid Build Coastguard Worker 
SSL_get_signature_algorithm_key_type(uint16_t sigalg)547*8fb009dcSAndroid Build Coastguard Worker int SSL_get_signature_algorithm_key_type(uint16_t sigalg) {
548*8fb009dcSAndroid Build Coastguard Worker   const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
549*8fb009dcSAndroid Build Coastguard Worker   return alg != nullptr ? alg->pkey_type : EVP_PKEY_NONE;
550*8fb009dcSAndroid Build Coastguard Worker }
551*8fb009dcSAndroid Build Coastguard Worker 
SSL_get_signature_algorithm_digest(uint16_t sigalg)552*8fb009dcSAndroid Build Coastguard Worker const EVP_MD *SSL_get_signature_algorithm_digest(uint16_t sigalg) {
553*8fb009dcSAndroid Build Coastguard Worker   const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
554*8fb009dcSAndroid Build Coastguard Worker   if (alg == nullptr || alg->digest_func == nullptr) {
555*8fb009dcSAndroid Build Coastguard Worker     return nullptr;
556*8fb009dcSAndroid Build Coastguard Worker   }
557*8fb009dcSAndroid Build Coastguard Worker   return alg->digest_func();
558*8fb009dcSAndroid Build Coastguard Worker }
559*8fb009dcSAndroid Build Coastguard Worker 
SSL_is_signature_algorithm_rsa_pss(uint16_t sigalg)560*8fb009dcSAndroid Build Coastguard Worker int SSL_is_signature_algorithm_rsa_pss(uint16_t sigalg) {
561*8fb009dcSAndroid Build Coastguard Worker   const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
562*8fb009dcSAndroid Build Coastguard Worker   return alg != nullptr && alg->is_rsa_pss;
563*8fb009dcSAndroid Build Coastguard Worker }
564*8fb009dcSAndroid Build Coastguard Worker 
compare_uint16_t(const void * p1,const void * p2)565*8fb009dcSAndroid Build Coastguard Worker static int compare_uint16_t(const void *p1, const void *p2) {
566*8fb009dcSAndroid Build Coastguard Worker   uint16_t u1 = *((const uint16_t *)p1);
567*8fb009dcSAndroid Build Coastguard Worker   uint16_t u2 = *((const uint16_t *)p2);
568*8fb009dcSAndroid Build Coastguard Worker   if (u1 < u2) {
569*8fb009dcSAndroid Build Coastguard Worker     return -1;
570*8fb009dcSAndroid Build Coastguard Worker   } else if (u1 > u2) {
571*8fb009dcSAndroid Build Coastguard Worker     return 1;
572*8fb009dcSAndroid Build Coastguard Worker   } else {
573*8fb009dcSAndroid Build Coastguard Worker     return 0;
574*8fb009dcSAndroid Build Coastguard Worker   }
575*8fb009dcSAndroid Build Coastguard Worker }
576*8fb009dcSAndroid Build Coastguard Worker 
sigalgs_unique(Span<const uint16_t> in_sigalgs)577*8fb009dcSAndroid Build Coastguard Worker static bool sigalgs_unique(Span<const uint16_t> in_sigalgs) {
578*8fb009dcSAndroid Build Coastguard Worker   if (in_sigalgs.size() < 2) {
579*8fb009dcSAndroid Build Coastguard Worker     return true;
580*8fb009dcSAndroid Build Coastguard Worker   }
581*8fb009dcSAndroid Build Coastguard Worker 
582*8fb009dcSAndroid Build Coastguard Worker   Array<uint16_t> sigalgs;
583*8fb009dcSAndroid Build Coastguard Worker   if (!sigalgs.CopyFrom(in_sigalgs)) {
584*8fb009dcSAndroid Build Coastguard Worker     return false;
585*8fb009dcSAndroid Build Coastguard Worker   }
586*8fb009dcSAndroid Build Coastguard Worker 
587*8fb009dcSAndroid Build Coastguard Worker   qsort(sigalgs.data(), sigalgs.size(), sizeof(uint16_t), compare_uint16_t);
588*8fb009dcSAndroid Build Coastguard Worker 
589*8fb009dcSAndroid Build Coastguard Worker   for (size_t i = 1; i < sigalgs.size(); i++) {
590*8fb009dcSAndroid Build Coastguard Worker     if (sigalgs[i - 1] == sigalgs[i]) {
591*8fb009dcSAndroid Build Coastguard Worker       OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_SIGNATURE_ALGORITHM);
592*8fb009dcSAndroid Build Coastguard Worker       return false;
593*8fb009dcSAndroid Build Coastguard Worker     }
594*8fb009dcSAndroid Build Coastguard Worker   }
595*8fb009dcSAndroid Build Coastguard Worker 
596*8fb009dcSAndroid Build Coastguard Worker   return true;
597*8fb009dcSAndroid Build Coastguard Worker }
598*8fb009dcSAndroid Build Coastguard Worker 
set_sigalg_prefs(Array<uint16_t> * out,Span<const uint16_t> prefs)599*8fb009dcSAndroid Build Coastguard Worker static bool set_sigalg_prefs(Array<uint16_t> *out, Span<const uint16_t> prefs) {
600*8fb009dcSAndroid Build Coastguard Worker   if (!sigalgs_unique(prefs)) {
601*8fb009dcSAndroid Build Coastguard Worker     return false;
602*8fb009dcSAndroid Build Coastguard Worker   }
603*8fb009dcSAndroid Build Coastguard Worker 
604*8fb009dcSAndroid Build Coastguard Worker   // Check for invalid algorithms, and filter out |SSL_SIGN_RSA_PKCS1_MD5_SHA1|.
605*8fb009dcSAndroid Build Coastguard Worker   Array<uint16_t> filtered;
606*8fb009dcSAndroid Build Coastguard Worker   if (!filtered.Init(prefs.size())) {
607*8fb009dcSAndroid Build Coastguard Worker     return false;
608*8fb009dcSAndroid Build Coastguard Worker   }
609*8fb009dcSAndroid Build Coastguard Worker   size_t added = 0;
610*8fb009dcSAndroid Build Coastguard Worker   for (uint16_t pref : prefs) {
611*8fb009dcSAndroid Build Coastguard Worker     if (pref == SSL_SIGN_RSA_PKCS1_MD5_SHA1) {
612*8fb009dcSAndroid Build Coastguard Worker       // Though not intended to be used with this API, we treat
613*8fb009dcSAndroid Build Coastguard Worker       // |SSL_SIGN_RSA_PKCS1_MD5_SHA1| as a real signature algorithm in
614*8fb009dcSAndroid Build Coastguard Worker       // |SSL_PRIVATE_KEY_METHOD|. Not accepting it here makes for a confusing
615*8fb009dcSAndroid Build Coastguard Worker       // abstraction.
616*8fb009dcSAndroid Build Coastguard Worker       continue;
617*8fb009dcSAndroid Build Coastguard Worker     }
618*8fb009dcSAndroid Build Coastguard Worker     if (get_signature_algorithm(pref) == nullptr) {
619*8fb009dcSAndroid Build Coastguard Worker       OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
620*8fb009dcSAndroid Build Coastguard Worker       return false;
621*8fb009dcSAndroid Build Coastguard Worker     }
622*8fb009dcSAndroid Build Coastguard Worker     filtered[added] = pref;
623*8fb009dcSAndroid Build Coastguard Worker     added++;
624*8fb009dcSAndroid Build Coastguard Worker   }
625*8fb009dcSAndroid Build Coastguard Worker   filtered.Shrink(added);
626*8fb009dcSAndroid Build Coastguard Worker 
627*8fb009dcSAndroid Build Coastguard Worker   // This can happen if |prefs| contained only |SSL_SIGN_RSA_PKCS1_MD5_SHA1|.
628*8fb009dcSAndroid Build Coastguard Worker   // Leaving it empty would revert to the default, so treat this as an error
629*8fb009dcSAndroid Build Coastguard Worker   // condition.
630*8fb009dcSAndroid Build Coastguard Worker   if (!prefs.empty() && filtered.empty()) {
631*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
632*8fb009dcSAndroid Build Coastguard Worker     return false;
633*8fb009dcSAndroid Build Coastguard Worker   }
634*8fb009dcSAndroid Build Coastguard Worker 
635*8fb009dcSAndroid Build Coastguard Worker   *out = std::move(filtered);
636*8fb009dcSAndroid Build Coastguard Worker   return true;
637*8fb009dcSAndroid Build Coastguard Worker }
638*8fb009dcSAndroid Build Coastguard Worker 
SSL_CREDENTIAL_set1_signing_algorithm_prefs(SSL_CREDENTIAL * cred,const uint16_t * prefs,size_t num_prefs)639*8fb009dcSAndroid Build Coastguard Worker int SSL_CREDENTIAL_set1_signing_algorithm_prefs(SSL_CREDENTIAL *cred,
640*8fb009dcSAndroid Build Coastguard Worker                                                 const uint16_t *prefs,
641*8fb009dcSAndroid Build Coastguard Worker                                                 size_t num_prefs) {
642*8fb009dcSAndroid Build Coastguard Worker   if (!cred->UsesPrivateKey()) {
643*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
644*8fb009dcSAndroid Build Coastguard Worker     return 0;
645*8fb009dcSAndroid Build Coastguard Worker   }
646*8fb009dcSAndroid Build Coastguard Worker 
647*8fb009dcSAndroid Build Coastguard Worker   // Delegated credentials are constrained to a single algorithm, so there is no
648*8fb009dcSAndroid Build Coastguard Worker   // need to configure this.
649*8fb009dcSAndroid Build Coastguard Worker   if (cred->type == SSLCredentialType::kDelegated) {
650*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
651*8fb009dcSAndroid Build Coastguard Worker     return 0;
652*8fb009dcSAndroid Build Coastguard Worker   }
653*8fb009dcSAndroid Build Coastguard Worker 
654*8fb009dcSAndroid Build Coastguard Worker   return set_sigalg_prefs(&cred->sigalgs, MakeConstSpan(prefs, num_prefs));
655*8fb009dcSAndroid Build Coastguard Worker }
656*8fb009dcSAndroid Build Coastguard Worker 
SSL_CTX_set_signing_algorithm_prefs(SSL_CTX * ctx,const uint16_t * prefs,size_t num_prefs)657*8fb009dcSAndroid Build Coastguard Worker int SSL_CTX_set_signing_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs,
658*8fb009dcSAndroid Build Coastguard Worker                                         size_t num_prefs) {
659*8fb009dcSAndroid Build Coastguard Worker   return SSL_CREDENTIAL_set1_signing_algorithm_prefs(
660*8fb009dcSAndroid Build Coastguard Worker       ctx->cert->default_credential.get(), prefs, num_prefs);
661*8fb009dcSAndroid Build Coastguard Worker }
662*8fb009dcSAndroid Build Coastguard Worker 
SSL_set_signing_algorithm_prefs(SSL * ssl,const uint16_t * prefs,size_t num_prefs)663*8fb009dcSAndroid Build Coastguard Worker int SSL_set_signing_algorithm_prefs(SSL *ssl, const uint16_t *prefs,
664*8fb009dcSAndroid Build Coastguard Worker                                     size_t num_prefs) {
665*8fb009dcSAndroid Build Coastguard Worker   if (!ssl->config) {
666*8fb009dcSAndroid Build Coastguard Worker     return 0;
667*8fb009dcSAndroid Build Coastguard Worker   }
668*8fb009dcSAndroid Build Coastguard Worker   return SSL_CREDENTIAL_set1_signing_algorithm_prefs(
669*8fb009dcSAndroid Build Coastguard Worker       ssl->config->cert->default_credential.get(), prefs, num_prefs);
670*8fb009dcSAndroid Build Coastguard Worker }
671*8fb009dcSAndroid Build Coastguard Worker 
672*8fb009dcSAndroid Build Coastguard Worker static constexpr struct {
673*8fb009dcSAndroid Build Coastguard Worker   int pkey_type;
674*8fb009dcSAndroid Build Coastguard Worker   int hash_nid;
675*8fb009dcSAndroid Build Coastguard Worker   uint16_t signature_algorithm;
676*8fb009dcSAndroid Build Coastguard Worker } kSignatureAlgorithmsMapping[] = {
677*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_RSA, NID_sha1, SSL_SIGN_RSA_PKCS1_SHA1},
678*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_RSA, NID_sha256, SSL_SIGN_RSA_PKCS1_SHA256},
679*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_RSA, NID_sha384, SSL_SIGN_RSA_PKCS1_SHA384},
680*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_RSA, NID_sha512, SSL_SIGN_RSA_PKCS1_SHA512},
681*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_RSA_PSS, NID_sha256, SSL_SIGN_RSA_PSS_RSAE_SHA256},
682*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_RSA_PSS, NID_sha384, SSL_SIGN_RSA_PSS_RSAE_SHA384},
683*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_RSA_PSS, NID_sha512, SSL_SIGN_RSA_PSS_RSAE_SHA512},
684*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_EC, NID_sha1, SSL_SIGN_ECDSA_SHA1},
685*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_EC, NID_sha256, SSL_SIGN_ECDSA_SECP256R1_SHA256},
686*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_EC, NID_sha384, SSL_SIGN_ECDSA_SECP384R1_SHA384},
687*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_EC, NID_sha512, SSL_SIGN_ECDSA_SECP521R1_SHA512},
688*8fb009dcSAndroid Build Coastguard Worker     {EVP_PKEY_ED25519, NID_undef, SSL_SIGN_ED25519},
689*8fb009dcSAndroid Build Coastguard Worker };
690*8fb009dcSAndroid Build Coastguard Worker 
parse_sigalg_pairs(Array<uint16_t> * out,const int * values,size_t num_values)691*8fb009dcSAndroid Build Coastguard Worker static bool parse_sigalg_pairs(Array<uint16_t> *out, const int *values,
692*8fb009dcSAndroid Build Coastguard Worker                                size_t num_values) {
693*8fb009dcSAndroid Build Coastguard Worker   if ((num_values & 1) == 1) {
694*8fb009dcSAndroid Build Coastguard Worker     return false;
695*8fb009dcSAndroid Build Coastguard Worker   }
696*8fb009dcSAndroid Build Coastguard Worker 
697*8fb009dcSAndroid Build Coastguard Worker   const size_t num_pairs = num_values / 2;
698*8fb009dcSAndroid Build Coastguard Worker   if (!out->Init(num_pairs)) {
699*8fb009dcSAndroid Build Coastguard Worker     return false;
700*8fb009dcSAndroid Build Coastguard Worker   }
701*8fb009dcSAndroid Build Coastguard Worker 
702*8fb009dcSAndroid Build Coastguard Worker   for (size_t i = 0; i < num_values; i += 2) {
703*8fb009dcSAndroid Build Coastguard Worker     const int hash_nid = values[i];
704*8fb009dcSAndroid Build Coastguard Worker     const int pkey_type = values[i+1];
705*8fb009dcSAndroid Build Coastguard Worker 
706*8fb009dcSAndroid Build Coastguard Worker     bool found = false;
707*8fb009dcSAndroid Build Coastguard Worker     for (const auto &candidate : kSignatureAlgorithmsMapping) {
708*8fb009dcSAndroid Build Coastguard Worker       if (candidate.pkey_type == pkey_type && candidate.hash_nid == hash_nid) {
709*8fb009dcSAndroid Build Coastguard Worker         (*out)[i / 2] = candidate.signature_algorithm;
710*8fb009dcSAndroid Build Coastguard Worker         found = true;
711*8fb009dcSAndroid Build Coastguard Worker         break;
712*8fb009dcSAndroid Build Coastguard Worker       }
713*8fb009dcSAndroid Build Coastguard Worker     }
714*8fb009dcSAndroid Build Coastguard Worker 
715*8fb009dcSAndroid Build Coastguard Worker     if (!found) {
716*8fb009dcSAndroid Build Coastguard Worker       OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
717*8fb009dcSAndroid Build Coastguard Worker       ERR_add_error_dataf("unknown hash:%d pkey:%d", hash_nid, pkey_type);
718*8fb009dcSAndroid Build Coastguard Worker       return false;
719*8fb009dcSAndroid Build Coastguard Worker     }
720*8fb009dcSAndroid Build Coastguard Worker   }
721*8fb009dcSAndroid Build Coastguard Worker 
722*8fb009dcSAndroid Build Coastguard Worker   return true;
723*8fb009dcSAndroid Build Coastguard Worker }
724*8fb009dcSAndroid Build Coastguard Worker 
SSL_CTX_set1_sigalgs(SSL_CTX * ctx,const int * values,size_t num_values)725*8fb009dcSAndroid Build Coastguard Worker int SSL_CTX_set1_sigalgs(SSL_CTX *ctx, const int *values, size_t num_values) {
726*8fb009dcSAndroid Build Coastguard Worker   Array<uint16_t> sigalgs;
727*8fb009dcSAndroid Build Coastguard Worker   if (!parse_sigalg_pairs(&sigalgs, values, num_values)) {
728*8fb009dcSAndroid Build Coastguard Worker     return 0;
729*8fb009dcSAndroid Build Coastguard Worker   }
730*8fb009dcSAndroid Build Coastguard Worker 
731*8fb009dcSAndroid Build Coastguard Worker   if (!SSL_CTX_set_signing_algorithm_prefs(ctx, sigalgs.data(),
732*8fb009dcSAndroid Build Coastguard Worker                                            sigalgs.size()) ||
733*8fb009dcSAndroid Build Coastguard Worker       !SSL_CTX_set_verify_algorithm_prefs(ctx, sigalgs.data(),
734*8fb009dcSAndroid Build Coastguard Worker                                           sigalgs.size())) {
735*8fb009dcSAndroid Build Coastguard Worker     return 0;
736*8fb009dcSAndroid Build Coastguard Worker   }
737*8fb009dcSAndroid Build Coastguard Worker 
738*8fb009dcSAndroid Build Coastguard Worker   return 1;
739*8fb009dcSAndroid Build Coastguard Worker }
740*8fb009dcSAndroid Build Coastguard Worker 
SSL_set1_sigalgs(SSL * ssl,const int * values,size_t num_values)741*8fb009dcSAndroid Build Coastguard Worker int SSL_set1_sigalgs(SSL *ssl, const int *values, size_t num_values) {
742*8fb009dcSAndroid Build Coastguard Worker   if (!ssl->config) {
743*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
744*8fb009dcSAndroid Build Coastguard Worker     return 0;
745*8fb009dcSAndroid Build Coastguard Worker   }
746*8fb009dcSAndroid Build Coastguard Worker 
747*8fb009dcSAndroid Build Coastguard Worker   Array<uint16_t> sigalgs;
748*8fb009dcSAndroid Build Coastguard Worker   if (!parse_sigalg_pairs(&sigalgs, values, num_values)) {
749*8fb009dcSAndroid Build Coastguard Worker     return 0;
750*8fb009dcSAndroid Build Coastguard Worker   }
751*8fb009dcSAndroid Build Coastguard Worker 
752*8fb009dcSAndroid Build Coastguard Worker   if (!SSL_set_signing_algorithm_prefs(ssl, sigalgs.data(), sigalgs.size()) ||
753*8fb009dcSAndroid Build Coastguard Worker       !SSL_set_verify_algorithm_prefs(ssl, sigalgs.data(), sigalgs.size())) {
754*8fb009dcSAndroid Build Coastguard Worker     return 0;
755*8fb009dcSAndroid Build Coastguard Worker   }
756*8fb009dcSAndroid Build Coastguard Worker 
757*8fb009dcSAndroid Build Coastguard Worker   return 1;
758*8fb009dcSAndroid Build Coastguard Worker }
759*8fb009dcSAndroid Build Coastguard Worker 
parse_sigalgs_list(Array<uint16_t> * out,const char * str)760*8fb009dcSAndroid Build Coastguard Worker static bool parse_sigalgs_list(Array<uint16_t> *out, const char *str) {
761*8fb009dcSAndroid Build Coastguard Worker   // str looks like "RSA+SHA1:ECDSA+SHA256:ecdsa_secp256r1_sha256".
762*8fb009dcSAndroid Build Coastguard Worker 
763*8fb009dcSAndroid Build Coastguard Worker   // Count colons to give the number of output elements from any successful
764*8fb009dcSAndroid Build Coastguard Worker   // parse.
765*8fb009dcSAndroid Build Coastguard Worker   size_t num_elements = 1;
766*8fb009dcSAndroid Build Coastguard Worker   size_t len = 0;
767*8fb009dcSAndroid Build Coastguard Worker   for (const char *p = str; *p; p++) {
768*8fb009dcSAndroid Build Coastguard Worker     len++;
769*8fb009dcSAndroid Build Coastguard Worker     if (*p == ':') {
770*8fb009dcSAndroid Build Coastguard Worker       num_elements++;
771*8fb009dcSAndroid Build Coastguard Worker     }
772*8fb009dcSAndroid Build Coastguard Worker   }
773*8fb009dcSAndroid Build Coastguard Worker 
774*8fb009dcSAndroid Build Coastguard Worker   if (!out->Init(num_elements)) {
775*8fb009dcSAndroid Build Coastguard Worker     return false;
776*8fb009dcSAndroid Build Coastguard Worker   }
777*8fb009dcSAndroid Build Coastguard Worker   size_t out_i = 0;
778*8fb009dcSAndroid Build Coastguard Worker 
779*8fb009dcSAndroid Build Coastguard Worker   enum {
780*8fb009dcSAndroid Build Coastguard Worker     pkey_or_name,
781*8fb009dcSAndroid Build Coastguard Worker     hash_name,
782*8fb009dcSAndroid Build Coastguard Worker   } state = pkey_or_name;
783*8fb009dcSAndroid Build Coastguard Worker 
784*8fb009dcSAndroid Build Coastguard Worker   char buf[kMaxSignatureAlgorithmNameLen];
785*8fb009dcSAndroid Build Coastguard Worker   // buf_used is always < sizeof(buf). I.e. it's always safe to write
786*8fb009dcSAndroid Build Coastguard Worker   // buf[buf_used] = 0.
787*8fb009dcSAndroid Build Coastguard Worker   size_t buf_used = 0;
788*8fb009dcSAndroid Build Coastguard Worker 
789*8fb009dcSAndroid Build Coastguard Worker   int pkey_type = 0, hash_nid = 0;
790*8fb009dcSAndroid Build Coastguard Worker 
791*8fb009dcSAndroid Build Coastguard Worker   // Note that the loop runs to len+1, i.e. it'll process the terminating NUL.
792*8fb009dcSAndroid Build Coastguard Worker   for (size_t offset = 0; offset < len+1; offset++) {
793*8fb009dcSAndroid Build Coastguard Worker     const unsigned char c = str[offset];
794*8fb009dcSAndroid Build Coastguard Worker 
795*8fb009dcSAndroid Build Coastguard Worker     switch (c) {
796*8fb009dcSAndroid Build Coastguard Worker       case '+':
797*8fb009dcSAndroid Build Coastguard Worker         if (state == hash_name) {
798*8fb009dcSAndroid Build Coastguard Worker           OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
799*8fb009dcSAndroid Build Coastguard Worker           ERR_add_error_dataf("+ found in hash name at offset %zu", offset);
800*8fb009dcSAndroid Build Coastguard Worker           return false;
801*8fb009dcSAndroid Build Coastguard Worker         }
802*8fb009dcSAndroid Build Coastguard Worker         if (buf_used == 0) {
803*8fb009dcSAndroid Build Coastguard Worker           OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
804*8fb009dcSAndroid Build Coastguard Worker           ERR_add_error_dataf("empty public key type at offset %zu", offset);
805*8fb009dcSAndroid Build Coastguard Worker           return false;
806*8fb009dcSAndroid Build Coastguard Worker         }
807*8fb009dcSAndroid Build Coastguard Worker         buf[buf_used] = 0;
808*8fb009dcSAndroid Build Coastguard Worker 
809*8fb009dcSAndroid Build Coastguard Worker         if (strcmp(buf, "RSA") == 0) {
810*8fb009dcSAndroid Build Coastguard Worker           pkey_type = EVP_PKEY_RSA;
811*8fb009dcSAndroid Build Coastguard Worker         } else if (strcmp(buf, "RSA-PSS") == 0 ||
812*8fb009dcSAndroid Build Coastguard Worker                    strcmp(buf, "PSS") == 0) {
813*8fb009dcSAndroid Build Coastguard Worker           pkey_type = EVP_PKEY_RSA_PSS;
814*8fb009dcSAndroid Build Coastguard Worker         } else if (strcmp(buf, "ECDSA") == 0) {
815*8fb009dcSAndroid Build Coastguard Worker           pkey_type = EVP_PKEY_EC;
816*8fb009dcSAndroid Build Coastguard Worker         } else {
817*8fb009dcSAndroid Build Coastguard Worker           OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
818*8fb009dcSAndroid Build Coastguard Worker           ERR_add_error_dataf("unknown public key type '%s'", buf);
819*8fb009dcSAndroid Build Coastguard Worker           return false;
820*8fb009dcSAndroid Build Coastguard Worker         }
821*8fb009dcSAndroid Build Coastguard Worker 
822*8fb009dcSAndroid Build Coastguard Worker         state = hash_name;
823*8fb009dcSAndroid Build Coastguard Worker         buf_used = 0;
824*8fb009dcSAndroid Build Coastguard Worker         break;
825*8fb009dcSAndroid Build Coastguard Worker 
826*8fb009dcSAndroid Build Coastguard Worker       case ':':
827*8fb009dcSAndroid Build Coastguard Worker         OPENSSL_FALLTHROUGH;
828*8fb009dcSAndroid Build Coastguard Worker       case 0:
829*8fb009dcSAndroid Build Coastguard Worker         if (buf_used == 0) {
830*8fb009dcSAndroid Build Coastguard Worker           OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
831*8fb009dcSAndroid Build Coastguard Worker           ERR_add_error_dataf("empty element at offset %zu", offset);
832*8fb009dcSAndroid Build Coastguard Worker           return false;
833*8fb009dcSAndroid Build Coastguard Worker         }
834*8fb009dcSAndroid Build Coastguard Worker 
835*8fb009dcSAndroid Build Coastguard Worker         buf[buf_used] = 0;
836*8fb009dcSAndroid Build Coastguard Worker 
837*8fb009dcSAndroid Build Coastguard Worker         if (state == pkey_or_name) {
838*8fb009dcSAndroid Build Coastguard Worker           // No '+' was seen thus this is a TLS 1.3-style name.
839*8fb009dcSAndroid Build Coastguard Worker           bool found = false;
840*8fb009dcSAndroid Build Coastguard Worker           for (const auto &candidate : kSignatureAlgorithmNames) {
841*8fb009dcSAndroid Build Coastguard Worker             if (strcmp(candidate.name, buf) == 0) {
842*8fb009dcSAndroid Build Coastguard Worker               assert(out_i < num_elements);
843*8fb009dcSAndroid Build Coastguard Worker               (*out)[out_i++] = candidate.signature_algorithm;
844*8fb009dcSAndroid Build Coastguard Worker               found = true;
845*8fb009dcSAndroid Build Coastguard Worker               break;
846*8fb009dcSAndroid Build Coastguard Worker             }
847*8fb009dcSAndroid Build Coastguard Worker           }
848*8fb009dcSAndroid Build Coastguard Worker 
849*8fb009dcSAndroid Build Coastguard Worker           if (!found) {
850*8fb009dcSAndroid Build Coastguard Worker             OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
851*8fb009dcSAndroid Build Coastguard Worker             ERR_add_error_dataf("unknown signature algorithm '%s'", buf);
852*8fb009dcSAndroid Build Coastguard Worker             return false;
853*8fb009dcSAndroid Build Coastguard Worker           }
854*8fb009dcSAndroid Build Coastguard Worker         } else {
855*8fb009dcSAndroid Build Coastguard Worker           if (strcmp(buf, "SHA1") == 0) {
856*8fb009dcSAndroid Build Coastguard Worker             hash_nid = NID_sha1;
857*8fb009dcSAndroid Build Coastguard Worker           } else if (strcmp(buf, "SHA256") == 0) {
858*8fb009dcSAndroid Build Coastguard Worker             hash_nid = NID_sha256;
859*8fb009dcSAndroid Build Coastguard Worker           } else if (strcmp(buf, "SHA384") == 0) {
860*8fb009dcSAndroid Build Coastguard Worker             hash_nid = NID_sha384;
861*8fb009dcSAndroid Build Coastguard Worker           } else if (strcmp(buf, "SHA512") == 0) {
862*8fb009dcSAndroid Build Coastguard Worker             hash_nid = NID_sha512;
863*8fb009dcSAndroid Build Coastguard Worker           } else {
864*8fb009dcSAndroid Build Coastguard Worker             OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
865*8fb009dcSAndroid Build Coastguard Worker             ERR_add_error_dataf("unknown hash function '%s'", buf);
866*8fb009dcSAndroid Build Coastguard Worker             return false;
867*8fb009dcSAndroid Build Coastguard Worker           }
868*8fb009dcSAndroid Build Coastguard Worker 
869*8fb009dcSAndroid Build Coastguard Worker           bool found = false;
870*8fb009dcSAndroid Build Coastguard Worker           for (const auto &candidate : kSignatureAlgorithmsMapping) {
871*8fb009dcSAndroid Build Coastguard Worker             if (candidate.pkey_type == pkey_type &&
872*8fb009dcSAndroid Build Coastguard Worker                 candidate.hash_nid == hash_nid) {
873*8fb009dcSAndroid Build Coastguard Worker               assert(out_i < num_elements);
874*8fb009dcSAndroid Build Coastguard Worker               (*out)[out_i++] = candidate.signature_algorithm;
875*8fb009dcSAndroid Build Coastguard Worker               found = true;
876*8fb009dcSAndroid Build Coastguard Worker               break;
877*8fb009dcSAndroid Build Coastguard Worker             }
878*8fb009dcSAndroid Build Coastguard Worker           }
879*8fb009dcSAndroid Build Coastguard Worker 
880*8fb009dcSAndroid Build Coastguard Worker           if (!found) {
881*8fb009dcSAndroid Build Coastguard Worker             OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
882*8fb009dcSAndroid Build Coastguard Worker             ERR_add_error_dataf("unknown pkey:%d hash:%s", pkey_type, buf);
883*8fb009dcSAndroid Build Coastguard Worker             return false;
884*8fb009dcSAndroid Build Coastguard Worker           }
885*8fb009dcSAndroid Build Coastguard Worker         }
886*8fb009dcSAndroid Build Coastguard Worker 
887*8fb009dcSAndroid Build Coastguard Worker         state = pkey_or_name;
888*8fb009dcSAndroid Build Coastguard Worker         buf_used = 0;
889*8fb009dcSAndroid Build Coastguard Worker         break;
890*8fb009dcSAndroid Build Coastguard Worker 
891*8fb009dcSAndroid Build Coastguard Worker       default:
892*8fb009dcSAndroid Build Coastguard Worker         if (buf_used == sizeof(buf) - 1) {
893*8fb009dcSAndroid Build Coastguard Worker           OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
894*8fb009dcSAndroid Build Coastguard Worker           ERR_add_error_dataf("substring too long at offset %zu", offset);
895*8fb009dcSAndroid Build Coastguard Worker           return false;
896*8fb009dcSAndroid Build Coastguard Worker         }
897*8fb009dcSAndroid Build Coastguard Worker 
898*8fb009dcSAndroid Build Coastguard Worker         if (OPENSSL_isalnum(c) || c == '-' || c == '_') {
899*8fb009dcSAndroid Build Coastguard Worker           buf[buf_used++] = c;
900*8fb009dcSAndroid Build Coastguard Worker         } else {
901*8fb009dcSAndroid Build Coastguard Worker           OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SIGNATURE_ALGORITHM);
902*8fb009dcSAndroid Build Coastguard Worker           ERR_add_error_dataf("invalid character 0x%02x at offest %zu", c,
903*8fb009dcSAndroid Build Coastguard Worker                               offset);
904*8fb009dcSAndroid Build Coastguard Worker           return false;
905*8fb009dcSAndroid Build Coastguard Worker         }
906*8fb009dcSAndroid Build Coastguard Worker     }
907*8fb009dcSAndroid Build Coastguard Worker   }
908*8fb009dcSAndroid Build Coastguard Worker 
909*8fb009dcSAndroid Build Coastguard Worker   assert(out_i == out->size());
910*8fb009dcSAndroid Build Coastguard Worker   return true;
911*8fb009dcSAndroid Build Coastguard Worker }
912*8fb009dcSAndroid Build Coastguard Worker 
SSL_CTX_set1_sigalgs_list(SSL_CTX * ctx,const char * str)913*8fb009dcSAndroid Build Coastguard Worker int SSL_CTX_set1_sigalgs_list(SSL_CTX *ctx, const char *str) {
914*8fb009dcSAndroid Build Coastguard Worker   Array<uint16_t> sigalgs;
915*8fb009dcSAndroid Build Coastguard Worker   if (!parse_sigalgs_list(&sigalgs, str)) {
916*8fb009dcSAndroid Build Coastguard Worker     return 0;
917*8fb009dcSAndroid Build Coastguard Worker   }
918*8fb009dcSAndroid Build Coastguard Worker 
919*8fb009dcSAndroid Build Coastguard Worker   if (!SSL_CTX_set_signing_algorithm_prefs(ctx, sigalgs.data(),
920*8fb009dcSAndroid Build Coastguard Worker                                            sigalgs.size()) ||
921*8fb009dcSAndroid Build Coastguard Worker       !SSL_CTX_set_verify_algorithm_prefs(ctx, sigalgs.data(),
922*8fb009dcSAndroid Build Coastguard Worker                                           sigalgs.size())) {
923*8fb009dcSAndroid Build Coastguard Worker     return 0;
924*8fb009dcSAndroid Build Coastguard Worker   }
925*8fb009dcSAndroid Build Coastguard Worker 
926*8fb009dcSAndroid Build Coastguard Worker   return 1;
927*8fb009dcSAndroid Build Coastguard Worker }
928*8fb009dcSAndroid Build Coastguard Worker 
SSL_set1_sigalgs_list(SSL * ssl,const char * str)929*8fb009dcSAndroid Build Coastguard Worker int SSL_set1_sigalgs_list(SSL *ssl, const char *str) {
930*8fb009dcSAndroid Build Coastguard Worker   if (!ssl->config) {
931*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
932*8fb009dcSAndroid Build Coastguard Worker     return 0;
933*8fb009dcSAndroid Build Coastguard Worker   }
934*8fb009dcSAndroid Build Coastguard Worker 
935*8fb009dcSAndroid Build Coastguard Worker   Array<uint16_t> sigalgs;
936*8fb009dcSAndroid Build Coastguard Worker   if (!parse_sigalgs_list(&sigalgs, str)) {
937*8fb009dcSAndroid Build Coastguard Worker     return 0;
938*8fb009dcSAndroid Build Coastguard Worker   }
939*8fb009dcSAndroid Build Coastguard Worker 
940*8fb009dcSAndroid Build Coastguard Worker   if (!SSL_set_signing_algorithm_prefs(ssl, sigalgs.data(), sigalgs.size()) ||
941*8fb009dcSAndroid Build Coastguard Worker       !SSL_set_verify_algorithm_prefs(ssl, sigalgs.data(), sigalgs.size())) {
942*8fb009dcSAndroid Build Coastguard Worker     return 0;
943*8fb009dcSAndroid Build Coastguard Worker   }
944*8fb009dcSAndroid Build Coastguard Worker 
945*8fb009dcSAndroid Build Coastguard Worker   return 1;
946*8fb009dcSAndroid Build Coastguard Worker }
947*8fb009dcSAndroid Build Coastguard Worker 
SSL_CTX_set_verify_algorithm_prefs(SSL_CTX * ctx,const uint16_t * prefs,size_t num_prefs)948*8fb009dcSAndroid Build Coastguard Worker int SSL_CTX_set_verify_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs,
949*8fb009dcSAndroid Build Coastguard Worker                                        size_t num_prefs) {
950*8fb009dcSAndroid Build Coastguard Worker   return set_sigalg_prefs(&ctx->verify_sigalgs,
951*8fb009dcSAndroid Build Coastguard Worker                           MakeConstSpan(prefs, num_prefs));
952*8fb009dcSAndroid Build Coastguard Worker }
953*8fb009dcSAndroid Build Coastguard Worker 
SSL_set_verify_algorithm_prefs(SSL * ssl,const uint16_t * prefs,size_t num_prefs)954*8fb009dcSAndroid Build Coastguard Worker int SSL_set_verify_algorithm_prefs(SSL *ssl, const uint16_t *prefs,
955*8fb009dcSAndroid Build Coastguard Worker                                    size_t num_prefs) {
956*8fb009dcSAndroid Build Coastguard Worker   if (!ssl->config) {
957*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
958*8fb009dcSAndroid Build Coastguard Worker     return 0;
959*8fb009dcSAndroid Build Coastguard Worker   }
960*8fb009dcSAndroid Build Coastguard Worker 
961*8fb009dcSAndroid Build Coastguard Worker   return set_sigalg_prefs(&ssl->config->verify_sigalgs,
962*8fb009dcSAndroid Build Coastguard Worker                           MakeConstSpan(prefs, num_prefs));
963*8fb009dcSAndroid Build Coastguard Worker }
964