Adding RSA-PSS signature algorithms.

[Rebased and tests added by davidben.]

In doing so, regenerate the test RSA certificate to be 2048-bit RSA.
RSA-PSS with SHA-512 is actually too large for 1024-bit RSA. Also make
the sigalg test loop test versions that do and don't work which subsumes
the ecdsa_sha1 TLS 1.3 test.

For now, RSA-PKCS1 is still allowed because NSS has yet to implement
RSA-PSS and we'd like to avoid complicated interop testing.

Change-Id: I686b003ef7042ff757bdaab8d5838b7a4d6edd87
Reviewed-on: https://boringssl-review.googlesource.com/8613
Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
Steven Valdez 2016-07-06 14:24:47 -04:00 committed by David Benjamin
parent 0c22295668
commit eff1e8d9c7
6 changed files with 234 additions and 89 deletions

View File

@ -253,6 +253,9 @@ extern "C" {
#define SSL_SIGN_ECDSA_SECP256R1_SHA256 0x0403
#define SSL_SIGN_ECDSA_SECP384R1_SHA384 0x0503
#define SSL_SIGN_ECDSA_SECP521R1_SHA512 0x0603
#define SSL_SIGN_RSA_PSS_SHA256 0x0700
#define SSL_SIGN_RSA_PSS_SHA384 0x0701
#define SSL_SIGN_RSA_PSS_SHA512 0x0702
/* Reserved SignatureScheme value to indicate RSA with MD5-SHA1. This will never
* be negotiated in TLS 1.2 and up, but is used to unify signing interfaces in

View File

@ -401,6 +401,9 @@ size_t ssl_private_key_max_signature_len(SSL *ssl) {
return EVP_PKEY_size(ssl->cert->privatekey);
}
/* TODO(davidben): Forbid RSA-PKCS1 in TLS 1.3. For now we allow it because NSS
* has yet to start doing RSA-PSS, so enforcing it would complicate interop
* testing. */
static int is_rsa_pkcs1(const EVP_MD **out_md, uint16_t sigalg) {
switch (sigalg) {
case SSL_SIGN_RSA_PKCS1_MD5_SHA1:
@ -530,6 +533,61 @@ static int ssl_verify_ecdsa(SSL *ssl, const uint8_t *signature,
return ret;
}
static int is_rsa_pss(const EVP_MD **out_md, uint16_t sigalg) {
switch (sigalg) {
case SSL_SIGN_RSA_PSS_SHA256:
*out_md = EVP_sha256();
return 1;
case SSL_SIGN_RSA_PSS_SHA384:
*out_md = EVP_sha384();
return 1;
case SSL_SIGN_RSA_PSS_SHA512:
*out_md = EVP_sha512();
return 1;
default:
return 0;
}
}
static int ssl_sign_rsa_pss(SSL *ssl, uint8_t *out, size_t *out_len,
size_t max_out, const EVP_MD *md,
const uint8_t *in, size_t in_len) {
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
*out_len = max_out;
EVP_PKEY_CTX *pctx;
int ret =
EVP_DigestSignInit(&ctx, &pctx, md, NULL, ssl->cert->privatekey) &&
EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) &&
EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) &&
EVP_DigestSignUpdate(&ctx, in, in_len) &&
EVP_DigestSignFinal(&ctx, out, out_len);
EVP_MD_CTX_cleanup(&ctx);
return ret;
}
static int ssl_verify_rsa_pss(SSL *ssl, const uint8_t *signature,
size_t signature_len, const EVP_MD *md,
EVP_PKEY *pkey, const uint8_t *in,
size_t in_len) {
if (pkey->type != EVP_PKEY_RSA) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
EVP_MD_CTX md_ctx;
EVP_MD_CTX_init(&md_ctx);
EVP_PKEY_CTX *pctx;
int ret =
EVP_DigestVerifyInit(&md_ctx, &pctx, md, NULL, pkey) &&
EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) &&
EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) &&
EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
EVP_MD_CTX_cleanup(&md_ctx);
return ret;
}
enum ssl_private_key_result_t ssl_private_key_sign(
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
uint16_t signature_algorithm, const uint8_t *in, size_t in_len) {
@ -562,6 +620,7 @@ enum ssl_private_key_result_t ssl_private_key_sign(
? ssl_private_key_success
: ssl_private_key_failure;
}
int curve;
if (is_ecdsa(&curve, &md, signature_algorithm)) {
return ssl_sign_ecdsa(ssl, out, out_len, max_out, curve, md, in, in_len)
@ -569,6 +628,13 @@ enum ssl_private_key_result_t ssl_private_key_sign(
: ssl_private_key_failure;
}
if (is_rsa_pss(&md, signature_algorithm) &&
ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return ssl_sign_rsa_pss(ssl, out, out_len, max_out, md, in, in_len)
? ssl_private_key_success
: ssl_private_key_failure;
}
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return ssl_private_key_failure;
}
@ -587,12 +653,19 @@ int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
return ssl_verify_rsa_pkcs1(ssl, signature, signature_len, md, pkey, in,
in_len);
}
int curve;
if (is_ecdsa(&curve, &md, signature_algorithm)) {
return ssl_verify_ecdsa(ssl, signature, signature_len, curve, md, pkey, in,
in_len);
}
if (is_rsa_pss(&md, signature_algorithm) &&
ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return ssl_verify_rsa_pss(ssl, signature, signature_len, md, pkey, in,
in_len);
}
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
@ -652,5 +725,10 @@ int ssl_private_key_supports_signature_algorithm(SSL *ssl,
return 1;
}
if (is_rsa_pss(&md, signature_algorithm)) {
return ssl_private_key_type(ssl) == EVP_PKEY_RSA &&
ssl3_protocol_version(ssl) >= TLS1_3_VERSION;
}
return 0;
}

View File

@ -517,7 +517,37 @@ static const uint16_t kDefaultSignatureAlgorithms[] = {
SSL_SIGN_ECDSA_SHA1,
};
static const uint16_t kDefaultTLS13SignatureAlgorithms[] = {
SSL_SIGN_RSA_PSS_SHA512,
SSL_SIGN_RSA_PKCS1_SHA512,
SSL_SIGN_ECDSA_SECP521R1_SHA512,
SSL_SIGN_RSA_PSS_SHA384,
SSL_SIGN_RSA_PKCS1_SHA384,
SSL_SIGN_ECDSA_SECP384R1_SHA384,
SSL_SIGN_RSA_PSS_SHA256,
SSL_SIGN_RSA_PKCS1_SHA256,
SSL_SIGN_ECDSA_SECP256R1_SHA256,
SSL_SIGN_RSA_PKCS1_SHA1,
SSL_SIGN_ECDSA_SHA1,
};
size_t tls12_get_psigalgs(SSL *ssl, const uint16_t **psigs) {
uint16_t version;
if (ssl->s3->have_version) {
version = ssl3_protocol_version(ssl);
} else {
version = ssl->method->version_from_wire(ssl->client_version);
}
if (version >= TLS1_3_VERSION) {
*psigs = kDefaultTLS13SignatureAlgorithms;
return sizeof(kDefaultTLS13SignatureAlgorithms) /
sizeof(kDefaultTLS13SignatureAlgorithms[0]);
}
*psigs = kDefaultSignatureAlgorithms;
return sizeof(kDefaultSignatureAlgorithms) /
sizeof(kDefaultSignatureAlgorithms[0]);
@ -561,6 +591,9 @@ void ssl_set_client_disabled(SSL *ssl) {
sigalgslen = tls12_get_psigalgs(ssl, &sigalgs);
for (i = 0; i < sigalgslen; i++) {
switch (sigalgs[i]) {
case SSL_SIGN_RSA_PSS_SHA512:
case SSL_SIGN_RSA_PSS_SHA384:
case SSL_SIGN_RSA_PSS_SHA256:
case SSL_SIGN_RSA_PKCS1_SHA512:
case SSL_SIGN_RSA_PKCS1_SHA384:
case SSL_SIGN_RSA_PKCS1_SHA256:
@ -2571,9 +2604,8 @@ int tls1_choose_signature_algorithm(SSL *ssl, uint16_t *out) {
return 1;
}
const uint16_t *sigalgs = kDefaultSignatureAlgorithms;
size_t sigalgs_len = sizeof(kDefaultSignatureAlgorithms) /
sizeof(kDefaultSignatureAlgorithms[0]);
const uint16_t *sigalgs;
size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs);
if (cert->sigalgs != NULL) {
sigalgs = cert->sigalgs;
sigalgs_len = cert->sigalgs_len;

View File

@ -1,15 +1,22 @@
-----BEGIN CERTIFICATE-----
MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci
HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV
W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV
HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f
Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht
ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr
T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f
j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==
MIIDtTCCAp2gAwIBAgIJALW2IrlaBKUhMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTYwNzA5MDQzODA5WhcNMTYwODA4MDQzODA5WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAugvahBkSAUF1fC49vb1bvlPrcl80kop1iLpiuYoz4Qptwy57+EWssZBc
HprZ5BkWf6PeGZ7F5AX1PyJbGHZLqvMCvViP6pd4MFox/igESISEHEixoiXCzepB
rhtp5UQSjHD4D4hKtgdMgVxX+LRtwgW3mnu/vBu7rzpr/DS8io99p3lqZ1Aky+aN
lcMj6MYy8U+YFEevb/V0lRY9oqwmW7BHnXikm/vi6sjIS350U8zb/mRzYeIs2R65
LUduTL50+UMgat9ocewI2dv8aO9Dph+8NdGtg8LFYyTTHcUxJoMr1PTOgnmET19W
JH4PrFwk7ZE1QJQQ1L4iKmPeQistuQIDAQABo4GnMIGkMB0GA1UdDgQWBBT5m6Vv
zYjVYHG30iBE+j2XDhUE8jB1BgNVHSMEbjBsgBT5m6VvzYjVYHG30iBE+j2XDhUE
8qFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJALW2IrlaBKUhMAwGA1UdEwQF
MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAD7Jg68SArYWlcoHfZAB90Pmyrt5H6D8
LRi+W2Ri1fBNxREELnezWJ2scjl4UMcsKYp4Pi950gVN+62IgrImcCNvtb5I1Cfy
/MNNur9ffas6X334D0hYVIQTePyFk3umI+2mJQrtZZyMPIKSY/sYGQHhGGX6wGK+
GO/og0PQk/Vu6D+GU2XRnDV0YZg1lsAsHd21XryK6fDmNkEMwbIWrts4xc7scRrG
HWy+iMf6/7p/Ak/SIicM4XSwmlQ8pPxAZPr+E2LoVd9pMpWUwpW2UbtO5wsGTrY5
sO45tFNN/y+jtUheB1C2ijObG/tXELaiyCdM+S/waeuv0MXtI4xnn1A=
-----END CERTIFICATE-----

View File

@ -1,15 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -4679,6 +4679,9 @@ var testSignatureAlgorithms = []struct {
{"ECDSA-P256-SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP256},
{"ECDSA-P384-SHA384", signatureECDSAWithP384AndSHA384, testCertECDSAP384},
{"ECDSA-P521-SHA512", signatureECDSAWithP521AndSHA512, testCertECDSAP521},
{"RSA-PSS-SHA256", signatureRSAPSSWithSHA256, testCertRSA},
{"RSA-PSS-SHA384", signatureRSAPSSWithSHA384, testCertRSA},
{"RSA-PSS-SHA512", signatureRSAPSSWithSHA512, testCertRSA},
}
const fakeSigAlg1 signatureAlgorithm = 0x2a01
@ -4693,12 +4696,27 @@ func addSignatureAlgorithmTests() {
continue
}
var shouldFail bool
// ecdsa_sha1 does not exist in TLS 1.3.
if ver.version == VersionTLS13 && alg.id == signatureECDSAWithSHA1 {
continue
if ver.version >= VersionTLS13 && alg.id == signatureECDSAWithSHA1 {
shouldFail = true
}
// RSA-PSS does not exist in TLS 1.2.
if ver.version == VersionTLS12 && hasComponent(alg.name, "PSS") {
shouldFail = true
}
var signError, verifyError string
if shouldFail {
signError = ":NO_COMMON_SIGNATURE_ALGORITHMS:"
verifyError = ":WRONG_SIGNATURE_TYPE:"
}
suffix := "-" + alg.name + "-" + ver.name
// TODO(davidben): Separate signing and verifying sigalg
// configuration in Go, so we can run both sides.
if !shouldFail {
testCases = append(testCases, testCase{
name: "SigningHash-ClientAuth-Sign" + suffix,
config: Config{
@ -4741,6 +4759,7 @@ func addSignatureAlgorithmTests() {
"-enable-all-curves",
},
})
}
testCases = append(testCases, testCase{
testType: serverTest,
@ -4756,12 +4775,18 @@ func addSignatureAlgorithmTests() {
alg.id,
fakeSigAlg2,
},
Bugs: ProtocolBugs{
SkipECDSACurveCheck: shouldFail,
IgnoreSignatureVersionChecks: shouldFail,
},
},
flags: []string{
"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
"-enable-all-curves",
},
shouldFail: shouldFail,
expectedError: signError,
expectedPeerSignatureAlgorithm: alg.id,
})
@ -4777,11 +4802,17 @@ func addSignatureAlgorithmTests() {
SignatureAlgorithms: []signatureAlgorithm{
alg.id,
},
Bugs: ProtocolBugs{
SkipECDSACurveCheck: shouldFail,
IgnoreSignatureVersionChecks: shouldFail,
},
},
flags: []string{
"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)),
"-enable-all-curves",
},
shouldFail: shouldFail,
expectedError: verifyError,
})
}
}
@ -5123,24 +5154,6 @@ func addSignatureAlgorithmTests() {
},
expectedPeerSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
})
// ecdsa_sha1 cannot be negotiated in TLS 1.3.
testCases = append(testCases, testCase{
name: "NoECDSAWithSHA1-TLS13",
config: Config{
MaxVersion: VersionTLS13,
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
Certificates: []Certificate{ecdsaP256Certificate},
SignatureAlgorithms: []signatureAlgorithm{
signatureECDSAWithSHA1,
},
Bugs: ProtocolBugs{
SkipECDSACurveCheck: true,
},
},
shouldFail: true,
expectedError: ":WRONG_SIGNATURE_TYPE:",
})
}
// timeouts is the retransmit schedule for BoringSSL. It doubles and