/** * gnutls_privkey_sign_hash: * @signer: Holds the signer's key * @hash_algo: The hash algorithm used * @flags: Zero or one of %gnutls_privkey_flags_t * @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. * * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine * the hash algorithm. * * Note that if %GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA flag is specified this function * will ignore @hash_algo and perform a raw PKCS1 signature. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 2.12.0 **/ int gnutls_privkey_sign_hash(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; if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA) return gnutls_privkey_sign_raw_data(signer, flags, hash_data, signature); 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, mac_to_entry(hash_algo), &digest); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_privkey_sign_raw_data(signer, flags, &digest, signature); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = 0; cleanup: _gnutls_free_datum(&digest); return ret; }
/** * gnutls_privkey_sign_data: * @signer: Holds the key * @hash: should be a digest algorithm * @flags: Zero or one of %gnutls_privkey_flags_t * @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 the SHA family for the DSA keys. * * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine * the hash algorithm. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 2.12.0 **/ int gnutls_privkey_sign_data(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; const mac_entry_st *me = mac_to_entry(hash); if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); ret = pk_hash_data(signer->pk_algorithm, me, NULL, data, &digest); if (ret < 0) { gnutls_assert(); return ret; } ret = pk_prepare_hash(signer->pk_algorithm, me, &digest); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_privkey_sign_raw_data(signer, flags, &digest, signature); _gnutls_free_datum(&digest); if (ret < 0) { gnutls_assert(); return ret; } return 0; cleanup: _gnutls_free_datum(&digest); return ret; }
/*- * _gnutls_x509_privkey_sign_hash2: * @signer: Holds the signer's key * @hash_algo: The hash algorithm used * @hash_data: holds the data to be signed * @signature: will contain newly allocated signature * @flags: (0) for now * * 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-1,SHA-224 and SHA-256 * for the DSA keys, depending on their bit size. * * Use gnutls_x509_crt_get_preferred_hash_algorithm() to determine * the hash algorithm. * * The RSA algorithm is used in PKCS #1 v1.5 mode. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. -*/ static int _gnutls_x509_privkey_sign_hash2 (gnutls_x509_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_soft_sign (signer->pk_algorithm, &signer->params, &digest, signature); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = 0; cleanup: _gnutls_free_datum (&digest); return ret; }
/** * 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; }
/* 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, const mac_entry_st * hash_algo, gnutls_pcert_st * cert, gnutls_privkey_t pkey, const gnutls_datum_t * hash_concat, gnutls_datum_t * signature) { const version_entry_st *ver = 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(); _gnutls_audit_log(session, "Peer's certificate does not allow digital signatures. Key usage violation detected (ignored).\n"); } /* External signing. Deprecated. To be removed. */ if (!pkey) { int ret; if (!session->internals.sign_func) return gnutls_assert_val (GNUTLS_E_INSUFFICIENT_CREDENTIALS); if (!_gnutls_version_has_selectable_sighash(ver)) return (*session->internals.sign_func) (session, session->internals.sign_func_userdata, cert->type, &cert->cert, hash_concat, signature); else { gnutls_datum_t digest; ret = _gnutls_set_datum(&digest, hash_concat->data, hash_concat->size); if (ret < 0) return gnutls_assert_val(ret); ret = pk_prepare_hash (gnutls_pubkey_get_pk_algorithm (cert->pubkey, NULL), hash_algo, &digest); if (ret < 0) { gnutls_assert(); goto es_cleanup; } ret = (*session->internals.sign_func) (session, session->internals.sign_func_userdata, cert->type, &cert->cert, &digest, signature); es_cleanup: gnutls_free(digest.data); return ret; } } } if (!_gnutls_version_has_selectable_sighash(ver)) return gnutls_privkey_sign_raw_data(pkey, 0, hash_concat, signature); else return gnutls_privkey_sign_hash(pkey, (gnutls_digest_algorithm_t)hash_algo->id, 0, hash_concat, signature); }
/** * cdk_pk_verify: * @pk: the public key * @sig: signature * @md: the message digest * * Verify the signature in @sig and compare it with the message digest in @md. **/ cdk_error_t cdk_pk_verify(cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md) { gnutls_datum_t s_sig = { NULL, 0 }, di = { NULL, 0}; byte *encmd = NULL; cdk_error_t rc; int ret, algo; unsigned int i; gnutls_pk_params_st params; const mac_entry_st *me; if (!pk || !sig || !md) { gnutls_assert(); return CDK_Inv_Value; } if (is_DSA(pk->pubkey_algo)) algo = GNUTLS_PK_DSA; else if (is_RSA(pk->pubkey_algo)) algo = GNUTLS_PK_RSA; else { gnutls_assert(); return CDK_Inv_Value; } rc = sig_to_datum(&s_sig, sig); if (rc) { gnutls_assert(); goto leave; } me = mac_to_entry(sig->digest_algo); rc = _gnutls_set_datum(&di, md, _gnutls_hash_get_algo_len(me)); if (rc < 0) { rc = gnutls_assert_val(CDK_Out_Of_Core); goto leave; } rc = pk_prepare_hash(algo, me, &di); if (rc < 0) { rc = gnutls_assert_val(CDK_General_Error); goto leave; } params.params_nr = cdk_pk_get_npkey(pk->pubkey_algo); for (i = 0; i < params.params_nr; i++) params.params[i] = pk->mpi[i]; params.flags = 0; ret = _gnutls_pk_verify(algo, &di, &s_sig, ¶ms); if (ret < 0) { gnutls_assert(); rc = map_gnutls_error(ret); goto leave; } rc = 0; leave: _gnutls_free_datum(&s_sig); _gnutls_free_datum(&di); cdk_free(encmd); return rc; }