summaryrefslogtreecommitdiff
path: root/lib/x509/key_encode.c
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2017-03-16 11:38:58 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2017-05-29 08:23:49 +0200
commit9e5452193c3510102801fd86b6e65d37b5dc1012 (patch)
tree1c401b3900c8a6f3ffac58ad839266e8c228f941 /lib/x509/key_encode.c
parent03c811b7f9a280182b486473567a0b93fe1dc291 (diff)
downloadgnutls-9e5452193c3510102801fd86b6e65d37b5dc1012.tar.gz
x509: implement RSA-PSS signature scheme
This patch enables RSA-PSS signature scheme in the X.509 functions and certtool. When creating RSA-PSS signature, there are 3 different scenarios: a. both a private key and a certificate are RSA-PSS b. the private key is RSA, while the certificate is RSA-PSS c. both the private key and the certificate are RSA For (a) and (b), the RSA-PSS parameters are read from the certificate. Any conflicts in parameters between the private key and the certificate are reported as an error. For (c), the sign functions, such as gnutls_x509_crt_privkey_sign() or gnutls_privkey_sign_data(), shall be instructed to generate an RSA-PSS signature. This can be done with the new flag GNUTLS_PRIVKEY_SIGN_FLAG_RSA_PSS. Verification is similar to signing, except for the case (c), use the flag GNUTLS_VERIFY_USE_RSA_PSS instead of GNUTLS_PRIVKEY_SIGN_FLAG_RSA_PSS. From the command line, certtool has a couple of new options: --rsa-pss and --rsa-pss-sign. The --rsa-pss option indicates that the generated private key or certificate is restricted to RSA-PSS, while the --rsa-pss-sign option indicates that the generated certificate is signed with RSA-PSS. For simplicity, there is no means of choosing arbitrary salt length. When it is not given by a private key or a certificate, it is automatically calculated from the underlying hash algorithm and the RSA modulus bits. [minor naming changes by nmav] Signed-off-by: Daiki Ueno <dueno@redhat.com> Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Diffstat (limited to 'lib/x509/key_encode.c')
-rw-r--r--lib/x509/key_encode.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/lib/x509/key_encode.c b/lib/x509/key_encode.c
index 3277ca2476..724f7402d9 100644
--- a/lib/x509/key_encode.c
+++ b/lib/x509/key_encode.c
@@ -144,6 +144,8 @@ _gnutls_x509_write_pubkey_params(gnutls_pk_algorithm_t algo,
memcpy(der->data, ASN1_NULL, ASN1_NULL_SIZE);
der->size = ASN1_NULL_SIZE;
return 0;
+ case GNUTLS_PK_RSA_PSS:
+ return _gnutls_x509_write_rsa_pss_params(&params->sign, der);
case GNUTLS_PK_EC:
return _gnutls_x509_write_ecc_params(params->flags, der);
default:
@@ -160,6 +162,7 @@ _gnutls_x509_write_pubkey(gnutls_pk_algorithm_t algo,
case GNUTLS_PK_DSA:
return _gnutls_x509_write_dsa_pubkey(params, der);
case GNUTLS_PK_RSA:
+ case GNUTLS_PK_RSA_PSS:
return _gnutls_x509_write_rsa_pubkey(params, der);
case GNUTLS_PK_EC:
return _gnutls_x509_write_ecc_pubkey(params, der);
@@ -285,6 +288,117 @@ _gnutls_x509_write_ecc_params(gnutls_ecc_curve_t curve,
return result;
}
+int
+_gnutls_x509_write_rsa_pss_params(gnutls_x509_spki_st *params,
+ gnutls_datum_t *der)
+{
+ int result;
+ ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+ const char *oid;
+ gnutls_datum_t tmp = { NULL, 0 };
+
+ der->data = NULL;
+ der->size = 0;
+
+ if ((result = asn1_create_element
+ (_gnutls_get_gnutls_asn(), "GNUTLS.RSAPSSParameters", &spk))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ oid = gnutls_digest_get_oid(params->dig);
+
+ if ((result = asn1_write_value(spk, "hashAlgorithm.algorithm", oid, 1))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_write_value(spk, "hashAlgorithm.parameters", NULL, 0))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result =
+ asn1_write_value(spk, "maskGenAlgorithm.algorithm",
+ PKIX1_RSA_PSS_MGF1_OID, 1))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_create_element
+ (_gnutls_get_pkix(), "PKIX1.AlgorithmIdentifier", &c2))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_write_value(c2, "algorithm", oid, 1))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_write_value(c2, "parameters", NULL, 0))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_der_encode(c2, "", &tmp, 0);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ if ((result =
+ asn1_write_value(spk, "maskGenAlgorithm.parameters",
+ tmp.data, tmp.size))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_write_uint32(spk, "saltLength",
+ params->salt_size);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_write_uint32(spk, "trailerField", 1);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_der_encode(spk, "", der, 0);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = 0;
+
+ cleanup:
+ _gnutls_free_datum(&tmp);
+ asn1_delete_structure(&c2);
+ asn1_delete_structure(&spk);
+ return result;
+}
+
/*
* This function writes the public parameters for DSS keys.
* Needs 1 parameter (y).
@@ -681,6 +795,7 @@ int _gnutls_asn1_encode_privkey(gnutls_pk_algorithm_t pk, ASN1_TYPE * c2,
{
switch (pk) {
case GNUTLS_PK_RSA:
+ case GNUTLS_PK_RSA_PSS:
return _gnutls_asn1_encode_rsa(c2, params, compat);
case GNUTLS_PK_DSA:
return _gnutls_asn1_encode_dsa(c2, params, compat);