/** * cdk_pk_sign: * @sk: secret key * @sig: signature * @md: the message digest * * Sign the message digest from @md and write the result into @sig. **/ cdk_error_t cdk_pk_sign (cdk_seckey_t sk, cdk_pkt_signature_t sig, const byte *md) { gcry_sexp_t s_skey = NULL, s_sig = NULL, s_hash = NULL; byte *encmd = NULL; size_t enclen = 0; int nbits; cdk_error_t rc; gcry_error_t err; if (!sk || !sk->pk || !sig || !md) return CDK_Inv_Value; if (!is_unprotected (sk)) return CDK_Inv_Mode; if (!KEY_CAN_SIGN (sig->pubkey_algo)) return CDK_Inv_Algo; nbits = cdk_pk_get_nbits (sk->pk); rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, sk->pk->pubkey_algo, md, sig->digest_algo, nbits); if (rc) return rc; rc = seckey_to_sexp (&s_skey, sk); if (!rc) rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen); if (rc) { cdk_free (encmd); gcry_sexp_release (s_skey); return rc; } err = gcry_pk_sign (&s_sig, s_hash, s_skey); if (err) rc = map_gcry_error (err); else { rc = sexp_to_sig (sig, s_sig); if (!rc) { sig->digest_start[0] = md[0]; sig->digest_start[1] = md[1]; } } gcry_sexp_release (s_skey); gcry_sexp_release (s_hash); gcry_sexp_release (s_sig); cdk_free (encmd); return rc; }
/** * 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) { gcry_sexp_t s_pkey = NULL, s_sig = NULL, s_hash = NULL; byte *encmd = NULL; size_t enclen; cdk_error_t rc; if (!pk || !sig || !md) return CDK_Inv_Value; rc = pubkey_to_sexp (&s_pkey, pk); if (rc) return rc; rc = sig_to_sexp (&s_sig, sig); if (rc) goto leave; rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, pk->pubkey_algo, md, sig->digest_algo, cdk_pk_get_nbits (pk)); if (rc) goto leave; rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen); if (rc) goto leave; if (gcry_pk_verify (s_sig, s_hash, s_pkey)) rc = CDK_Bad_Sig; leave: gcry_sexp_release (s_sig); gcry_sexp_release (s_hash); gcry_sexp_release (s_pkey); cdk_free (encmd); return rc; }
/** * 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; byte *encmd = NULL; size_t enclen; cdk_error_t rc; int ret, algo; unsigned int i; gnutls_datum_t data; gnutls_pk_params_st params; 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; } rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, pk->pubkey_algo, md, sig->digest_algo, cdk_pk_get_nbits (pk)); if (rc) { gnutls_assert (); goto leave; } data.data = encmd; data.size = enclen; 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, &data, &s_sig, ¶ms); if (ret < 0) { gnutls_assert (); rc = map_gnutls_error (ret); goto leave; } rc = 0; leave: _gnutls_free_datum (&s_sig); cdk_free (encmd); return rc; }