int _libssh2_rsa_sha1_sign(LIBSSH2_SESSION * session, libssh2_dsa_ctx * rsactx, const unsigned char *hash, size_t hash_len, unsigned char **signature, size_t *signature_len) { gcry_sexp_t sig_sexp; gcry_sexp_t data; int rc; const char *tmp; size_t size; if (hash_len != SHA_DIGEST_LENGTH) { return -1; } if (gcry_sexp_build(&data, NULL, "(data (flags pkcs1) (hash sha1 %b))", hash_len, hash)) { return -1; } rc = gcry_pk_sign(&sig_sexp, data, rsactx); gcry_sexp_release(data); if (rc != 0) { return -1; } data = gcry_sexp_find_token(sig_sexp, "s", 0); if (!data) { return -1; } tmp = gcry_sexp_nth_data(data, 1, &size); if (!tmp) { return -1; } if (tmp[0] == '\0') { tmp++; size--; } *signature = LIBSSH2_ALLOC(session, size); memcpy(*signature, tmp, size); *signature_len = size; return rc; }
static int read_single_mpi( gcry_sexp_t s_key, const char * val, gcry_mpi_t * r_resarr ) { gcry_sexp_t list; if( !r_resarr ) return CDK_Inv_Value; list = gcry_sexp_find_token( s_key, val, 0 ); if( list ) *r_resarr = gcry_sexp_nth_mpi( list, 1, 0 ); gcry_sexp_release( list ); return list? 0 : CDK_Gcry_Error; }
static gcry_mpi_t key_param_from_sexp (gcry_sexp_t sexp, const char *topname, const char *name) { gcry_sexp_t l1, l2; gcry_mpi_t result; l1 = gcry_sexp_find_token (sexp, topname, 0); if (!l1) return NULL; l2 = gcry_sexp_find_token (l1, name, 0); if (!l2) { gcry_sexp_release (l1); return NULL; } result = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l2); gcry_sexp_release (l1); return result; }
void crypto_rsa_encrypt(int len, uint8 * in, uint8 * out, uint32 modulus_size, uint8 * modulus, uint8 * exponent) { /* GnuTLS do not expose raw RSA, so we use the underlying gcrypt lib instead */ ASSERT(modulus_size <= SEC_MAX_MODULUS_SIZE); gcry_mpi_t m; gcry_error_t rc = gcry_mpi_scan(&m, GCRYMPI_FMT_USG, modulus, modulus_size, NULL); ASSERT(!rc); gcry_mpi_t e; rc = gcry_mpi_scan(&e, GCRYMPI_FMT_USG, exponent, SEC_EXPONENT_SIZE, NULL); gcry_sexp_t publickey_sexp; rc = gcry_sexp_build(&publickey_sexp, NULL, "(public-key(rsa(n%m)(e%m)))", m, e); ASSERT(!rc); gcry_mpi_release(m); gcry_mpi_release(e); gcry_mpi_t in_gcry; rc = gcry_mpi_scan(&in_gcry, GCRYMPI_FMT_USG, in, len, NULL); ASSERT(!rc); gcry_sexp_t in_sexp; rc = gcry_sexp_build(&in_sexp, NULL, "%m", in_gcry); ASSERT(!rc); gcry_sexp_t out_sexp; rc = gcry_pk_encrypt(&out_sexp, in_sexp, publickey_sexp); ASSERT(!rc); gcry_sexp_t out_list_sexp; out_list_sexp = gcry_sexp_find_token(out_sexp, "a", 0); ASSERT(out_list_sexp); gcry_mpi_t out_gcry = gcry_sexp_nth_mpi(out_list_sexp, 1, GCRYMPI_FMT_NONE); ASSERT(out_gcry); size_t s; rc = gcry_mpi_print(GCRYMPI_FMT_USG, out, modulus_size, &s, out_gcry); ASSERT(!rc); ASSERT(s == modulus_size); gcry_mpi_release(out_gcry); gcry_sexp_release(out_list_sexp); gcry_mpi_release(in_gcry); gcry_sexp_release(out_sexp); gcry_sexp_release(in_sexp); gcry_sexp_release(publickey_sexp); }
static void get_dsa_key_fips186_with_seed_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey" " (dsa" " (nbits 4:1024)" " (use-fips186)" " (transient-key)" " (derive-parms" " (seed #0cb1990c1fd3626055d7a0096f8fa99807399871#))))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) die ("error generating DSA key: %s\n", gcry_strerror (rc)); if (verbose > 1) show_sexp ("generated DSA key (fips 186 with seed):\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; }
void generate_key(rsa_packet * packet, char **public_key, char **private_key) { gcry_error_t error; int i; // Generate a reduced strength (to save time) RSA key, 1024 bits long // gcry_sexp_t params = sexp_new( "(genkey (rsa (transient-key) (nbits 3:512)))" ); gcry_sexp_t params = sexp_new( "(genkey (rsa (transient-key) (nbits 4:1024)))" ); gcry_sexp_t r_key; if ((error = gcry_pk_genkey(&r_key, params))) { printf("Error in gcry_pk_genkey(): %s\nSource: %s\n", gcry_strerror(error), gcry_strsource(error)); exit(1); } // Parse the S expression strings gcry_sexp_t public_sexp = gcry_sexp_nth(r_key, 1); gcry_sexp_t private_sexp = gcry_sexp_nth(r_key, 2); gcry_sexp_t mod_sexp = gcry_sexp_cdr(gcry_sexp_find_token(private_sexp, "n", 1)); gcry_sexp_t priv_exp_sexp = gcry_sexp_cdr(gcry_sexp_find_token(private_sexp, "d", 1)); gcry_sexp_t pub_exp_sexp = gcry_sexp_cdr(gcry_sexp_find_token(public_sexp, "e", 1)); // Extract the raw data in MPI format gcry_mpi_t mod_mpi, pubexp_mpi, privexp_mpi; mod_mpi = gcry_sexp_nth_mpi(mod_sexp, 0, GCRYMPI_FMT_USG); privexp_mpi = gcry_sexp_nth_mpi(priv_exp_sexp, 0, GCRYMPI_FMT_USG); pubexp_mpi = gcry_sexp_nth_mpi(pub_exp_sexp, 0, GCRYMPI_FMT_USG); //gcry_mpi_aprint(GCRYMPI_FMT_HEX, public_key, NULL, mod_mpi); // Now pack it into unsigned char gcry_mpi_print(GCRYMPI_FMT_USG, packet->mod, 256, &packet->mod_len, mod_mpi); gcry_mpi_print(GCRYMPI_FMT_USG, packet->priv_exp, 256, &packet->priv_len, privexp_mpi); gcry_mpi_print(GCRYMPI_FMT_USG, packet->pub_exp, 256, &packet->pub_len, pubexp_mpi); // printf ("fmt: %i: %.*s\n", (int)len, (int) len, ); *public_key = sexp_string(public_sexp); *private_key = sexp_string(private_sexp); }
static void extract_cmp_int (gcry_sexp_t sexp, const char *name, int expected) { gcry_sexp_t l1; char *a; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_string (l1, 1); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( strtoul (a, NULL, 10) != expected ) fail ("parameter \"%s\" does not match expected value\n", name); gcry_free (a); gcry_sexp_release (l1); }
static void extract_cmp_mpi (gcry_sexp_t sexp, const char *name, const char *expected) { gcry_sexp_t l1; gcry_mpi_t a, b; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); b = mpi_from_string (expected); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( gcry_mpi_cmp (a, b) ) fail ("parameter \"%s\" does not match expected value\n", name); gcry_mpi_release (b); gcry_mpi_release (a); gcry_sexp_release (l1); }
/** * Duplicate the given public key * * @param key the public key to duplicate * @return the duplicate key; NULL upon error */ struct GNUNET_CRYPTO_rsa_PublicKey * GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_rsa_PublicKey *key) { struct GNUNET_CRYPTO_rsa_PublicKey *dup; gcry_sexp_t dup_sexp; size_t erroff; /* check if we really are exporting a public key */ dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0); GNUNET_assert (NULL != dup_sexp); gcry_sexp_release (dup_sexp); /* copy the sexp */ GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp)); dup = GNUNET_new (struct GNUNET_CRYPTO_rsa_PublicKey); dup->sexp = dup_sexp; return dup; }
static gpg_err_code_t elg_generate_ext (int algo, unsigned int nbits, unsigned long evalue, const gcry_sexp_t genparms, gcry_mpi_t *skey, gcry_mpi_t **retfactors, gcry_sexp_t *r_extrainfo) { gpg_err_code_t ec; ELG_secret_key sk; gcry_mpi_t xvalue = NULL; gcry_sexp_t l1; (void)algo; (void)evalue; (void)r_extrainfo; if (genparms) { /* Parse the optional xvalue element. */ l1 = gcry_sexp_find_token (genparms, "xvalue", 0); if (l1) { xvalue = gcry_sexp_nth_mpi (l1, 1, 0); gcry_sexp_release (l1); if (!xvalue) return GPG_ERR_BAD_MPI; } } if (xvalue) { ec = generate_using_x (&sk, nbits, xvalue, retfactors); mpi_free (xvalue); } else { generate (&sk, nbits, retfactors); ec = 0; } skey[0] = sk.p; skey[1] = sk.g; skey[2] = sk.y; skey[3] = sk.x; return ec; }
/* Generate a private DSA key for a given account, storing it into a * FILE*, and loading it into the given OtrlUserState. Overwrite any * previously generated keys for that account in that OtrlUserState. * The FILE* must be open for reading and writing. */ gcry_error_t otrl_privkey_generate_FILEp(OtrlUserState us, FILE *privf, const char *accountname, const char *protocol) { gcry_error_t err; gcry_sexp_t key, parms, privkey; static const char *parmstr = "(genkey (dsa (nbits 4:1024)))"; OtrlPrivKey *p; if (!privf) return gcry_error(GPG_ERR_NO_ERROR); /* Create a DSA key */ err = gcry_sexp_new(&parms, parmstr, strlen(parmstr), 0); if (err) { return err; } err = gcry_pk_genkey(&key, parms); gcry_sexp_release(parms); if (err) { return err; } /* Extract the privkey */ privkey = gcry_sexp_find_token(key, "private-key", 0); gcry_sexp_release(key); /* Output the other keys we know */ fprintf(privf, "(privkeys\n"); for (p=us->privkey_root; p; p=p->next) { /* Skip this one if our new key replaces it */ if (!strcmp(p->accountname, accountname) && !strcmp(p->protocol, protocol)) { continue; } account_write(privf, p->accountname, p->protocol, p->privkey); } account_write(privf, accountname, protocol, privkey); gcry_sexp_release(privkey); fprintf(privf, ")\n"); fseek(privf, 0, SEEK_SET); return otrl_privkey_read_FILEp(us, privf); }
static cdk_error_t sexp_to_mpi (gcry_sexp_t sexp, const char *val, gcry_mpi_t *ret_buf) { gcry_sexp_t list; if (!sexp || !val || !ret_buf) return CDK_Inv_Value; list = gcry_sexp_find_token (sexp, val, 0); if (!list) return CDK_Inv_Value; *ret_buf = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); if (! *ret_buf) return CDK_Inv_Value; return 0; }
int p2p_encrypt(unsigned char *msg, size_t msglen, unsigned char *buf, size_t buflen, gcry_sexp_t r_key) { gcry_sexp_t ciph, data; size_t err; gcry_sexp_build(&data, &err, "(data (flags pkcs1) (value %b))", msglen, msg); gcry_pk_encrypt(&ciph, data, r_key); gcry_sexp_release(data); gcry_sexp_t a = gcry_sexp_find_token(ciph, "a", 0); gcry_sexp_release(ciph); gcry_sexp_t sexp_mpi = gcry_sexp_cdr(a); gcry_sexp_release(a); gcry_mpi_t data_mpi = gcry_sexp_nth_mpi(sexp_mpi, 0, GCRYMPI_FMT_USG); gcry_mpi_print(GCRYMPI_FMT_PGP, buf, buflen, &err, data_mpi); return err; }
/* * Extract an MPI from the given s-expression SEXP named NAME which is * encoded using INFORMAT and store it in a newly allocated ssh_string * encoded using OUTFORMAT. */ ssh_string ssh_sexp_extract_mpi(const gcry_sexp_t sexp, const char *name, enum gcry_mpi_format informat, enum gcry_mpi_format outformat) { gpg_error_t err; ssh_string result = NULL; gcry_sexp_t fragment = NULL; gcry_mpi_t mpi = NULL; size_t size; fragment = gcry_sexp_find_token(sexp, name, 0); if (fragment == NULL) { goto fail; } mpi = gcry_sexp_nth_mpi(fragment, 1, informat); if (mpi == NULL) { goto fail; } err = gcry_mpi_print(outformat, NULL, 0, &size, mpi); if (err != 0) { goto fail; } result = ssh_string_new(size); if (result == NULL) { goto fail; } err = gcry_mpi_print(outformat, ssh_string_data(result), size, NULL, mpi); if (err != 0) { ssh_string_burn(result); ssh_string_free(result); result = NULL; goto fail; } fail: gcry_sexp_release(fragment); gcry_mpi_release(mpi); return result; }
static void extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected) { gcry_sexp_t l1; const void *a; size_t alen; void *b; size_t blen; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_data (l1, 1, &alen); b = data_from_hex (expected, &blen); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( alen != blen || memcmp (a, b, alen) ) fail ("parameter \"%s\" does not match expected value\n", name); gcry_free (b); gcry_sexp_release (l1); }
static libspectrum_error get_mpi( gcry_mpi_t *mpi, gcry_sexp_t sexp, const char *token ) { gcry_sexp_t pair; pair = gcry_sexp_find_token( sexp, token, strlen( token ) ); if( !pair ) { libspectrum_print_error( LIBSPECTRUM_ERROR_LOGIC, "get_mpis: couldn't find '%s'", token ); return LIBSPECTRUM_ERROR_LOGIC; } *mpi = gcry_sexp_nth_mpi( pair, 1, GCRYMPI_FMT_STD ); if( !(*mpi) ) { libspectrum_print_error( LIBSPECTRUM_ERROR_LOGIC, "get_mpis: couldn't create MPI '%s'", token ); return LIBSPECTRUM_ERROR_LOGIC; } return LIBSPECTRUM_ERROR_NONE; }
static char * gcry_prikey2jwk (gcry_sexp_t * pubkey) { assert (NULL != pubkey); gcry_error_t rc = -1; gcry_sexp_t sexp_q; gcry_mpi_t mpi_q; unsigned char *raw_q; size_t size_q; size_t d_b64_len; char *d_b64 = NULL; if (NULL == (sexp_q = gcry_sexp_find_token(*pubkey, "d", 0))) goto OUT; if (NULL == (mpi_q = gcry_sexp_nth_mpi (sexp_q, 1, GCRYMPI_FMT_USG))) goto FREE_Q; rc = gcry_mpi_aprint(GCRYMPI_FMT_USG, &raw_q, &size_q, mpi_q); if (rc) goto FREE_MPI_Q; if (0 == (d_b64_len = base64url_encode_alloc (raw_q, size_q, &d_b64))) goto FREE_MPI_Q; gcry_free (raw_q); FREE_MPI_Q: gcry_mpi_release (mpi_q); FREE_Q: gcry_sexp_release (sexp_q); OUT: return d_b64; }
static int dsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) { #elif defined HAVE_LIBCRYPTO static int dsa_public_to_string(DSA *key, ssh_buffer buffer) { #endif ssh_string p = NULL; ssh_string q = NULL; ssh_string g = NULL; ssh_string n = NULL; int rc = -1; #ifdef HAVE_LIBGCRYPT const char *tmp = NULL; size_t size; gcry_sexp_t sexp; sexp = gcry_sexp_find_token(key, "p", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); p = ssh_string_new(size); if (p == NULL) { goto error; } ssh_string_fill(p, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(key, "q", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); q = ssh_string_new(size); if (q == NULL) { goto error; } ssh_string_fill(q, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(key, "g", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); g = ssh_string_new(size); if (g == NULL) { goto error; } ssh_string_fill(g, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(key, "y", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); n = ssh_string_new(size); if (n == NULL) { goto error; } ssh_string_fill(n, (char *) tmp, size); #elif defined HAVE_LIBCRYPTO p = make_bignum_string(key->p); q = make_bignum_string(key->q); g = make_bignum_string(key->g); n = make_bignum_string(key->pub_key); if (p == NULL || q == NULL || g == NULL || n == NULL) { goto error; } #endif /* HAVE_LIBCRYPTO */ if (buffer_add_ssh_string(buffer, p) < 0) { goto error; } if (buffer_add_ssh_string(buffer, q) < 0) { goto error; } if (buffer_add_ssh_string(buffer, g) < 0) { goto error; } if (buffer_add_ssh_string(buffer, n) < 0) { goto error; } rc = 0; error: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(sexp); #endif ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); ssh_string_burn(n); ssh_string_free(n); return rc; #if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO) }
/** * @brief Make a public_key object out of a private_key object. * * @param[in] prv The private key to generate the public key. * * @returns The generated public key, NULL on error. * * @see publickey_to_string() */ ssh_public_key publickey_from_privatekey(ssh_private_key prv) { ssh_public_key key = NULL; #ifdef HAVE_LIBGCRYPT gcry_sexp_t sexp; const char *tmp = NULL; size_t size; ssh_string p = NULL; ssh_string q = NULL; ssh_string g = NULL; ssh_string y = NULL; ssh_string e = NULL; ssh_string n = NULL; #endif /* HAVE_LIBGCRYPT */ key = malloc(sizeof(struct ssh_public_key_struct)); if (key == NULL) { return NULL; } ZERO_STRUCTP(key); key->type = prv->type; switch(key->type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(prv->dsa_priv, "p", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); p = ssh_string_new(size); if (p == NULL) { goto error; } ssh_string_fill(p,(char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv,"q",0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); q = ssh_string_new(size); if (q == NULL) { goto error; } ssh_string_fill(q,(char *) tmp,size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv, "g", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); g = ssh_string_new(size); if (g == NULL) { goto error; } ssh_string_fill(g,(char *) tmp,size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv,"y",0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); y = ssh_string_new(size); if (y == NULL) { goto error; } ssh_string_fill(y,(char *) tmp,size); gcry_sexp_release(sexp); gcry_sexp_build(&key->dsa_pub, NULL, "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))", ssh_string_len(p), ssh_string_data(p), ssh_string_len(q), ssh_string_data(q), ssh_string_len(g), ssh_string_data(g), ssh_string_len(y), ssh_string_data(y)); ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); ssh_string_burn(y); ssh_string_free(y); #elif defined HAVE_LIBCRYPTO key->dsa_pub = DSA_new(); if (key->dsa_pub == NULL) { goto error; } key->dsa_pub->p = BN_dup(prv->dsa_priv->p); key->dsa_pub->q = BN_dup(prv->dsa_priv->q); key->dsa_pub->g = BN_dup(prv->dsa_priv->g); key->dsa_pub->pub_key = BN_dup(prv->dsa_priv->pub_key); if (key->dsa_pub->p == NULL || key->dsa_pub->q == NULL || key->dsa_pub->g == NULL || key->dsa_pub->pub_key == NULL) { goto error; } #endif /* HAVE_LIBCRYPTO */ break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(prv->rsa_priv, "n", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); n = ssh_string_new(size); if (n == NULL) { goto error; } ssh_string_fill(n, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->rsa_priv, "e", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); e = ssh_string_new(size); if (e == NULL) { goto error; } ssh_string_fill(e, (char *) tmp, size); gcry_sexp_release(sexp); gcry_sexp_build(&key->rsa_pub, NULL, "(public-key(rsa(n %b)(e %b)))", ssh_string_len(n), ssh_string_data(n), ssh_string_len(e), ssh_string_data(e)); if (key->rsa_pub == NULL) { goto error; } ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); #elif defined HAVE_LIBCRYPTO key->rsa_pub = RSA_new(); if (key->rsa_pub == NULL) { goto error; } key->rsa_pub->e = BN_dup(prv->rsa_priv->e); key->rsa_pub->n = BN_dup(prv->rsa_priv->n); if (key->rsa_pub->e == NULL || key->rsa_pub->n == NULL) { goto error; } #endif break; default: publickey_free(key); return NULL; } key->type_c = ssh_type_to_char(prv->type); return key; error: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(sexp); ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); ssh_string_burn(y); ssh_string_free(y); ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); #endif publickey_free(key); return NULL; }
ssh_string ssh_encrypt_rsa1(ssh_session session, ssh_string data, ssh_public_key key) { ssh_string str = NULL; size_t len = ssh_string_len(data); size_t size = 0; #ifdef HAVE_LIBGCRYPT const char *tmp = NULL; gcry_sexp_t ret_sexp; gcry_sexp_t data_sexp; if (gcry_sexp_build(&data_sexp, NULL, "(data(flags pkcs1)(value %b))", len, ssh_string_data(data))) { ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error"); return NULL; } if (gcry_pk_encrypt(&ret_sexp, data_sexp, key->rsa_pub)) { gcry_sexp_release(data_sexp); ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error"); return NULL; } gcry_sexp_release(data_sexp); data_sexp = gcry_sexp_find_token(ret_sexp, "a", 0); if (data_sexp == NULL) { ssh_set_error(session, SSH_FATAL, "RSA1 encrypt: libgcrypt error"); gcry_sexp_release(ret_sexp); return NULL; } tmp = gcry_sexp_nth_data(data_sexp, 1, &size); if (*tmp == 0) { size--; tmp++; } str = ssh_string_new(size); if (str == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); gcry_sexp_release(data_sexp); gcry_sexp_release(ret_sexp); return NULL; } ssh_string_fill(str, tmp, size); gcry_sexp_release(data_sexp); gcry_sexp_release(ret_sexp); #elif defined HAVE_LIBCRYPTO size = RSA_size(key->rsa_pub); str = ssh_string_new(size); if (str == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); return NULL; } if (RSA_public_encrypt(len, ssh_string_data(data), ssh_string_data(str), key->rsa_pub, RSA_PKCS1_PADDING) < 0) { ssh_string_free(str); return NULL; } #endif return str; }
STRING *signature_to_string(SIGNATURE *sign){ STRING *str; STRING *rs; #ifdef HAVE_LIBGCRYPT const char *r,*s; gcry_sexp_t sexp; size_t size; #elif defined HAVE_LIBCRYPTO STRING *r,*s; #endif unsigned char buffer[40]; BUFFER *tmpbuf=buffer_new(); STRING *tmp; tmp=string_from_char(ssh_type_to_char(sign->type)); buffer_add_ssh_string(tmpbuf,tmp); free(tmp); switch(sign->type){ case TYPE_DSS: memset(buffer,0,40); #ifdef HAVE_LIBGCRYPT sexp=gcry_sexp_find_token(sign->dsa_sign,"r",0); r=gcry_sexp_nth_data(sexp,1,&size); if (*r == 0) /* libgcrypt put 0 when first bit is set */ { size--; r++; } memcpy(buffer,r + size - 20,20); gcry_sexp_release(sexp); sexp=gcry_sexp_find_token(sign->dsa_sign,"s",0); s=gcry_sexp_nth_data(sexp,1,&size); if (*s == 0) { size--; s++; } memcpy(buffer+ 20, s + size - 20, 20); gcry_sexp_release(sexp); #elif defined HAVE_LIBCRYPTO r=make_bignum_string(sign->dsa_sign->r); s=make_bignum_string(sign->dsa_sign->s); rs=string_new(40); memcpy(buffer,r->string+string_len(r)-20,20); memcpy(buffer+ 20, s->string + string_len(s) - 20, 20); free(r); free(s); #endif rs=string_new(40); string_fill(rs,buffer,40); buffer_add_ssh_string(tmpbuf,rs); free(rs); break; case TYPE_RSA: case TYPE_RSA1: #ifdef HAVE_LIBGCRYPT sexp=gcry_sexp_find_token(sign->rsa_sign,"s",0); s=gcry_sexp_nth_data(sexp,1,&size); if (*s == 0) { size--; s++; } rs=string_new(size); string_fill(rs,(char *)s,size); buffer_add_ssh_string(tmpbuf,rs); gcry_sexp_release(sexp); free(rs); #elif defined HAVE_LIBCRYPTO buffer_add_ssh_string(tmpbuf,sign->rsa_sign); #endif break; } str=string_new(buffer_get_len(tmpbuf)); string_fill(str,buffer_get(tmpbuf),buffer_get_len(tmpbuf)); buffer_free(tmpbuf); return str; }
/** \brief Makes a PUBLIC_KEY object out of a PRIVATE_KEY object * \param prv the Private key * \returns the public key * \see publickey_to_string() */ PUBLIC_KEY *publickey_from_privatekey(PRIVATE_KEY *prv){ PUBLIC_KEY *key=malloc(sizeof(PUBLIC_KEY)); #ifdef HAVE_LIBGCRYPT gcry_sexp_t sexp; const char *tmp; size_t size; STRING *p,*q,*g,*y,*e,*n; #endif key->type=prv->type; switch(key->type){ case TYPE_DSS: #ifdef HAVE_LIBGCRYPT sexp=gcry_sexp_find_token(prv->dsa_priv,"p",0); tmp=gcry_sexp_nth_data(sexp,1,&size); p=string_new(size); string_fill(p,(char *)tmp,size); gcry_sexp_release(sexp); sexp=gcry_sexp_find_token(prv->dsa_priv,"q",0); tmp=gcry_sexp_nth_data(sexp,1,&size); q=string_new(size); string_fill(q,(char *)tmp,size); gcry_sexp_release(sexp); sexp=gcry_sexp_find_token(prv->dsa_priv,"g",0); tmp=gcry_sexp_nth_data(sexp,1,&size); g=string_new(size); string_fill(g,(char *)tmp,size); gcry_sexp_release(sexp); sexp=gcry_sexp_find_token(prv->dsa_priv,"y",0); tmp=gcry_sexp_nth_data(sexp,1,&size); y=string_new(size); string_fill(y,(char *)tmp,size); gcry_sexp_release(sexp); gcry_sexp_build(&key->dsa_pub,NULL,"(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",string_len(p),p->string,string_len(q),q->string,string_len(g),g->string,string_len(y),y->string); free(p); free(q); free(g); free(y); #elif defined HAVE_LIBCRYPTO key->dsa_pub=DSA_new(); key->dsa_pub->p=BN_dup(prv->dsa_priv->p); key->dsa_pub->q=BN_dup(prv->dsa_priv->q); key->dsa_pub->pub_key=BN_dup(prv->dsa_priv->pub_key); key->dsa_pub->g=BN_dup(prv->dsa_priv->g); #endif break; case TYPE_RSA: case TYPE_RSA1: #ifdef HAVE_LIBGCRYPT sexp=gcry_sexp_find_token(prv->rsa_priv,"n",0); tmp=gcry_sexp_nth_data(sexp,1,&size); n=string_new(size); string_fill(n,(char *)tmp,size); gcry_sexp_release(sexp); sexp=gcry_sexp_find_token(prv->rsa_priv,"e",0); tmp=gcry_sexp_nth_data(sexp,1,&size); e=string_new(size); string_fill(e,(char *)tmp,size); gcry_sexp_release(sexp); gcry_sexp_build(&key->rsa_pub,NULL,"(public-key(rsa(n %b)(e %b)))",string_len(n),n->string,string_len(e),e->string); free(e); free(n); #elif defined HAVE_LIBCRYPTO key->rsa_pub=RSA_new(); key->rsa_pub->e=BN_dup(prv->rsa_priv->e); key->rsa_pub->n=BN_dup(prv->rsa_priv->n); #endif break; } key->type_c=ssh_type_to_char(prv->type); return key; }
/**************** * Emulate our old PK interface here - sometime in the future we might * change the internal design to directly fit to libgcrypt. */ static int _gnutls_pk_encrypt (int algo, mpi_t * resarr, mpi_t data, mpi_t * pkey, int pkey_len) { gcry_sexp_t s_ciph, s_data, s_pkey; int rc = -1; /* make a sexp from pkey */ switch (algo) { 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_data, NULL, "%m", data)) { gnutls_assert (); gcry_sexp_release (s_pkey); return GNUTLS_E_INTERNAL_ERROR; } /* pass it to libgcrypt */ rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); gcry_sexp_release (s_data); gcry_sexp_release (s_pkey); if (rc != 0) { gnutls_assert (); return GNUTLS_E_PK_ENCRYPTION_FAILED; } else { /* add better error handling or make gnupg use S-Exp directly */ gcry_sexp_t list = gcry_sexp_find_token (s_ciph, "a", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (s_ciph); return GNUTLS_E_INTERNAL_ERROR; } resarr[0] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); if (resarr[0] == NULL) { gnutls_assert (); gcry_sexp_release (s_ciph); return GNUTLS_E_INTERNAL_ERROR; } } gcry_sexp_release (s_ciph); return rc; }
static uint8_t* sig2sigbuf (const gcry_sexp_t *sig, uint8_t **out, size_t *rs_len) { assert (NULL != sig); assert (NULL != out); gcry_error_t rc = -1; gcry_sexp_t sexp_r, sexp_s; gcry_mpi_t mpi_r, mpi_s; unsigned char *raw_r, *raw_s; size_t size_r, size_s; uint8_t *rs; if (NULL == (sexp_r = gcry_sexp_find_token(*sig, "r", 0))) goto OUT; if (NULL == (sexp_s = gcry_sexp_find_token(*sig, "s", 0))) goto FREE_R; if (NULL == (mpi_r = gcry_sexp_nth_mpi (sexp_r, 1, GCRYMPI_FMT_USG))) goto FREE_S; if (NULL == (mpi_s = gcry_sexp_nth_mpi (sexp_s, 1, GCRYMPI_FMT_USG))) goto FREE_MPI_R; rc = gcry_mpi_aprint(GCRYMPI_FMT_USG, &raw_r, &size_r, mpi_r); if (rc) goto FREE_MPI_S; rc = gcry_mpi_aprint(GCRYMPI_FMT_USG, &raw_s, &size_s, mpi_s); if (rc) goto FREE_RAW_R; rs = malloc (size_r+size_s); memset (rs, 0, size_r+size_s); memcpy (rs, raw_r, size_r); memcpy (rs+size_r, raw_s, size_s); *rs_len = size_r + size_s; rc = 0; gcry_free (raw_s); FREE_RAW_R: gcry_free (raw_r); FREE_MPI_S: gcry_mpi_release (mpi_s); FREE_MPI_R: gcry_mpi_release (mpi_r); FREE_S: gcry_sexp_release (sexp_s); FREE_R: gcry_sexp_release (sexp_r); OUT: if (rc == 0) return rs; else return NULL; }
/* A test based on bug 1594. */ static void bug_1594 (void) { static char thing[] = "(signature" " (public-key" " (rsa" " (n #00A53A6B3A50BE571F805BD98ECE1FCE4CE291C3D4D3E971740E1EE6D447F526" " 6AC8973DDC82F0ADD234CC82E0A0A3F48B81ACC8B038DB8ACC3E78DC2ED2642F" " 6BA353FCA60F47C2801DEB477B37FB8B2F5508AA1C6D922780DB142DEA19B812" " C4E64F1138AD3BD61C58DB2D2591BE0BF36A1AC588AA45763BCDFF581050ABA8" " CA47BD9723ADD6A308AE28471EDD2B16D03C941D4F2B7E019C43AF8972880633" " 54E97B7E19F1677D84B69A26B184A77B719DD72C48E0EE36107046F786566A9D" " 13BAD724D6D78F24700FC22FC000E1B2A8C1B08ED62008395B0764CD9B55E80D" " A0A2B61C698DC27EA98E68BB576ACFC2B91B4D7283E7D960948D049D6E3C4CB1" " F489B460A120A4BB6C04A843FD3A67454136DE61CF68A927871EFFA9141BD372" " A748593C703E0301F039A9E674C50301BFC385BABE5B154250E7D57B82DB31F1" " E1AC696F870DCD8FE8DEC75608B988FCA3B484F1FD7755BF452F99597269AF02" " E8AF87D0F93DB427291659183D077254C835BFB6DDFD87CD0B5E0738682FCD34" " 923F22551F73944E6CBE3ED6879B4414676B5DA0F30ED21DFA12BD2230C3C5D2" " EA116A3EFEB4AEC21C58E63FAFA549A63190F01859445E9B80F427B80FD4C884" " 2AD41FE760A3E9DEDFB56CEBE8EA783838B2B392CACDDC760CCE212E388AFBC1" " 95DC6D0ED87E9091F82A82CE372738C8DE8ABD76ACD06AC8B80AA0597162DF59" " 67#)" " (e #010001#))))"; gcry_sexp_t sig, pubkey, n, n_val; info ("checking fix for bug 1594\n"); if (gcry_sexp_new (&sig, thing, 0, 1)) die ("scanning fixed string failed\n"); pubkey = gcry_sexp_find_token (sig, "public-key", 0); gcry_sexp_release (sig); if (!pubkey) { fail ("'public-key' token not found"); return; } n = gcry_sexp_find_token (pubkey, "n", 0); if (!n) { fail ("'n' token not found"); gcry_sexp_release (pubkey); return; } n_val = gcry_sexp_nth (n, 1); /* Bug 1594 would require the following test: * if (n_val) * fail ("extracting 1-th of 'n' list did not fail"); * However, we meanwhile modified the S-expression functions to * behave like Scheme to allow the access of any element of a list. */ if (!n_val) fail ("extracting 1-th of 'n' list failed"); /*gcry_log_debugsxp ("1-th", n_val); => "(#00A5...#)" */ gcry_sexp_release (n_val); n_val = gcry_sexp_nth (n, 2); if (n_val) fail ("extracting 2-th of 'n' list did not fail"); n_val = gcry_sexp_nth (n, 0); if (!n_val) fail ("extracting 0-th of 'n' list failed"); /*gcry_log_debugsxp ("0-th", n_val); => "(n)" */ if (gcry_sexp_nth (n_val, 1)) fail ("extracting 1-th of car of 'n' list did not fail"); gcry_sexp_release (n_val); gcry_sexp_release (n); gcry_sexp_release (pubkey); }
static int rsa_public_to_string(gcry_sexp_t key, ssh_buffer buffer) { #elif defined HAVE_LIBCRYPTO static int rsa_public_to_string(RSA *key, ssh_buffer buffer) { #endif ssh_string e = NULL; ssh_string n = NULL; int rc = -1; #ifdef HAVE_LIBGCRYPT const char *tmp; size_t size; gcry_sexp_t sexp; sexp = gcry_sexp_find_token(key, "n", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); n = ssh_string_new(size); if (n == NULL) { goto error; } ssh_string_fill(n, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(key, "e", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); e = ssh_string_new(size); if (e == NULL) { goto error; } ssh_string_fill(e, (char *) tmp, size); #elif defined HAVE_LIBCRYPTO e = make_bignum_string(key->e); n = make_bignum_string(key->n); if (e == NULL || n == NULL) { goto error; } #endif if (buffer_add_ssh_string(buffer, e) < 0) { goto error; } if (buffer_add_ssh_string(buffer, n) < 0) { goto error; } rc = 0; error: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(sexp); #endif ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); return rc; #if defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBCRYPTO) }
/* Signature decoding functions */ ssh_string signature_to_string(SIGNATURE *sign) { unsigned char buffer[40] = {0}; ssh_buffer tmpbuf = NULL; ssh_string str = NULL; ssh_string tmp = NULL; ssh_string rs = NULL; int rc = -1; #ifdef HAVE_LIBGCRYPT const char *r = NULL; const char *s = NULL; gcry_sexp_t sexp; size_t size = 0; #elif defined HAVE_LIBCRYPTO ssh_string r = NULL; ssh_string s = NULL; #endif tmpbuf = ssh_buffer_new(); if (tmpbuf == NULL) { return NULL; } tmp = ssh_string_from_char(ssh_type_to_char(sign->type)); if (tmp == NULL) { ssh_buffer_free(tmpbuf); return NULL; } if (buffer_add_ssh_string(tmpbuf, tmp) < 0) { ssh_buffer_free(tmpbuf); ssh_string_free(tmp); return NULL; } ssh_string_free(tmp); switch(sign->type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(sign->dsa_sign, "r", 0); if (sexp == NULL) { ssh_buffer_free(tmpbuf); return NULL; } r = gcry_sexp_nth_data(sexp, 1, &size); if (*r == 0) { /* libgcrypt put 0 when first bit is set */ size--; r++; } memcpy(buffer, r + size - 20, 20); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(sign->dsa_sign, "s", 0); if (sexp == NULL) { ssh_buffer_free(tmpbuf); return NULL; } s = gcry_sexp_nth_data(sexp,1,&size); if (*s == 0) { size--; s++; } memcpy(buffer+ 20, s + size - 20, 20); gcry_sexp_release(sexp); #elif defined HAVE_LIBCRYPTO r = make_bignum_string(sign->dsa_sign->r); if (r == NULL) { ssh_buffer_free(tmpbuf); return NULL; } s = make_bignum_string(sign->dsa_sign->s); if (s == NULL) { ssh_buffer_free(tmpbuf); ssh_string_free(r); return NULL; } memcpy(buffer, (char *)ssh_string_data(r) + ssh_string_len(r) - 20, 20); memcpy(buffer + 20, (char *)ssh_string_data(s) + ssh_string_len(s) - 20, 20); ssh_string_free(r); ssh_string_free(s); #endif /* HAVE_LIBCRYPTO */ rs = ssh_string_new(40); if (rs == NULL) { ssh_buffer_free(tmpbuf); return NULL; } ssh_string_fill(rs, buffer, 40); rc = buffer_add_ssh_string(tmpbuf, rs); ssh_string_free(rs); if (rc < 0) { ssh_buffer_free(tmpbuf); return NULL; } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(sign->rsa_sign, "s", 0); if (sexp == NULL) { ssh_buffer_free(tmpbuf); return NULL; } s = gcry_sexp_nth_data(sexp,1,&size); if (*s == 0) { size--; s++; } rs = ssh_string_new(size); if (rs == NULL) { ssh_buffer_free(tmpbuf); return NULL; } ssh_string_fill(rs, (char *) s, size); rc = buffer_add_ssh_string(tmpbuf, rs); gcry_sexp_release(sexp); ssh_string_free(rs); if (rc < 0) { ssh_buffer_free(tmpbuf); return NULL; } #elif defined HAVE_LIBCRYPTO if (buffer_add_ssh_string(tmpbuf,sign->rsa_sign) < 0) { ssh_buffer_free(tmpbuf); return NULL; } #endif break; } str = ssh_string_new(buffer_get_rest_len(tmpbuf)); if (str == NULL) { ssh_buffer_free(tmpbuf); return NULL; } ssh_string_fill(str, buffer_get_rest(tmpbuf), buffer_get_rest_len(tmpbuf)); ssh_buffer_free(tmpbuf); return str; }
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_byte))" , "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); int hash_len_bits = hash_len*8; 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 unsigned int j; for(e = 0; e < qbits ; e++){ gcry_mpi_t empi = gcry_mpi_set_ui(NULL,e); gcry_mpi_t twoi = gcry_mpi_new(e); gcry_mpi_mul_2exp(empi, one, e); // twoi = 2^e for( j=0; j< 256 ; j++){ gcry_mpi_t jmpi = gcry_mpi_set_ui(NULL,j); gcry_mpi_mulm(twoi,jmpi,empi,q); //retrieve k gcry_mpi_mulm(tmp, s_tilda, twoi, q); // s_tilda*(2^e) modq q gcry_mpi_subm(result, s_tilda, s, q); // s_tilda - s mod q gcry_mpi_invm(result, result, q); // (s_tilda - s mod q)^-1 gcry_mpi_mulm(result,result, tmp, q); // s_tilda*(2^3) mod q)*(s_tilda - s mod q)^-1 === 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] BYTE : %d * 2^%d FAULT: k-j*2^%d\n" , j , (int)e,(int)e); //DEBUG DEBUG_MPI_PRINT(result,"X = "); printf("\n"); return; } } } for(e = 0; e < qbits; e++){ gcry_mpi_t empi = gcry_mpi_set_ui(NULL,e); gcry_mpi_t twoi = gcry_mpi_new(e); gcry_mpi_mul_2exp(empi, one, e); // twoi = 2^e for( j=0; j< 256 ; j++){ gcry_mpi_t jmpi = gcry_mpi_set_ui(NULL,j); gcry_mpi_mulm(twoi,jmpi,empi,q); //retrieve k gcry_mpi_mulm(tmp, s_tilda, twoi, q); // s_tilda*(2^e) modq q gcry_mpi_subm(result, s, s_tilda, q); // s_tilda - s mod q gcry_mpi_invm(result, result, q); // (s_tilda - s mod q)^-1 gcry_mpi_mulm(result,result, tmp, q); // s_tilda*(2^3) mod q)*(s_tilda - s mod q)^-1 === 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) { continue; } else{ printf("\n[!!!]PRIVATE KEY %d %d BITS CRACKED!!\n" , pbits,qbits ); printf("[DBG] BYTE : %d * 2^%d FAULT: k+j*2^%d\n" , j , (int)e,(int)e); //DEBUG DEBUG_MPI_PRINT(result,"X = "); printf("\n"); return; } } } }
/* in case of DSA puts into data, r,s */ static int _gnutls_pk_sign (int algo, mpi_t * data, mpi_t hash, mpi_t * pkey, int pkey_len) { gcry_sexp_t s_hash, s_key, s_sig; int rc = -1; /* make a sexp from pkey */ switch (algo) { case GCRY_PK_DSA: if (pkey_len >= 5) rc = gcry_sexp_build (&s_key, NULL, "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))", pkey[0], pkey[1], pkey[2], pkey[3], pkey[4]); else { gnutls_assert (); } break; case GCRY_PK_RSA: if (pkey_len >= 6) rc = gcry_sexp_build (&s_key, NULL, "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))", pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], pkey[5]); else { gnutls_assert (); } 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 (); return GNUTLS_E_INTERNAL_ERROR; } /* pass it to libgcrypt */ rc = gcry_pk_sign (&s_sig, s_hash, s_key); gcry_sexp_release (s_hash); gcry_sexp_release (s_key); if (rc != 0) { gnutls_assert (); return GNUTLS_E_PK_SIGN_FAILED; } else { gcry_sexp_t list; if (algo == GCRY_PK_DSA) { list = gcry_sexp_find_token (s_sig, "r", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (s_sig); return GNUTLS_E_INTERNAL_ERROR; } data[0] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); list = gcry_sexp_find_token (s_sig, "s", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (s_sig); return GNUTLS_E_INTERNAL_ERROR; } data[1] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); } else { /* GCRY_PK_RSA */ list = gcry_sexp_find_token (s_sig, "s", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (s_sig); return GNUTLS_E_INTERNAL_ERROR; } data[0] = gcry_sexp_nth_mpi (list, 1, 0); gcry_sexp_release (list); } } gcry_sexp_release (s_sig); return 0; }
/* fixme: we need better tests */ static void basic (void) { int pass; gcry_sexp_t sexp; int idx; char *secure_buffer; size_t secure_buffer_len; const char *string; static struct { const char *token; const char *parm; } values[] = { { "public-key", NULL }, { "dsa", NULL }, { "dsa", "p" }, { "dsa", "y" }, { "dsa", "q" }, { "dsa", "g" }, { NULL } }; info ("doing some pretty pointless tests\n"); secure_buffer_len = 99; secure_buffer = gcry_xmalloc_secure (secure_buffer_len); memset (secure_buffer, 'G', secure_buffer_len); for (pass=0;;pass++) { gcry_mpi_t m; switch (pass) { case 0: string = ("(public-key (dsa (p #41424344#) (y this_is_y) " "(q #61626364656667#) (g %m)))"); m = gcry_mpi_set_ui (NULL, 42); if ( gcry_sexp_build (&sexp, NULL, string, m ) ) { gcry_mpi_release (m); fail (" scanning `%s' failed\n", string); return; } gcry_mpi_release (m); break; case 1: string = ("(public-key (dsa (p #41424344#) (y this_is_y) " "(q %b) (g %m)))"); m = gcry_mpi_set_ui (NULL, 42); if ( gcry_sexp_build (&sexp, NULL, string, 15, "foo\0\x01\0x02789012345", m) ) { gcry_mpi_release (m); fail (" scanning `%s' failed\n", string); return; } gcry_mpi_release (m); break; case 2: string = ("(public-key (dsa (p #41424344#) (y silly_y_value) " "(q %b) (g %m)))"); m = gcry_mpi_set_ui (NULL, 17); if ( gcry_sexp_build (&sexp, NULL, string, secure_buffer_len, secure_buffer, m) ) { gcry_mpi_release (m); fail (" scanning `%s' failed\n", string); return; } gcry_mpi_release (m); if (!gcry_is_secure (sexp)) fail ("gcry_sexp_build did not switch to secure memory\n"); break; case 3: { gcry_sexp_t help_sexp; if (gcry_sexp_new (&help_sexp, "(foobar-parms (xp #1234#)(xq #03#))", 0, 1)) { fail (" scanning fixed string failed\n"); return; } string = ("(public-key (dsa (p #41424344#) (parm %S) " "(y dummy)(q %b) (g %m)))"); m = gcry_mpi_set_ui (NULL, 17); if ( gcry_sexp_build (&sexp, NULL, string, help_sexp, secure_buffer_len, secure_buffer, m) ) { gcry_mpi_release (m); fail (" scanning `%s' failed\n", string); return; } gcry_mpi_release (m); gcry_sexp_release (help_sexp); } break; default: return; /* Ready. */ } /* now find something */ for (idx=0; values[idx].token; idx++) { const char *token = values[idx].token; const char *parm = values[idx].parm; gcry_sexp_t s1, s2; gcry_mpi_t a; const char *p; size_t n; s1 = gcry_sexp_find_token (sexp, token, strlen(token) ); if (!s1) { fail ("didn't found `%s'\n", token); continue; } p = gcry_sexp_nth_data (s1, 0, &n); if (!p) { gcry_sexp_release (s1); fail ("no car for `%s'\n", token); continue; } info ("car=`%.*s'\n", (int)n, p); s2 = gcry_sexp_cdr (s1); if (!s2) { gcry_sexp_release (s1); fail ("no cdr for `%s'\n", token); continue; } p = gcry_sexp_nth_data (s2, 0, &n); gcry_sexp_release (s2); if (p) { gcry_sexp_release (s1); fail ("data at car of `%s'\n", token); continue; } if (parm) { s2 = gcry_sexp_find_token (s1, parm, strlen (parm)); gcry_sexp_release (s1); if (!s2) { fail ("didn't found `%s'\n", parm); continue; } p = gcry_sexp_nth_data (s2, 0, &n); if (!p) { gcry_sexp_release (s2); fail("no car for `%s'\n", parm ); continue; } info ("car=`%.*s'\n", (int)n, p); p = gcry_sexp_nth_data (s2, 1, &n); if (!p) { gcry_sexp_release (s2); fail("no cdr for `%s'\n", parm ); continue; } info ("cdr=`%.*s'\n", (int)n, p); a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG); gcry_sexp_release (s2); if (!a) { fail("failed to cdr the mpi for `%s'\n", parm); continue; } gcry_mpi_release (a); } else gcry_sexp_release (s1); } gcry_sexp_release (sexp); sexp = NULL; } gcry_free (secure_buffer); }