/** * gnutls_privkey_sign_data: * @signer: Holds the key * @digest: should be a digest algorithm * @flags: should be 0 for now * @data: holds the data to be signed * @signature: will contain the signature allocate with gnutls_malloc() * * This function will sign the given data using a signature algorithm * supported by the private key. Signature algorithms are always used * together with a hash functions. Different hash functions may be * used for the RSA algorithm, but only SHA-1 for the DSA keys. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ int gnutls_privkey_sign_data2 (gnutls_privkey_t signer, gnutls_digest_algorithm_t hash, unsigned int flags, const gnutls_datum_t * data, gnutls_datum_t * signature) { int ret; gnutls_datum_t digest; ret = pk_hash_data (signer->pk_algorithm, hash, NULL, data, &digest); if (ret < 0) { gnutls_assert (); return ret; } ret = pk_prepare_hash (signer->pk_algorithm, hash, &digest); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = _gnutls_privkey_sign_hash (signer, &digest, signature); _gnutls_free_datum (&digest); if (ret < 0) { gnutls_assert (); return ret; } return 0; cleanup: _gnutls_free_datum (&digest); return ret; }
/** * gnutls_privkey_sign_hash2: * @signer: Holds the signer's key * @hash_algo: The hash algorithm used * @flags: zero for now * @hash_data: holds the data to be signed * @signature: will contain newly allocated signature * * This function will sign the given hashed data using a signature algorithm * supported by the private key. Signature algorithms are always used * together with a hash functions. Different hash functions may be * used for the RSA algorithm, but only SHA-XXX for the DSA keys. * * Use gnutls_x509_crt_get_preferred_hash_algorithm() to determine * the hash algorithm. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ int gnutls_privkey_sign_hash2 (gnutls_privkey_t signer, gnutls_digest_algorithm_t hash_algo, unsigned int flags, const gnutls_datum_t * hash_data, gnutls_datum_t * signature) { int ret; gnutls_datum_t digest; digest.data = gnutls_malloc (hash_data->size); if (digest.data == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } digest.size = hash_data->size; memcpy (digest.data, hash_data->data, digest.size); ret = pk_prepare_hash (signer->pk_algorithm, hash_algo, &digest); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = _gnutls_privkey_sign_hash (signer, &digest, signature); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = 0; cleanup: _gnutls_free_datum (&digest); return ret; }
/* This will create a PKCS1 or DSA signature, as defined in the TLS protocol. * Cert is the certificate of the corresponding private key. It is only checked if * it supports signing. */ static int sign_tls_hash (gnutls_session_t session, gnutls_digest_algorithm_t hash_algo, gnutls_pcert_st* cert, gnutls_privkey_t pkey, const gnutls_datum_t * hash_concat, gnutls_datum_t * signature) { gnutls_protocol_t ver = gnutls_protocol_get_version (session); unsigned int key_usage = 0; /* If our certificate supports signing */ if (cert != NULL) { gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage); if (key_usage != 0) if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) { gnutls_assert (); return GNUTLS_E_KEY_USAGE_VIOLATION; } /* External signing. */ if (!pkey) { if (!session->internals.sign_func) return GNUTLS_E_INSUFFICIENT_CREDENTIALS; return (*session->internals.sign_func) (session, session->internals.sign_func_userdata, cert->type, &cert->cert, hash_concat, signature); } } if (!_gnutls_version_has_selectable_sighash (ver)) return _gnutls_privkey_sign_hash (pkey, hash_concat, signature); else return gnutls_privkey_sign_hash (pkey, hash_algo, 0, hash_concat, signature); }