/** * cdk_pk_encrypt: * @pk: the public key * @pke: the public key encrypted packet * @esk: the actual session key * * Encrypt the session key in @esk and write its encrypted content * into the @pke struct. **/ cdk_error_t cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke, gcry_mpi_t esk) { gcry_sexp_t s_data = NULL, s_pkey = NULL, s_ciph = NULL; gcry_error_t err; cdk_error_t rc; if (!pk || !esk || !pke) return CDK_Inv_Value; if (!KEY_CAN_ENCRYPT (pk->pubkey_algo)) return CDK_Inv_Algo; rc = enckey_to_sexp (&s_data, esk); if (!rc) rc = pubkey_to_sexp (&s_pkey, pk); if (!rc) { err = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); if (err) return map_gcry_error (err); } if (!rc) rc = sexp_to_pubenc (pke, s_ciph); gcry_sexp_release (s_data); gcry_sexp_release (s_pkey); gcry_sexp_release (s_ciph); return rc; }
STRING *ssh_encrypt_rsa1(SSH_SESSION *session, STRING *data, PUBLIC_KEY *key){ int len=string_len(data); #ifdef HAVE_LIBGCRYPT STRING *ret; gcry_sexp_t ret_sexp; gcry_sexp_t data_sexp; const char *tmp; size_t size; gcry_sexp_build(&data_sexp,NULL,"(data(flags pkcs1)(value %b))",len,data->string); gcry_pk_encrypt(&ret_sexp,data_sexp,key->rsa_pub); gcry_sexp_release(data_sexp); data_sexp=gcry_sexp_find_token(ret_sexp,"a",0); tmp=gcry_sexp_nth_data(data_sexp,1,&size); if (*tmp == 0) { size--; tmp++; } ret=string_new(size); string_fill(ret,(char *)tmp,size); gcry_sexp_release(ret_sexp); #elif defined HAVE_LIBCRYPTO int flen=RSA_size(key->rsa_pub); STRING *ret=string_new(flen); RSA_public_encrypt(len,data->string,ret->string,key->rsa_pub, RSA_PKCS1_PADDING); #endif return ret; }
char* encrypt(rsa_packet * packet, char *public_key, char *plaintext){ gcry_error_t error; gcry_mpi_t r_mpi; if ((error = gcry_mpi_scan(&r_mpi, GCRYMPI_FMT_HEX, plaintext, 0, NULL))) { printf("Error in gcry_mpi_scan() in encrypt(): %s\nSource: %s\n", gcry_strerror(error), gcry_strsource(error)); exit(1); } gcry_sexp_t data; size_t erroff; if ((error = gcry_sexp_build(&data, &erroff, "(data (flags raw) (value %m))", r_mpi))) { printf("Error in gcry_sexp_build() in encrypt() at %ld: %s\nSource: %s\n", erroff, gcry_strerror(error), gcry_strsource(error)); exit(1); } gcry_sexp_t public_sexp = sexp_new(public_key); gcry_sexp_t r_ciph; struct timeval timer; timer_start(&timer); if ((error = gcry_pk_encrypt(&r_ciph, data, public_sexp))) { printf("Error in gcry_pk_encrypt(): %s\nSource: %s\n", gcry_strerror(error), gcry_strsource(error)); exit(1); } timer_poll("\nSoftware encrypt: %d.%06d seconds\n", &timer); gcry_sexp_t cipher_sexp = gcry_sexp_cdr(gcry_sexp_find_token(r_ciph, "a", 1)); gcry_mpi_t cipher_mpi = gcry_sexp_nth_mpi(cipher_sexp, 0, GCRYMPI_FMT_USG); gcry_mpi_print(GCRYMPI_FMT_USG, packet->ciphertext, 256, &packet->cipher_len, cipher_mpi); return sexp_string(r_ciph); }
/* Encrypt the DEK under the key contained in CERT and return it as a canonical S-Exp in encval. */ static int encrypt_dek (const DEK dek, ksba_cert_t cert, unsigned char **encval) { gcry_sexp_t s_ciph, s_data, s_pkey; int rc; ksba_sexp_t buf; size_t len; *encval = NULL; /* get the key from the cert */ buf = ksba_cert_get_public_key (cert); if (!buf) { log_error ("no public key for recipient\n"); return gpg_error (GPG_ERR_NO_PUBKEY); } len = gcry_sexp_canon_len (buf, 0, NULL, NULL); if (!len) { log_error ("libksba did not return a proper S-Exp\n"); return gpg_error (GPG_ERR_BUG); } rc = gcry_sexp_sscan (&s_pkey, NULL, (char*)buf, len); xfree (buf); buf = NULL; if (rc) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); return rc; } /* Put the encoded cleartext into a simple list. */ s_data = NULL; /* (avoid compiler warning) */ rc = encode_session_key (dek, &s_data); if (rc) { log_error ("encode_session_key failed: %s\n", gpg_strerror (rc)); return rc; } /* pass it to libgcrypt */ rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); gcry_sexp_release (s_data); gcry_sexp_release (s_pkey); /* Reformat it. */ if (!rc) { rc = make_canon_sexp (s_ciph, encval, NULL); gcry_sexp_release (s_ciph); } return rc; }
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); }
CK_RV gkm_rsa_mechanism_encrypt (gcry_sexp_t sexp, EggPadding padding, CK_BYTE_PTR data, CK_ULONG n_data, CK_BYTE_PTR encrypted, CK_ULONG_PTR n_encrypted) { gcry_sexp_t splain, sdata; gcry_error_t gcry; guint nbits; CK_RV rv; g_return_val_if_fail (sexp, CKR_GENERAL_ERROR); g_return_val_if_fail (n_encrypted, CKR_ARGUMENTS_BAD); g_return_val_if_fail (data, CKR_ARGUMENTS_BAD); nbits = gcry_pk_get_nbits (sexp); g_return_val_if_fail (nbits > 0, CKR_GENERAL_ERROR); /* Just want to know the length */ if (!encrypted) { *n_encrypted = (nbits + 7) / 8; return CKR_OK; } /* Prepare the input s expression */ rv = gkm_crypto_data_to_sexp ("(data (flags raw) (value %m))", nbits, padding, data, n_data, &splain); if (rv != CKR_OK) return rv; /* Do the magic */ gcry = gcry_pk_encrypt (&sdata, splain, sexp); gcry_sexp_release (splain); /* TODO: Certain codes should be returned (data too big etc... ) */ if (gcry) { g_message ("encrypting of the data failed: %s", gcry_strerror (gcry)); return CKR_FUNCTION_FAILED; } /* Now extract and send it back out */ rv = gkm_crypto_sexp_to_data (sdata, nbits, encrypted, n_encrypted, NULL, "enc-val", "rsa", "a", NULL); gcry_sexp_release (sdata); return rv; }
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; }
/**************** * 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; }
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; }
static int _wrap_gcry_pk_encrypt (gnutls_pk_algorithm_t algo, gnutls_datum_t * ciphertext, const gnutls_datum_t * plaintext, const gnutls_pk_params_st * pk_params) { gcry_sexp_t s_ciph = NULL, s_data = NULL, s_pkey = NULL; int rc = -1; int ret; bigint_t data, res; gcry_sexp_t list; if (_gnutls_mpi_scan_nz (&data, plaintext->data, plaintext->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* make a sexp from pkey */ switch (algo) { 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_data, NULL, "%m", data)) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } /* pass it to libgcrypt */ rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_PK_ENCRYPTION_FAILED; goto cleanup; } list = gcry_sexp_find_token (s_ciph, "a", 0); if (list == NULL) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } res = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); if (res == NULL) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = _gnutls_mpi_dprint_size (res, ciphertext, plaintext->size); _gnutls_mpi_release (&res); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = 0; cleanup: _gnutls_mpi_release (&data); if (s_ciph) gcry_sexp_release (s_ciph); if (s_data) gcry_sexp_release (s_data); if (s_pkey) gcry_sexp_release (s_pkey); return ret; }
GByteArray * steam_crypt_rsa_enc(const GByteArray *mod, const GByteArray *exp, const GByteArray *bytes) { GByteArray *ret = NULL; gcry_error_t res; gcry_mpi_t dmpi = NULL; gcry_mpi_t empi = NULL; gcry_mpi_t mmpi = NULL; gcry_sexp_t cata = NULL; gcry_sexp_t data = NULL; gcry_sexp_t kata = NULL; gsize size; g_return_val_if_fail(mod != NULL, NULL); g_return_val_if_fail(exp != NULL, NULL); g_return_val_if_fail(bytes != NULL, NULL); res = gcry_mpi_scan(&mmpi, GCRYMPI_FMT_USG, mod->data, mod->len, NULL); res |= gcry_mpi_scan(&empi, GCRYMPI_FMT_USG, exp->data, exp->len, NULL); res |= gcry_mpi_scan(&dmpi, GCRYMPI_FMT_USG, bytes->data, bytes->len, NULL); if (G_UNLIKELY(res != 0)) { goto finish; } res = gcry_sexp_build(&kata, NULL, "(public-key(rsa(n %m)(e %m)))", mmpi, empi); res |= gcry_sexp_build(&data, NULL, "(data(flags pkcs1)(value %m))", dmpi); if (G_UNLIKELY(res != 0)) { goto finish; } res = gcry_pk_encrypt(&cata, data, kata); if (G_UNLIKELY(res != 0)) { goto finish; } gcry_sexp_release(data); data = gcry_sexp_find_token(cata, "a", 0); if (G_UNLIKELY(data == NULL)) { g_warn_if_reached(); goto finish; } gcry_mpi_release(dmpi); dmpi = gcry_sexp_nth_mpi(data, 1, GCRYMPI_FMT_USG); if (G_UNLIKELY(dmpi == NULL)) { g_warn_if_reached(); goto finish; } ret = g_byte_array_new(); g_byte_array_set_size(ret, mod->len); gcry_mpi_print(GCRYMPI_FMT_USG, ret->data, ret->len, &size, dmpi); g_warn_if_fail(size <= mod->len); g_byte_array_set_size(ret, size); finish: gcry_sexp_release(cata); gcry_sexp_release(data); gcry_sexp_release(kata); gcry_mpi_release(dmpi); gcry_mpi_release(empi); gcry_mpi_release(mmpi); return ret; }
/* Check against PKCS#1 v1.5 encryption test vectors as found at ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15crypt-vectors.txt . */ static void check_v15crypt (void) { #include "pkcs1v2-v15c.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, *seed, *encr; size_t mesg_len, seed_len, encr_len; gcry_sexp_t plain, ciph; if (verbose) info ("running test: %s\n", tbl[tno].m[mno].desc); mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len); seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len); err = gcry_sexp_build (&plain, NULL, "(data (flags pkcs1)(hash-algo sha1)" "(value %b)(random-override %b))", (int)mesg_len, mesg, (int)seed_len, seed); if (err) die ("constructing plain data failed: %s\n", gpg_strerror (err)); gcry_free (mesg); gcry_free (seed); err = gcry_pk_encrypt (&ciph, plain, pub_key); if (err) { show_sexp ("plain:\n", ciph); fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err)); } else { if (extract_cmp_data (ciph, "a", tbl[tno].m[mno].encr, tbl[tno].m[mno].desc)) { show_sexp ("encrypt result:\n", ciph); fail ("mismatch in gcry_pk_encrypt\n"); } gcry_sexp_release (ciph); ciph = NULL; } gcry_sexp_release (plain); plain = NULL; /* Now test the decryption. */ seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len); encr = data_from_hex (tbl[tno].m[mno].encr, &encr_len); err = gcry_sexp_build (&ciph, NULL, "(enc-val (flags pkcs1)(hash-algo sha1)" "(random-override %b)" "(rsa (a %b)))", (int)seed_len, seed, (int)encr_len, encr); if (err) die ("constructing cipher data failed: %s\n", gpg_strerror (err)); gcry_free (encr); gcry_free (seed); err = gcry_pk_decrypt (&plain, ciph, sec_key); if (err) { show_sexp ("ciph:\n", ciph); fail ("gcry_pk_decrypt failed: %s\n", gpg_strerror (err)); } else { if (extract_cmp_data (plain, "value", tbl[tno].m[mno].mesg, tbl[tno].m[mno].desc)) { show_sexp ("decrypt result:\n", plain); fail ("mismatch in gcry_pk_decrypt\n"); } gcry_sexp_release (plain); plain = NULL; } gcry_sexp_release (ciph); ciph = NULL; } gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); } }
unsigned char *crypto_decrypt_signature(crypto_ctx *ctx, const unsigned char *sig_data, size_t sig_len, size_t *out_len, unsigned int padding, crypto_error **error) { unsigned char *buf = NULL, *rec_hash = NULL; gnutls_datum_t n = { NULL, 0 }, e = { NULL, 0 }; int err, algo; gcry_sexp_t key = NULL, sig = NULL, decrypted = NULL, child = NULL; gcry_mpi_t n_mpi = NULL, e_mpi = NULL, sig_mpi = NULL, dec_mpi = NULL; size_t buf_len = 0, hash_len = 0; if (!ctx) { crypto_error_set(error, 1, 0, "invalid crypto context"); return NULL; } if (!ctx->num) { crypto_error_set(error, 1, 0, "no certificates in the stack"); return NULL; } algo = gnutls_x509_crt_get_pk_algorithm(ctx->stack[ctx->num - 1], NULL); if (algo != GNUTLS_PK_RSA) { crypto_error_set(error, 1, 0, "certificate public key algorithm not RSA"); return NULL; } err = gnutls_x509_crt_get_pk_rsa_raw(ctx->stack[ctx->num - 1], &n, &e); if (err != GNUTLS_E_SUCCESS) { crypto_error_set(error, 1, 0, "error getting certificate public key"); return NULL; } err = gcry_mpi_scan(&n_mpi, GCRYMPI_FMT_USG, n.data, n.size, NULL); if (err) { crypto_error_set(error, 1, 0, "invalid RSA key 'n' format"); goto out; } err = gcry_mpi_scan(&e_mpi, GCRYMPI_FMT_USG, e.data, e.size, NULL); if (err) { crypto_error_set(error, 1, 0, "invalid RSA key 'e' format"); goto out; } err = gcry_sexp_build(&key, NULL, "(public-key (rsa (n %m) (e %m)))", n_mpi, e_mpi); if (err) { crypto_error_set(error, 1, 0, "could not create public-key expression"); goto out; } err = gcry_mpi_scan(&sig_mpi, GCRYMPI_FMT_USG, sig_data, sig_len, NULL); if (err) { crypto_error_set(error, 1, 0, "invalid signature format"); goto out; } err = gcry_sexp_build(&sig, NULL, "(data (flags raw) (value %m))", sig_mpi); if (err) { crypto_error_set(error, 1, 0, "could not create signature expression"); goto out; } /* encrypt is equivalent to public key decryption for RSA keys */ err = gcry_pk_encrypt(&decrypted, sig, key); if (err) { crypto_error_set(error, 1, 0, "could not decrypt signature"); goto out; } child = gcry_sexp_find_token(decrypted, "a", 1); if (!child) { crypto_error_set(error, 1, 0, "could not get decrypted signature result"); goto out; } dec_mpi = gcry_sexp_nth_mpi(child, 1, GCRYMPI_FMT_USG); gcry_sexp_release(child); if (!dec_mpi) { crypto_error_set(error, 1, 0, "could not get decrypted signature result"); goto out; } gcry_mpi_aprint(GCRYMPI_FMT_USG, &buf, &buf_len, dec_mpi); if (!buf) { crypto_error_set(error, 1, 0, "could not get extract decrypted signature"); goto out; } switch (padding) { case CRYPTO_PAD_NONE: rec_hash = buf; hash_len = buf_len; buf = NULL; *out_len = (int) hash_len; break; case CRYPTO_PAD_PKCS1: rec_hash = check_pkcs1_padding(buf, buf_len, &hash_len, error); if (!rec_hash) { crypto_error_set(error, 1, 0, "could not get extract decrypted padded signature"); goto out; } *out_len = (int) hash_len; break; default: crypto_error_set(error, 1, 0, "unknown padding mechanism %d", padding); break; } out: if (buf) free(buf); if (dec_mpi) gcry_mpi_release(dec_mpi); if (decrypted) gcry_sexp_release(decrypted); if (key) gcry_sexp_release(key); if (sig) gcry_sexp_release(sig); if (sig_mpi) gcry_mpi_release(sig_mpi); if (n_mpi) gcry_mpi_release(n_mpi); if (e_mpi) gcry_mpi_release(e_mpi); if (n.data) gcry_free(n.data); if (e.data) gcry_free(e.data); return rec_hash; }
static void check_keys_crypt (gcry_sexp_t pkey, gcry_sexp_t skey, gcry_sexp_t plain0, gpg_err_code_t decrypt_fail_code) { gcry_sexp_t plain1, cipher, l; gcry_mpi_t x0, x1; int rc; int have_flags; /* Extract data from plaintext. */ l = gcry_sexp_find_token (plain0, "value", 0); x0 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l); /* Encrypt data. */ rc = gcry_pk_encrypt (&cipher, plain0, pkey); if (rc) die ("encryption failed: %s\n", gcry_strerror (rc)); l = gcry_sexp_find_token (cipher, "flags", 0); have_flags = !!l; gcry_sexp_release (l); /* Decrypt data. */ rc = gcry_pk_decrypt (&plain1, cipher, skey); gcry_sexp_release (cipher); if (rc) { if (decrypt_fail_code && gpg_err_code (rc) == decrypt_fail_code) { gcry_mpi_release (x0); return; /* This is the expected failure code. */ } die ("decryption failed: %s\n", gcry_strerror (rc)); } /* Extract decrypted data. Note that for compatibility reasons, the output of gcry_pk_decrypt depends on whether a flags lists (even if empty) occurs in its input data. Because we passed the output of encrypt directly to decrypt, such a flag value won't be there as of today. We check it anyway. */ l = gcry_sexp_find_token (plain1, "value", 0); if (l) { if (!have_flags) die ("compatibility mode of pk_decrypt broken\n"); gcry_sexp_release (plain1); x1 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l); } else { if (have_flags) die ("compatibility mode of pk_decrypt broken\n"); x1 = gcry_sexp_nth_mpi (plain1, 0, GCRYMPI_FMT_USG); gcry_sexp_release (plain1); } /* Compare. */ if (gcry_mpi_cmp (x0, x1)) die ("data corrupted\n"); gcry_mpi_release (x0); gcry_mpi_release (x1); }
/* * Test X25519 functionality through higher layer crypto routines. * * Input: K (as hex string), U (as hex string), R (as hex string) * * where R is expected result of X25519 (K, U). * * It calls gcry_pk_decrypt with Curve25519 private key and let * it compute X25519. */ static void test_cv (int testno, const char *k_str, const char *u_str, const char *result_str) { gpg_error_t err; void *buffer = NULL; size_t buflen; gcry_sexp_t s_pk = NULL; gcry_mpi_t mpi_k = NULL; gcry_sexp_t s_data = NULL; gcry_sexp_t s_result = NULL; gcry_sexp_t s_tmp = NULL; unsigned char *res = NULL; size_t res_len; if (verbose > 1) info ("Running test %d\n", testno); if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) { fail ("error building s-exp for test %d, %s: %s", testno, "k", "invalid hex string"); goto leave; } reverse_buffer (buffer, buflen); if ((err = gcry_mpi_scan (&mpi_k, GCRYMPI_FMT_USG, buffer, buflen, NULL))) { fail ("error converting MPI for test %d: %s", testno, gpg_strerror (err)); goto leave; } if ((err = gcry_sexp_build (&s_data, NULL, "%m", mpi_k))) { fail ("error building s-exp for test %d, %s: %s", testno, "data", gpg_strerror (err)); goto leave; } xfree (buffer); if (!(buffer = hex2buffer (u_str, &buflen)) || buflen != 32) { fail ("error building s-exp for test %d, %s: %s", testno, "u", "invalid hex string"); goto leave; } /* * The procedure of decodeUCoordinate will be done internally * by _gcry_ecc_mont_decodepoint. So, we just put the little-endian * binary to build S-exp. * * We could add the prefix 0x40, but libgcrypt also supports * format with no prefix. So, it is OK not to put the prefix. */ if ((err = gcry_sexp_build (&s_pk, NULL, "(public-key" " (ecc" " (curve \"Curve25519\")" " (flags djb-tweak)" " (q%b)))", (int)buflen, buffer))) { fail ("error building s-exp for test %d, %s: %s", testno, "pk", gpg_strerror (err)); goto leave; } xfree (buffer); buffer = NULL; if ((err = gcry_pk_encrypt (&s_result, s_data, s_pk))) fail ("gcry_pk_encrypt failed for test %d: %s", testno, gpg_strerror (err)); s_tmp = gcry_sexp_find_token (s_result, "s", 0); if (!s_tmp || !(res = gcry_sexp_nth_buffer (s_tmp, 1, &res_len))) fail ("gcry_pk_encrypt failed for test %d: %s", testno, "missing value"); else { char *r, *r0; int i; /* To skip the prefix 0x40, for-loop start with i=1 */ r0 = r = xmalloc (2*(res_len)+1); if (!r0) { fail ("memory allocation for test %d", testno); goto leave; } for (i=1; i < res_len; i++, r += 2) snprintf (r, 3, "%02x", res[i]); if (strcmp (result_str, r0)) { fail ("gcry_pk_encrypt failed for test %d: %s", testno, "wrong value returned"); info (" expected: '%s'", result_str); info (" got: '%s'", r0); } xfree (r0); } leave: xfree (res); gcry_mpi_release (mpi_k); gcry_sexp_release (s_tmp); gcry_sexp_release (s_result); gcry_sexp_release (s_data); gcry_sexp_release (s_pk); xfree (buffer); }