static void check_keys (gcry_sexp_t pkey, gcry_sexp_t skey, unsigned int nbits_data, gpg_err_code_t decrypt_fail_code) { gcry_sexp_t plain; gcry_mpi_t x; int rc; /* Create plain text. */ x = gcry_mpi_new (nbits_data); gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM); rc = gcry_sexp_build (&plain, NULL, "(data (flags raw) (value %m))", x); if (rc) die ("converting data for encryption failed: %s\n", gcry_strerror (rc)); check_keys_crypt (pkey, skey, plain, decrypt_fail_code); gcry_sexp_release (plain); gcry_mpi_release (x); /* Create plain text. */ x = gcry_mpi_new (nbits_data); gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM); rc = gcry_sexp_build (&plain, NULL, "(data (flags raw no-blinding) (value %m))", x); gcry_mpi_release (x); if (rc) die ("converting data for encryption failed: %s\n", gcry_strerror (rc)); check_keys_crypt (pkey, skey, plain, decrypt_fail_code); gcry_sexp_release (plain); }
GBytes * gkm_data_der_write_public_key_rsa (gcry_sexp_t s_key) { GNode *asn = NULL; gcry_mpi_t n, e; GBytes *result = NULL; n = e = NULL; asn = egg_asn1x_create (pk_asn1_tab, "RSAPublicKey"); g_return_val_if_fail (asn, NULL); if (!gkm_sexp_extract_mpi (s_key, &n, "rsa", "n", NULL) || !gkm_sexp_extract_mpi (s_key, &e, "rsa", "e", NULL)) goto done; if (!gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "modulus", NULL), n) || !gkm_data_asn1_write_mpi (egg_asn1x_node (asn, "publicExponent", NULL), e)) goto done; result = egg_asn1x_encode (asn, NULL); if (result == NULL) g_warning ("couldn't encode public rsa key: %s", egg_asn1x_message (asn)); done: egg_asn1x_destroy (asn); gcry_mpi_release (n); gcry_mpi_release (e); return result; }
/** * Multiply the generator g of the elliptic curve by @a val * to obtain the point on the curve representing @a val. * Afterwards, point addition will correspond to integer * addition. #GNUNET_CRYPTO_ecc_dlog() can be used to * convert a point back to an integer (as long as the * integer is smaller than the MAX of the @a edc context). * * @param edc calculation context for ECC operations * @param val value to encode into a point * @return representation of the value as an ECC point, * must be freed using #GNUNET_CRYPTO_ecc_free() */ gcry_mpi_point_t GNUNET_CRYPTO_ecc_dexp (struct GNUNET_CRYPTO_EccDlogContext *edc, int val) { gcry_mpi_t fact; gcry_mpi_t n; gcry_mpi_point_t g; gcry_mpi_point_t r; g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); GNUNET_assert (NULL != g); fact = gcry_mpi_new (0); if (val < 0) { n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); gcry_mpi_set_ui (fact, - val); gcry_mpi_sub (fact, n, fact); gcry_mpi_release (n); } else { gcry_mpi_set_ui (fact, val); } r = gcry_mpi_point_new (0); gcry_mpi_ec_mul (r, fact, g, edc->ctx); gcry_mpi_release (fact); gcry_mpi_point_release (g); return r; }
/** * Obtain a random point on the curve and its * additive inverse. Both returned values * must be freed using #GNUNET_CRYPTO_ecc_free(). * * @param edc calculation context for ECC operations * @param[out] r set to a random point on the curve * @param[out] r_inv set to the additive inverse of @a r */ void GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccDlogContext *edc, gcry_mpi_point_t *r, gcry_mpi_point_t *r_inv) { gcry_mpi_t fact; gcry_mpi_t n; gcry_mpi_point_t g; fact = GNUNET_CRYPTO_ecc_random_mod_n (edc); /* calculate 'r' */ g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); GNUNET_assert (NULL != g); *r = gcry_mpi_point_new (0); gcry_mpi_ec_mul (*r, fact, g, edc->ctx); /* calculate 'r_inv' */ n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); gcry_mpi_sub (fact, n, fact); /* fact = n - fact = - fact */ *r_inv = gcry_mpi_point_new (0); gcry_mpi_ec_mul (*r_inv, fact, g, edc->ctx); gcry_mpi_release (n); gcry_mpi_release (fact); gcry_mpi_point_release (g); }
static int test_add (void) { gcry_mpi_t one; gcry_mpi_t two; gcry_mpi_t ff; gcry_mpi_t result; unsigned char* pc; gcry_mpi_scan(&one, GCRYMPI_FMT_USG, ones, sizeof(ones), NULL); gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL); gcry_mpi_scan(&ff, GCRYMPI_FMT_USG, manyff, sizeof(manyff), NULL); result = gcry_mpi_new(0); gcry_mpi_add(result, one, two); gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); if (debug) gcry_log_debug ("Result of one plus two:\n%s\n", pc); gcry_free(pc); gcry_mpi_add(result, ff, one); gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result); if (debug) gcry_log_debug ("Result of ff plus one:\n%s\n", pc); gcry_free(pc); gcry_mpi_release(one); gcry_mpi_release(two); gcry_mpi_release(ff); gcry_mpi_release(result); return 1; }
static void do_powm ( const char *n_str, const char *e_str, const char *m_str) { gcry_mpi_t e, n, msg, cip; gcry_error_t err; int i; err = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, n_str, 0, 0); if (err) BUG (); err = gcry_mpi_scan (&e, GCRYMPI_FMT_HEX, e_str, 0, 0); if (err) BUG (); err = gcry_mpi_scan (&msg, GCRYMPI_FMT_HEX, m_str, 0, 0); if (err) BUG (); cip = gcry_mpi_new (0); start_timer (); for (i=0; i < 1000; i++) gcry_mpi_powm (cip, msg, e, n); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); /* { */ /* char *buf; */ /* if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void**)&buf, NULL, cip)) */ /* BUG (); */ /* printf ("result: %s\n", buf); */ /* gcry_free (buf); */ /* } */ gcry_mpi_release (cip); gcry_mpi_release (msg); gcry_mpi_release (n); gcry_mpi_release (e); }
static void context_alloc (void) { gpg_error_t err; gcry_ctx_t ctx; gcry_mpi_t p, a; wherestr = "context_alloc"; show ("checking context functions\n"); p = gcry_mpi_set_ui (NULL, 1); a = gcry_mpi_set_ui (NULL, 1); err = ec_p_new (&ctx, p, a); if (err) die ("ec_p_new returned an error: %s\n", gpg_strerror (err)); gcry_mpi_release (p); gcry_mpi_release (a); gcry_ctx_release (ctx); p = NULL; a = gcry_mpi_set_ui (NULL, 0); err = ec_p_new (&ctx, p, a); if (!err || gpg_err_code (err) != GPG_ERR_EINVAL) fail ("ec_p_new: bad parameter detection failed (1)\n"); gcry_mpi_release (a); a = NULL; err = ec_p_new (&ctx, p, a); if (!err || gpg_err_code (err) != GPG_ERR_EINVAL) fail ("ec_p_new: bad parameter detection failed (2)\n"); }
/* Verify a signature on data using a public key. The data must be * small enough to be signed (i.e. already hashed, if necessary). */ gcry_error_t otrl_privkey_verify(const unsigned char *sigbuf, size_t siglen, unsigned short pubkey_type, gcry_sexp_t pubs, const unsigned char *data, size_t len) { gcry_error_t err; gcry_mpi_t datampi,r,s; gcry_sexp_t datas, sigs; if (pubkey_type != OTRL_PUBKEY_TYPE_DSA || siglen != 40) return gcry_error(GPG_ERR_INV_VALUE); if (len) { gcry_mpi_scan(&datampi, GCRYMPI_FMT_USG, data, len, NULL); } else { datampi = gcry_mpi_set_ui(NULL, 0); } gcry_sexp_build(&datas, NULL, "(%m)", datampi); gcry_mpi_release(datampi); gcry_mpi_scan(&r, GCRYMPI_FMT_USG, sigbuf, 20, NULL); gcry_mpi_scan(&s, GCRYMPI_FMT_USG, sigbuf+20, 20, NULL); gcry_sexp_build(&sigs, NULL, "(sig-val (dsa (r %m)(s %m)))", r, s); gcry_mpi_release(r); gcry_mpi_release(s); err = gcry_pk_verify(sigs, datas, pubs); gcry_sexp_release(datas); gcry_sexp_release(sigs); return err; }
/** * Do pre-calculation for ECC discrete logarithm for small factors. * * @param max maximum value the factor can be * @param mem memory to use (should be smaller than @a max), must not be zero. * @return @a max if dlog failed, otherwise the factor */ struct GNUNET_CRYPTO_EccDlogContext * GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, unsigned int mem) { struct GNUNET_CRYPTO_EccDlogContext *edc; unsigned int K = ((max + (mem-1)) / mem); gcry_mpi_point_t g; struct GNUNET_PeerIdentity key; gcry_mpi_point_t gKi; gcry_mpi_t fact; gcry_mpi_t n; unsigned int i; GNUNET_assert (max < INT32_MAX); edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext); edc->max = max; edc->mem = mem; edc->map = GNUNET_CONTAINER_multipeermap_create (mem * 2, GNUNET_NO); GNUNET_assert (0 == gcry_mpi_ec_new (&edc->ctx, NULL, CURVE)); g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); GNUNET_assert (NULL != g); fact = gcry_mpi_new (0); gKi = gcry_mpi_point_new (0); for (i=0;i<=mem;i++) { gcry_mpi_set_ui (fact, i * K); gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); extract_pk (gKi, edc->ctx, &key); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (edc->map, &key, (void*) (long) i + max, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } /* negative values */ n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); for (i=1;i<mem;i++) { gcry_mpi_set_ui (fact, i * K); gcry_mpi_sub (fact, n, fact); gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); extract_pk (gKi, edc->ctx, &key); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (edc->map, &key, (void*) (long) max - i, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } gcry_mpi_release (fact); gcry_mpi_release (n); gcry_mpi_point_release (gKi); gcry_mpi_point_release (g); return edc; }
/** Convert X.509 RSA public key into gcrypt internal sexp form. Only RSA public keys are accepted at the moment. The resul is stored in *sexp, which must be freed (using ) when not needed anymore. *sexp must be NULL on entry, since it is overwritten. */ gpg_err_code_t keyutil_get_cert_sexp ( unsigned char *der, size_t len, gcry_sexp_t *p_sexp ) { gpg_err_code_t error = GPG_ERR_GENERAL; gcry_mpi_t n_mpi = NULL; gcry_mpi_t e_mpi = NULL; gcry_sexp_t sexp = NULL; if ( (error = keyutil_get_cert_mpi ( der, len, &n_mpi, &e_mpi )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( gcry_sexp_build ( &sexp, NULL, "(public-key (rsa (n %m) (e %m)))", n_mpi, e_mpi ) ) { error = GPG_ERR_BAD_KEY; goto cleanup; } *p_sexp = sexp; sexp = NULL; error = GPG_ERR_NO_ERROR; cleanup: if (n_mpi != NULL) { gcry_mpi_release (n_mpi); n_mpi = NULL; } if (e_mpi != NULL) { gcry_mpi_release (e_mpi); e_mpi = NULL; } if (sexp != NULL) { gcry_sexp_release (sexp); sexp = NULL; } return error; }
static void free_gex_group (MSG_gexdh_group * gex) { if (gex) { gcry_mpi_release (gex->p); gcry_mpi_release (gex->g); } }
/* Check that right shifting actually works for an amount larger than the number of bits per limb. */ static void test_rshift (int pass) { gcry_mpi_t a, b; char *result, *result2; int i; wherestr = "test_rshift"; show ("checking that rshift works as expected (pass %d)\n", pass); a = gcry_mpi_new (0); b = gcry_mpi_new (0); gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); for (i=0; i < 75; i++) { gcry_mpi_rshift (b, a, i); result = mpi2bitstr (b, 72); result2 = mpi2bitstr (a, 72); rshiftbitstring (result2, i); if (strcmp (result, result2)) { show ("got =%s\n", result); show ("want=%s\n", result2); fail ("rshift by %d failed\n", i); } xfree (result); xfree (result2); } /* Again. This time using in-place operation. */ gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); for (i=0; i < 75; i++) { gcry_mpi_release (b); b = gcry_mpi_copy (a); gcry_mpi_rshift (b, b, i); result = mpi2bitstr (b, 72); result2 = mpi2bitstr (a, 72); rshiftbitstring (result2, i); if (strcmp (result, result2)) { show ("got =%s\n", result); show ("want=%s\n", result2); fail ("in-place rshift by %d failed\n", i); } xfree (result2); xfree (result); } gcry_mpi_release (b); gcry_mpi_release (a); }
/** * Do some DLOG operations for testing. * * @param edc context for ECC operations * @param do_dlog #GNUNET_YES if we want to actually do the bencharked operation */ static void test_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, int do_dlog) { gcry_mpi_t fact; gcry_mpi_t n; gcry_ctx_t ctx; gcry_mpi_point_t q; gcry_mpi_point_t g; unsigned int i; int x; int iret; GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); g = gcry_mpi_ec_get_point ("g", ctx, 0); GNUNET_assert (NULL != g); n = gcry_mpi_ec_get_mpi ("n", ctx, 0); q = gcry_mpi_point_new (0); fact = gcry_mpi_new (0); for (i=0;i<TEST_ITER;i++) { fprintf (stderr, "."); x = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, MAX_FACT); if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2)) { gcry_mpi_set_ui (fact, x); gcry_mpi_sub (fact, n, fact); x = - x; } else { gcry_mpi_set_ui (fact, x); } gcry_mpi_ec_mul (q, fact, g, ctx); if ( (GNUNET_YES == do_dlog) && (x != (iret = GNUNET_CRYPTO_ecc_dlog (edc, q))) ) { fprintf (stderr, "DLOG failed for value %d (%d)\n", x, iret); GNUNET_assert (0); } } gcry_mpi_release (fact); gcry_mpi_release (n); gcry_mpi_point_release (g); gcry_mpi_point_release (q); gcry_ctx_release (ctx); fprintf (stderr, "\n"); }
GkmDataResult gkm_data_der_read_private_key_dsa_parts (const guchar *keydata, gsize n_keydata, const guchar *params, gsize n_params, gcry_sexp_t *s_key) { gcry_mpi_t p, q, g, y, x; GkmDataResult ret = GKM_DATA_UNRECOGNIZED; int res; GNode *asn_params = NULL; GNode *asn_key = NULL; p = q = g = y = x = NULL; asn_params = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", params, n_params); asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivatePart", keydata, n_keydata); if (!asn_params || !asn_key) goto done; ret = GKM_DATA_FAILURE; if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "p", NULL), &p) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "q", NULL), &q) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "g", NULL), &g)) goto done; if (!gkm_data_asn1_read_mpi (asn_key, &x)) goto done; /* Now we calculate y */ y = gcry_mpi_snew (1024); gcry_mpi_powm (y, g, x, p); res = gcry_sexp_build (s_key, NULL, SEXP_PRIVATE_DSA, p, q, g, y, x); if (res) goto done; g_assert (*s_key); ret = GKM_DATA_SUCCESS; done: egg_asn1x_destroy (asn_key); egg_asn1x_destroy (asn_params); gcry_mpi_release (p); gcry_mpi_release (q); gcry_mpi_release (g); gcry_mpi_release (y); gcry_mpi_release (x); if (ret == GKM_DATA_FAILURE) g_message ("invalid DSA key"); return ret; }
ZrtpDH::~ZrtpDH() { gcryptCtx* tmpCtx = static_cast<gcryptCtx*>(ctx); if (tmpCtx != NULL) { gcry_mpi_release(tmpCtx->privKey); tmpCtx->privKey = NULL; gcry_mpi_release(tmpCtx->pubKey); tmpCtx->pubKey = NULL; delete tmpCtx; ctx = NULL; } }
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); }
/* Compose $(xp,xq) \in Z_p \times Z_q$ into $x \in Z_n$ using Chinese Remainder Theorem */ static void CRT_compose(gcry_mpi_t *x, const gcry_mpi_t xp, const gcry_mpi_t xq, const gcry_mpi_t p, const gcry_mpi_t q) { gcry_mpi_t a, u; a = gcry_mpi_new(0); u = gcry_mpi_new(0); *x = gcry_mpi_new(0); gcry_mpi_subm(a, xq, xp, q); gcry_mpi_invm(u, p, q); gcry_mpi_mulm(a, a, u, q); /* a = (xq - xp) / p (mod q) */ gcry_mpi_mul(*x, p, a); gcry_mpi_add(*x, *x, xp); /* x = p * ((xq - xp) / p mod q) + xp */ gcry_mpi_release(a); gcry_mpi_release(u); }
static void gcr_secret_exchange_default_free (gpointer to_free) { GcrSecretExchangeDefault *data = to_free; gcry_mpi_release (data->prime); gcry_mpi_release (data->base); gcry_mpi_release (data->pub); gcry_mpi_release (data->priv); if (data->key) { egg_secure_clear (data->key, EXCHANGE_1_KEY_LENGTH); egg_secure_free (data->key); } g_free (data); }
/* * Verify an OpenPGP signature made with some RSA public key */ static int verify_signature_rsa( 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(rsa(n %m)(e %m)))"; /* the signature */ const char *sig_sexp_s = "(sig-val(rsa(s%m)))"; size_t erroff; gcry_mpi_t n, e, s, hash; n = e = s = hash = NULL; gcry_sexp_t key_sexp, hash_sexp, sig_sexp; key_sexp = hash_sexp = sig_sexp = NULL; int i_n_len = mpi_len( p_key->sig.rsa.n ); int i_e_len = mpi_len( p_key->sig.rsa.e ); if( gcry_mpi_scan( &n, GCRYMPI_FMT_USG, p_key->sig.rsa.n + 2, i_n_len, NULL ) || gcry_mpi_scan( &e, GCRYMPI_FMT_USG, p_key->sig.rsa.e + 2, i_e_len, NULL ) || gcry_sexp_build( &key_sexp, &erroff, key_sexp_s, n, e ) ) goto out; uint8_t *p_s = sign->algo_specific.rsa.s; int i_s_len = mpi_len( p_s ); if( gcry_mpi_scan( &s, GCRYMPI_FMT_USG, p_s + 2, i_s_len, NULL ) || gcry_sexp_build( &sig_sexp, &erroff, sig_sexp_s, s ) ) goto out; if( rsa_pkcs1_encode_sig (&hash, i_n_len, p_hash, sign->digest_algo) || 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( n ) gcry_mpi_release( n ); if( e ) gcry_mpi_release( e ); 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; }
CK_RV gkm_dsa_mechanism_verify (gcry_sexp_t sexp, CK_BYTE_PTR data, CK_ULONG n_data, CK_BYTE_PTR signature, CK_ULONG n_signature) { gcry_sexp_t ssig, splain; gcry_error_t gcry; gcry_mpi_t mpi, mpi2; g_return_val_if_fail (sexp, CKR_GENERAL_ERROR); g_return_val_if_fail (signature, CKR_ARGUMENTS_BAD); g_return_val_if_fail (data, CKR_ARGUMENTS_BAD); if (n_data != 20) return CKR_DATA_LEN_RANGE; if (n_signature != 40) return CKR_SIGNATURE_LEN_RANGE; /* Prepare the input s-expressions */ gcry = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG, data, n_data, NULL); g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR); gcry = gcry_sexp_build (&splain, NULL, "(data (flags raw) (value %m))", mpi); gcry_mpi_release (mpi); g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR); gcry = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG, signature, 20, NULL); g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR); gcry = gcry_mpi_scan (&mpi2, GCRYMPI_FMT_USG, signature + 20, 20, NULL); g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR); gcry = gcry_sexp_build (&ssig, NULL, "(sig-val (dsa (r %m) (s %m)))", mpi, mpi2); gcry_mpi_release (mpi); gcry_mpi_release (mpi2); g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR); /* Do the magic */ gcry = gcry_pk_verify (ssig, splain, sexp); gcry_sexp_release (splain); gcry_sexp_release (ssig); /* TODO: See if any other codes should be mapped */ if (gcry_err_code (gcry) == GPG_ERR_BAD_SIGNATURE) { return CKR_SIGNATURE_INVALID; } else if (gcry) { g_message ("signing of the data failed: %s", gcry_strerror (gcry)); return CKR_FUNCTION_FAILED; } return CKR_OK; }
static libspectrum_error block_free( rzx_block_t *block ) { size_t i; input_block_t *input; #ifdef HAVE_GCRYPT_H signature_block_t *signature; #endif /* #ifdef HAVE_GCRYPT_H */ switch( block->type ) { case LIBSPECTRUM_RZX_INPUT_BLOCK: input = &( block->types.input ); for( i = 0; i < input->count; i++ ) if( !input->frames[i].repeat_last ) libspectrum_free( input->frames[i].in_bytes ); libspectrum_free( input->frames ); libspectrum_free( block ); return LIBSPECTRUM_ERROR_NONE; case LIBSPECTRUM_RZX_SNAPSHOT_BLOCK: libspectrum_snap_free( block->types.snap.snap ); libspectrum_free( block ); return LIBSPECTRUM_ERROR_NONE; case LIBSPECTRUM_RZX_SIGN_START_BLOCK: libspectrum_free( block ); return LIBSPECTRUM_ERROR_NONE; case LIBSPECTRUM_RZX_SIGN_END_BLOCK: #ifdef HAVE_GCRYPT_H signature = &( block->types.signature ); gcry_mpi_release( signature->r ); gcry_mpi_release( signature->s ); #endif /* #ifdef HAVE_GCRYPT_H */ libspectrum_free( block ); return LIBSPECTRUM_ERROR_NONE; case LIBSPECTRUM_RZX_CREATOR_BLOCK: break; } libspectrum_print_error( LIBSPECTRUM_ERROR_LOGIC, "unknown RZX block type %d at %s:%d", block->type, __FILE__, __LINE__ ); return LIBSPECTRUM_ERROR_LOGIC; }
GkmDataResult gkm_data_der_read_public_key_dsa_parts (const guchar *keydata, gsize n_keydata, const guchar *params, gsize n_params, gcry_sexp_t *s_key) { gcry_mpi_t p, q, g, y; GkmDataResult ret = GKM_DATA_UNRECOGNIZED; GNode *asn_params = NULL; GNode *asn_key = NULL; int res; p = q = g = y = NULL; asn_params = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", params, n_params); asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPublicPart", keydata, n_keydata); if (!asn_params || !asn_key) goto done; ret = GKM_DATA_FAILURE; if (!gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "p", NULL), &p) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "q", NULL), &q) || !gkm_data_asn1_read_mpi (egg_asn1x_node (asn_params, "g", NULL), &g)) goto done; if (!gkm_data_asn1_read_mpi (asn_key, &y)) goto done; res = gcry_sexp_build (s_key, NULL, SEXP_PUBLIC_DSA, p, q, g, y); if (res) goto done; g_assert (*s_key); ret = GKM_DATA_SUCCESS; done: egg_asn1x_destroy (asn_key); egg_asn1x_destroy (asn_params); gcry_mpi_release (p); gcry_mpi_release (q); gcry_mpi_release (g); gcry_mpi_release (y); if (ret == GKM_DATA_FAILURE) g_message ("invalid DSA key"); return ret; }
/* This is to check a bug reported by bpgcrypt at itaparica.org on 2006-07-31 against libgcrypt 1.2.2. */ static void one_bit_only (int highbit) { gcry_mpi_t a; char *result; int i; wherestr = "one_bit_only"; show ("checking that set_%sbit does only set one bit\n", highbit?"high":""); a = gcry_mpi_new (0); gcry_mpi_randomize (a, 70, GCRY_WEAK_RANDOM); gcry_mpi_set_ui (a, 0); if (highbit) gcry_mpi_set_highbit (a, 42); else gcry_mpi_set_bit (a, 42); if (!gcry_mpi_test_bit (a, 42)) fail ("failed to set a bit\n"); gcry_mpi_clear_bit (a, 42); if (gcry_mpi_test_bit (a, 42)) fail ("failed to clear a bit\n"); result = mpi2bitstr (a, 70); assert (strlen (result) == 70); for (i=0; result[i]; i++) if ( result[i] != '0' ) break; if (result[i]) fail ("spurious bits detected\n"); xfree (result); gcry_mpi_release (a); }
static void print_point (const char *text, gcry_mpi_point_t a) { gcry_mpi_t x, y, z; x = gcry_mpi_new (0); y = gcry_mpi_new (0); z = gcry_mpi_new (0); gcry_mpi_point_get (x, y, z, a); print_mpi_2 (text, ".x", x); print_mpi_2 (text, ".y", y); print_mpi_2 (text, ".z", z); gcry_mpi_release (x); gcry_mpi_release (y); gcry_mpi_release (z); }
static gboolean gcr_secret_exchange_default_derive_transport_key (GcrSecretExchange *exchange, const guchar *peer, gsize n_peer) { GcrSecretExchangeDefault *data = exchange->pv->default_exchange; gpointer ikm; gsize n_ikm; gcry_mpi_t mpi; g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (data->priv != NULL, FALSE); mpi = mpi_from_data (peer, n_peer); if (mpi == NULL) return FALSE; /* Build up a key we can use */ ikm = egg_dh_gen_secret (mpi, data->priv, data->prime, &n_ikm); g_return_val_if_fail (ikm != NULL, FALSE); if (data->key == NULL) data->key = egg_secure_alloc (EXCHANGE_1_KEY_LENGTH); if (!egg_hkdf_perform (EXCHANGE_1_HASH_ALGO, ikm, n_ikm, NULL, 0, NULL, 0, data->key, EXCHANGE_1_KEY_LENGTH)) g_return_val_if_reached (FALSE); egg_secure_free (ikm); gcry_mpi_release (mpi); return TRUE; }
/** * Decode the signature from the data-format back to the "normal", internal * format. * * @param buf the buffer where the public key data is stored * @param len the length of the data in @a buf * @return NULL on error */ struct GNUNET_CRYPTO_rsa_Signature * GNUNET_CRYPTO_rsa_signature_decode (const char *buf, size_t len) { struct GNUNET_CRYPTO_rsa_Signature *sig; int ret; gcry_mpi_t s; sig = GNUNET_new (struct GNUNET_CRYPTO_rsa_Signature); if (0 != gcry_sexp_new (&sig->sexp, buf, len, 0)) { GNUNET_break_op (0); GNUNET_free (sig); return NULL; } /* verify that this is an RSA signature */ ret = key_from_sexp (&s, sig->sexp, "sig-val", "s"); if (0 != ret) ret = key_from_sexp (&s, sig->sexp, "rsa", "s"); if (0 != ret) { /* this is no RSA Signature */ GNUNET_break_op (0); gcry_sexp_release (sig->sexp); GNUNET_free (sig); return NULL; } gcry_mpi_release (s); return sig; }
/** * Generate a random value mod n. * * @param edc ECC context * @return random value mod n. */ gcry_mpi_t GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccDlogContext *edc) { gcry_mpi_t n; unsigned int highbit; gcry_mpi_t r; n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); /* check public key for number of bits, bail out if key is all zeros */ highbit = 256; /* Curve25519 */ while ( (! gcry_mpi_test_bit (n, highbit)) && (0 != highbit) ) highbit--; GNUNET_assert (0 != highbit); /* generate fact < n (without bias) */ GNUNET_assert (NULL != (r = gcry_mpi_new (0))); do { gcry_mpi_randomize (r, highbit + 1, GCRY_STRONG_RANDOM); } while (gcry_mpi_cmp (r, n) >= 0); gcry_mpi_release (n); return r; }
/* compute 2^m (mod phi(p)), for a prime p */ static gcry_mpi_t twopowmodphi(uint64_t m, const gcry_mpi_t p) { gcry_mpi_t phi, r; int n; phi = gcry_mpi_new(0); gcry_mpi_sub_ui(phi, p, 1); /* count number of used bits in m */ for (n = 0; ((uint64_t)1 << n) <= m; n++) ; r = gcry_mpi_new(0); gcry_mpi_set_ui(r, 1); while (n) { /* square and multiply algorithm for fast exponentiation */ n--; gcry_mpi_mulm(r, r, r, phi); if (m & ((uint64_t)1 << n)) { gcry_mpi_add(r, r, r); if (gcry_mpi_cmp(r, phi) >= 0) gcry_mpi_sub(r, r, phi); } } gcry_mpi_release(phi); return r; }
/* Rotate in a new DH public key for our correspondent. Be sure to keep * the sesskeys array in sync. */ static gcry_error_t rotate_y_keys(ConnContext *context, gcry_mpi_t new_y) { gcry_error_t err; /* Rotate the public key */ gcry_mpi_release(context->their_old_y); context->their_old_y = context->their_y; /* Rotate the session keys */ err = reveal_macs(context, &(context->sesskeys[0][1]), &(context->sesskeys[1][1])); if (err) return err; otrl_dh_session_free(&(context->sesskeys[0][1])); otrl_dh_session_free(&(context->sesskeys[1][1])); memmove(&(context->sesskeys[0][1]), &(context->sesskeys[0][0]), sizeof(DH_sesskeys)); memmove(&(context->sesskeys[1][1]), &(context->sesskeys[1][0]), sizeof(DH_sesskeys)); /* Copy in the new public key */ context->their_y = gcry_mpi_copy(new_y); context->their_keyid++; /* Make the session keys */ err = otrl_dh_session(&(context->sesskeys[0][0]), &(context->our_dh_key), context->their_y); if (err) return err; err = otrl_dh_session(&(context->sesskeys[1][0]), &(context->our_old_dh_key), context->their_y); if (err) return err; return gcry_error(GPG_ERR_NO_ERROR); }
int deserialize_mpi(gcry_mpi_t *x, enum disp_format df, const char *buf, int inlen) { switch(df) { case DF_BIN: gcry_mpi_scan(x, GCRYMPI_FMT_USG, buf, inlen, NULL); gcry_mpi_set_flag(*x, GCRYMPI_FLAG_SECURE); break; case DF_COMPACT: case DF_BASE36: do { const char *digits = get_digits(df); unsigned int digit_count = get_digit_count(df); char *d; int i; *x = gcry_mpi_snew(0); for(i = 0; i < inlen; i++) { if (! (d = memchr(digits, buf[i], digit_count))) { gcry_mpi_release(*x); return 0; } gcry_mpi_mul_ui(*x, *x, digit_count); gcry_mpi_add_ui(*x, *x, d - digits); } } while (0); break; default: assert(0); } return 1; }