/* * Verify an OpenPGP signature made with some DSA public key */ static int verify_signature_dsa( signature_packet_t *sign, public_key_packet_t *p_key, uint8_t *p_hash ) { int ret = VLC_EGENERIC; /* the data to be verified (a hash) */ const char *hash_sexp_s = "(data(flags raw)(value %m))"; /* the public key */ const char *key_sexp_s = "(public-key(dsa(p %m)(q %m)(g %m)(y %m)))"; /* the signature */ const char *sig_sexp_s = "(sig-val(dsa(r %m )(s %m )))"; size_t erroff; gcry_mpi_t p, q, g, y, r, s, hash; p = q = g = y = r = s = hash = NULL; gcry_sexp_t key_sexp, hash_sexp, sig_sexp; key_sexp = hash_sexp = sig_sexp = NULL; int i_p_len = mpi_len( p_key->sig.dsa.p ); int i_q_len = mpi_len( p_key->sig.dsa.q ); int i_g_len = mpi_len( p_key->sig.dsa.g ); int i_y_len = mpi_len( p_key->sig.dsa.y ); if( gcry_mpi_scan( &p, GCRYMPI_FMT_USG, p_key->sig.dsa.p + 2, i_p_len, NULL ) || gcry_mpi_scan( &q, GCRYMPI_FMT_USG, p_key->sig.dsa.q + 2, i_q_len, NULL ) || gcry_mpi_scan( &g, GCRYMPI_FMT_USG, p_key->sig.dsa.g + 2, i_g_len, NULL ) || gcry_mpi_scan( &y, GCRYMPI_FMT_USG, p_key->sig.dsa.y + 2, i_y_len, NULL ) || gcry_sexp_build( &key_sexp, &erroff, key_sexp_s, p, q, g, y ) ) goto out; uint8_t *p_r = sign->algo_specific.dsa.r; uint8_t *p_s = sign->algo_specific.dsa.s; int i_r_len = mpi_len( p_r ); int i_s_len = mpi_len( p_s ); if( gcry_mpi_scan( &r, GCRYMPI_FMT_USG, p_r + 2, i_r_len, NULL ) || gcry_mpi_scan( &s, GCRYMPI_FMT_USG, p_s + 2, i_s_len, NULL ) || gcry_sexp_build( &sig_sexp, &erroff, sig_sexp_s, r, s ) ) goto out; int i_hash_len = gcry_md_get_algo_dlen (sign->digest_algo); if (i_hash_len > i_q_len) i_hash_len = i_q_len; if( gcry_mpi_scan( &hash, GCRYMPI_FMT_USG, p_hash, i_hash_len, NULL ) || gcry_sexp_build( &hash_sexp, &erroff, hash_sexp_s, hash ) ) goto out; if( gcry_pk_verify( sig_sexp, hash_sexp, key_sexp ) ) goto out; ret = VLC_SUCCESS; out: if( p ) gcry_mpi_release( p ); if( q ) gcry_mpi_release( q ); if( g ) gcry_mpi_release( g ); if( y ) gcry_mpi_release( y ); if( r ) gcry_mpi_release( r ); if( s ) gcry_mpi_release( s ); if( hash ) gcry_mpi_release( hash ); if( key_sexp ) gcry_sexp_release( key_sexp ); if( sig_sexp ) gcry_sexp_release( sig_sexp ); if( hash_sexp ) gcry_sexp_release( hash_sexp ); return ret; }
static int _wrap_gcry_pk_verify (gnutls_pk_algorithm_t algo, const gnutls_datum_t * vdata, const gnutls_datum_t * signature, const gnutls_pk_params_st * pk_params) { gcry_sexp_t s_sig = NULL, s_hash = NULL, s_pkey = NULL; int rc = -1, ret; bigint_t hash; bigint_t tmp[2] = { NULL, NULL }; if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* make a sexp from pkey */ switch (algo) { case GNUTLS_PK_DSA: if (pk_params->params_nr >= 4) rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", pk_params->params[0], pk_params->params[1], pk_params->params[2], pk_params->params[3]); break; case GNUTLS_PK_RSA: if (pk_params->params_nr >= 2) rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%m)(e%m)))", pk_params->params[0], pk_params->params[1]); break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } /* put the data into a simple list */ if (gcry_sexp_build (&s_hash, NULL, "%m", hash)) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } switch (algo) { case GNUTLS_PK_DSA: ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) { gnutls_assert (); goto cleanup; } rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(dsa(r%m)(s%m)))", tmp[0], tmp[1]); _gnutls_mpi_release (&tmp[0]); _gnutls_mpi_release (&tmp[1]); break; case GNUTLS_PK_RSA: ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size); if (ret < 0) { gnutls_assert (); goto cleanup; } rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", tmp[0]); _gnutls_mpi_release (&tmp[0]); break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } rc = gcry_pk_verify (s_sig, s_hash, s_pkey); if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; goto cleanup; } ret = 0; cleanup: _gnutls_mpi_release (&hash); if (s_sig) gcry_sexp_release (s_sig); if (s_hash) gcry_sexp_release (s_hash); if (s_pkey) gcry_sexp_release (s_pkey); return ret; }
static void dsa_bench (int iterations, int print_header) { gpg_error_t err; gcry_sexp_t pub_key[3], sec_key[3]; int p_sizes[3] = { 1024, 2048, 3072 }; int q_sizes[3] = { 160, 224, 256 }; gcry_sexp_t data; gcry_sexp_t sig = NULL; int i, j; err = gcry_sexp_sscan (pub_key+0, NULL, sample_public_dsa_key_1024, strlen (sample_public_dsa_key_1024)); if (!err) err = gcry_sexp_sscan (sec_key+0, NULL, sample_private_dsa_key_1024, strlen (sample_private_dsa_key_1024)); if (!err) err = gcry_sexp_sscan (pub_key+1, NULL, sample_public_dsa_key_2048, strlen (sample_public_dsa_key_2048)); if (!err) err = gcry_sexp_sscan (sec_key+1, NULL, sample_private_dsa_key_2048, strlen (sample_private_dsa_key_2048)); if (!err) err = gcry_sexp_sscan (pub_key+2, NULL, sample_public_dsa_key_3072, strlen (sample_public_dsa_key_3072)); if (!err) err = gcry_sexp_sscan (sec_key+2, NULL, sample_private_dsa_key_3072, strlen (sample_private_dsa_key_3072)); if (err) { fprintf (stderr, PGM ": converting sample keys failed: %s\n", gcry_strerror (err)); exit (1); } if (print_header) printf ("Algorithm generate %4d*sign %4d*verify\n" "------------------------------------------------\n", iterations, iterations ); for (i=0; i < DIM (q_sizes); i++) { gcry_mpi_t x; x = gcry_mpi_new (q_sizes[i]); gcry_mpi_randomize (x, q_sizes[i], GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); if (err) { fprintf (stderr, PGM ": converting data failed: %s\n", gcry_strerror (err)); exit (1); } printf ("DSA %d/%d -", p_sizes[i], q_sizes[i]); fflush (stdout); start_timer (); for (j=0; j < iterations; j++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key[i]); if (err) { putchar ('\n'); fprintf (stderr, PGM ": signing failed: %s\n", gpg_strerror (err)); exit (1); } } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); start_timer (); for (j=0; j < iterations; j++) { err = gcry_pk_verify (sig, data, pub_key[i]); if (err) { putchar ('\n'); fprintf (stderr, PGM ": verify failed: %s\n", gpg_strerror (err)); exit (1); } } stop_timer (); printf (" %s\n", elapsed_time ()); fflush (stdout); gcry_sexp_release (sig); gcry_sexp_release (data); sig = NULL; } for (i=0; i < DIM (q_sizes); i++) { gcry_sexp_release (sec_key[i]); gcry_sexp_release (pub_key[i]); } }
static void ecc_bench (int iterations, int print_header) { #if USE_ECC gpg_error_t err; int p_sizes[] = { 192, 224, 256, 384, 521 }; int testno; if (print_header) printf ("Algorithm generate %4d*sign %4d*verify\n" "------------------------------------------------\n", iterations, iterations ); for (testno=0; testno < DIM (p_sizes); testno++) { gcry_sexp_t key_spec, key_pair, pub_key, sec_key; gcry_mpi_t x; gcry_sexp_t data; gcry_sexp_t sig = NULL; int count; printf ("ECDSA %3d bit ", p_sizes[testno]); fflush (stdout); err = gcry_sexp_build (&key_spec, NULL, "(genkey (ECDSA (nbits %d)))", p_sizes[testno]); if (err) die ("creating S-expression failed: %s\n", gcry_strerror (err)); start_timer (); err = gcry_pk_genkey (&key_pair, key_spec); if (err) die ("creating %d bit ECC key failed: %s\n", p_sizes[testno], gcry_strerror (err)); pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); if (! pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key_pair, "private-key", 0); if (! sec_key) die ("private part missing in key\n"); gcry_sexp_release (key_pair); gcry_sexp_release (key_spec); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); x = gcry_mpi_new (p_sizes[testno]); gcry_mpi_randomize (x, p_sizes[testno], GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); if (err) die ("converting data failed: %s\n", gcry_strerror (err)); start_timer (); for (count=0; count < iterations; count++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key); if (err) die ("signing failed: %s\n", gpg_strerror (err)); } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); start_timer (); for (count=0; count < iterations; count++) { err = gcry_pk_verify (sig, data, pub_key); if (err) { putchar ('\n'); show_sexp ("seckey:\n", sec_key); show_sexp ("data:\n", data); show_sexp ("sig:\n", sig); die ("verify failed: %s\n", gpg_strerror (err)); } } stop_timer (); printf (" %s\n", elapsed_time ()); fflush (stdout); gcry_sexp_release (sig); gcry_sexp_release (data); gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); } #endif /*USE_ECC*/ }
void attack(int i, unsigned char *digest, int hash_len){ gcry_error_t err; gcry_sexp_t ciphertext , plaintext, ptx2, new_dsa_key_pair; gcry_sexp_t r_param, r_tilda_param, k_tilda_param, msg_digest_param; gcry_sexp_t s_param, s_tilda_param; gcry_sexp_t g_param; gcry_sexp_t p_param; gcry_sexp_t q_param; gcry_sexp_t x_param, y_param; gcry_mpi_t r , r_tilda, k_tilda, x, y; gcry_mpi_t s , s_tilda; gcry_mpi_t g; gcry_mpi_t p; gcry_mpi_t q; gcry_mpi_t msg_digest; retrieve_key_pair(files[i]); //*************** CORRECT SIGNATURE ********************// //20 is the mdlen of sha1 as specified in https://lists.gnupg.org/pipermail/gnupg-devel/2013-September/027916.html //a well formatted number for the immaediate has an even number of digits err = gcry_sexp_build(&plaintext, NULL, "(data (flags rfc6979) (hash %s %b))" , "sha1", hash_len , digest); err = gcry_pk_sign(&ciphertext, plaintext, dsa_key_pair); //now let's convert the s-expression representing r into an MPI in order //to use it in the equation of the attack //--------- CIPHERTEXT -------------- r_param = gcry_sexp_find_token(ciphertext, "r", 0); r = gcry_sexp_nth_mpi ( r_param , 1, GCRYMPI_FMT_USG); s_param = gcry_sexp_find_token(ciphertext, "s", 0); s = gcry_sexp_nth_mpi ( s_param , 1, GCRYMPI_FMT_USG); //--------- PUB KEY -------------- g_param = gcry_sexp_find_token(dsa_key_pair, "g", 0); g = gcry_sexp_nth_mpi ( g_param , 1, GCRYMPI_FMT_USG); p_param = gcry_sexp_find_token(dsa_key_pair, "p", 0); p = gcry_sexp_nth_mpi ( p_param , 1, GCRYMPI_FMT_USG); q_param = gcry_sexp_find_token(dsa_key_pair, "q", 0); q = gcry_sexp_nth_mpi ( q_param , 1, GCRYMPI_FMT_USG); x_param = gcry_sexp_find_token(dsa_key_pair, "x", 0); x = gcry_sexp_nth_mpi ( x_param , 1, GCRYMPI_FMT_USG); y_param = gcry_sexp_find_token(dsa_key_pair, "y", 0); y = gcry_sexp_nth_mpi ( y_param , 1, GCRYMPI_FMT_USG); unsigned int qbits = mpi_get_nbits(q); unsigned int pbits = mpi_get_nbits(p); msg_digest_param = gcry_sexp_find_token(plaintext, "hash", 0); msg_digest = gcry_sexp_nth_mpi ( msg_digest_param , 2, GCRYMPI_FMT_USG); //*************** FAULTY SIGNATURE ********************// err = gcry_sexp_build(&ptx2, NULL, "(data (flags rfc6979) (hash %s %b) (attack))" , "sha1", hash_len , digest); err = gcry_pk_sign(&ciphertext, ptx2, dsa_key_pair); s_tilda_param = gcry_sexp_find_token(ciphertext, "s", 0); s_tilda = gcry_sexp_nth_mpi ( s_tilda_param , 1, GCRYMPI_FMT_USG); r_tilda_param = gcry_sexp_find_token(ciphertext, "r", 0); r_tilda = gcry_sexp_nth_mpi ( r_tilda_param , 1, GCRYMPI_FMT_USG); k_tilda_param = gcry_sexp_find_token(ciphertext, "k", 0); k_tilda = gcry_sexp_nth_mpi ( k_tilda_param , 1, GCRYMPI_FMT_USG); //POC // 1 - choose a message // 2 - do the correct sign and obtain s and r // 3 - do the faulty sign and obtain s_tilda and r_tilda gcry_mpi_t tmp = gcry_mpi_new(mpi_get_nbits(p)); gcry_mpi_t result = gcry_mpi_new(mpi_get_nbits(p)); gcry_mpi_subm(tmp, s_tilda, s,q); //s-tilda -s mod q gcry_mpi_mulm(msg_digest, msg_digest, tmp, q); //m* (s-tilda -s mod q) mod q gcry_mpi_mulm(tmp, r_tilda, s, q); //r_tilda - s mod q gcry_mpi_mulm(result, s_tilda, r, q); //s_tilda - r mod q gcry_mpi_subm(result, tmp, result, q); //(r_tilda - s mod q) - (s_tilda - r mod q) mod q gcry_mpi_invm(result,result,q); //((r_tilda - s mod q) - (s_tilda - r mod q) mod q)^-1 mod q gcry_mpi_mulm(result, msg_digest, result, q); //( (m* (s-tilda -s mod q) mod q) * ((r_tilda - s mod q) - (s_tilda - r mod q) mod q)^-1 mod q ) mod q == x (private key) err = gcry_sexp_build(&new_dsa_key_pair,NULL, "(key-data" " (public-key" " (dsa(p%m)(q%m)(g%m)(y%m)))" " (private-key" " (dsa(p%m)(q%m)(g%m)(y%m)(x%m))))", p,q,g,y,p,q,g,y,result); err = gcry_pk_sign(&ciphertext, plaintext, new_dsa_key_pair); err = gcry_pk_verify(ciphertext, plaintext, dsa_key_pair); if (err) { printf("\nSomething went wrong...\n"); exit(0); } if(!printed){ DEBUG_MPI_PRINT(result,"\nX = "); printed = 1; } }
static void rsa_bench (int iterations, int print_header, int no_blinding) { gpg_error_t err; int p_sizes[] = { 1024, 2048, 3072, 4096 }; int testno; if (print_header) printf ("Algorithm generate %4d*sign %4d*verify\n" "------------------------------------------------\n", iterations, iterations ); for (testno=0; testno < DIM (p_sizes); testno++) { gcry_sexp_t key_spec, key_pair, pub_key, sec_key; gcry_mpi_t x; gcry_sexp_t data; gcry_sexp_t sig = NULL; int count; printf ("RSA %3d bit ", p_sizes[testno]); fflush (stdout); err = gcry_sexp_build (&key_spec, NULL, gcry_fips_mode_active () ? "(genkey (RSA (nbits %d)))" : "(genkey (RSA (nbits %d)(transient-key)))", p_sizes[testno]); if (err) die ("creating S-expression failed: %s\n", gcry_strerror (err)); start_timer (); err = gcry_pk_genkey (&key_pair, key_spec); if (err) die ("creating %d bit RSA key failed: %s\n", p_sizes[testno], gcry_strerror (err)); pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); if (! pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key_pair, "private-key", 0); if (! sec_key) die ("private part missing in key\n"); gcry_sexp_release (key_pair); gcry_sexp_release (key_spec); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); x = gcry_mpi_new (p_sizes[testno]); gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); if (err) die ("converting data failed: %s\n", gcry_strerror (err)); start_timer (); for (count=0; count < iterations; count++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key); if (err) die ("signing failed (%d): %s\n", count, gpg_strerror (err)); } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); start_timer (); for (count=0; count < iterations; count++) { err = gcry_pk_verify (sig, data, pub_key); if (err) { putchar ('\n'); show_sexp ("seckey:\n", sec_key); show_sexp ("data:\n", data); show_sexp ("sig:\n", sig); die ("verify failed (%d): %s\n", count, gpg_strerror (err)); } } stop_timer (); printf (" %s", elapsed_time ()); if (no_blinding) { fflush (stdout); x = gcry_mpi_new (p_sizes[testno]); gcry_mpi_randomize (x, p_sizes[testno]-8, GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags no-blinding) (value %m))", x); gcry_mpi_release (x); if (err) die ("converting data failed: %s\n", gcry_strerror (err)); start_timer (); for (count=0; count < iterations; count++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key); if (err) die ("signing failed (%d): %s\n", count, gpg_strerror (err)); } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); } putchar ('\n'); fflush (stdout); gcry_sexp_release (sig); gcry_sexp_release (data); gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); } }
/* Check against PKCS#1 v1.5 signature test vectors as found at ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt . */ static void check_v15sign (void) { #include "pkcs1v2-v15s.h" gpg_error_t err; int tno, mno; for (tno = 0; tno < DIM (tbl); tno++) { void *rsa_n, *rsa_e, *rsa_d; size_t rsa_n_len, rsa_e_len, rsa_d_len; gcry_sexp_t sec_key, pub_key; if (verbose > 1) info ("(%s)\n", tbl[tno].desc); rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len); rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len); rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len); err = gcry_sexp_build (&sec_key, NULL, "(private-key (rsa (n %b)(e %b)(d %b)))", (int)rsa_n_len, rsa_n, (int)rsa_e_len, rsa_e, (int)rsa_d_len, rsa_d); if (err) die ("constructing private key failed: %s\n", gpg_strerror (err)); err = gcry_sexp_build (&pub_key, NULL, "(public-key (rsa (n %b)(e %b)))", (int)rsa_n_len, rsa_n, (int)rsa_e_len, rsa_e); if (err) die ("constructing public key failed: %s\n", gpg_strerror (err)); gcry_free (rsa_n); gcry_free (rsa_e); gcry_free (rsa_d); for (mno = 0; mno < DIM (tbl[0].m); mno++) { void *mesg, *sign; size_t mesg_len, sign_len; gcry_sexp_t sigtmpl, sig; char mhash[20]; if (verbose) info ("running test: %s\n", tbl[tno].m[mno].desc); mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len); gcry_md_hash_buffer (GCRY_MD_SHA1, mhash, mesg, mesg_len); err = gcry_sexp_build (&sigtmpl, NULL, "(data (flags pkcs1)" "(hash sha1 %b))", 20, mhash); if (err) die ("constructing sig template failed: %s\n", gpg_strerror (err)); gcry_free (mesg); err = gcry_pk_sign (&sig, sigtmpl, sec_key); if (err) { show_sexp ("sigtmpl:\n", sigtmpl); fail ("gcry_pk_sign failed: %s\n", gpg_strerror (err)); } else { if (extract_cmp_data (sig, "s", tbl[tno].m[mno].sign, tbl[tno].m[mno].desc)) { show_sexp ("sign result:\n", sig); fail ("mismatch in gcry_pk_sign\n"); } gcry_sexp_release (sig); sig = NULL; } gcry_sexp_release (sigtmpl); sigtmpl = NULL; /* Now test the verification. */ sign = data_from_hex (tbl[tno].m[mno].sign, &sign_len); err = gcry_sexp_build (&sig, NULL, "(sig-val(rsa(s %b)))", (int)sign_len, sign); if (err) die ("constructing verify data failed: %s\n", gpg_strerror (err)); err = gcry_sexp_build (&sigtmpl, NULL, "(data (flags pkcs1)" "(hash sha1 %b))", 20, mhash); if (err) die ("constructing verify tmpl failed: %s\n", gpg_strerror (err)); gcry_free (sign); err = gcry_pk_verify (sig, sigtmpl, pub_key); if (err) { show_sexp ("sig:\n", sig); show_sexp ("sigtmpl:\n", sigtmpl); fail ("gcry_pk_verify failed: %s\n", gpg_strerror (err)); } gcry_sexp_release (sig); sig = NULL; gcry_sexp_release (sigtmpl); sigtmpl = NULL; } gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); } }
/* Check the signature on CERT using the ISSUER-CERT. This function does only test the cryptographic signature and nothing else. It is assumed that the ISSUER_CERT is valid. */ int gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) { const char *algoid; gcry_md_hd_t md; int rc, algo; gcry_mpi_t frame; ksba_sexp_t p; size_t n; gcry_sexp_t s_sig, s_hash, s_pkey; algo = gcry_md_map_name ( (algoid=ksba_cert_get_digest_algo (cert))); if (!algo) { log_error ("unknown hash algorithm '%s'\n", algoid? algoid:"?"); if (algoid && ( !strcmp (algoid, "1.2.840.113549.1.1.2") ||!strcmp (algoid, "1.2.840.113549.2.2"))) log_info (_("(this is the MD2 algorithm)\n")); return gpg_error (GPG_ERR_GENERAL); } rc = gcry_md_open (&md, algo, 0); if (rc) { log_error ("md_open failed: %s\n", gpg_strerror (rc)); return rc; } if (DBG_HASHING) gcry_md_debug (md, "hash.cert"); rc = ksba_cert_hash (cert, 1, HASH_FNC, md); if (rc) { log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc)); gcry_md_close (md); return rc; } gcry_md_final (md); p = ksba_cert_get_sig_val (cert); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { log_error ("libksba did not return a proper S-Exp\n"); gcry_md_close (md); ksba_free (p); return gpg_error (GPG_ERR_BUG); } if (DBG_CRYPTO) { int j; log_debug ("signature value:"); for (j=0; j < n; j++) log_printf (" %02X", p[j]); log_printf ("\n"); } rc = gcry_sexp_sscan ( &s_sig, NULL, (char*)p, n); ksba_free (p); if (rc) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); gcry_md_close (md); return rc; } p = ksba_cert_get_public_key (issuer_cert); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { log_error ("libksba did not return a proper S-Exp\n"); gcry_md_close (md); ksba_free (p); gcry_sexp_release (s_sig); return gpg_error (GPG_ERR_BUG); } rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n); ksba_free (p); if (rc) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); gcry_md_close (md); gcry_sexp_release (s_sig); return rc; } rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey), gcry_pk_get_nbits (s_pkey), s_pkey, &frame); if (rc) { gcry_md_close (md); gcry_sexp_release (s_sig); gcry_sexp_release (s_pkey); return rc; } /* put hash into the S-Exp s_hash */ if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) BUG (); gcry_mpi_release (frame); rc = gcry_pk_verify (s_sig, s_hash, s_pkey); if (DBG_X509) log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc)); gcry_md_close (md); gcry_sexp_release (s_sig); gcry_sexp_release (s_hash); gcry_sexp_release (s_pkey); return rc; }
static void one_test (int testno, const char *sk, const char *pk, const char *msg, const char *sig) { gpg_error_t err; int i; char *p; void *buffer = NULL; void *buffer2 = NULL; size_t buflen, buflen2; gcry_sexp_t s_tmp, s_tmp2; gcry_sexp_t s_sk = NULL; gcry_sexp_t s_pk = NULL; gcry_sexp_t s_msg= NULL; gcry_sexp_t s_sig= NULL; unsigned char *sig_r = NULL; unsigned char *sig_s = NULL; char *sig_rs_string = NULL; size_t sig_r_len, sig_s_len; if (verbose > 1) show ("Running test %d\n", testno); if (!(buffer = hex2buffer (sk, &buflen))) { fail ("error building s-exp for test %d, %s: %s", testno, "sk", "invalid hex string"); goto leave; } if (!(buffer2 = hex2buffer (pk, &buflen2))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", "invalid hex string"); goto leave; } if (sign_with_pk) err = gcry_sexp_build (&s_sk, NULL, "(private-key" " (ecc" " (curve \"Ed25519\")" " (flags eddsa)" " (q %b)" " (d %b)))", (int)buflen2, buffer2, (int)buflen, buffer); else err = gcry_sexp_build (&s_sk, NULL, "(private-key" " (ecc" " (curve \"Ed25519\")" " (flags eddsa)" " (d %b)))", (int)buflen, buffer); if (err) { fail ("error building s-exp for test %d, %s: %s", testno, "sk", gpg_strerror (err)); goto leave; } if ((err = gcry_sexp_build (&s_pk, NULL, "(public-key" " (ecc" " (curve \"Ed25519\")" " (flags eddsa)" " (q %b)))", (int)buflen2, buffer2))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", gpg_strerror (err)); goto leave; } xfree (buffer); if (!(buffer = hex2buffer (msg, &buflen))) { fail ("error building s-exp for test %d, %s: %s", testno, "msg", "invalid hex string"); goto leave; } if ((err = gcry_sexp_build (&s_msg, NULL, "(data" " (flags eddsa)" " (hash-algo sha512)" " (value %b))", (int)buflen, buffer))) { fail ("error building s-exp for test %d, %s: %s", testno, "msg", gpg_strerror (err)); goto leave; } if ((err = gcry_pk_sign (&s_sig, s_msg, s_sk))) fail ("gcry_pk_sign failed for test %d: %s", testno, gpg_strerror (err)); if (debug) show_sexp ("sig=", s_sig); s_tmp2 = NULL; s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); if (s_tmp) { s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "eddsa", 0); if (s_tmp) { gcry_sexp_release (s_tmp2); s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "r", 0); if (s_tmp) { sig_r = gcry_sexp_nth_buffer (s_tmp, 1, &sig_r_len); gcry_sexp_release (s_tmp); } s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0); if (s_tmp) { sig_s = gcry_sexp_nth_buffer (s_tmp, 1, &sig_s_len); gcry_sexp_release (s_tmp); } } } gcry_sexp_release (s_tmp2); s_tmp2 = NULL; if (!sig_r || !sig_s) fail ("gcry_pk_sign failed for test %d: %s", testno, "r or s missing"); else { sig_rs_string = xmalloc (2*(sig_r_len + sig_s_len)+1); p = sig_rs_string; *p = 0; for (i=0; i < sig_r_len; i++, p += 2) snprintf (p, 3, "%02x", sig_r[i]); for (i=0; i < sig_s_len; i++, p += 2) snprintf (p, 3, "%02x", sig_s[i]); if (strcmp (sig_rs_string, sig)) { fail ("gcry_pk_sign failed for test %d: %s", testno, "wrong value returned"); show (" expected: '%s'", sig); show (" got: '%s'", sig_rs_string); } } if (!no_verify) if ((err = gcry_pk_verify (s_sig, s_msg, s_pk))) fail ("gcry_pk_verify failed for test %d: %s", testno, gpg_strerror (err)); leave: gcry_sexp_release (s_sig); gcry_sexp_release (s_sk); gcry_sexp_release (s_pk); gcry_sexp_release (s_msg); xfree (buffer); xfree (buffer2); xfree (sig_r); xfree (sig_s); xfree (sig_rs_string); }
int sig_verify(ssh_session session, ssh_public_key pubkey, SIGNATURE *signature, unsigned char *digest, int size) { #ifdef HAVE_LIBGCRYPT gcry_error_t valid = 0; gcry_sexp_t gcryhash; #elif defined HAVE_LIBCRYPTO int valid = 0; #endif unsigned char hash[SHA_DIGEST_LEN + 1] = {0}; sha1(digest, size, hash + 1); #ifdef DEBUG_CRYPTO ssh_print_hexa("Hash to be verified with dsa", hash + 1, SHA_DIGEST_LEN); #endif switch(pubkey->type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_LIBGCRYPT valid = gcry_sexp_build(&gcryhash, NULL, "%b", SHA_DIGEST_LEN + 1, hash); if (valid != 0) { ssh_set_error(session, SSH_FATAL, "RSA error: %s", gcry_strerror(valid)); return -1; } valid = gcry_pk_verify(signature->dsa_sign, gcryhash, pubkey->dsa_pub); gcry_sexp_release(gcryhash); if (valid == 0) { return 0; } if (gcry_err_code(valid) != GPG_ERR_BAD_SIGNATURE) { ssh_set_error(session, SSH_FATAL, "DSA error: %s", gcry_strerror(valid)); return -1; } #elif defined HAVE_LIBCRYPTO valid = DSA_do_verify(hash + 1, SHA_DIGEST_LEN, signature->dsa_sign, pubkey->dsa_pub); if (valid == 1) { return 0; } if (valid == -1) { ssh_set_error(session, SSH_FATAL, "DSA error: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } #endif ssh_set_error(session, SSH_FATAL, "Invalid DSA signature"); return -1; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: #ifdef HAVE_LIBGCRYPT valid = gcry_sexp_build(&gcryhash, NULL, "(data(flags pkcs1)(hash sha1 %b))", SHA_DIGEST_LEN, hash + 1); if (valid != 0) { ssh_set_error(session, SSH_FATAL, "RSA error: %s", gcry_strerror(valid)); return -1; } valid = gcry_pk_verify(signature->rsa_sign,gcryhash,pubkey->rsa_pub); gcry_sexp_release(gcryhash); if (valid == 0) { return 0; } if (gcry_err_code(valid) != GPG_ERR_BAD_SIGNATURE) { ssh_set_error(session, SSH_FATAL, "RSA error: %s", gcry_strerror(valid)); return -1; } #elif defined HAVE_LIBCRYPTO valid = RSA_verify(NID_sha1, hash + 1, SHA_DIGEST_LEN, signature->rsa_sign->string, ssh_string_len(signature->rsa_sign), pubkey->rsa_pub); if (valid == 1) { return 0; } if (valid == -1) { ssh_set_error(session, SSH_FATAL, "RSA error: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } #endif ssh_set_error(session, SSH_FATAL, "Invalid RSA signature"); return -1; default: ssh_set_error(session, SSH_FATAL, "Unknown public key type"); return -1; } return -1; }
static void check_ecc_sample_key (void) { static const char ecc_private_key[] = "(private-key\n" " (ecdsa\n" " (curve \"NIST P-256\")\n" " (q #04D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2BEB6644D3609FC781" "B71F9A8072F58CB66AE2F89BB12451873ABF7D91F9E1FBF96BF2F70E73AAC9A283#)\n" " (d #5A1EF0035118F19F3110FB81813D3547BCE1E5BCE77D1F744715E1D5BBE70378#)" "))"; static const char ecc_private_key_wo_q[] = "(private-key\n" " (ecdsa\n" " (curve \"NIST P-256\")\n" " (d #5A1EF0035118F19F3110FB81813D3547BCE1E5BCE77D1F744715E1D5BBE70378#)" "))"; static const char ecc_public_key[] = "(public-key\n" " (ecdsa\n" " (curve \"NIST P-256\")\n" " (q #04D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2BEB6644D3609FC781" "B71F9A8072F58CB66AE2F89BB12451873ABF7D91F9E1FBF96BF2F70E73AAC9A283#)" "))"; static const char hash_string[] = "(data (flags raw)\n" " (value #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F#))"; gpg_error_t err; gcry_sexp_t key, hash, sig; if (verbose) fprintf (stderr, "Checking sample ECC key.\n"); if ((err = gcry_sexp_new (&hash, hash_string, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign failed: %s", gpg_strerror (err)); gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify failed: %s", gpg_strerror (err)); /* Now try signing without the Q parameter. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_private_key_wo_q, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); gcry_sexp_release (sig); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign without Q failed: %s", gpg_strerror (err)); gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify signed without Q failed: %s", gpg_strerror (err)); gcry_sexp_release (sig); gcry_sexp_release (key); gcry_sexp_release (hash); }
static void check_ed25519ecdsa_sample_key (void) { static const char ecc_private_key[] = "(private-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (q #044C056555BE4084BB3D8D8895FDF7C2893DFE0256251923053010977D12658321" " 156D1ADDC07987713A418783658B476358D48D582DB53233D9DED3C1C2577B04#)" " (d #09A0C38E0F1699073541447C19DA12E3A07A7BFDB0C186E4AC5BCE6F23D55252#)" "))"; static const char ecc_private_key_wo_q[] = "(private-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (d #09A0C38E0F1699073541447C19DA12E3A07A7BFDB0C186E4AC5BCE6F23D55252#)" "))"; static const char ecc_public_key[] = "(public-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (q #044C056555BE4084BB3D8D8895FDF7C2893DFE0256251923053010977D12658321" " 156D1ADDC07987713A418783658B476358D48D582DB53233D9DED3C1C2577B04#)" "))"; static const char ecc_public_key_comp[] = "(public-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (q #047b57c2c1d3ded93332b52d588dd45863478b658387413a718779c0dd1a6d95#)" "))"; static const char hash_string[] = "(data (flags ecdsa rfc6979)\n" " (hash sha256 #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F#))"; gpg_error_t err; gcry_sexp_t key, hash, sig; if (verbose) fprintf (stderr, "Checking sample Ed25519/ECDSA key.\n"); /* Sign. */ if ((err = gcry_sexp_new (&hash, hash_string, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign failed: %s", gpg_strerror (err)); /* Verify. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify failed: %s", gpg_strerror (err)); /* Verify again using a compressed public key. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key_comp, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify failed (comp): %s", gpg_strerror (err)); /* Sign without a Q parameter. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_private_key_wo_q, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); gcry_sexp_release (sig); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign w/o Q failed: %s", gpg_strerror (err)); /* Verify. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify signed w/o Q failed: %s", gpg_strerror (err)); /* Verify again using a compressed public key. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key_comp, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify signed w/o Q failed (comp): %s", gpg_strerror (err)); extract_cmp_data (sig, "r", ("a63123a783ef29b8276e08987daca4" "655d0179e22199bf63691fd88eb64e15")); extract_cmp_data (sig, "s", ("0d9b45c696ab90b96b08812b485df185" "623ddaf5d02fa65ca5056cb6bd0f16f1")); gcry_sexp_release (sig); gcry_sexp_release (key); gcry_sexp_release (hash); }
int gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, gcry_md_hd_t md, int mdalgo, int *r_pkalgo) { int rc; ksba_sexp_t p; gcry_mpi_t frame; gcry_sexp_t s_sig, s_hash, s_pkey; size_t n; int pkalgo; if (r_pkalgo) *r_pkalgo = 0; n = gcry_sexp_canon_len (sigval, 0, NULL, NULL); if (!n) { log_error ("libksba did not return a proper S-Exp\n"); return gpg_error (GPG_ERR_BUG); } rc = gcry_sexp_sscan (&s_sig, NULL, (char*)sigval, n); if (rc) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); return rc; } p = ksba_cert_get_public_key (cert); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { log_error ("libksba did not return a proper S-Exp\n"); ksba_free (p); gcry_sexp_release (s_sig); return gpg_error (GPG_ERR_BUG); } if (DBG_CRYPTO) log_printhex ("public key: ", p, n); rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n); ksba_free (p); if (rc) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); gcry_sexp_release (s_sig); return rc; } pkalgo = pk_algo_from_sexp (s_pkey); if (r_pkalgo) *r_pkalgo = pkalgo; rc = do_encode_md (md, mdalgo, pkalgo, gcry_pk_get_nbits (s_pkey), s_pkey, &frame); if (rc) { gcry_sexp_release (s_sig); gcry_sexp_release (s_pkey); return rc; } /* put hash into the S-Exp s_hash */ if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) BUG (); gcry_mpi_release (frame); rc = gcry_pk_verify (s_sig, s_hash, s_pkey); if (DBG_X509) log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc)); gcry_sexp_release (s_sig); gcry_sexp_release (s_hash); gcry_sexp_release (s_pkey); return rc; }
/* Check the signature on CERT using the ISSUER_CERT. This function does only test the cryptographic signature and nothing else. It is assumed that the ISSUER_CERT is valid. */ static gpg_error_t check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) { gpg_error_t err; const char *algoid; gcry_md_hd_t md; int i, algo; ksba_sexp_t p; size_t n; gcry_sexp_t s_sig, s_hash, s_pkey; const char *s; char algo_name[16+1]; /* hash algorithm name converted to lower case. */ int digestlen; unsigned char *digest; /* Hash the target certificate using the algorithm from that certificate. */ algoid = ksba_cert_get_digest_algo (cert); algo = gcry_md_map_name (algoid); if (!algo) { log_error (_("unknown hash algorithm '%s'\n"), algoid? algoid:"?"); return gpg_error (GPG_ERR_GENERAL); } s = gcry_md_algo_name (algo); for (i=0; *s && i < sizeof algo_name - 1; s++, i++) algo_name[i] = tolower (*s); algo_name[i] = 0; err = gcry_md_open (&md, algo, 0); if (err) { log_error ("md_open failed: %s\n", gpg_strerror (err)); return err; } if (DBG_HASHING) gcry_md_debug (md, "hash.cert"); err = ksba_cert_hash (cert, 1, HASH_FNC, md); if (err) { log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (err)); gcry_md_close (md); return err; } gcry_md_final (md); /* Get the signature value out of the target certificate. */ p = ksba_cert_get_sig_val (cert); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { log_error ("libksba did not return a proper S-Exp\n"); gcry_md_close (md); ksba_free (p); return gpg_error (GPG_ERR_BUG); } if (DBG_CRYPTO) { int j; log_debug ("signature value:"); for (j=0; j < n; j++) log_printf (" %02X", p[j]); log_printf ("\n"); } err = gcry_sexp_sscan ( &s_sig, NULL, p, n); ksba_free (p); if (err) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (err)); gcry_md_close (md); return err; } /* Get the public key from the issuer certificate. */ p = ksba_cert_get_public_key (issuer_cert); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { log_error ("libksba did not return a proper S-Exp\n"); gcry_md_close (md); ksba_free (p); gcry_sexp_release (s_sig); return gpg_error (GPG_ERR_BUG); } err = gcry_sexp_sscan ( &s_pkey, NULL, p, n); ksba_free (p); if (err) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (err)); gcry_md_close (md); gcry_sexp_release (s_sig); return err; } /* Prepare the values for signature verification. At this point we have these values: S_PKEY - S-expression with the issuer's public key. S_SIG - Signature value as given in the certrificate. MD - Finalized hash context with hash of the certificate. ALGO_NAME - Lowercase hash algorithm name */ digestlen = gcry_md_get_algo_dlen (algo); digest = gcry_md_read (md, algo); if (pk_algo_from_sexp (s_pkey) == GCRY_PK_DSA) { if (digestlen != 20) { log_error (_("DSA requires the use of a 160 bit hash algorithm\n")); gcry_md_close (md); gcry_sexp_release (s_sig); gcry_sexp_release (s_pkey); return gpg_error (GPG_ERR_INTERNAL); } if ( gcry_sexp_build (&s_hash, NULL, "(data(flags raw)(value %b))", (int)digestlen, digest) ) BUG (); } else /* Not DSA. */ { if ( gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))", algo_name, (int)digestlen, digest) ) BUG (); } err = gcry_pk_verify (s_sig, s_hash, s_pkey); if (DBG_X509) log_debug ("gcry_pk_verify: %s\n", gpg_strerror (err)); gcry_md_close (md); gcry_sexp_release (s_sig); gcry_sexp_release (s_hash); gcry_sexp_release (s_pkey); return err; }
/* * Checks the validity of the signature found on the regulatory * database against the array 'keys'. Returns 1 if there exists * at least one key in the array such that the signature is valid * against that key; 0 otherwise. */ int crda_verify_db_signature(__u8 *db, int dblen, int siglen) { #ifdef USE_OPENSSL RSA *rsa; __u8 hash[SHA_DIGEST_LENGTH]; unsigned int i; int ok = 0; DIR *pubkey_dir; struct dirent *nextfile; FILE *keyfile; char filename[PATH_MAX]; if (SHA1(db, dblen, hash) != hash) { fprintf(stderr, "Failed to calculate SHA1 sum.\n"); goto out; } for (i = 0; (i < sizeof(keys)/sizeof(keys[0])) && (!ok); i++) { rsa = RSA_new(); if (!rsa) { fprintf(stderr, "Failed to create RSA key.\n"); goto out; } rsa->e = &keys[i].e; rsa->n = &keys[i].n; ok = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH, db + dblen, siglen, rsa) == 1; rsa->e = NULL; rsa->n = NULL; RSA_free(rsa); } if (!ok && (pubkey_dir = opendir(PUBKEY_DIR))) { while (!ok && (nextfile = readdir(pubkey_dir))) { snprintf(filename, PATH_MAX, "%s/%s", PUBKEY_DIR, nextfile->d_name); if ((keyfile = fopen(filename, "rb"))) { rsa = PEM_read_RSA_PUBKEY(keyfile, NULL, NULL, NULL); if (rsa) ok = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH, db + dblen, siglen, rsa) == 1; RSA_free(rsa); fclose(keyfile); } } closedir(pubkey_dir); } #endif #ifdef USE_GCRYPT gcry_mpi_t mpi_e, mpi_n; gcry_sexp_t rsa, signature, data; __u8 hash[20]; unsigned int i; int ok = 0; /* initialise */ gcry_check_version(NULL); /* hash the db */ gcry_md_hash_buffer(GCRY_MD_SHA1, hash, db, dblen); if (gcry_sexp_build(&data, NULL, "(data (flags pkcs1) (hash sha1 %b))", 20, hash)) { fprintf(stderr, "Failed to build data S-expression.\n"); goto out; } if (gcry_sexp_build(&signature, NULL, "(sig-val (rsa (s %b)))", siglen, db + dblen)) { fprintf(stderr, "Failed to build signature S-expression.\n"); goto out; } for (i = 0; (i < sizeof(keys)/sizeof(keys[0])) && (!ok); i++) { if (gcry_mpi_scan(&mpi_e, GCRYMPI_FMT_USG, keys[i].e, keys[i].len_e, NULL) || gcry_mpi_scan(&mpi_n, GCRYMPI_FMT_USG, keys[i].n, keys[i].len_n, NULL)) { fprintf(stderr, "Failed to convert numbers.\n"); goto out; } if (gcry_sexp_build(&rsa, NULL, "(public-key (rsa (n %m) (e %m)))", mpi_n, mpi_e)) { fprintf(stderr, "Failed to build RSA S-expression.\n"); goto out; } ok = gcry_pk_verify(signature, data, rsa) == 0; } #endif #if defined(USE_OPENSSL) || defined(USE_GCRYPT) if (!ok) fprintf(stderr, "Database signature verification failed.\n"); out: return ok; #else return 1; #endif }
void attack(int i, unsigned char *digest, int hash_len){ void* dsa_buf; gcry_sexp_t new_dsa_key_pair; gcry_sexp_t ciphertext , plaintext, ptx2, ctx2; gcry_sexp_t r_param, r_tilda_param; gcry_sexp_t s_param, s_tilda_param; gcry_sexp_t g_param; gcry_sexp_t p_param; gcry_sexp_t q_param; gcry_sexp_t m_param; gcry_sexp_t y_param; gcry_sexp_t x_param; gcry_sexp_t misc_param; gcry_error_t err; gcry_mpi_t msg_digest, m; gcry_mpi_t r , r_tilda; gcry_mpi_t s , s_tilda; gcry_mpi_t g; gcry_mpi_t p; gcry_mpi_t q; gcry_mpi_t y; gcry_mpi_t x; retrieve_key_pair(files[i]); //*************** CORRECT SIGNATURE ********************// //20 is the mdlen of sha1 as specified in https://lists.gnupg.org/pipermail/gnupg-devel/2013-September/027916.html //a well formatted number for the immaediate has an even number of digits err = gcry_sexp_build(&plaintext, NULL, "(data (flags rfc6979) (hash %s %b))" , "sha1", hash_len , digest); err = gcry_pk_sign(&ciphertext, plaintext, dsa_key_pair); //now let's convert the s-expression representing r into an MPI in order //to use it in the equation of the attack //--------- CIPHERTEXT -------------- //intercepted during some sniffing... r_param = gcry_sexp_find_token(ciphertext, "r", 0); r = gcry_sexp_nth_mpi ( r_param , 1, GCRYMPI_FMT_USG); s_param = gcry_sexp_find_token(ciphertext, "s", 0); s = gcry_sexp_nth_mpi ( s_param , 1, GCRYMPI_FMT_USG); //--------- PUB KEY -------------- g_param = gcry_sexp_find_token(dsa_key_pair, "g", 0); g = gcry_sexp_nth_mpi ( g_param , 1, GCRYMPI_FMT_USG); p_param = gcry_sexp_find_token(dsa_key_pair, "p", 0); p = gcry_sexp_nth_mpi ( p_param , 1, GCRYMPI_FMT_USG); q_param = gcry_sexp_find_token(dsa_key_pair, "q", 0); q = gcry_sexp_nth_mpi ( q_param , 1, GCRYMPI_FMT_USG); y_param = gcry_sexp_find_token(dsa_key_pair, "y", 0); y = gcry_sexp_nth_mpi ( y_param , 1, GCRYMPI_FMT_USG); x_param = gcry_sexp_find_token(dsa_key_pair, "x", 0); x = gcry_sexp_nth_mpi ( x_param , 1, GCRYMPI_FMT_USG); misc_param = gcry_sexp_find_token(dsa_key_pair, "misc-key-info", 0); //*************** FAULTY SIGNATURE ********************// err = gcry_sexp_build(&ptx2, NULL, "(data (flags rfc6979) (hash %s %b) (attack2_inv))" , "sha1", hash_len , digest); err = gcry_pk_sign(&ctx2, ptx2, dsa_key_pair); s_tilda_param = gcry_sexp_find_token(ctx2, "s", 0); s_tilda = gcry_sexp_nth_mpi ( s_tilda_param , 1, GCRYMPI_FMT_USG); r_tilda_param = gcry_sexp_find_token(ctx2, "r", 0); r_tilda = gcry_sexp_nth_mpi ( r_tilda_param , 1, GCRYMPI_FMT_USG); m_param = gcry_sexp_find_token(ptx2, "hash", 0); m = gcry_sexp_nth_mpi ( m_param , 2, GCRYMPI_FMT_USG); //NOW LET'S START THE ATTACK unsigned long e = 0; unsigned int qbits = mpi_get_nbits(q); unsigned int pbits = mpi_get_nbits(p); gcry_mpi_t one = gcry_mpi_set_ui(NULL, 1); gcry_mpi_t tmp = gcry_mpi_new(qbits); gcry_mpi_t result = gcry_mpi_new(mpi_get_nbits(s)); gcry_mpi_invm(r,r,q); // r^-1 for(e = 0; e < qbits; e++){ gcry_mpi_t twoi = gcry_mpi_new(e); gcry_mpi_mul_2exp(twoi, one, e); // twoi = 2^e //retrieve k gcry_mpi_invm(tmp, twoi, q); // (2^e)^-1 mod q gcry_mpi_subm(result, s_tilda, s, q); // s_tilda - s mod q gcry_mpi_mulm(result,result, tmp, q); // (s_tilda - s mod q)*((2^e)^-1 mod q) === k //retrieve x gcry_mpi_mulm(result, s, result,q); // s*k mod q gcry_mpi_subm(result, result, m, q); // s*k - m mod q gcry_mpi_mulm(result, result,r,q); //(s*k -m)*r^-1 mod q err = gcry_sexp_build(&new_dsa_key_pair,NULL, "(key-data" " (public-key" " (dsa(p%m)(q%m)(g%m)(y%m)))" " (private-key" " (dsa(p%m)(q%m)(g%m)(y%m)(x%m))))", p,q,g,y,p,q,g,y,result); err = gcry_pk_sign(&ctx2, plaintext, new_dsa_key_pair); err = gcry_pk_verify(ctx2, plaintext, dsa_key_pair); if (err) { //puts("gcrypt: verify failed"); continue; } else{ printf("\n[!!!]PRIVATE KEY %d %d BITS CRACKED!!\n" , pbits,qbits ); printf("[DBG] BIT: %d FAULT: k-2^e\n" , (int)e); //DEBUG DEBUG_MPI_PRINT(result,"X = "); printf("\n"); return; } } for(e = 0; e < qbits; e++){ gcry_mpi_t twoi = gcry_mpi_new(e); gcry_mpi_mul_2exp(twoi, one, e); // twoi = 2^e //retrieve k gcry_mpi_invm(tmp, twoi, q); // (2^e)^-1 mod q gcry_mpi_subm(result, s, s_tilda, q); // s - s_tilda mod q gcry_mpi_mulm(result,result, tmp, q); // (s - s_tilda mod q)*((2^e)^-1 mod q) === k //retrieve x gcry_mpi_mulm(result, s, result,q); // s*k mod q gcry_mpi_subm(result, result, m, q); // s*k - m mod q gcry_mpi_mulm(result, result,r,q); //(s*k -m)*r^-1 mod q err = gcry_sexp_build(&new_dsa_key_pair,NULL, "(key-data" " (public-key" " (dsa(p%m)(q%m)(g%m)(y%m)))" " (private-key" " (dsa(p%m)(q%m)(g%m)(y%m)(x%m))))", p,q,g,y,p,q,g,y,result); err = gcry_pk_sign(&ctx2, plaintext, new_dsa_key_pair); err = gcry_pk_verify(ctx2, plaintext, dsa_key_pair); if (err) { //puts("gcrypt: verify failed"); continue; } else{ printf("\n[!!!]PRIVATE KEY %d %d BITS CRACKED!!\n" , pbits,qbits ); printf("[DBG] BIT: %d FAULT: k+2^e\n" , (int)e); //DEBUG DEBUG_MPI_PRINT(result,"X = "); printf("\n"); return; } } }
static int _gnutls_pk_verify (int algo, mpi_t hash, mpi_t * data, mpi_t * pkey, int pkey_len) { gcry_sexp_t s_sig, s_hash, s_pkey; int rc = -1; /* make a sexp from pkey */ switch (algo) { case GCRY_PK_DSA: if (pkey_len >= 4) rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", pkey[0], pkey[1], pkey[2], pkey[3]); break; case GCRY_PK_RSA: if (pkey_len >= 2) rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]); break; default: gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } if (rc != 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } /* put the data into a simple list */ if (gcry_sexp_build (&s_hash, NULL, "%m", hash)) { gnutls_assert (); gcry_sexp_release (s_pkey); return GNUTLS_E_INTERNAL_ERROR; } switch (algo) { case GCRY_PK_DSA: rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]); break; case GCRY_PK_RSA: rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", data[0]); break; default: gnutls_assert (); gcry_sexp_release (s_pkey); gcry_sexp_release (s_hash); return GNUTLS_E_INTERNAL_ERROR; } if (rc != 0) { gnutls_assert (); gcry_sexp_release (s_pkey); gcry_sexp_release (s_hash); return GNUTLS_E_INTERNAL_ERROR; } rc = gcry_pk_verify (s_sig, s_hash, s_pkey); gcry_sexp_release (s_sig); gcry_sexp_release (s_hash); gcry_sexp_release (s_pkey); if (rc != 0) { gnutls_assert (); return GNUTLS_E_PK_SIG_VERIFY_FAILED; } return 0; }