]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Pass the signature algorithm lower in the verification stack
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 21 Jul 2017 21:56:20 +0000 (23:56 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 3 Aug 2017 09:57:52 +0000 (11:57 +0200)
This will allow enhancing the back-ends (PKCS#11 and ext) for
signing with the new signature algorithms like RSA-PSS and Ed25519.

Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
lib/abstract_int.h
lib/algorithms.h
lib/algorithms/sign.c
lib/privkey.c
lib/x509/crq.c
lib/x509/pkcs7.c
lib/x509/sign.c

index f82e4f922aa10d7142f902d2114e2035248199c1..2fefa2cf37b7211e1fb01303ccb860c25be1cba1 100644 (file)
@@ -81,14 +81,16 @@ int _gnutls_privkey_update_sign_params(gnutls_privkey_t key,
 void _gnutls_privkey_cleanup(gnutls_privkey_t key);
 
 int privkey_sign_and_hash_data(gnutls_privkey_t signer,
+                              const gnutls_sign_entry_st *se,
                               const gnutls_datum_t * data,
                               gnutls_datum_t * signature,
                               gnutls_x509_spki_st *params);
 int
 privkey_sign_raw_data(gnutls_privkey_t key,
-                            const gnutls_datum_t * data,
-                            gnutls_datum_t * signature,
-                            gnutls_x509_spki_st * params);
+                     const gnutls_sign_entry_st *se,
+                     const gnutls_datum_t * data,
+                     gnutls_datum_t * signature,
+                     gnutls_x509_spki_st * params);
 
 unsigned pubkey_to_bits(gnutls_pk_algorithm_t pk, gnutls_pk_params_st * params);
 int _gnutls_pubkey_compatible_with_sig(gnutls_session_t,
index 97404ec8c14a3b283093bfc85bec504c69983cc5..631675462ebdb4e668f4bf7a1b570c544cccaa03 100644 (file)
@@ -321,6 +321,7 @@ struct gnutls_sign_entry_st {
 typedef struct gnutls_sign_entry_st gnutls_sign_entry_st;
 
 const gnutls_sign_entry_st *_gnutls_sign_to_entry(gnutls_sign_algorithm_t sign);
+const gnutls_sign_entry_st *_gnutls_pk_to_sign_entry(gnutls_pk_algorithm_t, gnutls_digest_algorithm_t);
 
 gnutls_pk_algorithm_t _gnutls_x509_sign_to_pk(gnutls_sign_algorithm_t
                                              sign);
index 062d926fcf6fe500bf0da36fdc08ac23350a4ee4..eca76fa48762377d77f295a550a7cc948b2227d9 100644 (file)
@@ -281,6 +281,17 @@ gnutls_sign_algorithm_t gnutls_oid_to_sign(const char *oid)
        return ret;
 }
 
+const gnutls_sign_entry_st *_gnutls_pk_to_sign_entry(gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash)
+{
+       GNUTLS_SIGN_LOOP(
+               if (pk == p->pk && hash == p->hash) {
+                       return p;
+               }
+       );
+
+       return NULL;
+}
+
 /**
  * gnutls_pk_to_sign:
  * @pk: is a public key algorithm
@@ -294,18 +305,12 @@ gnutls_sign_algorithm_t gnutls_oid_to_sign(const char *oid)
 gnutls_sign_algorithm_t
 gnutls_pk_to_sign(gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash)
 {
-       gnutls_sign_algorithm_t ret = 0;
+       const gnutls_sign_entry_st *e;
 
-       GNUTLS_SIGN_LOOP(
-               if (pk == p->pk && hash == p->hash) {
-                       ret = p->id;
-                       break;
-               }
-       );
-
-       if (ret == 0)
+       e = _gnutls_pk_to_sign_entry(pk, hash);
+       if (e == NULL)
                return GNUTLS_SIGN_UNKNOWN;
-       return ret;
+       return e->id;
 }
 
 /**
index e026ca48953cf66e9a560847408884ee3bc296e2..911829de16b5ce6a7dd3f095fc355f86e87762ba 100644 (file)
 
 static int
 privkey_sign_prehashed(gnutls_privkey_t signer,
-                 const gnutls_datum_t * hash_data,
-                 gnutls_datum_t * signature,
-                 gnutls_x509_spki_st * params, unsigned flags);
+                      const gnutls_sign_entry_st *se,
+                      const gnutls_datum_t * hash_data,
+                      gnutls_datum_t * signature,
+                      gnutls_x509_spki_st * params, unsigned flags);
 
 /**
  * gnutls_privkey_get_type:
@@ -1007,7 +1008,7 @@ gnutls_privkey_sign_data(gnutls_privkey_t signer,
                return ret;
        }
 
-       return privkey_sign_and_hash_data(signer, data, signature, &params);
+       return privkey_sign_and_hash_data(signer, _gnutls_pk_to_sign_entry(params.pk, hash), data, signature, &params);
 }
 
 /**
@@ -1059,7 +1060,7 @@ gnutls_privkey_sign_data2(gnutls_privkey_t signer,
                return ret;
        }
 
-       return privkey_sign_and_hash_data(signer, data, signature, &params);
+       return privkey_sign_and_hash_data(signer, _gnutls_sign_to_entry(algo), data, signature, &params);
 }
 
 /**
@@ -1099,10 +1100,10 @@ gnutls_privkey_sign_hash2(gnutls_privkey_t signer,
 {
        int ret;
        gnutls_x509_spki_st params;
-       const gnutls_sign_entry_st *e;
+       const gnutls_sign_entry_st *se;
 
-       e = _gnutls_sign_to_entry(algo);
-       if (e == NULL)
+       se = _gnutls_sign_to_entry(algo);
+       if (se == NULL)
                return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
        ret = _gnutls_privkey_get_sign_params(signer, &params);
@@ -1111,18 +1112,19 @@ gnutls_privkey_sign_hash2(gnutls_privkey_t signer,
                return ret;
        }
 
-       ret = _gnutls_privkey_update_sign_params(signer, e->pk, e->hash,
+       ret = _gnutls_privkey_update_sign_params(signer, se->pk, se->hash,
                                                 flags, &params);
        if (ret < 0) {
                gnutls_assert();
                return ret;
        }
 
-       return privkey_sign_prehashed(signer, hash_data, signature, &params, flags);
+       return privkey_sign_prehashed(signer, se, hash_data, signature, &params, flags);
 }
 
 int
 privkey_sign_and_hash_data(gnutls_privkey_t signer,
+                          const gnutls_sign_entry_st *se,
                           const gnutls_datum_t * data,
                           gnutls_datum_t * signature,
                           gnutls_x509_spki_st * params)
@@ -1131,34 +1133,30 @@ privkey_sign_and_hash_data(gnutls_privkey_t signer,
        gnutls_datum_t digest;
        const mac_entry_st *me;
 
-       if (_gnutls_pk_is_not_prehashed(signer->pk_algorithm)) {
-               if (params->dig != GNUTLS_DIG_UNKNOWN &&
-                   gnutls_pk_to_sign(params->pk, params->dig) == GNUTLS_SIGN_UNKNOWN)
-                       return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+       if (se == NULL)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
-               return privkey_sign_raw_data(signer, data, signature, params);
+       if (_gnutls_pk_is_not_prehashed(se->pk)) {
+               return privkey_sign_raw_data(signer, se, data, signature, params);
        }
 
-       if (gnutls_pk_to_sign(params->pk, params->dig) == GNUTLS_SIGN_UNKNOWN)
-               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-
-       me = hash_to_entry(params->dig);
+       me = hash_to_entry(se->hash);
        if (me == NULL)
                return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
-       ret = pk_hash_data(params->pk, me, NULL, data, &digest);
+       ret = pk_hash_data(se->pk, me, NULL, data, &digest);
        if (ret < 0) {
                gnutls_assert();
                return ret;
        }
 
-       ret = pk_prepare_hash(params->pk, me, &digest);
+       ret = pk_prepare_hash(se->pk, me, &digest);
        if (ret < 0) {
                gnutls_assert();
                goto cleanup;
        }
 
-       ret = privkey_sign_raw_data(signer, &digest, signature, params);
+       ret = privkey_sign_raw_data(signer, se, &digest, signature, params);
        _gnutls_free_datum(&digest);
 
        if (ret < 0) {
@@ -1225,21 +1223,24 @@ gnutls_privkey_sign_hash(gnutls_privkey_t signer,
                return ret;
        }
 
-       return privkey_sign_prehashed(signer, hash_data, signature, &params, flags);
+       return privkey_sign_prehashed(signer, _gnutls_pk_to_sign_entry(params.pk, hash_algo),
+                                     hash_data, signature, &params, flags);
 }
 
 static int
 privkey_sign_prehashed(gnutls_privkey_t signer,
-                 const gnutls_datum_t * hash_data,
-                 gnutls_datum_t * signature,
-                 gnutls_x509_spki_st * params,
-                 unsigned flags)
+                      const gnutls_sign_entry_st *se,
+                      const gnutls_datum_t * hash_data,
+                      gnutls_datum_t * signature,
+                      gnutls_x509_spki_st * params,
+                      unsigned flags)
 {
        int ret;
        gnutls_datum_t digest;
 
        if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)
                return privkey_sign_raw_data(signer,
+                                            se,
                                             hash_data, signature,
                                             params);
 
@@ -1247,6 +1248,9 @@ privkey_sign_prehashed(gnutls_privkey_t signer,
                return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
        }
 
+       if (se == NULL)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
        digest.data = gnutls_malloc(hash_data->size);
        if (digest.data == NULL) {
                gnutls_assert();
@@ -1255,13 +1259,14 @@ privkey_sign_prehashed(gnutls_privkey_t signer,
        digest.size = hash_data->size;
        memcpy(digest.data, hash_data->data, digest.size);
 
-       ret = pk_prepare_hash(params->pk, hash_to_entry(params->dig), &digest);
+       ret = pk_prepare_hash(se->pk, hash_to_entry(se->hash), &digest);
        if (ret < 0) {
                gnutls_assert();
                goto cleanup;
        }
 
        ret = privkey_sign_raw_data(signer,
+                                   se,
                                    &digest, signature,
                                    params);
        if (ret < 0) {
@@ -1299,10 +1304,18 @@ privkey_sign_prehashed(gnutls_privkey_t signer,
  -*/
 int
 privkey_sign_raw_data(gnutls_privkey_t key,
-                    const gnutls_datum_t * data,
-                    gnutls_datum_t * signature,
-                    gnutls_x509_spki_st * params)
+                     const gnutls_sign_entry_st *se,
+                     const gnutls_datum_t * data,
+                     gnutls_datum_t * signature,
+                     gnutls_x509_spki_st * params)
 {
+       gnutls_pk_algorithm_t pk;
+
+       if (se == NULL) /* it can be null when signing raw-rsa */
+               pk = params->pk;
+       else
+               pk = se->pk;
+
        switch (key->type) {
 #ifdef ENABLE_PKCS11
        case GNUTLS_PRIVKEY_PKCS11:
@@ -1310,7 +1323,7 @@ privkey_sign_raw_data(gnutls_privkey_t key,
                                                        data, signature);
 #endif
        case GNUTLS_PRIVKEY_X509:
-               return _gnutls_pk_sign(params->pk, signature, data,
+               return _gnutls_pk_sign(pk, signature, data,
                                       &key->key.x509->params, params);
        case GNUTLS_PRIVKEY_EXT:
                if (key->key.ext.sign_func == NULL)
index 0f91278b4ec358aa6e3c59566126d52dd9cd46d3..fc90e3296d74c91fb0d7a6f3a7f60d6a385302a8 100644 (file)
@@ -2862,7 +2862,8 @@ gnutls_x509_crq_privkey_sign(gnutls_x509_crq_t crq, gnutls_privkey_t key,
                return result;
        }
 
-       result = privkey_sign_and_hash_data(key, &tbs, &signature, &params);
+       result = privkey_sign_and_hash_data(key, _gnutls_pk_to_sign_entry(params.pk, dig),
+                                           &tbs, &signature, &params);
        gnutls_free(tbs.data);
 
        if (result < 0) {
index c0b0810b0cf37cfbdab756f9282a816cd3ae9d77..4bb8d863a80dd1aec7873f7de1087153ec5b4447 100644 (file)
@@ -2536,7 +2536,8 @@ int gnutls_pkcs7_sign(gnutls_pkcs7_t pkcs7,
                goto cleanup;
        }
 
-       ret = privkey_sign_and_hash_data(signer_key, &sigdata, &signature, &params);
+       ret = privkey_sign_and_hash_data(signer_key, _gnutls_pk_to_sign_entry(params.pk, dig),
+                                        &sigdata, &signature, &params);
        if (ret < 0) {
                gnutls_assert();
                goto cleanup;
index dd688ea9abeee8100c62cceceabff8ed89a00400..8a00d7741111d2d9502d9d5beaee1733d2878cc4 100644 (file)
@@ -111,6 +111,7 @@ _gnutls_x509_pkix_sign(ASN1_TYPE src, const char *src_name,
        char name[128];
        gnutls_pk_algorithm_t pk;
        gnutls_x509_spki_st key_params, params;
+       const gnutls_sign_entry_st *se;
 
        pk = gnutls_x509_crt_get_pk_algorithm(issuer, NULL);
        if (pk == GNUTLS_PK_UNKNOWN)
@@ -168,10 +169,12 @@ _gnutls_x509_pkix_sign(ASN1_TYPE src, const char *src_name,
                return result;
        }
 
-       if (_gnutls_pk_is_not_prehashed(issuer_key->pk_algorithm)) {
-               result = privkey_sign_raw_data(issuer_key, &tbs, &signature, &params);
+       se = _gnutls_pk_to_sign_entry(params.pk, dig);
+       if (_gnutls_pk_is_not_prehashed(params.pk)) {
+               result = privkey_sign_raw_data(issuer_key, se, &tbs, &signature, &params);
        } else {
-               result = privkey_sign_and_hash_data(issuer_key, &tbs, &signature, &params);
+               result = privkey_sign_and_hash_data(issuer_key, se,
+                                                   &tbs, &signature, &params);
        }
        gnutls_free(tbs.data);